Example #1
0
  /**
   * * This is a special method to perform a more efficient packet receive. It should only be used
   * after calling {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps() initializes a
   * set of buffers used internally that prevent the new allocation of a DatagramPacket and byte
   * array for each send and receive. To use these buffers you must call the bufferedReceive() and
   * bufferedSend() methods instead of send() and receive(). You must also be certain that you don't
   * manipulate the resulting packet in such a way that it interferes with future buffered
   * operations. For example, a TFTPDataPacket received with bufferedReceive() will have a reference
   * to the internal byte buffer. You must finish using this data before calling bufferedReceive()
   * again, or else the data will be overwritten by the the call.
   *
   * <p>
   *
   * @return The TFTPPacket received.
   * @exception InterruptedIOException If a socket timeout occurs. The Java documentation claims an
   *     InterruptedIOException is thrown on a DatagramSocket timeout, but in practice we find a
   *     SocketException is thrown. You should catch both to be safe.
   * @exception SocketException If a socket timeout occurs. The Java documentation claims an
   *     InterruptedIOException is thrown on a DatagramSocket timeout, but in practice we find a
   *     SocketException is thrown. You should catch both to be safe.
   * @exception IOException If some other I/O error occurs.
   * @exception TFTPPacketException If an invalid TFTP packet is received. *
   */
  public final TFTPPacket bufferedReceive()
      throws IOException, InterruptedIOException, SocketException, TFTPPacketException {
    __receiveDatagram.setData(__receiveBuffer);
    __receiveDatagram.setLength(__receiveBuffer.length);
    _socket_.receive(__receiveDatagram);

    return TFTPPacket.newTFTPPacket(__receiveDatagram);
  }
Example #2
0
  /**
   * * Receives a TFTPPacket.
   *
   * <p>
   *
   * @return The TFTPPacket received.
   * @exception InterruptedIOException If a socket timeout occurs. The Java documentation claims an
   *     InterruptedIOException is thrown on a DatagramSocket timeout, but in practice we find a
   *     SocketException is thrown. You should catch both to be safe.
   * @exception SocketException If a socket timeout occurs. The Java documentation claims an
   *     InterruptedIOException is thrown on a DatagramSocket timeout, but in practice we find a
   *     SocketException is thrown. You should catch both to be safe.
   * @exception IOException If some other I/O error occurs.
   * @exception TFTPPacketException If an invalid TFTP packet is received. *
   */
  public final TFTPPacket receive()
      throws IOException, InterruptedIOException, SocketException, TFTPPacketException {
    DatagramPacket packet;

    packet = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE);

    _socket_.receive(packet);

    return TFTPPacket.newTFTPPacket(packet);
  }
Example #3
0
 /**
  * * Sends a TFTP packet to its destination.
  *
  * <p>
  *
  * @param packet The TFTP packet to send.
  * @exception IOException If some I/O error occurs. *
  */
 public final void send(TFTPPacket packet) throws IOException {
   _socket_.send(packet.newDatagram());
 }
Example #4
0
 /**
  * * This is a special method to perform a more efficient packet send. It should only be used
  * after calling {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps() initializes a
  * set of buffers used internally that prevent the new allocation of a DatagramPacket and byte
  * array for each send and receive. To use these buffers you must call the bufferedReceive() and
  * bufferedSend() methods instead of send() and receive(). You must also be certain that you don't
  * manipulate the resulting packet in such a way that it interferes with future buffered
  * operations. For example, a TFTPDataPacket received with bufferedReceive() will have a reference
  * to the internal byte buffer. You must finish using this data before calling bufferedReceive()
  * again, or else the data will be overwritten by the the call.
  *
  * <p>
  *
  * @param packet The TFTP packet to send.
  * @exception IOException If some I/O error occurs. *
  */
 public final void bufferedSend(TFTPPacket packet) throws IOException {
   _socket_.send(packet._newDatagram(__sendDatagram, _sendBuffer));
 }
