// Path: tftp-protocol/src/main/java/org/anarres/tftp/protocol/packet/TftpPacket.java
// public abstract class TftpPacket {
// 
//     // Substitute for netascii in the RFC. ISO_8859_1 is 8-bit transparent.
//     public static final Charset CHARSET = Charsets.ISO_8859_1;
//     private SocketAddress remoteAddress;
// 
//     @Nonnull
//     public SocketAddress getRemoteAddress() {
//         return remoteAddress;
//     }
// 
//     public void setRemoteAddress(@Nonnull SocketAddress remoteAddress) {
//         this.remoteAddress = Preconditions.checkNotNull(remoteAddress, "Remote address was null.");
//     }
// 
//     /** At most this long, possibly less. */
//     @Nonnegative
//     public int getWireLength() {
//         return 256;
//     }
// 
//     @Nonnull
//     public abstract TftpOpcode getOpcode();
// 
//     @Nonnull
//     protected Objects.ToStringHelper toStringHelper() {
//         return Objects.toStringHelper(this).add("opcode", getOpcode());
//     }
// 
//     public void toWire(@Nonnull ByteBuffer buffer) {
//         buffer.putShort(getOpcode().getCode());
//     }
// 
//     /** This is called after the opcode has already been read. */
//     public abstract void fromWire(@Nonnull ByteBuffer buffer);
// 
//     protected static void putString(@Nonnull ByteBuffer buffer, @Nonnull String text) {
//         buffer.put(text.getBytes(CHARSET));
//         buffer.put((byte) 0);
//     }
// 
//     @Nonnull
//     protected static String getString(@Nonnull ByteBuffer buffer) {
//         int start = buffer.position();
//         int finish;
//         int end = -1;
//         for (finish = start; finish < buffer.limit(); finish++) {
//             if (buffer.get(finish) == 0) {
//                 end = finish;
//                 finish++;
//                 break;
//             }
//         }
//         // We didn't find a zero byte.
//         if (end == -1)
//             end = buffer.limit();
// 
//         byte[] bytes = new byte[end - start];
//         buffer.get(bytes);
//         buffer.position(finish);
//         return new String(bytes, CHARSET);
//     }
// 
//     @Override
//     public String toString() {
//         return toStringHelper().toString();
//     }
// }
// 
// Path: tftp-protocol/src/main/java/org/anarres/tftp/protocol/engine/TftpTransfer.java
// public interface TftpTransfer<TftpTransferContext> {
// 
//     /**
//      * Opens this TftpTransfer and sends the initial packets.
//      *
//      * Implemented by the transfer.
//      */
//     public void open(@Nonnull TftpTransferContext context) throws Exception;
// 
//     /**
//      * Responds to an incoming packet on this transfer.
//      *
//      * Implemented by the transfer.
//      */
//     public void handle(@Nonnull TftpTransferContext context, @Nonnull TftpPacket packet) throws Exception;
// 
//     /** Implemented by the transfer. */
//     public void timeout(@Nonnull TftpTransferContext context) throws Exception;
// 
//     /** Implemented by the channel. */
//     public void send(@Nonnull TftpTransferContext context, @Nonnull TftpPacket packet) throws Exception;
// 
//     /** Implemented by the channel. */
//     public void flush(@Nonnull TftpTransferContext context) throws Exception;
// 
//     /** Implemented by the channel. */
//     public void close(@Nonnull TftpTransferContext context) throws Exception;
// }


import javax.annotation.Nonnull;
import org.anarres.tftp.protocol.packet.TftpPacket;
import org.anarres.tftp.protocol.engine.TftpTransfer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.service.IoService;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.anarres.tftp.server.mina;


/**
 *
 * @author shevek
 */
// TODO: Re-code this to use a window of (say) 8 packets.
public class TftpTransferProtocolHandler extends IoHandlerAdapter implements IoFutureListener<ConnectFuture> {

    private static final Logger LOG = LoggerFactory.getLogger(TftpTransferProtocolHandler.class);
    private final IoService connector;
    private final TftpTransfer<IoSession> transfer;

    public TftpTransferProtocolHandler(@Nonnull IoService connector, @Nonnull TftpTransfer<IoSession> transfer) {
        this.connector = connector;
        this.transfer = transfer;
    }

