X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=common%2Fhttp.c;h=9c34a3b02d329f2ea9496e9d485eec0778ee874d;hb=473597657df72ce78026ab1fe487219fa349e8d2;hp=3342a603a318a06e2b33b42d086c887f9449eee5;hpb=95c14b735e08d5350a43722b4b02889c4f0c6c2a;p=doldaconnect.git diff --git a/common/http.c b/common/http.c index 3342a60..9c34a3b 100644 --- a/common/http.c +++ b/common/http.c @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef HAVE_CONFIG_H #include @@ -29,6 +30,18 @@ #include #include +#define STATE_SYN 0 +#define STATE_TXREQ 1 + +void freeurl(struct hturlinfo *ui) +{ + free(ui->host); + free(ui->path); + free(ui->query); + free(ui->fragment); + free(ui); +} + struct hturlinfo *parseurl(char *url) { char *p, *p2, *p3; @@ -43,6 +56,8 @@ struct hturlinfo *parseurl(char *url) if((p3 = strrchr(p, ':')) != NULL) { *(p3++) = 0; ui->port = atoi(p3); + } else { + ui->port = 80; } ui->host = sstrdup(p); if(p2 == NULL) { @@ -56,7 +71,107 @@ struct hturlinfo *parseurl(char *url) if(p2 == NULL) { ui->query = sstrdup(""); } else { - ui->query = sstrdup(p2); + p = p2; + if((p2 = strchr(p, '#')) != NULL) + *(p2++) = 0; + ui->query = sstrdup(p); + } + if(p2 == NULL) { + ui->fragment = sstrdup(""); + } else { + ui->fragment = sstrdup(p2); } return(ui); } + +static struct hturlinfo *dupurl(struct hturlinfo *ui) +{ + struct hturlinfo *new; + + new = memset(smalloc(sizeof(*new)), 0, sizeof(*new)); + new->host = sstrdup(ui->host); + new->port = ui->port; + new->path = sstrdup(ui->path); + new->query = sstrdup(ui->query); + new->fragment = sstrdup(ui->fragment); + return(new); +} + +static struct addrinfo *resolvtcp(char *name, int port) +{ + struct addrinfo hint, *ret; + char tmp[32]; + + memset(&hint, 0, sizeof(hint)); + hint.ai_socktype = SOCK_STREAM; + hint.ai_flags = AI_NUMERICSERV | AI_CANONNAME; + snprintf(tmp, sizeof(tmp), "%i", port); + if(!getaddrinfo(name, tmp, &hint, &ret)) + return(ret); + return(NULL); +} + +void freehtconn(struct htconn *cn) +{ + if(cn->outbuf != NULL) + free(cn->outbuf); + if(cn->inbuf != NULL) + free(cn->inbuf); + freeurl(cn->url); + freeaddrinfo(cn->ailist); + if(cn->fd != -1) + close(cn->fd); + free(cn); +} + +struct htconn *htconnect(struct hturlinfo *ui) +{ + struct htconn *cn; + + cn = memset(smalloc(sizeof(*cn)), 0, sizeof(*cn)); + cn->fd = -1; + cn->url = dupurl(ui); + cn->ailist = resolvtcp(ui->host, ui->port); + return(cn); +} + +int htpollflags(struct htconn *hc) +{ + int ret; + + ret = POLLIN; + if(hc->outbufdata > 0) + ret |= POLLOUT; + return(ret); +} + +int htprocess(struct htconn *hc) +{ + int ret; + socklen_t optlen; + + if(hc->state == STATE_SYN) { + if(hc->fd != -1) { + optlen = sizeof(ret); + getsockopt(hc->fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); + if(ret) { + hc->fd = -1; + } else { + hc->state = STATE_TXREQ; + } + } + if(hc->fd == -1) { + if(hc->curai == NULL) + hc->curai = hc->ailist; + else + hc->curai = hc->curai->ai_next; + if(hc->curai == NULL) { + /* Bleh! Linux and BSD don't share any good + * errno for this. */ + errno = ENOENT; + return(-1); + } + } + } + return(0); +}