File copy remote close signal to ensure completed tar pipe data

This commit is contained in:
Russ Magee 2018-09-04 22:24:16 -07:00
parent 0586f306c0
commit b419b2e002
3 changed files with 70 additions and 55 deletions

View file

@ -92,7 +92,8 @@ func (hc Conn) GetStatus() uint8 {
func (hc *Conn) SetStatus(stat uint8) { func (hc *Conn) SetStatus(stat uint8) {
*hc.closeStat = stat *hc.closeStat = stat
log.Println("closeStat:", *hc.closeStat) fmt.Println("closeStat:", *hc.closeStat)
//log.Println("closeStat:", *hc.closeStat)
} }
// ConnOpts returns the cipher/hmac options value, which is sent to the // ConnOpts returns the cipher/hmac options value, which is sent to the
@ -209,7 +210,7 @@ func Dial(protocol string, ipport string, extensions ...string) (hc *Conn, err e
} }
// Close a hkex.Conn // Close a hkex.Conn
func (hc Conn) Close() (err error) { func (hc *Conn) Close() (err error) {
hc.DisableChaff() hc.DisableChaff()
hc.WritePacket([]byte{byte(*hc.closeStat)}, CSOExitStatus) hc.WritePacket([]byte{byte(*hc.closeStat)}, CSOExitStatus)
*hc.closeStat = 0 *hc.closeStat = 0
@ -219,12 +220,12 @@ func (hc Conn) Close() (err error) {
} }
// LocalAddr returns the local network address. // LocalAddr returns the local network address.
func (hc Conn) LocalAddr() net.Addr { func (hc *Conn) LocalAddr() net.Addr {
return hc.c.LocalAddr() return hc.c.LocalAddr()
} }
// RemoteAddr returns the remote network address. // RemoteAddr returns the remote network address.
func (hc Conn) RemoteAddr() net.Addr { func (hc *Conn) RemoteAddr() net.Addr {
return hc.c.RemoteAddr() return hc.c.RemoteAddr()
} }
@ -243,7 +244,7 @@ func (hc Conn) RemoteAddr() net.Addr {
// the deadline after successful Read or Write calls. // the deadline after successful Read or Write calls.
// //
// A zero value for t means I/O operations will not time out. // A zero value for t means I/O operations will not time out.
func (hc Conn) SetDeadline(t time.Time) error { func (hc *Conn) SetDeadline(t time.Time) error {
return hc.c.SetDeadline(t) return hc.c.SetDeadline(t)
} }
@ -252,14 +253,14 @@ func (hc Conn) SetDeadline(t time.Time) error {
// Even if write times out, it may return n > 0, indicating that // Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written. // some of the data was successfully written.
// A zero value for t means Write will not time out. // A zero value for t means Write will not time out.
func (hc Conn) SetWriteDeadline(t time.Time) error { func (hc *Conn) SetWriteDeadline(t time.Time) error {
return hc.c.SetWriteDeadline(t) return hc.c.SetWriteDeadline(t)
} }
// SetReadDeadline sets the deadline for future Read calls // SetReadDeadline sets the deadline for future Read calls
// and any currently-blocked Read call. // and any currently-blocked Read call.
// A zero value for t means Read will not time out. // A zero value for t means Read will not time out.
func (hc Conn) SetReadDeadline(t time.Time) error { func (hc *Conn) SetReadDeadline(t time.Time) error {
return hc.c.SetReadDeadline(t) return hc.c.SetReadDeadline(t)
} }
@ -304,7 +305,7 @@ func (hl HKExListener) Addr() net.Addr {
// Accept a client connection, conforming to net.Listener.Accept() // Accept a client connection, conforming to net.Listener.Accept()
// //
// See go doc net.Listener.Accept // See go doc net.Listener.Accept
func (hl HKExListener) Accept() (hc Conn, err error) { func (hl *HKExListener) Accept() (hc Conn, err error) {
// Open raw Conn c // Open raw Conn c
c, err := hl.l.Accept() c, err := hl.l.Accept()
if err != nil { if err != nil {
@ -405,7 +406,10 @@ func (hc Conn) Read(b []byte) (n int, err error) {
var payloadBytes = make([]byte, payloadLen) var payloadBytes = make([]byte, payloadLen)
n, err = io.ReadFull(hc.c, payloadBytes) n, err = io.ReadFull(hc.c, payloadBytes)
//log.Print(" << Read ", n, " payloadBytes") //!fmt.Println(" << Read ", n, " payloadBytes")
//time.Sleep(100 * time.Millisecond)
//log.Println(" << Read ", n, " payloadBytes")
// Normal client 'exit' from interactive session will cause // Normal client 'exit' from interactive session will cause
// (on server side) err.Error() == "<iface/addr info ...>: use of closed network connection" // (on server side) err.Error() == "<iface/addr info ...>: use of closed network connection"
@ -442,6 +446,11 @@ func (hc Conn) Read(b []byte) (n int, err error) {
} else if ctrlStatOp == CSOExitStatus { } else if ctrlStatOp == CSOExitStatus {
if len(payloadBytes) > 0 { if len(payloadBytes) > 0 {
*hc.closeStat = uint8(payloadBytes[0]) *hc.closeStat = uint8(payloadBytes[0])
// If remote end is closing (255), reply we're closing ours
if payloadBytes[0] == 255 {
hc.SetStatus(255)
hc.Close()
}
} else { } else {
log.Println("[truncated payload, cannot determine CSOExitStatus]") log.Println("[truncated payload, cannot determine CSOExitStatus]")
*hc.closeStat = 98 *hc.closeStat = 98
@ -487,7 +496,7 @@ func (hc Conn) Write(b []byte) (n int, err error) {
} }
// Write a byte slice with specified ctrlStatusOp byte // Write a byte slice with specified ctrlStatusOp byte
func (hc Conn) WritePacket(b []byte, op byte) (n int, err error) { func (hc *Conn) WritePacket(b []byte, op byte) (n int, err error) {
//log.Printf("[Encrypting...]\r\n") //log.Printf("[Encrypting...]\r\n")
var hmacOut []uint8 var hmacOut []uint8
var payloadLen uint32 var payloadLen uint32
@ -500,16 +509,10 @@ func (hc Conn) WritePacket(b []byte, op byte) (n int, err error) {
// //
// Would be nice to determine if the mutex scope // Would be nice to determine if the mutex scope
// could be tightened. // could be tightened.
for uint32(len(b)) > 0 {
hc.m.Lock() hc.m.Lock()
fmt.Printf("--== TOTAL payloadLen (b):%d\n", len(b)) //fmt.Printf("--== TOTAL payloadLen (b):%d\n", len(b))
payloadLen = uint32(len(b)) payloadLen = uint32(len(b))
if payloadLen > MAX_PAYLOAD_LEN { //!fmt.Printf(" --== payloadLen:%d\n", payloadLen)
payloadLen = MAX_PAYLOAD_LEN
//fmt.Printf("--== payloadLen:%d\n", payloadLen)
} else {
//fmt.Printf("--== payloadLen:%d\n", payloadLen)
}
log.Printf(" :>ptext:\r\n%s\r\n", hex.Dump(b[0:payloadLen])) log.Printf(" :>ptext:\r\n%s\r\n", hex.Dump(b[0:payloadLen]))
// Calculate hmac on payload // Calculate hmac on payload
@ -537,17 +540,20 @@ func (hc Conn) WritePacket(b []byte, op byte) (n int, err error) {
err = binary.Write(hc.c, binary.BigEndian, payloadLen) err = binary.Write(hc.c, binary.BigEndian, payloadLen)
if err == nil { if err == nil {
n, err = hc.c.Write(wb.Bytes()) n, err = hc.c.Write(wb.Bytes())
} else {
//fmt.Println("[c]WriteError!")
} }
} else {
//fmt.Println("[b]WriteError!")
} }
} else {
//fmt.Println("[a]WriteError!")
} }
//Advance to next full (or final, partial) chunk of payload
b = b[payloadLen:]
hc.m.Unlock() hc.m.Unlock()
//time.Sleep(200 * time.Millisecond)
}
if err != nil { if err != nil {
//panic(err) //panic(err)
fmt.Println(err)
log.Println(err) log.Println(err)
} }
return return

View file

@ -168,7 +168,10 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec)
} }
} }
} }
fmt.Println("*** client->server cp finished ***") //fmt.Println("*** client->server cp finished ***")
// Signal other end transfer is complete
conn.WritePacket([]byte{byte(255)}, hkexnet.CSOExitStatus)
_, _ = conn.Read(nil /*ackByte*/)
} }
} else { } else {
fmt.Println("remote filepath:", string(rec.cmd), "local files:", files) fmt.Println("remote filepath:", string(rec.cmd), "local files:", files)
@ -212,7 +215,7 @@ func doCopyMode(conn *hkexnet.Conn, remoteDest bool, files string, rec *cmdSpec)
} }
} }
} }
fmt.Println("*** server->client cp finished ***") //fmt.Println("*** server->client cp finished ***")
} }
} }
return return

