LEFT | RIGHT |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package ssh | 5 package ssh |
6 | 6 |
7 import ( | 7 import ( |
8 "io" | 8 "io" |
9 "sync" | 9 "sync" |
10 ) | 10 ) |
11 | 11 |
12 // buffer provides a linked list buffer for data exchange | 12 // buffer provides a linked list buffer for data exchange |
13 // between producer and consumer. Theoretically the buffer is | 13 // between producer and consumer. Theoretically the buffer is |
14 // of unlimited capacity as it does no allocation of its own. | 14 // of unlimited capacity as it does no allocation of its own. |
15 type buffer struct { | 15 type buffer struct { |
16 » // protects concurrent access to head, tail and eof | 16 » // protects concurrent access to head, tail and closed |
17 *sync.Cond | 17 *sync.Cond |
18 | 18 |
19 head *element // the buffer that will be read first | 19 head *element // the buffer that will be read first |
20 tail *element // the buffer that will be read last | 20 tail *element // the buffer that will be read last |
21 | 21 |
22 closed bool | 22 closed bool |
23 } | 23 } |
24 | 24 |
25 // An element represents a single link in a linked list. | 25 // An element represents a single link in a linked list. |
26 type element struct { | 26 type element struct { |
27 buf []byte | 27 buf []byte |
28 next *element | 28 next *element |
29 } | 29 } |
30 | 30 |
31 // newBuffer returns an empty buffer that is not closed. | 31 // newBuffer returns an empty buffer that is not closed. |
32 func newBuffer() *buffer { | 32 func newBuffer() *buffer { |
33 e := new(element) | 33 e := new(element) |
34 b := &buffer{ | 34 b := &buffer{ |
35 Cond: newCond(), | 35 Cond: newCond(), |
36 head: e, | 36 head: e, |
37 tail: e, | 37 tail: e, |
38 } | 38 } |
39 return b | 39 return b |
40 } | 40 } |
41 | 41 |
42 // Write makes buf available for Read to receive. | 42 // write makes buf available for Read to receive. |
43 // buf must not be modified after the call to Write. | 43 // buf must not be modified after the call to write. |
44 func (b *buffer) Write(buf []byte) (int, error) { | 44 func (b *buffer) write(buf []byte) { |
45 b.Cond.L.Lock() | 45 b.Cond.L.Lock() |
46 defer b.Cond.L.Unlock() | 46 defer b.Cond.L.Unlock() |
47 e := &element{buf: buf} | 47 e := &element{buf: buf} |
48 b.tail.next = e | 48 b.tail.next = e |
49 b.tail = e | 49 b.tail = e |
50 b.Cond.Signal() | 50 b.Cond.Signal() |
51 return len(buf), nil | |
52 } | 51 } |
53 | 52 |
54 // eof closes the buffer. Reads from the buffer once all· | 53 // eof closes the buffer. Reads from the buffer once all· |
55 // the data has been consumed wiil receive os.EOF. | 54 // the data has been consumed will receive os.EOF. |
56 func (b *buffer) eof() error { | 55 func (b *buffer) eof() error { |
57 b.Cond.L.Lock() | 56 b.Cond.L.Lock() |
58 defer b.Cond.L.Unlock() | 57 defer b.Cond.L.Unlock() |
59 b.closed = true | 58 b.closed = true |
60 b.Cond.Signal() | 59 b.Cond.Signal() |
61 return nil | 60 return nil |
62 } | 61 } |
63 | 62 |
64 // Read reads data from the internal buffer in buf.· | 63 // Read reads data from the internal buffer in buf.· |
65 // Reads will block if not data is available, or until | 64 // Reads will block if no data is available, or until |
66 // the buffer is closed. | 65 // the buffer is closed. |
67 func (b *buffer) Read(buf []byte) (n int, err error) { | 66 func (b *buffer) Read(buf []byte) (n int, err error) { |
68 b.Cond.L.Lock() | 67 b.Cond.L.Lock() |
69 defer b.Cond.L.Unlock() | 68 defer b.Cond.L.Unlock() |
70 » for { | 69 » for len(buf) > 0 { |
71 // if there is data in b.head, copy it | 70 // if there is data in b.head, copy it |
72 if len(b.head.buf) > 0 { | 71 if len(b.head.buf) > 0 { |
73 r := copy(buf, b.head.buf) | 72 r := copy(buf, b.head.buf) |
74 buf, b.head.buf = buf[r:], b.head.buf[r:] | 73 buf, b.head.buf = buf[r:], b.head.buf[r:] |
75 n += r | 74 n += r |
76 if len(buf) == 0 { | |
77 // dest full | |
78 break | |
79 } | |
80 continue | 75 continue |
81 } | 76 } |
82 // if there is a next buffer, make it the head | 77 // if there is a next buffer, make it the head |
83 if len(b.head.buf) == 0 && b.head != b.tail { | 78 if len(b.head.buf) == 0 && b.head != b.tail { |
84 b.head = b.head.next | 79 b.head = b.head.next |
85 continue | 80 continue |
86 } | 81 } |
87 » » // if at least one byte has been copied return | 82 » » // if at least one byte has been copied, return |
88 if n > 0 { | 83 if n > 0 { |
89 break | 84 break |
90 } | 85 } |
91 » » // out of buffers, wait for producer | 86 » » // if nothing was read, and there is nothing outstanding |
| 87 » » // check to see if the buffer is closed. |
92 if b.closed { | 88 if b.closed { |
93 err = io.EOF | 89 err = io.EOF |
94 break | 90 break |
95 } | 91 } |
| 92 // out of buffers, wait for producer |
96 b.Cond.Wait() | 93 b.Cond.Wait() |
97 } | 94 } |
98 return | 95 return |
99 } | 96 } |
LEFT | RIGHT |