Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie by
libs/Network/uip/sftp/sftpd.cpp@2:1df0b61d3b5a, 2014-02-28 (annotated)
- Committer:
- Michael J. Spencer
- Date:
- Fri Feb 28 18:52:52 2014 -0800
- Revision:
- 2:1df0b61d3b5a
Update to latest Smoothie.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Michael J. Spencer |
2:1df0b61d3b5a | 1 | #pragma GCC diagnostic ignored "-Wunused-but-set-variable" |
Michael J. Spencer |
2:1df0b61d3b5a | 2 | |
Michael J. Spencer |
2:1df0b61d3b5a | 3 | #include "sftpd.h" |
Michael J. Spencer |
2:1df0b61d3b5a | 4 | #include "string.h" |
Michael J. Spencer |
2:1df0b61d3b5a | 5 | #include "stdlib.h" |
Michael J. Spencer |
2:1df0b61d3b5a | 6 | |
Michael J. Spencer |
2:1df0b61d3b5a | 7 | extern "C" { |
Michael J. Spencer |
2:1df0b61d3b5a | 8 | #include "uip.h" |
Michael J. Spencer |
2:1df0b61d3b5a | 9 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 10 | |
Michael J. Spencer |
2:1df0b61d3b5a | 11 | #define ISO_nl 0x0a |
Michael J. Spencer |
2:1df0b61d3b5a | 12 | #define ISO_cr 0x0d |
Michael J. Spencer |
2:1df0b61d3b5a | 13 | #define ISO_sp 0x20 |
Michael J. Spencer |
2:1df0b61d3b5a | 14 | |
Michael J. Spencer |
2:1df0b61d3b5a | 15 | #define DEBUG_PRINTF(...) |
Michael J. Spencer |
2:1df0b61d3b5a | 16 | |
Michael J. Spencer |
2:1df0b61d3b5a | 17 | Sftpd::Sftpd() |
Michael J. Spencer |
2:1df0b61d3b5a | 18 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 19 | fd = NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 20 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 21 | outbuf = NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 22 | filename= NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 23 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 24 | |
Michael J. Spencer |
2:1df0b61d3b5a | 25 | Sftpd::~Sftpd() |
Michael J. Spencer |
2:1df0b61d3b5a | 26 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 27 | if (fd != NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 28 | fclose(fd); |
Michael J. Spencer |
2:1df0b61d3b5a | 29 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 30 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 31 | |
Michael J. Spencer |
2:1df0b61d3b5a | 32 | int Sftpd::senddata() |
Michael J. Spencer |
2:1df0b61d3b5a | 33 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 34 | if (outbuf != NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 35 | DEBUG_PRINTF("sftp: senddata %s\n", outbuf); |
Michael J. Spencer |
2:1df0b61d3b5a | 36 | strcpy((char *)uip_appdata, outbuf); |
Michael J. Spencer |
2:1df0b61d3b5a | 37 | uip_send(uip_appdata, strlen(outbuf)); |
Michael J. Spencer |
2:1df0b61d3b5a | 38 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 39 | return 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 40 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 41 | |
Michael J. Spencer |
2:1df0b61d3b5a | 42 | int Sftpd::handle_command() |
Michael J. Spencer |
2:1df0b61d3b5a | 43 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 44 | PSOCK_BEGIN(&sin); |
Michael J. Spencer |
2:1df0b61d3b5a | 45 | |
Michael J. Spencer |
2:1df0b61d3b5a | 46 | do { |
Michael J. Spencer |
2:1df0b61d3b5a | 47 | PSOCK_READTO(&sin, ISO_nl); |
Michael J. Spencer |
2:1df0b61d3b5a | 48 | buf[PSOCK_DATALEN(&sin) - 1] = 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 49 | int len = PSOCK_DATALEN(&sin) - 1; |
Michael J. Spencer |
2:1df0b61d3b5a | 50 | DEBUG_PRINTF("sftp: got command: %s, %d\n", buf, len); |
Michael J. Spencer |
2:1df0b61d3b5a | 51 | |
Michael J. Spencer |
2:1df0b61d3b5a | 52 | if (state == STATE_CONNECTED) { |
Michael J. Spencer |
2:1df0b61d3b5a | 53 | if (strncmp(buf, "USER", 4) == 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 54 | outbuf = "!user logged in\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 55 | |
Michael J. Spencer |
2:1df0b61d3b5a | 56 | } else if (strncmp(buf, "KILL", 4) == 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 57 | if (len < 6) { |
Michael J. Spencer |
2:1df0b61d3b5a | 58 | outbuf = "- incomplete KILL command\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 59 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 60 | char *fn = &buf[5]; |
Michael J. Spencer |
2:1df0b61d3b5a | 61 | int s = remove(fn); |
Michael J. Spencer |
2:1df0b61d3b5a | 62 | if (s == 0) outbuf = "+ deleted\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 63 | else outbuf = "- delete failed\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 64 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 65 | |
Michael J. Spencer |
2:1df0b61d3b5a | 66 | } else if (strncmp(buf, "DONE", 4) == 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 67 | outbuf = "+ exit\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 68 | state = STATE_CLOSE; |
Michael J. Spencer |
2:1df0b61d3b5a | 69 | |
Michael J. Spencer |
2:1df0b61d3b5a | 70 | } else if (strncmp(buf, "STOR", 4) == 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 71 | if (len < 11) { |
Michael J. Spencer |
2:1df0b61d3b5a | 72 | outbuf = "- incomplete STOR command\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 73 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 74 | char *fn = &buf[9]; |
Michael J. Spencer |
2:1df0b61d3b5a | 75 | if(this->filename != NULL) free(this->filename); |
Michael J. Spencer |
2:1df0b61d3b5a | 76 | this->filename= strdup(fn); // REMOVE when bug fixed |
Michael J. Spencer |
2:1df0b61d3b5a | 77 | // get { NEW|OLD|APP } |
Michael J. Spencer |
2:1df0b61d3b5a | 78 | if (strncmp(&buf[5], "OLD", 3) == 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 79 | DEBUG_PRINTF("sftp: Opening file: %s\n", fn); |
Michael J. Spencer |
2:1df0b61d3b5a | 80 | fd = fopen(fn, "w"); |
Michael J. Spencer |
2:1df0b61d3b5a | 81 | if (fd != NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 82 | outbuf = "+ new file\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 83 | state = STATE_GET_LENGTH; |
Michael J. Spencer |
2:1df0b61d3b5a | 84 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 85 | outbuf = "- failed\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 86 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 87 | } else if (strncmp(&buf[5], "APP", 3) == 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 88 | fd = fopen(fn, "a"); |
Michael J. Spencer |
2:1df0b61d3b5a | 89 | if (fd != NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 90 | outbuf = "+ append file\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 91 | state = STATE_GET_LENGTH; |
Michael J. Spencer |
2:1df0b61d3b5a | 92 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 93 | outbuf = "- failed\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 94 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 95 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 96 | outbuf = "- Only OLD|APP supported\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 97 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 98 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 99 | |
Michael J. Spencer |
2:1df0b61d3b5a | 100 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 101 | outbuf = "- Unknown command\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 102 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 103 | |
Michael J. Spencer |
2:1df0b61d3b5a | 104 | } else if (state == STATE_GET_LENGTH) { |
Michael J. Spencer |
2:1df0b61d3b5a | 105 | if (len < 6 || strncmp(buf, "SIZE", 4) != 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 106 | fclose(fd); |
Michael J. Spencer |
2:1df0b61d3b5a | 107 | fd = NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 108 | outbuf = "- Expected size\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 109 | state = STATE_CONNECTED; |
Michael J. Spencer |
2:1df0b61d3b5a | 110 | |
Michael J. Spencer |
2:1df0b61d3b5a | 111 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 112 | filesize = atoi(&buf[5]); |
Michael J. Spencer |
2:1df0b61d3b5a | 113 | if (filesize > 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 114 | outbuf = "+ ok, waiting for file\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 115 | state = STATE_DOWNLOAD; |
Michael J. Spencer |
2:1df0b61d3b5a | 116 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 117 | fclose(fd); |
Michael J. Spencer |
2:1df0b61d3b5a | 118 | fd = NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 119 | outbuf = "- bad filesize\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 120 | state = STATE_CONNECTED; |
Michael J. Spencer |
2:1df0b61d3b5a | 121 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 122 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 123 | |
Michael J. Spencer |
2:1df0b61d3b5a | 124 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 125 | DEBUG_PRINTF("WTF state: %d\n", state); |
Michael J. Spencer |
2:1df0b61d3b5a | 126 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 127 | |
Michael J. Spencer |
2:1df0b61d3b5a | 128 | } while(state == STATE_CONNECTED || state == STATE_GET_LENGTH); |
Michael J. Spencer |
2:1df0b61d3b5a | 129 | |
Michael J. Spencer |
2:1df0b61d3b5a | 130 | PSOCK_END(&sin); |
Michael J. Spencer |
2:1df0b61d3b5a | 131 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 132 | |
Michael J. Spencer |
2:1df0b61d3b5a | 133 | int Sftpd::handle_download() |
Michael J. Spencer |
2:1df0b61d3b5a | 134 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 135 | // Note this is not using PSOCK and it consumes all read data |
Michael J. Spencer |
2:1df0b61d3b5a | 136 | char *readptr = (char *)uip_appdata; |
Michael J. Spencer |
2:1df0b61d3b5a | 137 | unsigned int readlen = uip_datalen(); |
Michael J. Spencer |
2:1df0b61d3b5a | 138 | DEBUG_PRINTF("sftp: starting download, expecting %d bytes, read %d\n", filesize, readlen); |
Michael J. Spencer |
2:1df0b61d3b5a | 139 | |
Michael J. Spencer |
2:1df0b61d3b5a | 140 | if (filesize > 0 && readlen > 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 141 | if (readlen > filesize) readlen = filesize; |
Michael J. Spencer |
2:1df0b61d3b5a | 142 | if (fwrite(readptr, 1, readlen, fd) != readlen) { |
Michael J. Spencer |
2:1df0b61d3b5a | 143 | DEBUG_PRINTF("sftp: Error writing file\n"); |
Michael J. Spencer |
2:1df0b61d3b5a | 144 | fclose(fd); |
Michael J. Spencer |
2:1df0b61d3b5a | 145 | fd = NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 146 | outbuf = "- Error saving file\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 147 | state = STATE_CONNECTED; |
Michael J. Spencer |
2:1df0b61d3b5a | 148 | return 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 149 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 150 | filesize -= readlen; |
Michael J. Spencer |
2:1df0b61d3b5a | 151 | DEBUG_PRINTF("sftp: saved %d bytes %d left\n", readlen, filesize); |
Michael J. Spencer |
2:1df0b61d3b5a | 152 | // HACK ALERT... to work around the fwrite/filesystem bug where writing large amounts of data corrupts the file |
Michael J. Spencer |
2:1df0b61d3b5a | 153 | // we workaround by closing the file, the reopening for append until we are done |
Michael J. Spencer |
2:1df0b61d3b5a | 154 | fclose(fd); |
Michael J. Spencer |
2:1df0b61d3b5a | 155 | fd = fopen(this->filename, "a"); |
Michael J. Spencer |
2:1df0b61d3b5a | 156 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 157 | if (filesize == 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 158 | DEBUG_PRINTF("sftp: download complete\n"); |
Michael J. Spencer |
2:1df0b61d3b5a | 159 | fclose(fd); |
Michael J. Spencer |
2:1df0b61d3b5a | 160 | fd = NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 161 | outbuf = "+ Saved file\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 162 | state = STATE_CONNECTED; |
Michael J. Spencer |
2:1df0b61d3b5a | 163 | return 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 164 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 165 | return 1; |
Michael J. Spencer |
2:1df0b61d3b5a | 166 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 167 | |
Michael J. Spencer |
2:1df0b61d3b5a | 168 | int Sftpd::acked() |
Michael J. Spencer |
2:1df0b61d3b5a | 169 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 170 | outbuf= NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 171 | return 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 172 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 173 | |
Michael J. Spencer |
2:1df0b61d3b5a | 174 | |
Michael J. Spencer |
2:1df0b61d3b5a | 175 | void Sftpd::appcall(void) |
Michael J. Spencer |
2:1df0b61d3b5a | 176 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 177 | if (uip_connected()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 178 | // TODO check for other connections |
Michael J. Spencer |
2:1df0b61d3b5a | 179 | PSOCK_INIT(&sin, buf, sizeof(buf)); |
Michael J. Spencer |
2:1df0b61d3b5a | 180 | state = STATE_CONNECTED; |
Michael J. Spencer |
2:1df0b61d3b5a | 181 | outbuf = "+Smoothie SFTP Service\n"; |
Michael J. Spencer |
2:1df0b61d3b5a | 182 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 183 | |
Michael J. Spencer |
2:1df0b61d3b5a | 184 | if (state == STATE_CLOSE) { |
Michael J. Spencer |
2:1df0b61d3b5a | 185 | DEBUG_PRINTF("sftp: state close\n"); |
Michael J. Spencer |
2:1df0b61d3b5a | 186 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 187 | uip_close(); |
Michael J. Spencer |
2:1df0b61d3b5a | 188 | return; |
Michael J. Spencer |
2:1df0b61d3b5a | 189 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 190 | |
Michael J. Spencer |
2:1df0b61d3b5a | 191 | if (uip_closed() || uip_aborted() || uip_timedout()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 192 | DEBUG_PRINTF("sftp: closed\n"); |
Michael J. Spencer |
2:1df0b61d3b5a | 193 | if (fd != NULL) |
Michael J. Spencer |
2:1df0b61d3b5a | 194 | fclose(fd); |
Michael J. Spencer |
2:1df0b61d3b5a | 195 | fd = NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 196 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 197 | return; |
Michael J. Spencer |
2:1df0b61d3b5a | 198 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 199 | |
Michael J. Spencer |
2:1df0b61d3b5a | 200 | if (uip_acked()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 201 | DEBUG_PRINTF("sftp: acked\n"); |
Michael J. Spencer |
2:1df0b61d3b5a | 202 | this->acked(); |
Michael J. Spencer |
2:1df0b61d3b5a | 203 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 204 | |
Michael J. Spencer |
2:1df0b61d3b5a | 205 | if (uip_newdata()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 206 | DEBUG_PRINTF("sftp: newdata\n"); |
Michael J. Spencer |
2:1df0b61d3b5a | 207 | if (state == STATE_DOWNLOAD) { |
Michael J. Spencer |
2:1df0b61d3b5a | 208 | if(handle_download() == 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 209 | // we need to reset the input PSOCK again before using it after using the raw input buffer |
Michael J. Spencer |
2:1df0b61d3b5a | 210 | PSOCK_INIT(&sin, buf, sizeof(buf)); |
Michael J. Spencer |
2:1df0b61d3b5a | 211 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 212 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 213 | handle_command(); |
Michael J. Spencer |
2:1df0b61d3b5a | 214 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 215 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 216 | |
Michael J. Spencer |
2:1df0b61d3b5a | 217 | if (uip_rexmit() || uip_newdata() || uip_acked() || uip_connected() || uip_poll()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 218 | this->senddata(); |
Michael J. Spencer |
2:1df0b61d3b5a | 219 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 220 | |
Michael J. Spencer |
2:1df0b61d3b5a | 221 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 222 | |
Michael J. Spencer |
2:1df0b61d3b5a | 223 | void Sftpd::init(void) |
Michael J. Spencer |
2:1df0b61d3b5a | 224 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 225 | |
Michael J. Spencer |
2:1df0b61d3b5a | 226 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 227 | |
Michael J. Spencer |
2:1df0b61d3b5a | 228 |