in agent/session/plugin/client/client.go [433:508]
func (c *Client) writeLoopRawMode(wg *sync.WaitGroup) int {
defer wg.Done()
fname := "writeLoop"
buff := make([]byte, sendPackageSize)
br := bufio.NewReader(c.Input)
if c.PortForward {
// wait agent build local connect
time.Sleep(time.Duration(3) * time.Second)
c.real_connected = true
if c.verbosemode {
log.GetLogger().Info("set real_connected true")
}
}
var resend_buff []byte
for {
time.Sleep(time.Duration(c.sendInterval) * time.Millisecond)
// if resend_buff not empty, set read timeout avoid blocking forever
if c.PortForward && len(resend_buff) > 0 {
c.Input.(net.Conn).SetReadDeadline(time.Now().Add(1 * time.Second))
}
size, err := br.Read(buff)
if c.PortForward {
// cancel the read timeout
c.Input.(net.Conn).SetReadDeadline(time.Time{})
}
if err != nil {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
if c.verbosemode {
log.GetLogger().Warnln("read from local conn timeout:", err)
}
} else {
log.GetLogger().Errorf("get raw input failed: %v", err)
// tell agent to close session
log.GetLogger().Infoln("local conn closed, send CloseMessage")
if err = c.SendCloseMessage(); err != nil {
log.GetLogger().Errorf("SendCloseMessage err: %v", err)
}
return openPoison(fname, c.poison)
}
}
if size == 0 && len(resend_buff) == 0 {
continue
}
data := buff[:size]
if c.real_connected == true {
if len(resend_buff) > 0 {
time.Sleep(time.Duration(100) * time.Millisecond)
c.SendStreamDataMessage(resend_buff)
log.GetLogger().Infoln("agent ready resend user input:", string(resend_buff), len(resend_buff))
resend_buff = nil
}
err = c.SendStreamDataMessage(data)
if err != nil {
return openPoison(fname, c.poison)
}
if c.verbosemode {
log.GetLogger().Infoln("send user input:", string(data), size)
}
} else {
if len(resend_buff) == 0 {
resend_buff = make([]byte, size)
copy(resend_buff, buff[:size])
log.GetLogger().Infoln("store user input:", string(data), size)
}
}
}
return 0
}