/* * 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.FileOutputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.nio.ByteBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ServerPutProcessor { private static final int MAXIMUM_TFTP_PACKET_SIZE = 512; private Logger logger = LoggerFactory.getLogger(ClientGetProcessor.class.getName()); private DatagramSocket socket; private InetAddress clientIp; private int clientPort; private int ackNum = 0; public ServerPutProcessor(DatagramPacket p) { try { socket = new DatagramSocket(); clientIp = p.getAddress(); clientPort = p.getPort(); } catch (SocketException e) { logger.error("kraken tftp: ack socket error", e); } } public void start(String fileName) { FileOutputStream os = null; try { os = new FileOutputStream(new File(fileName)); sendFirstPacket(); processing(os); } catch (IOException e) { logger.error("kraken tftp: cannot handle put request, stopped", e); } finally { if (os != null) try { os.close(); } catch (IOException e) { } } } public void block() { try { byte[] b = new byte[] { 0x00, 0x05, 0x00, 0x00, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x00 }; DatagramPacket outgoing = new DatagramPacket(b, b.length, clientIp, clientPort); socket.send(outgoing); } catch (IOException e) { logger.error("kraken tftp: cannot block", e); } } private void sendFirstPacket() throws IOException { byte[] firstPacket = setData(ackNum); DatagramPacket outgoing = new DatagramPacket(firstPacket, firstPacket.length, clientIp, clientPort); socket.send(outgoing); } private void processing(FileOutputStream os) throws IOException { 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++; if (ackNum > 65535) { sendFileSizeLimitExceededError(); break; } byte[] b = setData(ackNum); outgoing = new DatagramPacket(b, b.length, clientIp, clientPort); socket.send(outgoing); // last packet will be smaller than maximum packet size if (incoming.getLength() < MAXIMUM_TFTP_PACKET_SIZE) break; } } private byte[] setData(int ackNum) { ByteBuffer bb = ByteBuffer.allocate(4); bb.putShort((short) 4); bb.putShort((short) ackNum); bb.flip(); byte[] b = new byte[4]; bb.get(b); return b; } private void sendFileSizeLimitExceededError() throws IOException { /* generate tftp error packet(File size limit exceed) */ byte[] b = new byte[] { 0x00, 0x05, 0x00, 0x03, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x00 }; DatagramPacket outgoing = new DatagramPacket(b, b.length, clientIp, clientPort); socket.send(outgoing); } }