    @Override
    public void operationComplete(ConnectFuture future) {
        if (!future.isConnected()) {
            connector.dispose(false);
            return;
        }
        final IoSession session = future.getSession();
        try {
            // This does "real" I/O, so can really throw an exception.
            transfer.open(session);
// Path: tftp-protocol/src/main/java/org/anarres/tftp/protocol/packet/TftpPacket.java
// public abstract class TftpPacket {
// 
//     // Substitute for netascii in the RFC. ISO_8859_1 is 8-bit transparent.
//     public static final Charset CHARSET = Charsets.ISO_8859_1;
//     private SocketAddress remoteAddress;
// 
//     @Nonnull
//     public SocketAddress getRemoteAddress() {
//         return remoteAddress;
//     }
// 
//     public void setRemoteAddress(@Nonnull SocketAddress remoteAddress) {
//         this.remoteAddress = Preconditions.checkNotNull(remoteAddress, "Remote address was null.");
//     }
// 
//     /** At most this long, possibly less. */
//     @Nonnegative
//     public int getWireLength() {
//         return 256;
//     }
// 
//     @Nonnull
//     public abstract TftpOpcode getOpcode();
// 
//     @Nonnull
//     protected Objects.ToStringHelper toStringHelper() {
//         return Objects.toStringHelper(this).add("opcode", getOpcode());
//     }
// 
//     public void toWire(@Nonnull ByteBuffer buffer) {
//         buffer.putShort(getOpcode().getCode());
//     }
// 
//     /** This is called after the opcode has already been read. */
//     public abstract void fromWire(@Nonnull ByteBuffer buffer);
// 
//     protected static void putString(@Nonnull ByteBuffer buffer, @Nonnull String text) {
//         buffer.put(text.getBytes(CHARSET));
//         buffer.put((byte) 0);
//     }
// 
//     @Nonnull
//     protected static String getString(@Nonnull ByteBuffer buffer) {
//         int start = buffer.position();
//         int finish;
//         int end = -1;
//         for (finish = start; finish < buffer.limit(); finish++) {
//             if (buffer.get(finish) == 0) {
//                 end = finish;
//                 finish++;
//                 break;
//             }
//         }
//         // We didn't find a zero byte.
//         if (end == -1)
//             end = buffer.limit();
// 
//         byte[] bytes = new byte[end - start];
//         buffer.get(bytes);
//         buffer.position(finish);
//         return new String(bytes, CHARSET);
//     }
// 
//     @Override
//     public String toString() {
//         return toStringHelper().toString();
//     }
// }
// 
// Path: tftp-protocol/src/main/java/org/anarres/tftp/protocol/engine/TftpTransfer.java
// public interface TftpTransfer<TftpTransferContext> {
// 
//     /**
//      * Opens this TftpTransfer and sends the initial packets.
//      *
//      * Implemented by the transfer.
//      */
//     public void open(@Nonnull TftpTransferContext context) throws Exception;
// 
//     /**
//      * Responds to an incoming packet on this transfer.
//      *
//      * Implemented by the transfer.
//      */
//     public void handle(@Nonnull TftpTransferContext context, @Nonnull TftpPacket packet) throws Exception;
// 
//     /** Implemented by the transfer. */
//     public void timeout(@Nonnull TftpTransferContext context) throws Exception;
// 
//     /** Implemented by the channel. */
//     public void send(@Nonnull TftpTransferContext context, @Nonnull TftpPacket packet) throws Exception;
// 
//     /** Implemented by the channel. */
//     public void flush(@Nonnull TftpTransferContext context) throws Exception;
// 
//     /** Implemented by the channel. */
//     public void close(@Nonnull TftpTransferContext context) throws Exception;
// }


// Path: tftp-server-mina/src/main/java/org/anarres/tftp/server/mina/TftpTransferProtocolHandler.java
import javax.annotation.Nonnull;
import org.anarres.tftp.protocol.packet.TftpPacket;
import org.anarres.tftp.protocol.engine.TftpTransfer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.service.IoService;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.anarres.tftp.server.mina;


/**
 *
 * @author shevek
 */
// TODO: Re-code this to use a window of (say) 8 packets.
public class TftpTransferProtocolHandler extends IoHandlerAdapter implements IoFutureListener<ConnectFuture> {

    private static final Logger LOG = LoggerFactory.getLogger(TftpTransferProtocolHandler.class);
    private final IoService connector;
    private final TftpTransfer<IoSession> transfer;

    public TftpTransferProtocolHandler(@Nonnull IoService connector, @Nonnull TftpTransfer<IoSession> transfer) {
        this.connector = connector;
        this.transfer = transfer;
    }

    @Override
    public void operationComplete(ConnectFuture future) {
        if (!future.isConnected()) {
            connector.dispose(false);
            return;
        }
        final IoSession session = future.getSession();
        try {
            // This does "real" I/O, so can really throw an exception.
            transfer.open(session);
        } catch (Exception e) {