Example #5
0
  /**
   * * Requests to send a file to a remote host, reads the file from an InputStream, sends the file
   * to the remote host, and closes the connection. A local UDP socket must first be created by <a
   * href="org.apache.commons.net.DatagramSocketClient.html#open">open()</a> before invoking this
   * method. This method will not close the InputStream containing the file; you must close it after
   * the method invocation.
   *
   * <p>
   *
   * @param filename The name the remote server should use when creating the file on its file
   *     system.
   * @param mode The TFTP mode of the transfer (one of the MODE constants).
   * @param host The remote host receiving the file.
   * @param port The port number of the remote TFTP server.
   * @exception IOException If an I/O error occurs. The nature of the error will be reported in the
   *     message. *
   */
  public void sendFile(String filename, int mode, InputStream input, InetAddress host, int port)
      throws IOException {
    int bytesRead, timeouts, lastBlock, block, hostPort, dataLength, offset;
    TFTPPacket sent, received = null;
    TFTPErrorPacket error;
    TFTPDataPacket data = new TFTPDataPacket(host, port, 0, _sendBuffer, 4, 0);
    ;
    TFTPAckPacket ack;

    beginBufferedOps();

    dataLength = lastBlock = hostPort = bytesRead = 0;
    block = 0;

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

    sent = new TFTPWriteRequestPacket(host, port, filename, mode);

    _sendPacket:
    do {
      bufferedSend(sent);

      _receivePacket:
      while (true) {
        timeouts = 0;
        while (timeouts < __maxTimeouts) {
          try {
            received = bufferedReceive();
            break;
          } catch (SocketException e) {
            if (++timeouts >= __maxTimeouts) {
              endBufferedOps();
              throw new IOException("Connection timed out.");
            }
            continue;
          } catch (InterruptedIOException e) {
            if (++timeouts >= __maxTimeouts) {
              endBufferedOps();
              throw new IOException("Connection timed out.");
            }
            continue;
          } catch (TFTPPacketException e) {
            endBufferedOps();
            throw new IOException("Bad packet: " + e.getMessage());
          }
        }

        // The first time we receive we get the port number and
        // answering host address (for hosts with multiple IPs)
        if (lastBlock == 0) {
          hostPort = received.getPort();
          data.setPort(hostPort);
          if (!host.equals(received.getAddress())) {
            host = received.getAddress();
            data.setAddress(host);
            sent.setAddress(host);
          }
        }

        // Comply with RFC 783 indication that an error acknowledgement
        // should be sent to originator if unexpected TID or host.
        if (host.equals(received.getAddress()) && received.getPort() == hostPort) {

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

              lastBlock = ack.getBlockNumber();

              if (lastBlock == block) {
                ++block;
                break _receivePacket;
              } else {
                discardPackets();

                if (lastBlock == (block - 1)) continue _sendPacket; // Resend last acknowledgement.

                continue _receivePacket; // Start fetching packets again.
              }
              // break;

            default:
              endBufferedOps();
              throw new IOException("Received unexpected packet type.");
          }
        } else {
          error =
              new TFTPErrorPacket(
                  received.getAddress(),
                  received.getPort(),
                  TFTPErrorPacket.UNKNOWN_TID,
                  "Unexpected host or port.");
          bufferedSend(error);
          continue _sendPacket;
        }

        // We should never get here, but this is a safety to avoid
        // infinite loop.  If only Java had the goto statement.
        // break;
      }

      dataLength = TFTPPacket.SEGMENT_SIZE;
      offset = 4;
      while (dataLength > 0 && (bytesRead = input.read(_sendBuffer, offset, dataLength)) > 0) {
        offset += bytesRead;
        dataLength -= bytesRead;
      }

      data.setBlockNumber(block);
      data.setData(_sendBuffer, 4, offset - 4);
      sent = data;
    } while (dataLength == 0);

    bufferedSend(sent);
    endBufferedOps();
  }
