Source File
mux.go
Belonging Package
golang.org/x/crypto/ssh
package ssh
import (
)
type mux struct {
conn packetConn
chanList chanList
incomingChannels chan NewChannel
globalSentMu sync.Mutex
globalResponses chan interface{}
incomingRequests chan *Request
errCond *sync.Cond
err error
}
func ( packetConn) *mux {
:= &mux{
conn: ,
incomingChannels: make(chan NewChannel, chanSize),
globalResponses: make(chan interface{}, 1),
incomingRequests: make(chan *Request, chanSize),
errCond: newCond(),
}
if debugMux {
.chanList.offset = atomic.AddUint32(&globalOff, 1)
}
go .loop()
return
}
func ( *mux) ( interface{}) error {
:= Marshal()
if debugMux {
log.Printf("send global(%d): %#v", .chanList.offset, )
}
return .conn.writePacket()
}
func ( *mux) ( string, bool, []byte) (bool, []byte, error) {
if {
.globalSentMu.Lock()
defer .globalSentMu.Unlock()
}
if := .sendMessage(globalRequestMsg{
Type: ,
WantReply: ,
Data: ,
}); != nil {
return false, nil,
}
if ! {
return false, nil, nil
}
, := <-.globalResponses
if ! {
return false, nil, io.EOF
}
switch msg := .(type) {
case *globalRequestFailureMsg:
return false, .Data, nil
case *globalRequestSuccessMsg:
return true, .Data, nil
default:
return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", )
}
}
func ( *mux) ( bool, []byte) error {
if {
return .sendMessage(globalRequestSuccessMsg{Data: })
}
return .sendMessage(globalRequestFailureMsg{Data: })
}
func ( *mux) () error {
return .conn.Close()
}
func ( *mux) () {
var error
for == nil {
= .onePacket()
}
for , := range .chanList.dropAll() {
.close()
}
close(.incomingChannels)
close(.incomingRequests)
close(.globalResponses)
.conn.Close()
.errCond.L.Lock()
.err =
.errCond.Broadcast()
.errCond.L.Unlock()
if debugMux {
log.Println("loop exit", )
}
}
func ( *mux) () error {
, := .conn.readPacket()
if != nil {
return
}
if debugMux {
if [0] == msgChannelData || [0] == msgChannelExtendedData {
log.Printf("decoding(%d): data packet - %d bytes", .chanList.offset, len())
} else {
, := decode()
log.Printf("decoding(%d): %d %#v - %d bytes", .chanList.offset, [0], , len())
}
}
switch [0] {
case msgChannelOpen:
return .handleChannelOpen()
case msgGlobalRequest, msgRequestSuccess, msgRequestFailure:
return .handleGlobalPacket()
}
if len() < 5 {
return parseError([0])
}
:= binary.BigEndian.Uint32([1:])
:= .chanList.getChan()
if == nil {
return .handleUnknownChannelPacket(, )
}
return .handlePacket()
}
func ( *mux) ( []byte) error {
, := decode()
if != nil {
return
}
switch msg := .(type) {
case *globalRequestMsg:
.incomingRequests <- &Request{
Type: .Type,
WantReply: .WantReply,
Payload: .Data,
mux: ,
}
case *globalRequestSuccessMsg, *globalRequestFailureMsg:
.globalResponses <-
default:
panic(fmt.Sprintf("not a global message %#v", ))
}
return nil
}
func ( *mux) ( []byte) error {
var channelOpenMsg
if := Unmarshal(, &); != nil {
return
}
if .MaxPacketSize < minPacketLength || .MaxPacketSize > 1<<31 {
:= channelOpenFailureMsg{
PeersID: .PeersID,
Reason: ConnectionFailed,
Message: "invalid request",
Language: "en_US.UTF-8",
}
return .sendMessage()
}
:= .newChannel(.ChanType, channelInbound, .TypeSpecificData)
.remoteId = .PeersID
.maxRemotePayload = .MaxPacketSize
.remoteWin.add(.PeersWindow)
.incomingChannels <-
return nil
}
func ( *mux) ( string, []byte) (Channel, <-chan *Request, error) {
, := .openChannel(, )
if != nil {
return nil, nil,
}
return , .incomingRequests, nil
}
func ( *mux) ( string, []byte) (*channel, error) {
:= .newChannel(, channelOutbound, )
.maxIncomingPayload = channelMaxPacket
:= channelOpenMsg{
ChanType: ,
PeersWindow: .myWindow,
MaxPacketSize: .maxIncomingPayload,
TypeSpecificData: ,
PeersID: .localId,
}
if := .sendMessage(); != nil {
return nil,
}
switch msg := (<-.msg).(type) {
case *channelOpenConfirmMsg:
return , nil
case *channelOpenFailureMsg:
return nil, &OpenChannelError{.Reason, .Message}
default:
return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", )
}
}
func ( *mux) ( uint32, []byte) error {
, := decode()
if != nil {
return
}
case *channelRequestMsg:
if .WantReply {
return .sendMessage(channelRequestFailureMsg{
PeersID: .PeersID,
})
}
return nil
default:
return fmt.Errorf("ssh: invalid channel %d", )
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |