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