// Path: tftp-protocol/src/main/java/org/anarres/tftp/protocol/codec/TftpPacketDecoder.java
// public class TftpPacketDecoder {
// 
//     private static final Logger LOG = LoggerFactory.getLogger(TftpPacketDecoder.class);
// 
//     @Nonnull
//     public TftpPacket decode(@Nonnull SocketAddress remoteAddress, @Nonnull ByteBuffer buf) {
//         TftpOpcode opcode = TftpOpcode.forCode(buf.getShort());
//         TftpPacket packet;
//         switch (opcode) {
//             case RRQ:
//                 packet = new TftpReadRequestPacket();
//                 break;
//             case WRQ:
//                 packet = new TftpWriteRequestPacket();
//                 break;
//             case DATA:
//                 packet = new TftpDataPacket();
//                 break;
//             case ACK:
//                 packet = new TftpAckPacket();
//                 break;
//             case ERROR:
//                 packet = new TftpErrorPacket();
//                 break;
//             case ACK_WITH_OPTIONS:
//             default:
//                 throw new IllegalStateException("Unknown TftpOpcode in decoder: " + opcode);
//         }
//         packet.setRemoteAddress(remoteAddress);
//         packet.fromWire(buf);
//         if (buf.position() < buf.limit()) {
//             LOG.warn("Discarded " + (buf.limit() - buf.position()) + " trailing bytes in TFTP packet: " + buf);
//             buf.position(buf.limit());
//         }
//         return packet;
//     }
// }
// 
// 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();
//     }
// }


import java.io.IOException;
import javax.annotation.Nonnull;
import org.anarres.tftp.protocol.codec.TftpPacketDecoder;
import org.anarres.tftp.protocol.packet.TftpPacket;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.anarres.tftp.server.mina;


/**
 *
 * @author shevek
 */
public class TftpProtocolCodecFactory implements ProtocolCodecFactory {

    private static TftpProtocolCodecFactory INSTANCE = new TftpProtocolCodecFactory();

    /**
     * Returns the singleton instance of {@link TftpProtocolCodecFactory}.
     *
     * @return The singleton instance of {@link TftpProtocolCodecFactory}.
     */
    @Nonnull
    public static TftpProtocolCodecFactory getInstance() {
        return INSTANCE;
    }

    private static class TftpEncoder implements ProtocolEncoder {

        public static final TftpEncoder INSTANCE = new TftpEncoder();

        @Override
        public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws IOException {
// Path: tftp-protocol/src/main/java/org/anarres/tftp/protocol/codec/TftpPacketDecoder.java
// public class TftpPacketDecoder {
// 
//     private static final Logger LOG = LoggerFactory.getLogger(TftpPacketDecoder.class);
// 
//     @Nonnull
//     public TftpPacket decode(@Nonnull SocketAddress remoteAddress, @Nonnull ByteBuffer buf) {
//         TftpOpcode opcode = TftpOpcode.forCode(buf.getShort());
//         TftpPacket packet;
//         switch (opcode) {
//             case RRQ:
//                 packet = new TftpReadRequestPacket();
//                 break;
//             case WRQ:
//                 packet = new TftpWriteRequestPacket();
//                 break;
//             case DATA:
//                 packet = new TftpDataPacket();
//                 break;
//             case ACK:
//                 packet = new TftpAckPacket();
//                 break;
//             case ERROR:
//                 packet = new TftpErrorPacket();
//                 break;
//             case ACK_WITH_OPTIONS:
//             default:
//                 throw new IllegalStateException("Unknown TftpOpcode in decoder: " + opcode);
//         }
//         packet.setRemoteAddress(remoteAddress);
//         packet.fromWire(buf);
//         if (buf.position() < buf.limit()) {
//             LOG.warn("Discarded " + (buf.limit() - buf.position()) + " trailing bytes in TFTP packet: " + buf);
//             buf.position(buf.limit());
//         }
//         return packet;
//     }
// }
// 
// 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-server-mina/src/main/java/org/anarres/tftp/server/mina/TftpProtocolCodecFactory.java
import java.io.IOException;
import javax.annotation.Nonnull;
import org.anarres.tftp.protocol.codec.TftpPacketDecoder;
import org.anarres.tftp.protocol.packet.TftpPacket;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

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


/**
 *
 * @author shevek
 */
public class TftpProtocolCodecFactory implements ProtocolCodecFactory {

    private static TftpProtocolCodecFactory INSTANCE = new TftpProtocolCodecFactory();

    /**
     * Returns the singleton instance of {@link TftpProtocolCodecFactory}.
     *
     * @return The singleton instance of {@link TftpProtocolCodecFactory}.
     */
    @Nonnull
    public static TftpProtocolCodecFactory getInstance() {
        return INSTANCE;
    }

    private static class TftpEncoder implements ProtocolEncoder {

        public static final TftpEncoder INSTANCE = new TftpEncoder();

        @Override
        public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws IOException {
            TftpPacket packet = (TftpPacket) message;