/* * Copyright 2011 Future Systems * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.tftp; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketTimeoutException; import java.nio.ByteBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ClientGetProcessor { private static final int TIMEOUT = 60 * 1000; // 1min timeout private static final int MAXIMUM_TFTP_PACKET_SIZE = 512; private Logger logger = LoggerFactory.getLogger(ClientGetProcessor.class.getName()); private DatagramSocket socket; private short ackNum = 0; public ClientGetProcessor() { } public void start(InetSocketAddress target, byte[] firstPacket, String source, String destination) throws IOException { socket = new DatagramSocket(); socket.setSoTimeout(TIMEOUT); sendFirstPacket(target, firstPacket); processing(target.getAddress(), source, destination); } private void sendFirstPacket(InetSocketAddress target, byte[] firstPacket) throws IOException { DatagramPacket outgoing = new DatagramPacket(firstPacket, firstPacket.length, target.getAddress(), target .getPort()); socket.send(outgoing); } private void processing(InetAddress target, String source, String destination) throws IOException { FileOutputStream os = null; try { /* first received */ byte[] inbuf = new byte[516]; DatagramPacket incoming = new DatagramPacket(inbuf, inbuf.length); socket.receive(incoming); if (incoming == null || incoming.getData()[1] == 0x05) throw new FileNotFoundException(); if (destination == null) { int pos = source.lastIndexOf("/"); if (pos == -1) os = new FileOutputStream(new File(source)); else os = new FileOutputStream(new File(source.substring(pos + 1))); } else os = new FileOutputStream(new File(destination)); os.write(incoming.getData(), 4, incoming.getLength() - 4); int port = incoming.getPort(); /* first ACK */ ackNum++; byte[] b = setData(ackNum); DatagramPacket outgoing = new DatagramPacket(b, b.length, target, port); socket.send(outgoing); if (incoming.getLength() < MAXIMUM_TFTP_PACKET_SIZE) return; handleSocket(target, port, os); } finally { if (os != null) os.close(); } } private void handleSocket(InetAddress target, int port, FileOutputStream os) throws IOException { try { DatagramPacket incoming; DatagramPacket outgoing; byte[] inbuf; while (true) { inbuf = new byte[516]; incoming = new DatagramPacket(inbuf, inbuf.length); socket.receive(incoming); os.write(incoming.getData(), 4, incoming.getLength() - 4); ackNum++; byte[] b = setData(ackNum); outgoing = new DatagramPacket(b, b.length, target, port); socket.send(outgoing); if (incoming.getLength() < MAXIMUM_TFTP_PACKET_SIZE) break; } } catch (SocketTimeoutException e) { if (logger.isDebugEnabled()) logger.debug("kraken tftp: socket timeout exception"); } } private byte[] setData(short ackNum) { ByteBuffer bb = ByteBuffer.allocate(4); bb.putShort((short) 4); bb.putShort(ackNum); bb.flip(); byte[] b1 = new byte[4]; bb.get(b1); return b1; } }