--- TFTPClient.javaCURR 2006-09-22 08:53:57.265625000 -0700 +++ TFTPClient.java 2006-06-21 16:56:14.436984000 -0700 @@ -360,7 +360,7 @@ public void sendFile(String filename, int mode, InputStream input, InetAddress host, int port) throws IOException { - int bytesRead, timeouts, lastBlock, block, hostPort, dataLength, offset; + int bytesRead, timeouts, lastBlock, block, hostPort, dataLength, offset, totalThisPacket; TFTPPacket sent, received = null; TFTPErrorPacket error; TFTPDataPacket data = @@ -368,10 +368,13 @@ ; TFTPAckPacket ack; + boolean justStarted = true; + beginBufferedOps(); - dataLength = lastBlock = hostPort = bytesRead = 0; + dataLength = lastBlock = hostPort = bytesRead = totalThisPacket = 0; block = 0; + boolean lastAckWait = false; if (mode == TFTP.ASCII_MODE) input = new ToNetASCIIInputStream(input); @@ -382,11 +385,16 @@ _sendPacket: do { + // first time: block is 0, lastBlock is 0, send a request packet. + // subsequent: block is integer starting at 1, send data packet. bufferedSend(sent); - + + // this is trying to receive an ACK _receivePacket: while (true) { + + timeouts = 0; while (timeouts < __maxTimeouts) { @@ -418,12 +426,13 @@ endBufferedOps(); throw new IOException("Bad packet: " + e.getMessage()); } - } + } // end of while loop over tries to receive // The first time we receive we get the port number and // answering host address (for hosts with multiple IPs) - if (lastBlock == 0) + if (justStarted) { + justStarted = false; hostPort = received.getPort(); data.setPort(hostPort); if(!host.equals(received.getAddress())) @@ -455,7 +464,13 @@ if (lastBlock == block) { ++block; - break _receivePacket; + if (lastAckWait) { + + break _sendPacket; + } + else { + break _receivePacket; + } } else { @@ -488,22 +503,33 @@ //break; } + // OK, we have just gotten ACK about the last data we sent. Make another + // and send it + dataLength = TFTPPacket.SEGMENT_SIZE; offset = 4; + totalThisPacket = 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, offset - 4); + data.setData(_sendBuffer, 4, totalThisPacket); sent = data; } - while (dataLength == 0); - - bufferedSend(sent); + while ( totalThisPacket > 0 || lastAckWait ); + // Note: this was looping while dataLength == 0 || lastAckWait, + // which was discarding the last packet if it was not full size + // Should send the packet. + endBufferedOps(); }