Beispiel #1
0
// sendReadRequest send RRQ to server and negotiates transfer options
//
// If the server doesn't support options and responds with data, the data will be added
// to rxBuf.
func (c *conn) sendReadRequest(filename string, opts map[string]string) error {
	// Build RRQ
	c.tx.writeReadReq(filename, c.mode, opts)

	// Send request
	if err := c.sendRequest(); err != nil {
		return wrapError(err, "sending RRQ")
	}

	// Should have received OACK if server supports options, or DATA if not
	switch op := c.rx.opcode(); op {
	case opCodeOACK:
		// Got OACK, parse options
		if err := c.readSetup(); err != nil {
			return wrapError(err, "got OACK, read setup")
		}
	case opCodeDATA:
		// Server doesn't support options,
		// write data to the buf so it's available for reading

		var writer io.Writer = &c.rxBuf
		if c.mode == ModeNetASCII {
			na := netascii.NewWriter(writer)
			defer errorDefer(na.Flush, c.log, "error flushing netascii encoder")
			writer = na
		}

		n, err := writer.Write(c.rx.data())
		if err != nil {
			return wrapError(err, "writing RRQ response data")
		}

		// Set optionsParsed
		c.optionsParsed = true

		// If less than blksize, we're done
		if n < int(c.blksize) {
			c.done = true
		}

		// Ack data
		if err := c.sendAck(c.rx.block()); err != nil {
			return wrapError(err, "sending ACK for RRQ DATA")
		}
		c.block = c.rx.block()
	case opCodeERROR:
		// Received an error
		return wrapError(c.remoteError(), "RRQ OACK response")
	default:
		return wrapError(&errUnexpectedDatagram{dg: c.rx.String()}, "RRQ OACK response")
	}

	return nil
}
Beispiel #2
0
// Write implements io.Writer and wraps write().
//
// If mode is ModeNetASCII, wrap write() with netascii.EncodeWriter.
func (c *conn) Write(p []byte) (int, error) {
	// Can't write if an error has been sent/received
	if c.err != nil {
		return 0, wrapError(c.err, "checking conn err before Write")
	}

	if c.mode == ModeNetASCII {
		if c.netasciiEnc == nil {
			c.netasciiEnc = netascii.NewWriter(writerFunc(c.write))
		}
		n, err := c.netasciiEnc.Write(p)
		return n, wrapError(err, "writing through netascii encoder")
	}

	n, err := c.write(p)
	return n, wrapError(err, "writing through standard writer")
}