Incremental work.
[doldaconnect.git] / common / http.c
CommitLineData
672dbb8f
FT
1/*
2 * Dolda Connect - Modular multiuser Direct Connect-style client
3 * Copyright (C) 2007 Fredrik Tolf (fredrik@dolda2000.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <unistd.h>
95c14b73 23#include <string.h>
672dbb8f 24#include <sys/socket.h>
f4663439 25#include <sys/poll.h>
672dbb8f
FT
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
95c14b73
FT
30#include <utils.h>
31#include <http.h>
672dbb8f 32
f4663439
FT
33#define STATE_SYN 0
34#define STATE_TXREQ 1
35
061d5c59
FT
36void freeurl(struct hturlinfo *ui)
37{
38 free(ui->host);
39 free(ui->path);
40 free(ui->query);
41 free(ui);
42}
43
95c14b73
FT
44struct hturlinfo *parseurl(char *url)
45{
46 char *p, *p2, *p3;
47 struct hturlinfo *ui;
48
49 if(strncmp(url, "http://", 7))
50 return(NULL);
51 ui = memset(smalloc(sizeof(*ui)), 0, sizeof(*ui));
52 p = url + 7;
53 if((p2 = strchr(p, '/')) != NULL)
54 *(p2++) = 0;
55 if((p3 = strrchr(p, ':')) != NULL) {
56 *(p3++) = 0;
57 ui->port = atoi(p3);
f4663439
FT
58 } else {
59 ui->port = 80;
95c14b73
FT
60 }
61 ui->host = sstrdup(p);
62 if(p2 == NULL) {
63 ui->path = sstrdup("/");
64 } else {
65 p = p2;
66 if((p2 = strchr(p, '?')) != NULL)
67 *(p2++) = 0;
68 ui->path = sstrdup(p);
69 }
70 if(p2 == NULL) {
71 ui->query = sstrdup("");
72 } else {
73 ui->query = sstrdup(p2);
74 }
75 return(ui);
76}
f4663439
FT
77
78static struct hturlinfo *dupurl(struct hturlinfo *ui)
79{
80 struct hturlinfo *new;
81
82 new = memset(smalloc(sizeof(*new)), 0, sizeof(*new));
83 new->host = sstrdup(ui->host);
84 new->port = ui->port;
85 new->path = sstrdup(ui->path);
86 new->query = sstrdup(ui->query);
87 return(new);
88}
89
90static struct addrinfo *resolvtcp(char *name, int port)
91{
92 struct addrinfo hint, *ret;
93 char tmp[32];
94
95 memset(&hint, 0, sizeof(hint));
96 hint.ai_socktype = SOCK_STREAM;
97 hint.ai_flags = AI_NUMERICSERV | AI_CANONNAME;
98 snprintf(tmp, sizeof(tmp), "%i", port);
99 if(!getaddrinfo(name, tmp, &hint, &ret))
100 return(ret);
101 return(NULL);
102}
103
104void freehtconn(struct htconn *cn)
105{
106 if(cn->outbuf != NULL)
107 free(cn->outbuf);
108 if(cn->inbuf != NULL)
109 free(cn->inbuf);
110 freeurl(cn->url);
111 freeaddrinfo(cn->ailist);
112 if(cn->fd != -1)
113 close(cn->fd);
114 free(cn);
115}
116
117struct htconn *htconnect(struct hturlinfo *ui)
118{
119 struct htconn *cn;
120
121 cn = memset(smalloc(sizeof(*cn)), 0, sizeof(*cn));
122 cn->fd = -1;
123 cn->url = dupurl(ui);
124 cn->ailist = resolvtcp(ui->host, ui->port);
125 return(cn);
126}
127
128int htpollflags(struct htconn *hc)
129{
130 int ret;
131
132 ret = POLLIN;
133 if(hc->outbufdata > 0)
134 ret |= POLLOUT;
135 return(ret);
136}
137
138int htprocess(struct htconn *hc)
139{
140 int ret;
141 socklen_t optlen;
142
143 if(hc->state == STATE_SYN) {
144 if(hc->fd != -1) {
145 optlen = sizeof(ret);
146 getsockopt(hc->fd, SOL_SOCKET, SO_ERROR, &ret, &optlen);
147 if(ret) {
148 hc->fd = -1;
149 } else {
150 hc->state = STATE_TXREQ;
151 }
152 }
153 if(hc->fd == -1) {
154 if(hc->curai == NULL)
155 hc->curai = hc->ailist;
156 else
157 hc->curai = hc->curai->ai_next;
158 if(hc->curai == NULL) {
159 /* Bleh! Linux and BSD don't share any good
160 * errno for this. */
161 errno = ENOENT;
162 return(-1);
163 }
164 }
165 }
166 return(0);
167}