X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fftp.c;fp=src%2Fftp.c;h=59bc284cd303cb87654e7ab74c9d37bc67eef875;hb=4577dd26b3ecbf7ccc5ff55efa991334136866e1;hp=262140d79b2e3b2432539cb9d7a3dc9cac44f886;hpb=2ba6401e39bcfaaccaa45e6b7ef780a7a15b0c48;p=oftp diff --git a/src/ftp.c b/src/ftp.c index 262140d..59bc284 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -11,14 +12,20 @@ #ifdef __unix__ #include -#define closesocket(s) close(s) +#include +#define closesocket close +#define fcntlsocket fcntl #endif +static int handle_control(struct ftp *ftp); +static int handle_data(struct ftp *ftp, int s); +static void proc_control(struct ftp *ftp, const char *buf); + struct ftp *ftp_alloc(void) { struct ftp *ftp; - if(!(ftp = malloc(sizeof *ftp))) { + if(!(ftp = calloc(1, sizeof *ftp))) { return 0; } ftp->ctl = ftp->data = -1; @@ -28,6 +35,7 @@ struct ftp *ftp_alloc(void) void ftp_free(struct ftp *ftp) { if(!ftp) return; + if(ftp->ctl >= 0) { ftp_close(ftp); } @@ -61,6 +69,9 @@ int ftp_connect(struct ftp *ftp, const char *hostname, int port) ftp->ctl = -1; return -1; } + + fcntlsocket(ftp->ctl, F_SETFL, fcntlsocket(ftp->ctl, F_GETFL) | O_NONBLOCK); + ftp->num_crecv = 0; return 0; } @@ -68,10 +79,97 @@ void ftp_close(struct ftp *ftp) { if(ftp->ctl >= 0) { closesocket(ftp->ctl); + ftp->ctl = -1; + ftp->num_crecv = 0; } if(ftp->data >= 0) { closesocket(ftp->data); + ftp->data = -1; + ftp->num_drecv = 0; + } +} + +int ftp_sockets(struct ftp *ftp, int *sockv, int maxsize) +{ + if(ftp->ctl >= 0 && maxsize) { + *sockv++ = ftp->ctl; + maxsize--; } + return 1; +} + +int ftp_pending(struct ftp *ftp) +{ + int maxfd = -1; + fd_set rdset; + struct timeval tv = {0, 0}; + + FD_ZERO(&rdset); + if(ftp->ctl >= 0) { + FD_SET(ftp->ctl, &rdset); + maxfd = ftp->ctl; + } + if(ftp->data >= 0) { + FD_SET(ftp->data, &rdset); + if(ftp->data > maxfd) maxfd = ftp->data; + } + if(maxfd == -1) return 0; + + return select(maxfd + 1, &rdset, 0, 0, &tv) > 0 ? 1 : 0; +} + +int ftp_handle(struct ftp *ftp, int s) +{ + if(s == ftp->ctl) { + return handle_control(ftp); + } + if(s == ftp->data) { + return handle_data(ftp, s); + } + return -1; +} + +static int handle_control(struct ftp *ftp) +{ + int i, sz, rd; + char *buf, *start, *end; + + while((sz = sizeof ftp->crecv - ftp->num_crecv) > 0) { + start = ftp->crecv + ftp->num_crecv; + if((rd = recv(ftp->ctl, start, sz, 0)) == -1) { + if(errno == EINTR) continue; + /* assume EWOULDBLOCK, try again next time */ + return 0; + } + if(rd == 0) { + ftp_close(ftp); + return -1; + } + + end = start + rd; + buf = ftp->crecv; + for(i=0; icrecv && buf < end) { + ftp->num_crecv = end - buf; + memmove(ftp->crecv, buf, ftp->num_crecv); + } + } + return 0; +} + +static int handle_data(struct ftp *ftp, int s) +{ + return -1; +} + +static void proc_control(struct ftp *ftp, const char *buf) +{ } int ftp_update(struct ftp *ftp)