Michael Spencer / Mbed 2 deprecated LaOS

Dependencies:   mbed

Committer:
Michael J. Spencer
Date:
Wed Mar 05 06:14:02 2014 -0800
Revision:
1:f5ac63519541
Initial commit.

Who changed what in which revision?

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