public void sendFile()

in src/main/java/org/apache/commons/net/tftp/TFTPClient.java [291:402]


    public void sendFile(final String fileName, final int mode, InputStream input, InetAddress host, final int port) throws IOException {
        int block = 0;
        int hostPort = 0;
        boolean justStarted = true;
        boolean lastAckWait = false;

        totalBytesSent = 0L;

        if (mode == TFTP.ASCII_MODE) {
            input = new ToNetASCIIInputStream(input);
        }

        TFTPPacket sent = new TFTPWriteRequestPacket(host, port, fileName, mode);
        final TFTPDataPacket data = new TFTPDataPacket(host, port, 0, sendBuffer, 4, 0);

        beginBufferedOps();

        try {
            do { // until eof
                 // first time: block is 0, lastBlock is 0, send a request packet.
                 // subsequent: block is integer starting at 1, send data packet.
                bufferedSend(sent);
                boolean wantReply = true;
                int timeouts = 0;
                do {
                    try {
                        final TFTPPacket received = bufferedReceive();
                        final InetAddress recdAddress = received.getAddress();
                        final int recdPort = received.getPort();
                        // The first time we receive we get the port number and
                        // answering host address (for hosts with multiple IPs)
                        if (justStarted) {
                            justStarted = false;
                            if (recdPort == port) { // must not use the control port here
                                final TFTPErrorPacket error = new TFTPErrorPacket(recdAddress, recdPort, TFTPErrorPacket.UNKNOWN_TID, "INCORRECT SOURCE PORT");
                                bufferedSend(error);
                                throw new IOException("Incorrect source port (" + recdPort + ") in request reply.");
                            }
                            hostPort = recdPort;
                            data.setPort(hostPort);
                            if (!host.equals(recdAddress)) {
                                host = recdAddress;
                                data.setAddress(host);
                                sent.setAddress(host);
                            }
                        }
                        // Comply with RFC 783 indication that an error acknowledgment
                        // should be sent to originator if unexpected TID or host.
                        if (host.equals(recdAddress) && recdPort == hostPort) {

                            switch (received.getType()) {
                            case TFTPPacket.ERROR:
                                final TFTPErrorPacket error = (TFTPErrorPacket) received;
                                throw new IOException("Error code " + error.getError() + " received: " + error.getMessage());
                            case TFTPPacket.ACKNOWLEDGEMENT:

                                final int lastBlock = ((TFTPAckPacket) received).getBlockNumber();

                                if (lastBlock == block) {
                                    ++block;
                                    if (block > 65535) {
                                        // wrap the block number
                                        block = 0;
                                    }
                                    wantReply = false; // got the ack we want
                                } else {
                                    discardPackets();
                                }
                                break;
                            default:
                                throw new IOException("Received unexpected packet type.");
                            }
                        } else { // wrong host or TID; send error
                            final TFTPErrorPacket error = new TFTPErrorPacket(recdAddress, recdPort, TFTPErrorPacket.UNKNOWN_TID, "Unexpected host or port.");
                            bufferedSend(error);
                        }
                    } catch (final SocketException | InterruptedIOException e) {
                        if (++timeouts >= maxTimeouts) {
                            throw new IOException("Connection timed out.");
                        }
                    } catch (final TFTPPacketException e) {
                        throw new IOException("Bad packet: " + e.getMessage());
                    }
                    // retry until a good ack
                } while (wantReply);

                if (lastAckWait) {
                    break; // we were waiting for this; now all done
                }

                int dataLength = TFTPPacket.SEGMENT_SIZE;
                int offset = 4;
                int totalThisPacket = 0;
                int bytesRead = 0;
                while (dataLength > 0 && (bytesRead = input.read(sendBuffer, offset, dataLength)) > 0) {
                    offset += bytesRead;
                    dataLength -= bytesRead;
                    totalThisPacket += bytesRead;
                }
                if (totalThisPacket < TFTPPacket.SEGMENT_SIZE) {
                    /* this will be our last packet -- send, wait for ack, stop */
                    lastAckWait = true;
                }
                data.setBlockNumber(block);
                data.setData(sendBuffer, 4, totalThisPacket);
                sent = data;
                totalBytesSent += totalThisPacket;
            } while (true); // loops until after lastAckWait is set
        } finally {
            endBufferedOps();
        }
    }