|
|
@@ -276,7 +276,7 @@ func (c *ClientConn) mainLoop() {
|
|
|
case *channelRequestMsg:
|
|
|
c.getChan(msg.PeersId).msg <- msg
|
|
|
case *windowAdjustMsg:
|
|
|
- if !c.getChan(msg.PeersId).stdin.win.add(msg.AdditionalBytes) {
|
|
|
+ if !c.getChan(msg.PeersId).remoteWin.add(msg.AdditionalBytes) {
|
|
|
// invalid window update
|
|
|
return
|
|
|
}
|
|
|
@@ -317,7 +317,7 @@ func (c *ClientConn) handleChanOpen(msg *channelOpenMsg) {
|
|
|
}
|
|
|
ch := c.newChan(c.transport)
|
|
|
ch.remoteId = msg.PeersId
|
|
|
- ch.stdin.win.add(msg.PeersWindow)
|
|
|
+ ch.remoteWin.add(msg.PeersWindow)
|
|
|
|
|
|
m := channelOpenConfirmMsg{
|
|
|
PeersId: ch.remoteId,
|
|
|
@@ -438,13 +438,13 @@ type clientChan struct {
|
|
|
func newClientChan(cc conn, id uint32) *clientChan {
|
|
|
c := &clientChan{
|
|
|
channel: channel{
|
|
|
- conn: cc,
|
|
|
- localId: id,
|
|
|
+ conn: cc,
|
|
|
+ localId: id,
|
|
|
+ remoteWin: window{Cond: newCond()},
|
|
|
},
|
|
|
msg: make(chan interface{}, 16),
|
|
|
}
|
|
|
c.stdin = &chanWriter{
|
|
|
- win: &window{Cond: sync.NewCond(new(sync.Mutex))},
|
|
|
channel: &c.channel,
|
|
|
}
|
|
|
c.stdout = &chanReader{
|
|
|
@@ -465,7 +465,7 @@ func (c *clientChan) waitForChannelOpenResponse() error {
|
|
|
case *channelOpenConfirmMsg:
|
|
|
// fixup remoteId field
|
|
|
c.remoteId = msg.MyId
|
|
|
- c.stdin.win.add(msg.MyWindow)
|
|
|
+ c.remoteWin.add(msg.MyWindow)
|
|
|
return nil
|
|
|
case *channelOpenFailureMsg:
|
|
|
return errors.New(safeString(msg.Message))
|
|
|
@@ -542,7 +542,6 @@ func (c *chanList) closeAll() {
|
|
|
|
|
|
// A chanWriter represents the stdin of a remote process.
|
|
|
type chanWriter struct {
|
|
|
- win *window
|
|
|
*channel
|
|
|
}
|
|
|
|
|
|
@@ -551,7 +550,7 @@ func (w *chanWriter) Write(data []byte) (written int, err error) {
|
|
|
for len(data) > 0 {
|
|
|
// n cannot be larger than 2^31 as len(data) cannot
|
|
|
// be larger than 2^31
|
|
|
- n := int(w.win.reserve(uint32(len(data))))
|
|
|
+ n := int(w.remoteWin.reserve(uint32(len(data))))
|
|
|
remoteId := w.remoteId
|
|
|
packet := []byte{
|
|
|
msgChannelData,
|
|
|
@@ -621,46 +620,3 @@ func (r *chanReader) Read(data []byte) (int, error) {
|
|
|
}
|
|
|
panic("unreachable")
|
|
|
}
|
|
|
-
|
|
|
-// window represents the buffer available to clients
|
|
|
-// wishing to write to a channel.
|
|
|
-type window struct {
|
|
|
- *sync.Cond
|
|
|
- win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1
|
|
|
-}
|
|
|
-
|
|
|
-// add adds win to the amount of window available
|
|
|
-// for consumers.
|
|
|
-func (w *window) add(win uint32) bool {
|
|
|
- if win == 0 {
|
|
|
- return false
|
|
|
- }
|
|
|
- w.L.Lock()
|
|
|
- if w.win+win < win {
|
|
|
- w.L.Unlock()
|
|
|
- return false
|
|
|
- }
|
|
|
- w.win += win
|
|
|
- // It is unusual that multiple goroutines would be attempting to reserve
|
|
|
- // window space, but not guaranteed. Use broadcast to notify all waiters
|
|
|
- // that additional window is available.
|
|
|
- w.Broadcast()
|
|
|
- w.L.Unlock()
|
|
|
- return true
|
|
|
-}
|
|
|
-
|
|
|
-// reserve reserves win from the available window capacity.
|
|
|
-// If no capacity remains, reserve will block. reserve may
|
|
|
-// return less than requested.
|
|
|
-func (w *window) reserve(win uint32) uint32 {
|
|
|
- w.L.Lock()
|
|
|
- for w.win == 0 {
|
|
|
- w.Wait()
|
|
|
- }
|
|
|
- if w.win < win {
|
|
|
- win = w.win
|
|
|
- }
|
|
|
- w.win -= win
|
|
|
- w.L.Unlock()
|
|
|
- return win
|
|
|
-}
|