This is a simple but complete TFTP server, It can receive and send files and listens on port 69. It is part of the LaOS (Laser Open Source) project: http://www.laoslaser.org/

Dependents:   TFTPServerTest RMFWeb

Committer:
tuxic
Date:
Mon Dec 26 18:18:32 2011 +0000
Revision:
0:3b0027b76acf
First version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tuxic 0:3b0027b76acf 1 /*
tuxic 0:3b0027b76acf 2 * TFTPServer.cpp
tuxic 0:3b0027b76acf 3 * Simple TFTP server
tuxic 0:3b0027b76acf 4 *
tuxic 0:3b0027b76acf 5 * Copyright (c) 2011 Jaap Vermaas
tuxic 0:3b0027b76acf 6 *
tuxic 0:3b0027b76acf 7 * This file is part of the LaOS project (see: http://wiki.laoslaser.org)
tuxic 0:3b0027b76acf 8 *
tuxic 0:3b0027b76acf 9 * LaOS is free software: you can redistribute it and/or modify
tuxic 0:3b0027b76acf 10 * it under the terms of the GNU General Public License as published by
tuxic 0:3b0027b76acf 11 * the Free Software Foundation, either version 3 of the License, or
tuxic 0:3b0027b76acf 12 * (at your option) any later version.
tuxic 0:3b0027b76acf 13 *
tuxic 0:3b0027b76acf 14 * LaOS is distributed in the hope that it will be useful,
tuxic 0:3b0027b76acf 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
tuxic 0:3b0027b76acf 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
tuxic 0:3b0027b76acf 17 * GNU General Public License for more details.
tuxic 0:3b0027b76acf 18 *
tuxic 0:3b0027b76acf 19 * You should have received a copy of the GNU General Public License
tuxic 0:3b0027b76acf 20 * along with LaOS. If not, see <http://www.gnu.org/licenses/>.
tuxic 0:3b0027b76acf 21 *
tuxic 0:3b0027b76acf 22 */
tuxic 0:3b0027b76acf 23 #include "TFTPServer.h"
tuxic 0:3b0027b76acf 24
tuxic 0:3b0027b76acf 25 // create a new tftp server, with file directory dir and
tuxic 0:3b0027b76acf 26 // listening on port
tuxic 0:3b0027b76acf 27 TFTPServer::TFTPServer(char* dir) {
tuxic 0:3b0027b76acf 28 ListenSock = new UDPSocket();
tuxic 0:3b0027b76acf 29 ListenSock->setOnEvent(this, &TFTPServer::onListenUDPSocketEvent);
tuxic 0:3b0027b76acf 30 state = listen;
tuxic 0:3b0027b76acf 31 if (ListenSock->bind(Host(IpAddr(), TFTP_PORT)))
tuxic 0:3b0027b76acf 32 state = error;
tuxic 0:3b0027b76acf 33 TFTPServerTimer.attach(this, &TFTPServer::cleanUp, 5000);
tuxic 0:3b0027b76acf 34 sprintf(workdir, "%s", dir);
tuxic 0:3b0027b76acf 35 filecnt = 0;
tuxic 0:3b0027b76acf 36 }
tuxic 0:3b0027b76acf 37
tuxic 0:3b0027b76acf 38 // destroy this instance of the tftp server
tuxic 0:3b0027b76acf 39 TFTPServer::~TFTPServer() {
tuxic 0:3b0027b76acf 40 ListenSock->resetOnEvent();
tuxic 0:3b0027b76acf 41 delete(ListenSock);
tuxic 0:3b0027b76acf 42 delete(remote);
tuxic 0:3b0027b76acf 43 state = deleted;
tuxic 0:3b0027b76acf 44 }
tuxic 0:3b0027b76acf 45
tuxic 0:3b0027b76acf 46 void TFTPServer::reset() {
tuxic 0:3b0027b76acf 47 ListenSock->resetOnEvent();
tuxic 0:3b0027b76acf 48 delete(ListenSock);
tuxic 0:3b0027b76acf 49 delete(remote);
tuxic 0:3b0027b76acf 50 TFTPServerTimer.detach();
tuxic 0:3b0027b76acf 51 ListenSock = new UDPSocket();
tuxic 0:3b0027b76acf 52 ListenSock->setOnEvent(this, &TFTPServer::onListenUDPSocketEvent);
tuxic 0:3b0027b76acf 53 state = listen;
tuxic 0:3b0027b76acf 54 if (ListenSock->bind(Host(IpAddr(), TFTP_PORT)))
tuxic 0:3b0027b76acf 55 state = error;
tuxic 0:3b0027b76acf 56 TFTPServerTimer.attach(this, &TFTPServer::cleanUp, 5000);
tuxic 0:3b0027b76acf 57 sprintf(filename, "");
tuxic 0:3b0027b76acf 58 filecnt = 0;
tuxic 0:3b0027b76acf 59 }
tuxic 0:3b0027b76acf 60
tuxic 0:3b0027b76acf 61 // get current tftp status
tuxic 0:3b0027b76acf 62 TFTPServerState TFTPServer::State() {
tuxic 0:3b0027b76acf 63 return state;
tuxic 0:3b0027b76acf 64 }
tuxic 0:3b0027b76acf 65
tuxic 0:3b0027b76acf 66 // Temporarily disable incoming TFTP connections
tuxic 0:3b0027b76acf 67 void TFTPServer::suspend() {
tuxic 0:3b0027b76acf 68 state = suspended;
tuxic 0:3b0027b76acf 69 }
tuxic 0:3b0027b76acf 70
tuxic 0:3b0027b76acf 71 // Resume after suspension
tuxic 0:3b0027b76acf 72 void TFTPServer::resume() {
tuxic 0:3b0027b76acf 73 if (state == suspended)
tuxic 0:3b0027b76acf 74 state = listen;
tuxic 0:3b0027b76acf 75 }
tuxic 0:3b0027b76acf 76
tuxic 0:3b0027b76acf 77 // During read and write, this gives you the filename
tuxic 0:3b0027b76acf 78 void TFTPServer::getFilename(char* name) {
tuxic 0:3b0027b76acf 79 sprintf(name, "%s", filename);
tuxic 0:3b0027b76acf 80 }
tuxic 0:3b0027b76acf 81
tuxic 0:3b0027b76acf 82 // return number of received files
tuxic 0:3b0027b76acf 83 int TFTPServer::fileCnt() {
tuxic 0:3b0027b76acf 84 return filecnt;
tuxic 0:3b0027b76acf 85 }
tuxic 0:3b0027b76acf 86
tuxic 0:3b0027b76acf 87 // create a new connection reading a file from server
tuxic 0:3b0027b76acf 88 void TFTPServer::ConnectRead(char* buff, Host* client) {
tuxic 0:3b0027b76acf 89 IpAddr clientIp = client->getIp();
tuxic 0:3b0027b76acf 90 int clientPort = client->getPort();
tuxic 0:3b0027b76acf 91 remote = new Host(clientIp, clientPort);
tuxic 0:3b0027b76acf 92 Ack(0);
tuxic 0:3b0027b76acf 93 blockcnt = 0;
tuxic 0:3b0027b76acf 94 dupcnt = 0;
tuxic 0:3b0027b76acf 95
tuxic 0:3b0027b76acf 96 sprintf(filename, "%s%s", workdir, &buff[2]);
tuxic 0:3b0027b76acf 97
tuxic 0:3b0027b76acf 98 fp = fopen(filename, "rb");
tuxic 0:3b0027b76acf 99 if (fp == NULL) {
tuxic 0:3b0027b76acf 100 state = listen;
tuxic 0:3b0027b76acf 101 delete(remote);
tuxic 0:3b0027b76acf 102 Err("Could not read file", client);
tuxic 0:3b0027b76acf 103 } else {
tuxic 0:3b0027b76acf 104 // file ready for reading
tuxic 0:3b0027b76acf 105 blockcnt = 0;
tuxic 0:3b0027b76acf 106 state = reading;
tuxic 0:3b0027b76acf 107 #ifdef TFTP_DEBUG
tuxic 0:3b0027b76acf 108 char debugmsg[256];
tuxic 0:3b0027b76acf 109 sprintf(debugmsg, "Listen: Requested file %s from TFTP connection %d.%d.%d.%d port %d",
tuxic 0:3b0027b76acf 110 filename, clientIp[0], clientIp[1], clientIp[2], clientIp[3], clientPort);
tuxic 0:3b0027b76acf 111 TFTP_DEBUG(debugmsg);
tuxic 0:3b0027b76acf 112 #endif
tuxic 0:3b0027b76acf 113 getBlock();
tuxic 0:3b0027b76acf 114 sendBlock();
tuxic 0:3b0027b76acf 115 }
tuxic 0:3b0027b76acf 116 }
tuxic 0:3b0027b76acf 117
tuxic 0:3b0027b76acf 118 // create a new connection writing a file to the server
tuxic 0:3b0027b76acf 119 void TFTPServer::ConnectWrite(char* buff, Host* client) {
tuxic 0:3b0027b76acf 120 IpAddr clientIp = client->getIp();
tuxic 0:3b0027b76acf 121 int clientPort = client->getPort();
tuxic 0:3b0027b76acf 122 remote = new Host(clientIp, clientPort);
tuxic 0:3b0027b76acf 123 Ack(0);
tuxic 0:3b0027b76acf 124 blockcnt = 0;
tuxic 0:3b0027b76acf 125 dupcnt = 0;
tuxic 0:3b0027b76acf 126
tuxic 0:3b0027b76acf 127 sprintf(filename, "%s%s", workdir, &buff[2]);
tuxic 0:3b0027b76acf 128
tuxic 0:3b0027b76acf 129 fp = fopen(filename, "wb");
tuxic 0:3b0027b76acf 130 if (fp == NULL) {
tuxic 0:3b0027b76acf 131 Err("Could not open file to write", client);
tuxic 0:3b0027b76acf 132 state = listen;
tuxic 0:3b0027b76acf 133 delete(remote);
tuxic 0:3b0027b76acf 134 } else {
tuxic 0:3b0027b76acf 135 // file ready for writing
tuxic 0:3b0027b76acf 136 blockcnt = 0;
tuxic 0:3b0027b76acf 137 state = writing;
tuxic 0:3b0027b76acf 138 #ifdef TFTP_DEBUG
tuxic 0:3b0027b76acf 139 char debugmsg[256];
tuxic 0:3b0027b76acf 140 sprintf(debugmsg, "Listen: Incoming file %s on TFTP connection from %d.%d.%d.%d clientPort %d",
tuxic 0:3b0027b76acf 141 filename, clientIp[0], clientIp[1], clientIp[2], clientIp[3], clientPort);
tuxic 0:3b0027b76acf 142 TFTP_DEBUG(debugmsg);
tuxic 0:3b0027b76acf 143 #endif
tuxic 0:3b0027b76acf 144 }
tuxic 0:3b0027b76acf 145 }
tuxic 0:3b0027b76acf 146
tuxic 0:3b0027b76acf 147 // get DATA block from file on disk into memory
tuxic 0:3b0027b76acf 148 void TFTPServer::getBlock() {
tuxic 0:3b0027b76acf 149 blockcnt++;
tuxic 0:3b0027b76acf 150 char *p;
tuxic 0:3b0027b76acf 151 p = &sendbuff[4];
tuxic 0:3b0027b76acf 152 int len = fread(p, 1, 512, fp);
tuxic 0:3b0027b76acf 153 sendbuff[0] = 0x00;
tuxic 0:3b0027b76acf 154 sendbuff[1] = 0x03;
tuxic 0:3b0027b76acf 155 sendbuff[2] = blockcnt >> 8;
tuxic 0:3b0027b76acf 156 sendbuff[3] = blockcnt & 255;
tuxic 0:3b0027b76acf 157 blocksize = len+4;
tuxic 0:3b0027b76acf 158 }
tuxic 0:3b0027b76acf 159
tuxic 0:3b0027b76acf 160 // send DATA block to the client
tuxic 0:3b0027b76acf 161 void TFTPServer::sendBlock() {
tuxic 0:3b0027b76acf 162 ListenSock->sendto(sendbuff, blocksize, remote);
tuxic 0:3b0027b76acf 163 }
tuxic 0:3b0027b76acf 164
tuxic 0:3b0027b76acf 165
tuxic 0:3b0027b76acf 166 // compare host IP and Port with connected remote machine
tuxic 0:3b0027b76acf 167 int TFTPServer::cmpHost(Host* client) {
tuxic 0:3b0027b76acf 168 IpAddr clientIp = client->getIp();
tuxic 0:3b0027b76acf 169 IpAddr remoteIp = remote->getIp();
tuxic 0:3b0027b76acf 170 int clientPort = client->getPort();
tuxic 0:3b0027b76acf 171 int remotePort = remote->getPort();
tuxic 0:3b0027b76acf 172 return ((clientIp == remoteIp) && (clientPort == remotePort));
tuxic 0:3b0027b76acf 173 }
tuxic 0:3b0027b76acf 174
tuxic 0:3b0027b76acf 175 // send ACK to remote
tuxic 0:3b0027b76acf 176 void TFTPServer::Ack(int val) {
tuxic 0:3b0027b76acf 177 char ack[4];
tuxic 0:3b0027b76acf 178 ack[0] = 0x00;
tuxic 0:3b0027b76acf 179 ack[1] = 0x04;
tuxic 0:3b0027b76acf 180 if ((val>603135) || (val<0)) val = 0;
tuxic 0:3b0027b76acf 181 ack[2] = val >> 8;
tuxic 0:3b0027b76acf 182 ack[3] = val & 255;
tuxic 0:3b0027b76acf 183 ListenSock->sendto(ack, 4, remote);
tuxic 0:3b0027b76acf 184 }
tuxic 0:3b0027b76acf 185
tuxic 0:3b0027b76acf 186 // send ERR message to named client
tuxic 0:3b0027b76acf 187 void TFTPServer::Err(char* msg, Host* client) {
tuxic 0:3b0027b76acf 188 char message[32];
tuxic 0:3b0027b76acf 189 strncpy(message, msg, 32);
tuxic 0:3b0027b76acf 190 char err[37];
tuxic 0:3b0027b76acf 191 sprintf(err, "0000%s0", message);
tuxic 0:3b0027b76acf 192 err[0] = 0x00;
tuxic 0:3b0027b76acf 193 err[1] = 0x05;
tuxic 0:3b0027b76acf 194 err[2]=0x00;
tuxic 0:3b0027b76acf 195 err[3]=0x00;
tuxic 0:3b0027b76acf 196 int len = strlen(err);
tuxic 0:3b0027b76acf 197 err[len-1] = 0x00;
tuxic 0:3b0027b76acf 198 ListenSock->sendto(err, len, client);
tuxic 0:3b0027b76acf 199 #ifdef TFTP_DEBUG
tuxic 0:3b0027b76acf 200 char debugmsg[256];
tuxic 0:3b0027b76acf 201 sprintf(debugmsg, "Error: %s", message);
tuxic 0:3b0027b76acf 202 TFTP_DEBUG(debugmsg);
tuxic 0:3b0027b76acf 203 #endif
tuxic 0:3b0027b76acf 204 }
tuxic 0:3b0027b76acf 205
tuxic 0:3b0027b76acf 206 // check if connection mode of client is octet/binary
tuxic 0:3b0027b76acf 207 int TFTPServer::modeOctet(char* buff) {
tuxic 0:3b0027b76acf 208 int x = 2;
tuxic 0:3b0027b76acf 209 while (buff[x++] != 0); // get beginning of mode field
tuxic 0:3b0027b76acf 210 int y = x;
tuxic 0:3b0027b76acf 211 while (buff[y] != 0) {
tuxic 0:3b0027b76acf 212 buff[y] = tolower(buff[y]);
tuxic 0:3b0027b76acf 213 y++;
tuxic 0:3b0027b76acf 214 } // make mode field lowercase
tuxic 0:3b0027b76acf 215 return (strcmp(&buff[x++], "octet") == 0);
tuxic 0:3b0027b76acf 216 }
tuxic 0:3b0027b76acf 217
tuxic 0:3b0027b76acf 218 // timed routine to avoid hanging after interrupted transfers
tuxic 0:3b0027b76acf 219 void TFTPServer::cleanUp() {
tuxic 0:3b0027b76acf 220 static int lastcnt;
tuxic 0:3b0027b76acf 221 switch (state) {
tuxic 0:3b0027b76acf 222 case reading:
tuxic 0:3b0027b76acf 223 if (lastcnt == blockcnt) {
tuxic 0:3b0027b76acf 224 fclose(fp);
tuxic 0:3b0027b76acf 225 state=listen;
tuxic 0:3b0027b76acf 226 delete(remote);
tuxic 0:3b0027b76acf 227 }
tuxic 0:3b0027b76acf 228 break;
tuxic 0:3b0027b76acf 229 case writing:
tuxic 0:3b0027b76acf 230 if (lastcnt == blockcnt) {
tuxic 0:3b0027b76acf 231 fclose(fp);
tuxic 0:3b0027b76acf 232 state = listen;
tuxic 0:3b0027b76acf 233 remove(filename);
tuxic 0:3b0027b76acf 234 delete(remote);
tuxic 0:3b0027b76acf 235 }
tuxic 0:3b0027b76acf 236 break;
tuxic 0:3b0027b76acf 237 } // state
tuxic 0:3b0027b76acf 238 lastcnt = blockcnt;
tuxic 0:3b0027b76acf 239 }
tuxic 0:3b0027b76acf 240
tuxic 0:3b0027b76acf 241 // event driven routines to handle incoming packets
tuxic 0:3b0027b76acf 242 void TFTPServer::onListenUDPSocketEvent(UDPSocketEvent e) {
tuxic 0:3b0027b76acf 243 extern SDFileSystem sd;
tuxic 0:3b0027b76acf 244 Host* client = new Host();
tuxic 0:3b0027b76acf 245 char buff[516];
tuxic 0:3b0027b76acf 246 if (e == UDPSOCKET_READABLE) {
tuxic 0:3b0027b76acf 247 switch (state) {
tuxic 0:3b0027b76acf 248 case listen:
tuxic 0:3b0027b76acf 249 if (int len = ListenSock->recvfrom(buff, 516, client)) {
tuxic 0:3b0027b76acf 250 switch (buff[1]) {
tuxic 0:3b0027b76acf 251 case 0x01: // RRQ
tuxic 0:3b0027b76acf 252 if (modeOctet(buff))
tuxic 0:3b0027b76acf 253 ConnectRead(buff, client);
tuxic 0:3b0027b76acf 254 else
tuxic 0:3b0027b76acf 255 Err("Not in octet mode", client);
tuxic 0:3b0027b76acf 256 break;
tuxic 0:3b0027b76acf 257 case 0x02: // WRQ
tuxic 0:3b0027b76acf 258 if (modeOctet(buff))
tuxic 0:3b0027b76acf 259 ConnectWrite(buff, client);
tuxic 0:3b0027b76acf 260 else
tuxic 0:3b0027b76acf 261 Err("Not in octet mode", client);
tuxic 0:3b0027b76acf 262 break;
tuxic 0:3b0027b76acf 263 case 0x03: // DATA before connection established
tuxic 0:3b0027b76acf 264 Err("No data expected", client);
tuxic 0:3b0027b76acf 265 break;
tuxic 0:3b0027b76acf 266 case 0x04: // ACK before connection established
tuxic 0:3b0027b76acf 267 Err("No ack expected", client);
tuxic 0:3b0027b76acf 268 break;
tuxic 0:3b0027b76acf 269 case 0x05: // ERROR packet received
tuxic 0:3b0027b76acf 270 #ifdef TFTP_DEBUG
tuxic 0:3b0027b76acf 271 TFTP_DEBUG("TFTP Eror received\n\r");
tuxic 0:3b0027b76acf 272 #endif
tuxic 0:3b0027b76acf 273 break;
tuxic 0:3b0027b76acf 274 default: // unknown TFTP packet type
tuxic 0:3b0027b76acf 275 Err("Unknown TFTP packet type", client);
tuxic 0:3b0027b76acf 276 break;
tuxic 0:3b0027b76acf 277 } // switch buff[1]
tuxic 0:3b0027b76acf 278 } // recvfrom
tuxic 0:3b0027b76acf 279 break; // case listen
tuxic 0:3b0027b76acf 280 case reading:
tuxic 0:3b0027b76acf 281 while (int len = ListenSock->recvfrom(buff, 516, client) ) {
tuxic 0:3b0027b76acf 282 switch (buff[1]) {
tuxic 0:3b0027b76acf 283 case 0x01:
tuxic 0:3b0027b76acf 284 // if this is the receiving host, send first packet again
tuxic 0:3b0027b76acf 285 if ((cmpHost(client) && blockcnt==1)) {
tuxic 0:3b0027b76acf 286 sendBlock();
tuxic 0:3b0027b76acf 287 dupcnt++;
tuxic 0:3b0027b76acf 288 }
tuxic 0:3b0027b76acf 289 if (dupcnt>10) { // too many dups, stop sending
tuxic 0:3b0027b76acf 290 fclose(fp);
tuxic 0:3b0027b76acf 291 state=listen;
tuxic 0:3b0027b76acf 292 delete(remote);
tuxic 0:3b0027b76acf 293 }
tuxic 0:3b0027b76acf 294 break;
tuxic 0:3b0027b76acf 295 case 0x02:
tuxic 0:3b0027b76acf 296 // this should never happen, ignore
tuxic 0:3b0027b76acf 297 break; // case 0x02
tuxic 0:3b0027b76acf 298 case 0x03:
tuxic 0:3b0027b76acf 299 // we are the sending side, ignore
tuxic 0:3b0027b76acf 300 break;
tuxic 0:3b0027b76acf 301 case 0x04:
tuxic 0:3b0027b76acf 302 // last packet received, send next if there is one
tuxic 0:3b0027b76acf 303 dupcnt = 0;
tuxic 0:3b0027b76acf 304 if (blocksize == 516) {
tuxic 0:3b0027b76acf 305 getBlock();
tuxic 0:3b0027b76acf 306 sendBlock();
tuxic 0:3b0027b76acf 307 } else { //EOF
tuxic 0:3b0027b76acf 308 fclose(fp);
tuxic 0:3b0027b76acf 309 state = listen;
tuxic 0:3b0027b76acf 310 delete(remote);
tuxic 0:3b0027b76acf 311 }
tuxic 0:3b0027b76acf 312 break;
tuxic 0:3b0027b76acf 313 default: // this includes 0x05 errors
tuxic 0:3b0027b76acf 314 fclose(fp);
tuxic 0:3b0027b76acf 315 state = listen;
tuxic 0:3b0027b76acf 316 delete(remote);
tuxic 0:3b0027b76acf 317 break;
tuxic 0:3b0027b76acf 318 } // switch (buff[1])
tuxic 0:3b0027b76acf 319 } // while
tuxic 0:3b0027b76acf 320 break; // reading
tuxic 0:3b0027b76acf 321 case writing:
tuxic 0:3b0027b76acf 322 while (int len = ListenSock->recvfrom(buff, 516, client) ) {
tuxic 0:3b0027b76acf 323 switch (buff[1]) {
tuxic 0:3b0027b76acf 324 case 0x02:
tuxic 0:3b0027b76acf 325 // if this is a returning host, send ack again
tuxic 0:3b0027b76acf 326 if (cmpHost(client)) {
tuxic 0:3b0027b76acf 327 Ack(0);
tuxic 0:3b0027b76acf 328 #ifdef TFTP_DEBUG
tuxic 0:3b0027b76acf 329 TFTP_DEBUG("Resending Ack on WRQ");
tuxic 0:3b0027b76acf 330 #endif
tuxic 0:3b0027b76acf 331 }
tuxic 0:3b0027b76acf 332 break; // case 0x02
tuxic 0:3b0027b76acf 333 case 0x03:
tuxic 0:3b0027b76acf 334 if (cmpHost(client)) { // check if this is our partner
tuxic 0:3b0027b76acf 335 int block = (buff[2] << 8) + buff[3];
tuxic 0:3b0027b76acf 336 if ((blockcnt+1) == block) {
tuxic 0:3b0027b76acf 337 Ack(block);
tuxic 0:3b0027b76acf 338 // new packet
tuxic 0:3b0027b76acf 339 char *data = &buff[4];
tuxic 0:3b0027b76acf 340 fwrite(data, 1,len-4, fp);
tuxic 0:3b0027b76acf 341 blockcnt++;
tuxic 0:3b0027b76acf 342 dupcnt = 0;
tuxic 0:3b0027b76acf 343 } else {
tuxic 0:3b0027b76acf 344 if ((blockcnt+1) < block) { // high block nr
tuxic 0:3b0027b76acf 345 // we missed a packet, error
tuxic 0:3b0027b76acf 346 #ifdef TFTP_DEBUG
tuxic 0:3b0027b76acf 347 TFTP_DEBUG("Missed packet!");
tuxic 0:3b0027b76acf 348 #endif
tuxic 0:3b0027b76acf 349 fclose(fp);
tuxic 0:3b0027b76acf 350 state = listen;
tuxic 0:3b0027b76acf 351 remove(filename);
tuxic 0:3b0027b76acf 352 delete(remote);
tuxic 0:3b0027b76acf 353 } else { // duplicate packet, do nothing
tuxic 0:3b0027b76acf 354 #ifdef TFTP_DEBUG
tuxic 0:3b0027b76acf 355 char debugmsg[256];
tuxic 0:3b0027b76acf 356 sprintf(debugmsg, "Dupblicate packet %d", blockcnt);
tuxic 0:3b0027b76acf 357 TFTP_DEBUG(debugmsg);
tuxic 0:3b0027b76acf 358 #endif
tuxic 0:3b0027b76acf 359 if (dupcnt > 10) {
tuxic 0:3b0027b76acf 360 Err("Too many dups", client);
tuxic 0:3b0027b76acf 361 fclose(fp);
tuxic 0:3b0027b76acf 362 remove(filename);
tuxic 0:3b0027b76acf 363 state = listen;
tuxic 0:3b0027b76acf 364 } else {
tuxic 0:3b0027b76acf 365 Ack(blockcnt);
tuxic 0:3b0027b76acf 366 }
tuxic 0:3b0027b76acf 367 dupcnt++;
tuxic 0:3b0027b76acf 368 }
tuxic 0:3b0027b76acf 369 }
tuxic 0:3b0027b76acf 370 //printf ("Read packet %d with blocksize = %d\n\r", blockcnt, len);
tuxic 0:3b0027b76acf 371 if (len<516) {
tuxic 0:3b0027b76acf 372 #ifdef TFTP_DEBUG
tuxic 0:3b0027b76acf 373 char debugmsg[256];
tuxic 0:3b0027b76acf 374 sprintf(debugmsg, "Read last block %d", len);
tuxic 0:3b0027b76acf 375 TFTP_DEBUG(debugmsg);
tuxic 0:3b0027b76acf 376 #endif
tuxic 0:3b0027b76acf 377 fclose(fp);
tuxic 0:3b0027b76acf 378 state = listen;
tuxic 0:3b0027b76acf 379 delete(remote);
tuxic 0:3b0027b76acf 380 filecnt++;
tuxic 0:3b0027b76acf 381 }
tuxic 0:3b0027b76acf 382 break; // case 0x03
tuxic 0:3b0027b76acf 383 } else // if cmpHost
tuxic 0:3b0027b76acf 384 Err("Wrong IP/Port: Not your connection!", client);
tuxic 0:3b0027b76acf 385 break; // case 0x03
tuxic 0:3b0027b76acf 386 default:
tuxic 0:3b0027b76acf 387 Err("No idea why you're sending me this!", client);
tuxic 0:3b0027b76acf 388 break; // default
tuxic 0:3b0027b76acf 389 } // switch (buff[1])
tuxic 0:3b0027b76acf 390 } // while
tuxic 0:3b0027b76acf 391 break; // writing
tuxic 0:3b0027b76acf 392 case suspended:
tuxic 0:3b0027b76acf 393 if (int len = ListenSock->recvfrom(buff, 516, client))
tuxic 0:3b0027b76acf 394 Err("Packet received on suspended socket, discarded", client);
tuxic 0:3b0027b76acf 395 break;
tuxic 0:3b0027b76acf 396 } // state
tuxic 0:3b0027b76acf 397 } else {
tuxic 0:3b0027b76acf 398 #ifdef TFTP_DEBUG
tuxic 0:3b0027b76acf 399 TFTP_DEBUG("TFTP unknown UDP status");
tuxic 0:3b0027b76acf 400 #endif
tuxic 0:3b0027b76acf 401 }
tuxic 0:3b0027b76acf 402 delete(client);
tuxic 0:3b0027b76acf 403 }