Example #6
0
  /**
   * * Requests a named file from a remote host, writes the file to an OutputStream, closes the
   * connection, and returns the number of bytes read. A local UDP socket must first be created by
   * <a href="org.apache.commons.net.DatagramSocketClient.html#open">open()</a> before invoking this
   * method. This method will not close the OutputStream containing the file; you must close it
   * after the method invocation.
   *
   * <p>
   *
   * @param filename The name of the file to receive.
   * @param mode The TFTP mode of the transfer (one of the MODE constants).
   * @param output The OutputStream to which the file should be written.
   * @param host The remote host serving the file.
   * @param port The port number of the remote TFTP server.
   * @exception IOException If an I/O error occurs. The nature of the error will be reported in the
   *     message. *
   */
  public int receiveFile(String filename, int mode, OutputStream output, InetAddress host, int port)
      throws IOException {
    int bytesRead, timeouts, lastBlock, block, hostPort, dataLength;
    TFTPPacket sent, received = null;
    TFTPErrorPacket error;
    TFTPDataPacket data;
    TFTPAckPacket ack = new TFTPAckPacket(host, port, 0);

    beginBufferedOps();

    dataLength = lastBlock = hostPort = bytesRead = 0;
    block = 1;

    if (mode == TFTP.ASCII_MODE) output = new FromNetASCIIOutputStream(output);

    sent = new TFTPReadRequestPacket(host, port, filename, mode);

    _sendPacket:
    do {
      bufferedSend(sent);

      _receivePacket:
      while (true) {
        timeouts = 0;
        while (timeouts < __maxTimeouts) {
          try {
            received = bufferedReceive();
            break;
          } catch (SocketException e) {
            if (++timeouts >= __maxTimeouts) {
              endBufferedOps();
              throw new IOException("Connection timed out.");
            }
            continue;
          } catch (InterruptedIOException e) {
            if (++timeouts >= __maxTimeouts) {
              endBufferedOps();
              throw new IOException("Connection timed out.");
            }
            continue;
          } catch (TFTPPacketException e) {
            endBufferedOps();
            throw new IOException("Bad packet: " + e.getMessage());
          }
        }

        // The first time we receive we get the port number and
        // answering host address (for hosts with multiple IPs)
        if (lastBlock == 0) {
          hostPort = received.getPort();
          ack.setPort(hostPort);
          if (!host.equals(received.getAddress())) {
            host = received.getAddress();
            ack.setAddress(host);
            sent.setAddress(host);
          }
        }

        // Comply with RFC 783 indication that an error acknowledgement
        // should be sent to originator if unexpected TID or host.
        if (host.equals(received.getAddress()) && received.getPort() == hostPort) {

          switch (received.getType()) {
            case TFTPPacket.ERROR:
              error = (TFTPErrorPacket) received;
              endBufferedOps();
              throw new IOException(
                  "Error code " + error.getError() + " received: " + error.getMessage());
            case TFTPPacket.DATA:
              data = (TFTPDataPacket) received;
              dataLength = data.getDataLength();

              lastBlock = data.getBlockNumber();

              if (lastBlock == block) {
                try {
                  output.write(data.getData(), data.getDataOffset(), dataLength);
                } catch (IOException e) {
                  error =
                      new TFTPErrorPacket(
                          host, hostPort, TFTPErrorPacket.OUT_OF_SPACE, "File write failed.");
                  bufferedSend(error);
                  endBufferedOps();
                  throw e;
                }
                ++block;
                break _receivePacket;
              } else {
                discardPackets();

                if (lastBlock == (block - 1)) continue _sendPacket; // Resend last acknowledgement.

                continue _receivePacket; // Start fetching packets again.
              }
              // break;

            default:
              endBufferedOps();
              throw new IOException("Received unexpected packet type.");
          }
        } else {
          error =
              new TFTPErrorPacket(
                  received.getAddress(),
                  received.getPort(),
                  TFTPErrorPacket.UNKNOWN_TID,
                  "Unexpected host or port.");
          bufferedSend(error);
          continue _sendPacket;
        }

        // We should never get here, but this is a safety to avoid
        // infinite loop.  If only Java had the goto statement.
        // break;
      }

      ack.setBlockNumber(lastBlock);
      sent = ack;
      bytesRead += dataLength;
    } // First data packet less than 512 bytes signals end of stream.
    while (dataLength == TFTPPacket.SEGMENT_SIZE);

    bufferedSend(sent);
    endBufferedOps();

    return bytesRead;
  }