Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

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?

UserRevisionLine numberNew 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