View file

@ -115,7 +115,7 @@ func runClientToServerCopyAs(who string, conn hkexnet.Conn, fpath string, chaffi
} }
} }
} }
fmt.Println("*** client->server cp finished ***") //fmt.Println("*** client->server cp finished ***")
return return
} }
} }
@ -192,7 +192,7 @@ func runServerToClientCopyAs(who string, conn hkexnet.Conn, srcPath string, chaf
} }
} }
} }
fmt.Println("*** server->client cp finished ***") //fmt.Println("*** server->client cp finished ***")
return return
} }
} }
@ -519,6 +519,12 @@ func main() {
log.Printf("[Command completed for %s@%s, status %d]\n", rec.who, hname, cmdStatus) log.Printf("[Command completed for %s@%s, status %d]\n", rec.who, hname, cmdStatus)
hc.SetStatus(uint8(cmdStatus)) hc.SetStatus(uint8(cmdStatus))
} }
// Signal other end transfer is complete
hc.WritePacket([]byte{byte(255)}, hkexnet.CSOExitStatus)
//fmt.Println("Waiting for EOF from other end.")
//ackByte := make([]byte, 1, 1)
_, _ = hc.Read(nil /*ackByte*/)
//fmt.Println("Got remote end ack.")
} else { } else {
log.Println("[Bad cmdSpec]") log.Println("[Bad cmdSpec]")
} }