1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Update docs + fix endian issue

This commit is contained in:
Guillaume J. Charmes 2013-09-26 15:59:02 -07:00
parent 082d142024
commit cb18a6e1b9
No known key found for this signature in database
GPG key ID: B33E4642CB6E3FF3
6 changed files with 63 additions and 95 deletions

View file

@ -951,7 +951,7 @@ func TestPostContainersAttach(t *testing.T) {
})
setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
if err := assertPipe("hello\n", string([]byte{1, 0, 0, 0, 6, 0, 0, 0})+"hello", stdout, stdinPipe, 15); err != nil {
if err := assertPipe("hello\n", string([]byte{1, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 15); err != nil {
t.Fatal(err)
}
})
@ -1040,7 +1040,7 @@ func TestPostContainersAttachStderr(t *testing.T) {
})
setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
if err := assertPipe("hello\n", string([]byte{2, 0, 0, 0, 6, 0, 0, 0})+"hello", stdout, stdinPipe, 15); err != nil {
if err := assertPipe("hello\n", string([]byte{2, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 15); err != nil {
t.Fatal(err)
}
})

View file

@ -1,52 +0,0 @@
:title: Attach stream API
:description: API Documentation for the Attach command in Docker
:keywords: API, Docker, Attach, Stream, REST, documentation
=================
Docker Attach stream API
=================
.. contents:: Table of Contents
1. Brief introduction
=====================
- This is the Attach stream API for Docker
2. Format
=========
The attach format is a Header and a Payload (frame).
2.1 Header
^^^^^^^^^^
The header will contain the information on which stream write
the stream (stdout or stderr).
It also contain the size of the associated frame encoded on the last 4 bytes (uint32).
It is encoded on the first 8 bytes like this:
header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
STREAM_TYPE can be:
- 0: stdin (will be writen on stdout)
- 1: stdout
- 2: stderr
SIZE1, SIZE2, SIZE3, SIZE4 are the 4 bytes of the uint32 size.
2.1 Payload (frame)
^^^^^^^^^^^^^^^^^^^
The payload is the raw stream.
3. Implementation
=================
The simplest way to implement the Attach protocol is the following:
1) Read 8 bytes
2) chose stdout or stderr depending on the first byte
3) Extract the frame size from the last 4 byets
4) Read the extracted size and output it on the correct output
5) Goto 1)

View file

@ -44,10 +44,10 @@ What's new
.. http:post:: /containers/(id)/attach
**New!** You can now split stderr from stdout. This is done by prefixing
a header to each transmition. See :doc:`attach_api_1.6`.
a header to each transmition. See :http:post:`/containers/(id)/attach`.
The WebSocket attach is unchanged.
Note that attach calls on previous API version didn't change. Stdout and
stderr are merge.
Note that attach calls on the previous API version didn't change. Stdout and
stderr are merged.
:doc:`docker_remote_api_v1.5`

View file

@ -468,7 +468,7 @@ Attach to a container
HTTP/1.1 200 OK
Content-Type: application/vnd.docker.raw-stream
{{ PREFIXED STREAM }} See :doc:`attach_api_1.6`
{{ STREAM }}
:query logs: 1/True/true or 0/False/false, return logs. Default false
:query stream: 1/True/true or 0/False/false, return stream. Default false
@ -480,6 +480,49 @@ Attach to a container
:statuscode 404: no such container
:statuscode 500: server error
**Stream details**:
When using the TTY setting is enabled in
:http:post:`/containers/create`, the stream is the raw data
from the process PTY and client's stdin. When the TTY is
disabled, then the stream is multiplexed to separate stdout
and stderr.
The format is a **Header** and a **Payload** (frame).
**HEADER**
The header will contain the information on which stream write
the stream (stdout or stderr). It also contain the size of
the associated frame encoded on the last 4 bytes (uint32).
It is encoded on the first 8 bytes like this::
header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
``STREAM_TYPE`` can be:
- 0: stdin (will be writen on stdout)
- 1: stdout
- 2: stderr
``SIZE1, SIZE2, SIZE3, SIZE4`` are the 4 bytes of the uint32 size encoded as big endian.
**PAYLOAD**
The payload is the raw stream.
**IMPLEMENTATION**
The simplest way to implement the Attach protocol is the following:
1) Read 8 bytes
2) chose stdout or stderr depending on the first byte
3) Extract the frame size from the last 4 byets
4) Read the extracted size and output it on the correct output
5) Goto 1)
Wait a container
****************

View file

@ -1208,16 +1208,20 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std
} else {
dec := json.NewDecoder(cLog)
for {
var l utils.JSONLog
if err := dec.Decode(&l); err == io.EOF {
l := &utils.JSONLog{}
if err := dec.Decode(l); err == io.EOF {
break
} else if err != nil {
utils.Debugf("Error streaming logs: %s", err)
break
}
if (l.Stream == "stdout" && stdout) || (l.Stream == "stderr" && stderr) {
if l.Stream == "stdout" && stdout {
fmt.Fprintf(outStream, "%s", l.Log)
}
if l.Stream == "stderr" && stderr {
fmt.Fprintf(errStream, "%s", l.Log)
}
}
}
}

View file

@ -4,18 +4,8 @@ import (
"encoding/binary"
"errors"
"io"
"unsafe"
)
func CheckBigEndian() bool {
var x uint32 = 0x01020304
if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
return true
}
return false
}
const (
StdWriterPrefixLen = 8
StdWriterFdIndex = 0
@ -32,16 +22,15 @@ var (
type StdWriter struct {
io.Writer
prefix StdType
sizeBuf []byte
byteOrder binary.ByteOrder
prefix StdType
sizeBuf []byte
}
func (w *StdWriter) Write(buf []byte) (n int, err error) {
if w == nil || w.Writer == nil {
return 0, errors.New("Writer not instanciated")
}
w.byteOrder.PutUint32(w.prefix[4:], uint32(len(buf)))
binary.BigEndian.PutUint32(w.prefix[4:], uint32(len(buf)))
buf = append(w.prefix[:], buf...)
n, err = w.Writer.Write(buf)
@ -55,18 +44,10 @@ func NewStdWriter(w io.Writer, t StdType) *StdWriter {
return nil
}
var bo binary.ByteOrder
if CheckBigEndian() {
bo = binary.BigEndian
} else {
bo = binary.LittleEndian
}
return &StdWriter{
Writer: w,
prefix: t,
sizeBuf: make([]byte, 4),
byteOrder: bo,
Writer: w,
prefix: t,
sizeBuf: make([]byte, 4),
}
}
@ -91,17 +72,9 @@ func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error)
nr, nw int
er, ew error
out io.Writer
byteOrder binary.ByteOrder
frameSize int
)
// Check the machine's endianness
if CheckBigEndian() {
byteOrder = binary.BigEndian
} else {
byteOrder = binary.LittleEndian
}
for {
// Make sure we have at least a full header
for nr < StdWriterPrefixLen {
@ -132,7 +105,7 @@ func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error)
}
// Retrieve the size of the frame
frameSize = int(byteOrder.Uint32(buf[StdWriterSizeIndex : StdWriterSizeIndex+4]))
frameSize = int(binary.BigEndian.Uint32(buf[StdWriterSizeIndex : StdWriterSizeIndex+4]))
// Check if the buffer is big enough to read the frame.
// Extend it if necessary.