//throwBytes chucks bytes at the remote server then listens for a response func throwBytes(conn io.ReadWriter, count uint64) error { var writeBytes uint64 var b []byte buff := make([]byte, 128) for writeBytes < count { if (count - writeBytes) >= uint64(len(dataBlock)) { b = dataBlock } else { b = dataBlock[0:(count - writeBytes)] } n, err := conn.Write(b) if err != nil { return err } writeBytes += uint64(n) } //read the response n, err := conn.Read(buff) if err != nil { return err } if n == 0 { return fmt.Errorf("Failed to get OK on upload") } if !strings.HasPrefix(string(buff[0:n]), "OK ") { return fmt.Errorf("Failed to get OK on upload") } return nil }
func (r *Receiver) handleTransfer(conn io.ReadWriter) ( transfer.TransferResults, error, ) { if _, err := conn.Write([]byte("ok")); err != nil { return transfer.TransferResults{}, err } res := transfer.TransferResults{} buffer := make([]byte, 1024) startTime := time.Now() for { n, err := conn.Read(buffer) if err != nil { // done reading break } res.BytesSent += uint32(n) res.Checksum = crc32.Update(res.Checksum, crc32.IEEETable, buffer) } endTime := time.Now() res.Duration = endTime.Sub(startTime) return res, nil }
func ClientHandshake(stream io.ReadWriter, local Certificate) (*Transport, error) { pub, priv, err := GenerateExchangeKey() if err != nil { return nil, err } if _, err = stream.Write(pub); err != nil { return nil, err } theirkey := make([]byte, PublicKeySize) if _, err = stream.Read(theirkey); err != nil { return nil, err } cipher1, cipher2, err := CreateExchangedCipher(theirkey, priv) if err != nil { return nil, err } macKey, err := GenerateMACKey() if err != nil { return nil, err } encryptedMACKey := make([]byte, MACSize) cipher1.XORKeyStream(encryptedMACKey, macKey) if _, err = stream.Write(encryptedMACKey); err != nil { return nil, err } transport := new(Transport) transport.stream = stream transport.macKey = macKey transport.readCipher = cipher2 transport.writeCipher = cipher1 if err := sendCertificate(transport, local); err != nil { return nil, err } remote, err := requireCertificate(transport) if err != nil { return nil, err } transport.local = local transport.remote = remote return transport, nil }
// dnsRoundTripUDP implements the dnsRoundTrip interface for RFC 1035's // "UDP usage" transport mechanism. c should be a packet-oriented connection, // such as a *UDPConn. func dnsRoundTripUDP(c io.ReadWriter, query *dnsMsg) (*dnsMsg, error) { b, ok := query.Pack() if !ok { return nil, errors.New("cannot marshal DNS message") } if _, err := c.Write(b); err != nil { return nil, err } b = make([]byte, 512) // see RFC 1035 for { n, err := c.Read(b) if err != nil { return nil, err } resp := &dnsMsg{} if !resp.Unpack(b[:n]) || !resp.IsResponseTo(query) { // Ignore invalid responses as they may be malicious // forgery attempts. Instead continue waiting until // timeout. See golang.org/issue/13281. continue } return resp, nil } }
func verifyPipe(t *testing.T, a, b io.ReadWriter) { mes := make([]byte, 1024) rand.Read(mes) go func() { b.Write(mes) a.Write(mes) }() buf := make([]byte, len(mes)) n, err := a.Read(buf) if err != nil { t.Fatal(err) } if n != len(buf) { t.Fatal("failed to read enough") } if string(buf) != string(mes) { t.Fatal("somehow read wrong message") } n, err = b.Read(buf) if err != nil { t.Fatal(err) } if n != len(buf) { t.Fatal("failed to read enough") } if string(buf) != string(mes) { t.Fatal("somehow read wrong message") } }
func negotiateMethod(c Context, rw io.ReadWriter) { rw.Write(methodRequest(proxy.MethodNoPassword)) if _, err := rw.Read(make([]byte, 3)); err != nil { c.Error(err) } return }
func echoOnce(rw io.ReadWriter) error { buf := make([]byte, 256) n, err := rw.Read(buf) if err != nil { return err } _, err = rw.Write(buf[:n]) return err }
func ServerHandshake(stream io.ReadWriter, local Certificate) (*Transport, error) { pub, priv, err := GenerateExchangeKey() if err != nil { return nil, err } theirkey := make([]byte, PublicKeySize) if _, err = stream.Read(theirkey); err != nil { return nil, err } if _, err = stream.Write(pub); err != nil { return nil, err } cipher1, cipher2, err := CreateExchangedCipher(theirkey, priv) if err != nil { return nil, err } macKey := make([]byte, MACSize) if n, err := stream.Read(macKey); err != nil { return nil, err } else if n < MACSize { return nil, MacKeyTooSmallError } cipher1.XORKeyStream(macKey, macKey) transport := new(Transport) transport.stream = stream transport.macKey = macKey transport.readCipher = cipher1 transport.writeCipher = cipher2 remote, err := requireCertificate(transport) if err != nil { return nil, err } if err := sendCertificate(transport, local); err != nil { return nil, err } transport.local = local transport.remote = remote return transport, nil }
// exchangeKeys performs a key exchange with a remote peer // and returns peer's public key after successfull exchange. func exchangeKeys(conn io.ReadWriter, pub *[32]byte) (*[32]byte, error) { var ppub [32]byte if _, err := conn.Write(pub[:]); err != nil { return nil, err } if _, err := conn.Read(ppub[:]); err != nil { return nil, err } return &ppub, nil }
// exchangeKeys performs the exchange of the keys // by writing the public key into the data stream first and // then reading the shared key from the data stream. func exchangeKeys(pub, peerPub *[32]byte, rw io.ReadWriter) error { if _, err := rw.Write(pub[:]); err != nil { return err } if _, err := rw.Read(peerPub[:]); err != nil { return err } return nil }
func (p *Proxy) pipe(src, dst io.ReadWriter) { islocal := src == p.lconn var dataDirection string if islocal { dataDirection = ">>> %d bytes sent%s" } else { dataDirection = "<<< %d bytes recieved%s" } var byteFormat string if p.OutputHex { byteFormat = "%x" } else { byteFormat = "%s" } //directional copy (64k buffer) buff := make([]byte, 0xffff) for { n, err := src.Read(buff) if err != nil { p.err("Read failed '%s'\n", err) return } b := buff[:n] //execute match if p.Matcher != nil { p.Matcher(b) } //execute replace if p.Replacer != nil { b = p.Replacer(b) } //show output p.Log.Debug(dataDirection, n, "") p.Log.Trace(byteFormat, b) //write out result n, err = dst.Write(b) if err != nil { p.err("Write failed '%s'\n", err) return } if islocal { p.sentBytes += uint64(n) } else { p.receivedBytes += uint64(n) } } }
// CopyToWebsocket copies pipe data to/from a websocket. It blocks. func (p *pipe) CopyToWebsocket(end io.ReadWriter, conn *websocket.Conn) error { p.mtx.Lock() if p.closed { p.mtx.Unlock() return nil } p.wg.Add(1) p.mtx.Unlock() defer p.wg.Done() errors := make(chan error, 1) // Read-from-UI loop go func() { for { _, buf, err := conn.ReadMessage() // TODO type should be binary message if err != nil { errors <- err return } if _, err := end.Write(buf); err != nil { errors <- err return } } }() // Write-to-UI loop go func() { buf := make([]byte, 1024) for { n, err := end.Read(buf) if err != nil { errors <- err return } if err := conn.WriteMessage(websocket.BinaryMessage, buf[:n]); err != nil { errors <- err return } } }() // block until one of the goroutines exits // this convoluted mechanism is to ensure we only close the websocket once. select { case err := <-errors: return err case <-p.quit: return nil } }
func (us *UnixSock) processBuffer(fd io.ReadWriter) { var buf [1024]byte for { n, err := fd.Read(buf[0:]) if err != nil || n == 0 { break } us.data <- pipe.NewSimpleChunk(buf[0:n]) } }
func runEcho(fd io.ReadWriter, done chan<- int) { var buf [1024]byte for { n, err := fd.Read(buf[0:]) if err != nil || n == 0 || string(buf[:n]) == "END" { break } fd.Write(buf[0:n]) } done <- 1 }
func runEcho(fd io.ReadWriter, done chan<- int) { var buf [1024]byte; for { n, err := fd.Read(&buf); if err != nil || n == 0 { break } fd.Write(buf[0:n]); } done <- 1; }
func exchangeKeys(pub *[32]byte, conn io.ReadWriter) (*[32]byte, error) { _, err := conn.Write(pub[:]) if err != nil { return nil, err } otherPub := [32]byte{} _, err = conn.Read(otherPub[:]) if err != nil { return nil, err } return &otherPub, nil }
// submitTPMRequest sends a structure to the TPM device file and gets results // back, interpreting them as a new provided structure. func submitTPMRequest(rw io.ReadWriter, tag uint16, ord uint32, in []interface{}, out []interface{}) (uint32, error) { if rw == nil { return 0, errors.New("nil TPM handle") } ch := commandHeader{tag, 0, ord} inb, err := packWithHeader(ch, in) if err != nil { return 0, err } if _, err := rw.Write(inb); err != nil { return 0, err } // Try to read the whole thing, but handle the case where it's just a // ResponseHeader and not the body, since that's what happens in the error // case. var rh responseHeader rhSize := binary.Size(rh) outb := make([]byte, maxTPMResponse) outlen, err := rw.Read(outb) if err != nil { return 0, err } // Resize the buffer to match the amount read from the TPM. outb = outb[:outlen] if err := unpack(outb[:rhSize], []interface{}{&rh}); err != nil { return 0, err } // Check success before trying to read the rest of the result. // Note that the command tag and its associated response tag differ by 3, // e.g., tagRQUCommand == 0x00C1, and tagRSPCommand == 0x00C4. if rh.Res != 0 { return rh.Res, tpmError(rh.Res) } if rh.Tag != ch.Tag+3 { return 0, errors.New("inconsistent tag returned by TPM. Expected " + strconv.Itoa(int(ch.Tag+3)) + " but got " + strconv.Itoa(int(rh.Tag))) } if rh.Size > uint32(rhSize) { if err := unpack(outb[rhSize:], out); err != nil { return 0, err } } return rh.Res, nil }
// DefaultInteractive is the default server selection prompt for users during // session forward. func DefaultInteractive(comm io.ReadWriter, session *Session) (string, error) { remotes := session.Remotes fmt.Fprintf(comm, "Welcome to sshmux, %s\r\n", session.Conn.User()) for i, v := range remotes { fmt.Fprintf(comm, " [%d] %s\r\n", i, v) } // Beware, nasty comm parsing loop loop: for { fmt.Fprintf(comm, "Please select remote server: ") var buf []byte b := make([]byte, 1) var ( n int err error ) for { if err != nil { return "", err } n, err = comm.Read(b) if n == 1 { fmt.Fprintf(comm, "%s", b) switch b[0] { case '\r': fmt.Fprintf(comm, "\r\n") res, err := strconv.ParseInt(string(buf), 10, 64) if err != nil { fmt.Fprintf(comm, "comm not a valid integer. Please try again\r\n") continue loop } if int(res) >= len(remotes) || res < 0 { fmt.Fprintf(comm, "No such server. Please try again\r\n") continue loop } return remotes[int(res)], nil case 0x03: fmt.Fprintf(comm, "\r\nGoodbye\r\n") return "", errors.New("user terminated session") } buf = append(buf, b[0]) } } } }
func (s *Sender) handshake(conn io.ReadWriter) error { msgBytes := make([]byte, 16) n, err := conn.Read(msgBytes) if err != nil { return err } msg := string(msgBytes[:n]) if msg == "ok" { return nil } else if msg == "i-am-busy" { return ErrBusy } else { return fmt.Errorf("unrecognized server response `%s`", msg) } }
// echo server on top of a generic io.ReadWriter. Reads from the reader, // and writes received data back to the writer. To implement secure echo, // rw must be composed of a secure reader and writer, as produced by // serverHandshake. func echo(rw io.ReadWriter) error { var ( n int err error ) buf := make([]byte, msglen) for { if n, err = rw.Read(buf); err != nil { return err } if _, err := rw.Write(buf[:n]); err != nil { return err } } }
func WriteFileHandler(parameters string, connection io.ReadWriter) { segments := strings.Split(parameters, " ") if len(segments) != 2 { log.Println("Invalid put command formatting") } lengtha, _ := strconv.Atoi(segments[1]) fileName := segments[0] log.Printf("Receive file '%s' (length = %d)", fileName, lengtha) file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0) if err != nil { log.Printf("Failed to open file for writing: %s\n", err) return } common.WriteString(connection, "ok") buffer := make([]byte, 1024) for { // Read from socket n, err := connection.Read(buffer) if err != nil { log.Println("Failed to read data from socket; abandoning transfer") break } // Read into buffer _, err = file.Write(buffer[:n]) lengtha = lengtha - n if lengtha == 0 { log.Println("Transfer completed") break } } common.WriteString(connection, "ok") file.Close() }
func testRws(a, b io.ReadWriter) error { data := []byte("ABCD") go a.Write(data) buf := make([]byte, 10) n, err := b.Read(buf) if err != nil { return err } if n != 4 { return fmt.Errorf("n must be 4, not %d", n) } if !bytes.Equal(buf[:n], data) { return fmt.Errorf("invalid data received: %s", hex.EncodeToString(buf[:n])) } return nil }
func (s *Sender) handshake(conn io.ReadWriter) (uint16, error) { msgBytes := make([]byte, 16) n, err := conn.Read(msgBytes) if err != nil { return 0, err } msg := string(msgBytes[:n]) var iperfPort uint16 _, err = fmt.Sscanf(msg, "ok - %d", &iperfPort) if err != nil { if msg == "i-am-busy" { return 0, ErrBusy } else { return 0, fmt.Errorf("unrecognized server response `%s`: %s", msg, err) } } return iperfPort, nil }
func ModemSend(c io.ReadWriter, data []byte) error { oBuffer := make([]byte, 1) if _, err := c.Read(oBuffer); err != nil { return err } if oBuffer[0] == POLL { var blocks uint8 = uint8(len(data) / LONG_PACKET_PAYLOAD_LEN) if len(data) > int(int(blocks)*int(LONG_PACKET_PAYLOAD_LEN)) { blocks++ } failed := 0 var currentBlock uint8 = 0 for currentBlock < blocks && failed < 10 { if int(int(currentBlock+1)*int(LONG_PACKET_PAYLOAD_LEN)) > len(data) { sendBlock(c, currentBlock+1, data[int(currentBlock)*int(LONG_PACKET_PAYLOAD_LEN):]) } else { sendBlock(c, currentBlock+1, data[int(currentBlock)*int(LONG_PACKET_PAYLOAD_LEN):(int(currentBlock)+1)*int(LONG_PACKET_PAYLOAD_LEN)]) } if _, err := c.Read(oBuffer); err != nil { return err } if oBuffer[0] == ACK { currentBlock++ } else { failed++ } } if _, err := c.Write([]byte{EOT}); err != nil { return err } } return nil }
func testSecureSessionMessage(conn1, conn2 io.ReadWriter) error { pt := []byte("hello peer!") nw, err := conn1.Write(pt) if err != nil { return fmt.Errorf("write error: %s", err) } ptr := make([]byte, len(pt)) nr, err := conn2.Read(ptr) if err != nil { return fmt.Errorf("read error: %s", err) } if nr != nw { return fmt.Errorf("bytes read not equal to bytes written: %d != %d", nr, nw) } if !bytes.Equal(ptr, pt) { return fmt.Errorf("message read not equal to message written: %q != %q", ptr, pt) } return nil }
func receivePacket(c io.ReadWriter) ([]byte, error) { oBuffer := make([]byte, 1) dBuffer := make([]byte, LONG_PACKET_PAYLOAD_LEN) if _, err := c.Read(oBuffer); err != nil { return nil, err } pType := oBuffer[0] if pType == EOT { return nil, nil } var packetSize int switch pType { case SOH: packetSize = SHORT_PACKET_PAYLOAD_LEN break case STX: packetSize = LONG_PACKET_PAYLOAD_LEN break } if _, err := c.Read(oBuffer); err != nil { return nil, err } packetCount := oBuffer[0] if _, err := c.Read(oBuffer); err != nil { return nil, err } inverseCount := oBuffer[0] if packetCount > inverseCount || inverseCount+packetCount != 255 { if _, err := c.Write([]byte{NAK}); err != nil { return nil, err } return nil, InvalidPacket } received := 0 var pData bytes.Buffer for received < packetSize { n, err := c.Read(dBuffer) if err != nil { return nil, err } received += n pData.Write(dBuffer[:n]) } var crc uint16 if _, err := c.Read(oBuffer); err != nil { return nil, err } crc = uint16(oBuffer[0]) if _, err := c.Read(oBuffer); err != nil { return nil, err } crc <<= 8 crc |= uint16(oBuffer[0]) // Calculate CRC crcCalc := CRC16(pData.Bytes()) if crcCalc != crc { if _, err := c.Write([]byte{NAK}); err != nil { return nil, err } } if _, err := c.Write([]byte{ACK}); err != nil { return nil, err } return pData.Bytes(), nil }
// HandshakeClient establishes connection with the server making sure // they both are in sync. func HandshakeClient(conn io.ReadWriter, debug bool) error { if tracing { defer trace.End(trace.Begin("")) } buf1byte := make([]byte, 1) if _, err := rand.Read(buf1byte); err != nil { log.Errorf("HandshakeClient: Could not read a random byte due to: %v", err) } pos := incrementByte(buf1byte[0]) // set the read deadline for timeout // this has no effect on windows as the deadline is set at port open time log.Debug("HandshakeClient: Sending syn.") conn.Write([]byte{flagSyn, pos}) pos = incrementByte(pos) if _, err := conn.Read(buf1byte); err != nil { return err } if buf1byte[0] != flagAck { if buf1byte[0] == flagNak { log.Debugf("HandshakeClient: Server didn't accept sync. Trying one more time.") return &HandshakeError{ msg: "Server declined handshake request", } } return &HandshakeError{ msg: fmt.Sprintf("Unexpected server response: %d", buf1byte[0]), } } // read response sync position. if _, err := conn.Read(buf1byte); err != nil { return err } if buf1byte[0] != pos { log.Debugf("HandshakeClient: Unexpected byte pos for SynAck: %x, expected: %x", buf1byte[0], pos) return &HandshakeError{ msg: fmt.Sprintf("Unexpected sync position response: %d", buf1byte[0]), } } if _, err := conn.Read(buf1byte); err != nil { return err } log.Debug("HandshakeClient: Sending ack.") if !debug { conn.Write([]byte{flagAck, incrementByte(buf1byte[0])}) } else { conn.Write([]byte{flagDebugAck, incrementByte(buf1byte[0])}) // Verify packet length handling works. We're going to send a known stream // of data to the container and it will echo it back. Verify the sent and // received bufs are the same and we know the channel is lossless. log.Debugf("HandshakeClient: Checking for lossiness") txbuf := []byte("\x1b[32mhello world\x1b[39m!\n") rxbuf := make([]byte, len(txbuf)) _, err := conn.Write(txbuf) if err != nil { return err } var n int log.Debugf("HandshakeClient: Reading response") n, err = io.ReadFull(conn, rxbuf) if err != nil { log.Error(err) return err } if n != len(rxbuf) { return fmt.Errorf("packet size mismatch (expected %d, received %d)", len(rxbuf), n) } if bytes.Compare(rxbuf, txbuf) != 0 { return fmt.Errorf("HandshakeClient: lossiness check FAILED") } // Tell the server we're good. if _, err = conn.Write([]byte{flagAck}); err != nil { return err } log.Infof("HandshakeClient: lossiness check PASSED") } log.Debug("HandshakeClient: Connection established.") return nil }
// HandshakeServer establishes connection with the client making sure // they both are in sync. func HandshakeServer(conn io.ReadWriter) error { if tracing { defer trace.End(trace.Begin("")) } buf1byte := make([]byte, 1) syncBuf := make([]byte, 4096) if _, err := rand.Read(buf1byte); err != nil { log.Errorf("HandshakeClient: Could not read a random byte due to: %v", err) } pos := incrementByte(buf1byte[0]) log.Debug("HandshakeServer: Waiting for incoming syn request...") // Sync packet is 2 bytes, however if we read more than 2 // it means buffer is not empty and data is not trusted for this sync. n, err := io.ReadAtLeast(conn, syncBuf, 2) if err != nil { return err } if n != 2 { log.Debugf("HandshakeServer: Received %d bytes while awaiting for syn.", n) } syncBuf = syncBuf[n-2:] if syncBuf[0] != flagSyn { conn.Write([]byte{flagNak}) return &HandshakeError{ msg: fmt.Sprintf("Unexpected syn packet: %x", syncBuf[0]), } } log.Debugf("HandshakeServer: Received Syn. Writing SynAck.") // syncBuf[1] contains position token that needs to be incremented // by one to send it back. conn.Write([]byte{flagAck, incrementByte(syncBuf[1]), pos}) pos = incrementByte(pos) if _, err := conn.Read(buf1byte); err != nil { return err } ackType := buf1byte[0] if ackType != flagAck && ackType != flagDebugAck { conn.Write([]byte{flagNak}) return &HandshakeError{ msg: fmt.Sprintf("Not an ack packet received: %x", ackType), } } if _, err := conn.Read(buf1byte); err != nil { return err } if buf1byte[0] != pos { conn.Write([]byte{flagNak}) return &HandshakeError{ msg: fmt.Sprintf( "HandshakeServer: Unexpected position %x, expected: %x", buf1byte[0], pos), } } if ackType == flagDebugAck { log.Debugf("HandshakeServer: Debug ACK received") rxbuf := make([]byte, 23) log.Debugf("HandshakeServer: Checking for lossiness") n, err := io.ReadFull(conn, rxbuf) if err != nil { return err } if n != len(rxbuf) { return fmt.Errorf("packet size mismatch (expected %d, received %d)", len(rxbuf), n) } // echo the data back _, err = conn.Write(rxbuf) if err != nil { return err } // wait for the ack if _, err = conn.Read(buf1byte); err != nil { return err } if buf1byte[0] != flagAck { return fmt.Errorf("lossiness check FAILED") } log.Infof("HandshakeServer: lossiness check PASSED") } log.Debug("HandshakeServer: Connection established.") return nil }
func ModemSend(c io.ReadWriter, data []byte, filename string) error { oBuffer := make([]byte, 1) // Wait for Poll if _, err := c.Read(oBuffer); err != nil { return err } // Send zero block with filename and size if oBuffer[0] == POLL { var send bytes.Buffer send.WriteString(filename) send.WriteByte(0x0) send.WriteString(fmt.Sprintf("%d", len(data))) for send.Len() < LONG_PACKET_PAYLOAD_LEN { send.Write([]byte{0x0}) } sendBlock(c, 0, send.Bytes()) // Wait for ACK if _, err := c.Read(oBuffer); err != nil { return err } if oBuffer[0] != ACK { return errors.New("Failed to send header block") } } // Wait for Poll if _, err := c.Read(oBuffer); err != nil { return err } // Send remaining data if oBuffer[0] == POLL { var blocks uint8 = uint8(len(data) / LONG_PACKET_PAYLOAD_LEN) if len(data) > int(int(blocks)*int(LONG_PACKET_PAYLOAD_LEN)) { blocks++ } failed := 0 var currentBlock uint8 = 0 for currentBlock < blocks && failed < 10 { if int(int(currentBlock+1)*int(LONG_PACKET_PAYLOAD_LEN)) > len(data) { sendBlock(c, currentBlock+1, data[int(currentBlock)*int(LONG_PACKET_PAYLOAD_LEN):]) } else { sendBlock(c, currentBlock+1, data[int(currentBlock)*int(LONG_PACKET_PAYLOAD_LEN):(int(currentBlock)+1)*int(LONG_PACKET_PAYLOAD_LEN)]) } if _, err := c.Read(oBuffer); err != nil { return err } if oBuffer[0] == ACK { currentBlock++ } else { failed++ } } } // Wait for NAK and send EOT if _, err := c.Write([]byte{EOT}); err != nil { return err } if _, err := c.Read(oBuffer); err != nil { return err } if oBuffer[0] != NAK { return errors.New("") } // Send EOT again if _, err := c.Write([]byte{EOT}); err != nil { return err } if _, err := c.Read(oBuffer); err != nil { return err } if oBuffer[0] != ACK { return errors.New("Failed to send end block") } // Wait for POLL if _, err := c.Read(oBuffer); err != nil { return err } if oBuffer[0] != POLL { return errors.New("Failed to send end block") } // Send empty block to signify end var zero bytes.Buffer for zero.Len() < LONG_PACKET_PAYLOAD_LEN { zero.Write([]byte{0x0}) } sendBlock(c, 0, zero.Bytes()) // Wait for ACK if _, err := c.Read(oBuffer); err != nil { return err } if oBuffer[0] != ACK { return errors.New("Failed to send end block") } return nil }
func ModemReceive(c io.ReadWriter) (string, []byte, error) { var data bytes.Buffer // Start Connection if _, err := c.Write([]byte{POLL}); err != nil { return "", nil, err } // Read file information pktData, err := receivePacket(c) if err != nil { return "", nil, err } filenameEnd := bytes.IndexByte(pktData, 0x0) filename := string(pktData[0:filenameEnd]) var filesize int fmt.Sscanf(string(pktData[filenameEnd+1:]), "%d", &filesize) if _, err := c.Write([]byte{POLL}); err != nil { return "", nil, err } // Read Packets for { pktData, err := receivePacket(c) if err == InvalidPacket { continue } if err != nil { return "", nil, err } // End of Transmission if pktData == nil { break } data.Write(pktData) } // Send NAK to respond to EOT if _, err := c.Write([]byte{NAK}); err != nil { return "", nil, err } oBuffer := make([]byte, 1) if _, err := c.Read(oBuffer); err != nil { return "", nil, err } // Send ACK to respond to second EOT if oBuffer[0] != EOT { return "", nil, err } if _, err := c.Write([]byte{ACK}); err != nil { return "", nil, err } // Second POLL to get remaining file or close if _, err := c.Write([]byte{POLL}); err != nil { return "", nil, err } // Get remaining data ( for now assume one file ) if _, err := receivePacket(c); err != nil { return "", nil, err } return filename, data.Bytes()[0:filesize], nil }