Example #1
0
func (t *attachServerSSH) channelMux(in <-chan *ssh.Request, process *os.Process, pty *os.File, detach func()) {
	defer trace.End(trace.Begin("start attach server channel request handler"))

	var err error
	for req := range in {
		var pendingFn func()
		ok := true

		switch req.Type {
		case msgs.WindowChangeReq:
			msg := msgs.WindowChangeMsg{}
			if pty == nil {
				ok = false
				log.Errorf("illegal window-change request for non-tty")
			} else if err = msg.Unmarshal(req.Payload); err != nil {
				ok = false
				log.Errorf(err.Error())
			} else if err = resizePty(pty.Fd(), &msg); err != nil {
				ok = false
				log.Errorf(err.Error())
			}
		case msgs.SignalReq:
			msg := msgs.SignalMsg{}
			if err = msg.Unmarshal(req.Payload); err != nil {
				ok = false
				log.Errorf(err.Error())
			} else {
				log.Infof("Sending signal %s to container process, pid=%d\n", string(msg.Signal), process.Pid)
				err = signalProcess(process, msg.Signal)
				if err != nil {
					log.Errorf("Failed to dispatch signal to process: %s\n", err)
				}
			}
		default:
			ok = false
			err = fmt.Errorf("ssh request type %s is not supported", req.Type)
			log.Error(err.Error())
		}

		// payload is ignored on channel specific replies.  The ok is passed, however.
		if req.WantReply {
			req.Reply(ok, nil)
		}

		// run any pending work now that a reply has been sent
		if pendingFn != nil {
			log.Debug("Invoking pending work")
			go pendingFn()
			pendingFn = nil
		}
	}

	detach()
}
Example #2
0
File: client.go Project: vmware/vic
// Resize resizes the terminal.
func (t *attachSSH) Resize(cols, rows, widthpx, heightpx uint32) error {
	defer trace.End(trace.Begin(""))

	msg := msgs.WindowChangeMsg{
		Columns:  cols,
		Rows:     rows,
		WidthPx:  widthpx,
		HeightPx: heightpx,
	}
	ok, err := t.channel.SendRequest(msgs.WindowChangeReq, true, msg.Marshal())
	if err == nil && !ok {
		return fmt.Errorf("unknown error")
	}

	if err != nil {
		return fmt.Errorf("resize error: %s", err)
	}
	return nil
}
Example #3
0
File: attach.go Project: vmware/vic
func (t *attachServerSSH) channelMux(in <-chan *ssh.Request, session *tether.SessionConfig, cleanup func()) {
	defer trace.End(trace.Begin("attach server channel request handler"))

	// for the actions after we process the request
	var pendingFn func()

	// cleanup function passed by the caller
	defer cleanup()

	for req := range in {
		ok := true

		switch req.Type {
		case msgs.WindowChangeReq:
			session.Lock()
			pty := session.Pty
			session.Unlock()

			msg := msgs.WindowChangeMsg{}
			if pty == nil {
				ok = false
				log.Errorf("illegal window-change request for non-tty")
			} else if err := msg.Unmarshal(req.Payload); err != nil {
				ok = false
				log.Errorf(err.Error())
			} else if err := resizePty(pty.Fd(), &msg); err != nil {
				ok = false
				log.Errorf(err.Error())
			}
		case msgs.CloseStdinReq:
			// call Close as the pendingFn so that we can send reply back before closing the channel
			pendingFn = func() {
				session.Lock()
				defer session.Unlock()

				log.Debugf("Closing stdin for %s", session.ID)
				session.Reader.Close()
			}
		default:
			ok = false
			err := fmt.Errorf("ssh request type %s is not supported", req.Type)
			log.Error(err.Error())
		}

		// payload is ignored on channel specific replies.  The ok is passed, however.
		if req.WantReply {
			log.Debugf("Sending channel request reply %t back", ok)
			if err := req.Reply(ok, nil); err != nil {
				log.Warnf("Failed to reply a channel request back")
			}
		}

		// run any pending work now that a reply has been sent
		if pendingFn != nil {
			log.Debug("Invoking pending work for channel mux")
			go pendingFn()
			pendingFn = nil
		}
	}

}