46 #define MAX_FILENAMELEN 32
50 unsigned char conntype;
51 #define CONNTYPE_LIST 0
52 #define CONNTYPE_FILE 1
56 unsigned char filenameptr;
57 char filename[MAX_FILENAMELEN];
62 struct ftp_connection {
64 #define TYPE_CONTROL 1
71 #define STATE_INITIAL 1
72 #define STATE_SEND_USER 2
73 #define STATE_USER_SENT 3
74 #define STATE_SEND_PASS 4
75 #define STATE_PASS_SENT 5
76 #define STATE_SEND_PORT 6
77 #define STATE_PORT_SENT 7
78 #define STATE_SEND_OPTIONS 8
79 #define STATE_OPTION_SENT 9
80 #define STATE_CONNECTED 10
81 #define STATE_SEND_NLST 11
82 #define STATE_NLST_SENT 12
83 #define STATE_SEND_RETR 13
84 #define STATE_RETR_SENT 14
86 #define STATE_SEND_CWD 15
87 #define STATE_CWD_SENT 16
89 #define STATE_SEND_CDUP 17
90 #define STATE_CDUP_SENT 18
92 #define STATE_SEND_QUIT 19
93 #define STATE_QUIT_SENT 20
95 unsigned char connected_confirmed;
97 struct ftp_dataconn dataconn;
100 unsigned char codeptr;
102 unsigned char optionsptr;
104 char filename[MAX_FILENAMELEN];
108 #define NUM_OPTIONS 1
109 static const struct {
111 char *commands[NUM_OPTIONS];
117 static struct ftp_connection *waiting_for_dataconn;
119 MEMB(connections,
struct ftp_connection, 1);
130 ftpc_connect(uip_ipaddr_t *ipaddr, uint16_t port)
132 struct ftp_connection *c;
134 c = (
struct ftp_connection *)
memb_alloc(&connections);
138 c->type = TYPE_CONTROL;
139 c->state = STATE_INITIAL;
140 c->connected_confirmed = 0;
142 c->dataconn.type = TYPE_DATA;
143 c->dataconn.port = DATAPORT;
155 handle_input(
struct ftp_connection *c)
159 code = (c->code[0] -
'0') * 100 +
160 (c->code[1] -
'0') * 10 +
164 if(c->state == STATE_INITIAL) {
166 c->state = STATE_SEND_USER;
168 }
else if(c->state == STATE_USER_SENT) {
170 c->state = STATE_SEND_PASS;
172 }
else if(c->state == STATE_PASS_SENT) {
174 c->state = STATE_SEND_OPTIONS;
177 }
else if(c->state == STATE_PORT_SENT) {
178 c->state = STATE_CONNECTED;
179 if(c->connected_confirmed == 0) {
181 c->connected_confirmed = 1;
183 }
else if(c->state == STATE_OPTION_SENT) {
184 if(c->optionsptr >= options.num) {
185 c->state = STATE_SEND_PORT;
187 c->state = STATE_SEND_OPTIONS;
189 }
else if((c->state == STATE_NLST_SENT ||
190 c->state == STATE_RETR_SENT ||
191 c->state == STATE_CONNECTED)) {
192 if(code == 226 || code == 550) {
196 c->state = STATE_SEND_PORT;
200 ftpc_list_file(
NULL);
202 }
else if(c->state == STATE_CWD_SENT ||
203 c->state == STATE_CDUP_SENT) {
204 c->state = STATE_CONNECTED;
212 newdata(
struct ftp_connection *c)
219 if(c->codeptr <
sizeof(c->code)) {
220 c->code[c->codeptr] = d;
232 acked(
struct ftp_connection *c)
235 case STATE_SEND_USER:
236 c->state = STATE_USER_SENT;
238 case STATE_SEND_PASS:
239 c->state = STATE_PASS_SENT;
241 case STATE_SEND_PORT:
242 c->state = STATE_PORT_SENT;
244 case STATE_SEND_OPTIONS:
246 c->state = STATE_OPTION_SENT;
248 case STATE_SEND_NLST:
249 c->state = STATE_NLST_SENT;
251 case STATE_SEND_RETR:
252 c->state = STATE_RETR_SENT;
255 c->state = STATE_CWD_SENT;
257 case STATE_SEND_CDUP:
258 c->state = STATE_CDUP_SENT;
260 case STATE_SEND_QUIT:
261 c->state = STATE_QUIT_SENT;
268 senddata(
struct ftp_connection *c)
273 case STATE_SEND_USER:
274 len = 5 + (uint16_t)strlen(ftpc_username()) + 2;
279 case STATE_SEND_PASS:
280 len = 5 + (uint16_t)strlen(ftpc_password()) + 2;
285 case STATE_SEND_PORT:
286 len = sprintf(
uip_appdata,
"PORT %d,%d,%d,%d,%d,%d\n",
288 (c->dataconn.port) >> 8,
289 (c->dataconn.port) & 0xff);
291 case STATE_SEND_OPTIONS:
292 len = (uint16_t)strlen(options.commands[c->optionsptr]);
293 strcpy(
uip_appdata, options.commands[c->optionsptr]);
295 case STATE_SEND_NLST:
299 case STATE_SEND_RETR:
300 len = sprintf(
uip_appdata,
"RETR %s\r\n", c->filename);
303 len = sprintf(
uip_appdata,
"CWD %s\r\n", c->filename);
305 case STATE_SEND_CDUP:
309 case STATE_SEND_QUIT:
322 ftpc_appcall(
void *state)
325 struct ftp_connection *c = (
struct ftp_connection *)state;
326 struct ftp_dataconn *d = (
struct ftp_dataconn *)state;
330 if(waiting_for_dataconn !=
NULL) {
331 d = &waiting_for_dataconn->dataconn;
332 waiting_for_dataconn =
NULL;
346 if(c->type == TYPE_ABORT) {
351 if(c->type == TYPE_CLOSE) {
353 c->type = TYPE_CONTROL;
357 if(c->type == TYPE_CONTROL) {
359 c->dataconn.type = TYPE_ABORT;
364 c->dataconn.type = TYPE_ABORT;
369 c->dataconn.type = TYPE_ABORT;
389 if(d->conntype == CONNTYPE_LIST) {
394 if(d->filenameptr <
sizeof(d->filename) - 1 &&
397 d->filename[d->filenameptr] = t;
402 d->filename[d->filenameptr] = 0;
403 petsciiconv_topetscii(d->filename, d->filenameptr);
404 ftpc_list_file(d->filename);
411 ftpc_list_file(
NULL);
426 ftpc_list(
void *conn)
428 struct ftp_connection *c;
433 c->state != STATE_CONNECTED) {
437 c->state = STATE_SEND_NLST;
438 c->dataconn.conntype = CONNTYPE_LIST;
439 waiting_for_dataconn = c;
444 ftpc_get(
void *conn,
char *filename)
446 struct ftp_connection *c;
451 c->state != STATE_CONNECTED) {
455 strncpy(c->filename, filename,
sizeof(c->filename));
456 petsciiconv_toascii(c->filename,
sizeof(c->filename));
458 c->state = STATE_SEND_RETR;
459 c->dataconn.conntype = CONNTYPE_FILE;
460 waiting_for_dataconn = c;
465 ftpc_close(
void *conn)
467 struct ftp_connection *c;
475 c->type = TYPE_CLOSE;
479 ftpc_cwd(
void *conn,
char *dirname)
481 struct ftp_connection *c;
486 c->state != STATE_CONNECTED) {
490 strncpy(c->filename, dirname,
sizeof(c->filename));
491 c->state = STATE_SEND_CWD;
495 ftpc_cdup(
void *conn)
497 struct ftp_connection *c;
502 c->state != STATE_CONNECTED) {
506 c->state = STATE_SEND_CDUP;
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Representation of a uIP TCP connection.
CCIF struct uip_conn * tcp_connect(uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Open a TCP connection to the specified IP address and port.
#define uip_aborted()
Has the connection been aborted by the other end?
CCIF void uip_send(const void *data, int len)
Send data on the current connection.
#define uip_newdata()
Is new incoming data available?
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
#define uip_mss()
Get the current maximum segment size that can be sent on the current connection.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
#define NULL
The null pointer.
#define uip_poll()
Is the connection being polled by uIP?
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
CCIF void tcp_unlisten(uint16_t port)
Close a listening TCP port.
#define uip_acked()
Has previously sent data been acknowledged?
#define uip_connected()
Has the connection just been connected?
#define uip_abort()
Abort the current connection.
PETSCII/ASCII conversion functions.
#define MEMB(name, structure, num)
Declare a memory block.
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
#define uip_ipaddr_to_quad(a)
Convert an IP address to four bytes separated by commas.
#define uip_close()
Close the current connection.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
#define uip_timedout()
Has the connection timed out?
CCIF void tcp_listen(uint16_t port)
Open a TCP port.
#define uip_closed()
Has the connection been closed by the other end?
uip_appdata
Pointer to the application data in the packet buffer.
#define uip_rexmit()
Do we need to retransmit previously data?