TFTP Server not allowing data transfer
Hi all, my TFTP server I want to use as a template will not alllow me to send or recieve data. Any advice would be great as I don't know if its possibly a folder access problem on my PC. Here is the code:
Code :
public class TFTPS {
/**
* @param args the command line arguments
*/
// TODO code application logic here
public static final int tftpRRQ=1;
public static final int tftpWRQ=2;
public static final int tftpDATA=3;
public static final int tftpACK=4;
public static final int tftpERROR=5;
public static final int maxTftpPakLen=516;
public static void main(String argv[]) {
int port = 69;
try {
DatagramSocket sock = new DatagramSocket(port);
System.out.println("Server Ready. Listening on port: "+sock.getLocalPort());
for(;;) {
UdpData reqData = new UdpData(maxTftpPakLen);
DatagramPacket reqPak = reqData.mkPacket();
sock.receive(reqPak);
if (reqData.getInt(0)==tftpRRQ) {
System.out.println("Request from "+reqPak.getAddress());
tftpTransfer t = new tftpTransfer(reqPak);
}
}
}
catch(Exception e) { System.out.println("Server terminated"); }
}
}
Code :
class UdpData {
private byte data[];
public UdpData(int len) { data = new byte[len]; };
public UdpData(DatagramPacket pack) { data = pack.getData(); }
public byte[] getData() { return data; };
public int length() { return data.length; };
public DatagramPacket mkPacket() { return new DatagramPacket(data,data.length); };
public DatagramPacket mkPacket(int len) { return new DatagramPacket(data,len); };
public DatagramPacket mkPacket(InetAddress dest, int port) {
return new DatagramPacket(data,data.length,dest,port);
};
public DatagramPacket mkPacket(InetAddress dest, int port, int len) {
return new DatagramPacket(data,len,dest,port);
};
public int getInt(int offset) {
// Fix to avoid sign extension
// Remember what the MSB is and then turn it off to avoid sign extension. It is
// then added back to the sum after everything has been converted to integers.
byte lo = data[offset+1];
int signBit = (int)(lo&0x80);
lo&=0x7f;
// Standard TCP/IP byte order is hiByte followed by loByte (big endian)
int hiByte = (int)data[offset];
int loByte = (int)lo;
return (hiByte<<8)+signBit+loByte;
};
public void putInt(int val, int offset) {
int loByte = val%256;
int hiByte = val>>>8;
// Standard TCP/IP byte order is hiByte followed by loByte (big endian)
data[offset] = (byte)hiByte;
data[offset+1] = (byte)loByte;
};
public String getString(int offset) {
StringBuffer strBuf = new StringBuffer();
int curPos = offset;
while (data[curPos]!=0) {
strBuf.append((char)data[curPos]);
curPos++;
}
return new String(strBuf);
};
public void putString(String str, int offset) {
str.getBytes(0,str.length(),data,offset);
data[offset+str.length()]=0;
};
}
Code :
class tftpTransfer {
protected DatagramSocket sock;
protected InetAddress clientIP;
protected int clientPort;
protected FileInputStream source;
protected UdpData dataPak;
public tftpTransfer(DatagramPacket reqPak) {
try {
sock = new DatagramSocket();
clientIP = reqPak.getAddress();
clientPort = reqPak.getPort();
UdpData reqData = new UdpData(reqPak);
File srcFile = new File(reqData.getString(2));
if (srcFile.exists() && srcFile.isFile() && srcFile.canRead()) {
source = new FileInputStream(srcFile);
dataPak = new UdpData(516); // 516==max pak len
dataPak.putInt(3,0); // 3==DATA opcode
this.start(); //This also seems to be an isssue
}
} catch (Exception e) { System.out.println("Client failed"); };
}
public void run() {
int bytesRead = 512;
DatagramPacket ack = new DatagramPacket(new byte[4],4);
try {
for (int blkNum=0; bytesRead==512; blkNum++) { // 512==max data len
dataPak.putInt(blkNum,2);
bytesRead = source.read(dataPak.getData(),4,512);
sock.send(dataPak.mkPacket(clientIP,clientPort,516)); // 516==max data len + header
sock.receive(ack);
}
} catch (Exception e) { System.out.println("Client failed"); }
try {
source.close();
sock.close();
} catch (Exception e) {};
}
}
I have had a few late nights (5am) trying to solve this, to no avail so I have decided to seek advice.
Re: TFTP Server not allowing data transfer
Are there error messages when it "not alllow me to send or recieve data"?
Is the code executing the parts that would send or receive data?
Have you tried debugging the code to see what it does when it executes? Add some printlns to show the execution flow and the values of variables that are used.
Be SURE to add calls to printStackTrace to all the catch blocks so you get the full text and location of any errors.
The posted code will not compile. The main problem is there are no import statements. Please fix the code so it will compile if you want help testing it.
Re: TFTP Server not allowing data transfer
I have used WireShark while connecting with a client but all it shows is the client requesting a "Write Request", the server just does not respond, resulting in the client timing out. The server and WireShark report no errors. I have tried debugging, but this was little help as I have not used this tool very much. I just did some print lines and it seems to be a problem with the tftpTransfer class. Thanks for that advice.
Re: TFTP Server not allowing data transfer
The posted code will not compile. The main problem is there are no import statements. Please fix the code so it will compile if you want help testing it.
Quote:
it seems to be a problem with the tftpTransfer class.
Can you be more specific? What happens in that class that makes you think there is a problem?
Re: TFTP Server not allowing data transfer
Did some more debugging the server is getting to here:
Code :
public int getInt(int offset) {
System.out.println("Getting to GetInt");
// Fix to avoid sign extension
// Remember what the MSB is and then turn it off to avoid sign extension. It is
// then added back to the sum after everything has been converted to integers.
byte lo = data[offset+1];
int signBit = (int)(lo&0x80);
lo&=0x7f;
// Standard TCP/IP byte order is hiByte followed by loByte (big endian)
int hiByte = (int)data[offset];
int loByte = (int)lo;
return (hiByte<<8)+signBit+loByte;
};
public void putInt(int val, int offset) {
int loByte = val%256;
int hiByte = val>>>8;
// Standard TCP/IP byte order is hiByte followed by loByte (big endian)
data[offset] = (byte)hiByte;
data[offset+1] = (byte)loByte;
};
public String getString(int offset) {
StringBuffer strBuf = new StringBuffer();
int curPos = offset;
while (data[curPos]!=0) {
strBuf.append((char)data[curPos]);
curPos++;
}
return new String(strBuf);
};
public void putString(String str, int offset) {
str.getBytes(0,str.length(),data,offset);
data[offset+str.length()]=0;
};
}
Then timing out. with the following displayed at the command line:
Server Ready. Listening on port: 69
Getting to GetInt
Getting to GetInt
Getting to GetInt
Getting to GetInt
Getting to GetInt
This is in the UdpData class, so the problem could be here, also this line
Code :
str.getBytes(0,str.length(),data,offset);
is showing in my code with a line through "getBytes" anychance this could be the cause.
Re: TFTP Server not allowing data transfer
Sorry Here is full code:
Code :
package tftps;
import java.net.*;
import java.io.*;
import java.util.*;
/**
*
* @author Error1
*/
public class TFTPS {
/**
* @param args the command line arguments
*/
// TODO code application logic here
public static final int tftpRRQ=1;
public static final int tftpWRQ=2;
public static final int tftpDATA=3;
public static final int tftpACK=4;
public static final int tftpERROR=5;
public static final int maxTftpPakLen=516;
public static void main(String argv[]) {
int port = 69;
try {
DatagramSocket sock = new DatagramSocket(port);
System.out.println("Server Ready. Listening on port: "+sock.getLocalPort());
for(;;) {
UdpData reqData = new UdpData(maxTftpPakLen);
DatagramPacket reqPak = reqData.mkPacket();
sock.receive(reqPak);
if (reqData.getInt(0)==tftpRRQ) {
System.out.println("Request from "+reqPak.getAddress());
tftpTransfer t = new tftpTransfer(reqPak);
}
}
}
catch(Exception e) { System.out.println("Server terminated"); }
}
}
Code :
package tftps;
import java.net.*;
import java.io.*;
import java.util.*;
/**
*
* @author Error1
*/
class UdpData {
private byte data[];
public UdpData(int len) { data = new byte[len]; };
public UdpData(DatagramPacket pack) { data = pack.getData(); }
public byte[] getData() { return data; };
public int length() { return data.length; };
public DatagramPacket mkPacket() { return new DatagramPacket(data,data.length); };
public DatagramPacket mkPacket(int len) { return new DatagramPacket(data,len); };
public DatagramPacket mkPacket(InetAddress dest, int port) {
return new DatagramPacket(data,data.length,dest,port);
};
public DatagramPacket mkPacket(InetAddress dest, int port, int len) {
return new DatagramPacket(data,len,dest,port);
};
public int getInt(int offset) {
System.out.println("Getting to GetInt");
// Fix to avoid sign extension
// Remember what the MSB is and then turn it off to avoid sign extension. It is
// then added back to the sum after everything has been converted to integers.
byte lo = data[offset+1];
int signBit = (int)(lo&0x80);
lo&=0x7f;
// Standard TCP/IP byte order is hiByte followed by loByte (big endian)
int hiByte = (int)data[offset];
int loByte = (int)lo;
return (hiByte<<8)+signBit+loByte;
};
public void putInt(int val, int offset) {
int loByte = val%256;
int hiByte = val>>>8;
// Standard TCP/IP byte order is hiByte followed by loByte (big endian)
data[offset] = (byte)hiByte;
data[offset+1] = (byte)loByte;
};
public String getString(int offset) {
StringBuffer strBuf = new StringBuffer();
int curPos = offset;
while (data[curPos]!=0) {
strBuf.append((char)data[curPos]);
curPos++;
}
return new String(strBuf);
};
public void putString(String str, int offset) {
str.getBytes(0,str.length(),data,offset);
data[offset+str.length()]=0;
};
}
Code :
package tftps;
import java.net.*;
import java.io.*;
import java.util.*;
/**
*
* @author Error1
*/
class tftpTransfer {
protected DatagramSocket sock;
protected InetAddress clientIP;
protected int clientPort;
protected FileInputStream source;
protected UdpData dataPak;
public tftpTransfer(DatagramPacket reqPak) {
System.out.println("Getting to reqPak");
try {
sock = new DatagramSocket();
clientIP = reqPak.getAddress();
clientPort = reqPak.getPort();
UdpData reqData = new UdpData(reqPak);
File srcFile = new File(reqData.getString(2));
if (srcFile.exists() && srcFile.isFile() && srcFile.canRead()) {
source = new FileInputStream(srcFile);
dataPak = new UdpData(516); // 516==max pak len
dataPak.putInt(3,0); // 3==DATA opcode
}
} catch (Exception e) { System.out.println("Client failed"); };
}
public void run() {
System.out.println("Getting run");
int bytesRead = 512;
DatagramPacket ack = new DatagramPacket(new byte[4],4);
try {
for (int blkNum=0; bytesRead==512; blkNum++) { // 512==max data len
dataPak.putInt(blkNum,2);
bytesRead = source.read(dataPak.getData(),4,512);
sock.send(dataPak.mkPacket(clientIP,clientPort,516)); // 516==max data len + header
sock.receive(ack);
}
} catch (Exception e) { System.out.println("Client failed"); }
try {
source.close();
sock.close();
} catch (Exception e) {};
}
}
Re: TFTP Server not allowing data transfer
I have no idea what "a line through" means.
What are the values of all the variables used in that statement?
What does that print out tell you? Is that what you expect to see when the code executes?
The TftpTransfer class you first posted does not compile without errors.
You have a comment on the statement with the error.
There is no way to execute it when it has errors on my system.
Which classes did you make source changes to for the second post?
Re: TFTP Server not allowing data transfer
No the print out is just a println I placed there as a debug. This shows that the server gets the clients request but it goes no further.
Re: TFTP Server not allowing data transfer
How can I test it? Do you have a client program that goes with it?
Re: TFTP Server not allowing data transfer
Its just a stand alone server so I have been using Tftpd32 App TFTPD32 : an opensource IPv6 ready TFTP server/service for windows : TFTP server , to connect to the server this running on a Virtual Machine, I have also tested it using a Cisco router to back up the routers configuration files none of which worked. Though I keep getting access denied error when I try to do this on my all on the same PC, i.e. client and server.
Re: TFTP Server not allowing data transfer
As well as command line prompt.
Re: TFTP Server not allowing data transfer
I have to go to work now, so any more advice would be mostly appreciated and I will reply to any questions later.
Re: TFTP Server not allowing data transfer
I have no client code for testing the server.
Re: TFTP Server not allowing data transfer
Found this client code if it helps:
Code :
package tftpclient;
import java.net.*;
import java.io.*;
import java.util.*;
/**
*
* @author Error1
*/
public class TftpClient {
public static void main(String argv[]) {
String host="",fileName="",line;
int replyLen,blockNum = 0;
try {
// Process command line args.....
InetAddress server = InetAddress.getByName(host);
DatagramSocket sock = new DatagramSocket();
FileOutputStream outFile = new FileOutputStream(fileName);
// Create the request packet and send it off
UdpData reqData = new UdpData(4+fileName.length()+5); // 5==len("octet")
reqData.putInt(1,0); // RREQ opcode
reqData.putString(fileName,2); // Requested file
reqData.putString("octet",2+fileName.length()+1); // Trans mode
DatagramPacket pack = reqData.mkPacket(server,69); // 69==TFTP port
sock.send(pack);
// Create the ACK packet
UdpData ackData = new UdpData(4);
ackData.putInt(4,0); // ACK opcode
DatagramPacket ackPack = ackData.mkPacket(server,69);
// Create a packet to receive the data
UdpData recData = new UdpData(516); // 516==max pak len
pack = recData.mkPacket();
for(int pakLen=516; pakLen==516; ) {
sock.receive(pack);
pakLen=pack.getLength();
if (recData.getInt(0)==3) { // If a DATA pak then... blockNum=recData.getInt(2);
outFile.write(recData.getData(),4,pakLen-4);
ackData.putInt(blockNum,2);
ackPack = ackData.mkPacket(server,pack.getPort());
sock.send(ackPack);
}
else
throw new Exception();
};
outFile.close();
sock.close();
}
catch (Exception e) { System.out.println("tftp session failed"); }
}
}
Code :
package tftpclient;
import java.net.*;
import java.io.*;
import java.util.*;
/**
*
* @author Error1
*/
class UdpData {
private byte data[];
public UdpData(int len) { data = new byte[len]; };
public UdpData(DatagramPacket pack) { data = pack.getData(); }
public byte[] getData() { return data; };
public int length() { return data.length; };
public DatagramPacket mkPacket() { return new DatagramPacket(data,data.length); };
public DatagramPacket mkPacket(int len) { return new DatagramPacket(data,len); };
public DatagramPacket mkPacket(InetAddress dest, int port) {
return new DatagramPacket(data,data.length,dest,port);
};
public DatagramPacket mkPacket(InetAddress dest, int port, int len) {
return new DatagramPacket(data,len,dest,port);
};
public int getInt(int offset) {
System.out.println("Getting to getInt ");
// Fix to avoid sign extension
// Remember what the MSB is and then turn it off to avoid sign extension. It is
// then added back to the sum after everything has been converted to integers.
byte lo = data[offset+1];
int signBit = (int)(lo&0x80);
lo&=0x7f;
// Standard TCP/IP byte order is hiByte followed by loByte (big endian)
int hiByte = (int)data[offset];
int loByte = (int)lo;
return (hiByte<<8)+signBit+loByte;
};
public void putInt(int val, int offset) {
int loByte = val%256;
int hiByte = val>>>8;
// Standard TCP/IP byte order is hiByte followed by loByte (big endian)
data[offset] = (byte)hiByte;
data[offset+1] = (byte)loByte;
};
public String getString(int offset) {
StringBuffer strBuf = new StringBuffer();
int curPos = offset;
while (data[curPos]!=0) {
strBuf.append((char)data[curPos]);
curPos++;
}
return new String(strBuf);
};
public void putString(String str, int offset) {
str.getBytes(0,str.length(),data,offset);
data[offset+str.length()]=0;
};
}
Which when used displays:
Server Ready. Listening on port: 69
Getting to
Getting to
Getting to
Getting to
Getting to
Getting to
Request from /30.0.0.2
Getting to reqPak
Getting to sourcefile
At the command prompt. It will not do this with any other client.
Re: TFTP Server not allowing data transfer
What does the display show? Is it working or not?
Re: TFTP Server not allowing data transfer
Sorry for the delay in answering your questions, it seems to partially work when connecting to the server using a client (code above) that came as part of this server template. But it still will not work using a standard TFTP client i.e. command line etc. I understand its hard to test without some form of network. I have a network at home for my Cisco studies so I am able to do this.
Re: TFTP Server not allowing data transfer
What is a "standard TFTP client"?
How is its protocol different from the client code you posted?
Re: TFTP Server not allowing data transfer
I need this server to work with the TFTP clients that are coded into routers and switches opperating systems, also with the Windows 7 built in TFTP client that runs from the command line. I just can't understand why it will not transfer data even though its looping through the code. I have specified file to transfer on the client to the server, the server responds to connection but I am still getting a time out on the client and no file is transferred. Its all good fun but!
Re: TFTP Server not allowing data transfer
What is the difference between the protocol the posted code has and that of the other TFTP client programs you want to use?
Quote:
the server responds to connection but I am still getting a time out on the client
Add printlns to show everything that the server does.
One thing I noticed with the code you posted was that the code did not consider reducing the number of bytes sent if they were less than 512. It sent a block of data padded with binary 0s, instead of reducing the buffer to the number of bytes being sent.
Re: TFTP Server not allowing data transfer
Yes I think I will be spending a few more late nights trying to solve this. But I will add some additional printlns and see what it shows.