Question

I am programming a tftp client and it works just fine, as long as i use default block size (512). But since it is a school assignment, i need to test it also with a block size of 1430 and 4300.

When i first comunicate with the server, i use this method:

public void setFilename( String s, String mode) {
        byte []a = s.getBytes();
        int i,j,k;
        for ( i=0; i+2<lenght && i<a.length; i++ ) {
            packet[i+2] = a[i];
        }
        packet[i+2] = 0;
        a = mode.getBytes();
        for ( j=0,i++; i<lenght && j<a.length; i++,j++ ) {
            packet[i+2] = a[j];
        }
        packet[i+2] = 0;


    }

It will set the filename i want to read. and it works just fine.

But i've changed it so i can define a block size:

public void setFilename( String s, String mode, String blockSize ) {
        byte []a = s.getBytes();
        int i,j,k;
        for ( i=0; i+2<lenght && i<a.length; i++ ) {
            packet[i+2] = a[i];
        }
        packet[i+2] = 0;
        a = mode.getBytes();
        for ( j=0,i++; i<lenght && j<a.length; i++,j++ ) {
            packet[i+2] = a[j];
        }
        packet[i+2] = 0;

        a = BLOCKSIZE.getBytes();
        for ( k=0,i++; i<lenght && k<a.length; i++,k++ ) {
            packet[i+2] = a[k];
        }
        packet[i+2] = 0;

        a = blockSize.getBytes();
        for ( k=0,i++; i<lenght && k<a.length; i++,k++ ) {
            packet[i+2] = a[k];
        }
        packet[i+2] = 0;

    }

and here BLOCKSIZE = "blksize" (string) and blockSize = 1430 (int); The problem is, it doesn't work :-/

Can somebody please explain to me how can i define the block size?

Thank you guys :-)

Was it helpful?

Solution

The problem was in the reading part and not here. Here is the complete code for building a packet if anyone is interested :-)

/** *

 * TftpPacket - look at a byte array as a tftp packet.
 *
 * 

Message format according to the TFTP protocol (rfc 1350, 2347). *

Note: this implementation assumes that all JAva Strings used only contain * ASCII characters. If it's not so, lenght() and getBytes() return different values * and unexpected problems can appear ...

*tftp request packet * 2 bytes string 1 byte string 1 byte optional options (strings) * -----------------------------------------+ - - - + - + - - - + - + -> *RRQ/WRQ | 01/02 | Filename | 0 | Mode | 0 | opt1 | 0 | value1| 0 | ... * -----------------------------------------+ - - - + - + - - - + - + -> * Modes (ascii chars/1 byte each): * "netascii", "octet",... * * 2 bytes 2 bytes n bytes * --------------------------------- *DATA | 03 | Block # | Data | * --------------------------------- * 2 bytes 2 bytes * ------------------- *ACK | 04 | Block # | * -------------------- * 2 bytes 2 bytes string 1 byte * ---------------------------------------- *ERROR | 05 | ErrorCode | ErrMsg | 0 | * ---------------------------------------- * Error Codes: * 0 Not defined, see error message (if any). * 1 File not found. * 2 Access violation. * 3 Disk full or allocation exceeded. * 4 Illegal TFTP operation. * 5 Unknown transfer ID. * 6 File already exists. * 7 No such user. *

*/

public class TftpPacket {

// Opcodes
protected static final short RRQ=1;
protected static final short WRQ=2;
protected static final short DATA=3;
protected static final short ACK=4;
protected static final short ERROR=5;
protected static final String BLOCKSIZE = "blksize";

byte []packet;
int lenght;

/**
 *  Builds a view to a byte array as a tftp packet.
 *  The original byte array is the one manipulated by all methods
 */
public TftpPacket( byte []data, int len ) {
    packet = data;
    lenght = len;
}

/**
 *  Gets number at first two bytes of packet
 */
public int getOpcode() {
    return (packet[0]<<8)|(packet[1]&0xff);  //net byte order = Big-Endian
}

/**
 *  Sets first two bytes of packet
 */
public void setOpcode(int code) {
    packet[0] = (byte) ((code>>8)&0xff);
    packet[1] = (byte) (code&0xff);
}

/**
 *  Gets string starting at byte 2
 */
public String getFileName() {
    int i;
    for ( i=2; i<lenght; i++ )
        if (packet[i]==0) //end of string
            return new String(packet, 2, i-2);
    return null;
}

/**
 *  Sets two strings (NUL terminated) starting at byte 2
 */
public void setFilename( String s, String mode, String blockSize ) {
    byte []a = s.getBytes();
    int i,j,k;
    for ( i=0; i+2<lenght && i<a.length; i++ ) {
        packet[i+2] = a[i];
    }
    packet[i+2] = 0;
    a = mode.getBytes();
    for ( j=0,i++; i<lenght && j<a.length; i++,j++ ) {
        packet[i+2] = a[j];
    }
    packet[i+2] = 0;

    a = BLOCKSIZE.getBytes();
    for ( k=0,i++; i<lenght && k<a.length; i++,k++ ) {
        packet[i+2] = a[k];
    }
    packet[i+2] = 0;

    a = blockSize.getBytes();
    for ( k=0,i++; i<lenght && k<a.length; i++,k++ ) {
        packet[i+2] = a[k];
    }
    packet[i+2] = 0;

}

/**
 *  Gets second string in packet
 */
public String getMode(){
    for ( int i=2; i<lenght; i++ )
        if (packet[i]==0) { //end of 1st string
            for ( int j=i+2; j<lenght; j++ )
                if ( packet[j]==0 ) return new String(packet, i+1, j-i-1);
        }
    return null; 
}

/**
 *  Gets number at bytes 2 and 3 of packet (can be block count or error code)
 */
public int getBlockCount() {
    return (packet[2]<<8)|(packet[3]&0xff);  //net byte order = Big-Endian
}

/**
 *  Sets bytes 2 and 3 of packet (can be block count or error code)
 */
public void setBlockCount(int count) {
    packet[2] = (byte) ((count>>8)&0xff);
    packet[3] = (byte) (count&0xff);
}

/**
 *  Sets string (NUL-terminated) starting at byte 4
 */
public void setErrMsg( String s ) {
    byte []a = s.getBytes();
    int i;
    for ( i=0; i<a.length; i++ ) {
        packet[i+4] = a[i];
    }
    packet[i+4] = 0;
}

}

OTHER TIPS

I recommend you using Wireshark and see how the packet gets conformed and sent to the wire. that way you can very quickly spot any problem when assembling your TFTP protocol in you code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top