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