Blame


1 18824b58 2008-08-03 rsc #include "a.h"
2 18824b58 2008-08-03 rsc
3 18824b58 2008-08-03 rsc static char*
4 18824b58 2008-08-03 rsc haveheader(char *buf, int n)
5 18824b58 2008-08-03 rsc {
6 18824b58 2008-08-03 rsc int i;
7 18824b58 2008-08-03 rsc
8 18824b58 2008-08-03 rsc for(i=0; i<n; i++){
9 18824b58 2008-08-03 rsc if(buf[i] == '\n'){
10 18824b58 2008-08-03 rsc if(i+2 < n && buf[i+1] == '\r' && buf[i+2] == '\n')
11 18824b58 2008-08-03 rsc return buf+i+3;
12 18824b58 2008-08-03 rsc if(i+1 < n && buf[i+1] == '\n')
13 18824b58 2008-08-03 rsc return buf+i+2;
14 18824b58 2008-08-03 rsc }
15 18824b58 2008-08-03 rsc }
16 18824b58 2008-08-03 rsc return 0;
17 18824b58 2008-08-03 rsc }
18 18824b58 2008-08-03 rsc
19 18824b58 2008-08-03 rsc static int
20 18824b58 2008-08-03 rsc parseheader(char *buf, int n, HTTPHeader *hdr)
21 18824b58 2008-08-03 rsc {
22 18824b58 2008-08-03 rsc int nline;
23 18824b58 2008-08-03 rsc char *data, *ebuf, *p, *q, *next;
24 fa325e9b 2020-01-10 cross
25 18824b58 2008-08-03 rsc memset(hdr, 0, sizeof *hdr);
26 18824b58 2008-08-03 rsc ebuf = buf+n;
27 18824b58 2008-08-03 rsc data = haveheader(buf, n);
28 18824b58 2008-08-03 rsc if(data == nil)
29 18824b58 2008-08-03 rsc return -1;
30 18824b58 2008-08-03 rsc
31 18824b58 2008-08-03 rsc data[-1] = 0;
32 18824b58 2008-08-03 rsc if(data[-2] == '\r')
33 18824b58 2008-08-03 rsc data[-2] = 0;
34 18824b58 2008-08-03 rsc if(chattyhttp > 1){
35 18824b58 2008-08-03 rsc fprint(2, "--HTTP Response Header:\n");
36 18824b58 2008-08-03 rsc fprint(2, "%s\n", buf);
37 18824b58 2008-08-03 rsc fprint(2, "--\n");
38 18824b58 2008-08-03 rsc }
39 18824b58 2008-08-03 rsc nline = 0;
40 18824b58 2008-08-03 rsc for(p=buf; *p; p=next, nline++){
41 18824b58 2008-08-03 rsc q = strchr(p, '\n');
42 18824b58 2008-08-03 rsc if(q){
43 18824b58 2008-08-03 rsc next = q+1;
44 18824b58 2008-08-03 rsc *q = 0;
45 18824b58 2008-08-03 rsc if(q > p && q[-1] == '\r')
46 18824b58 2008-08-03 rsc q[-1] = 0;
47 18824b58 2008-08-03 rsc }else
48 18824b58 2008-08-03 rsc next = p+strlen(p);
49 18824b58 2008-08-03 rsc if(nline == 0){
50 18824b58 2008-08-03 rsc if(memcmp(p, "HTTP/", 5) != 0){
51 18824b58 2008-08-03 rsc werrstr("invalid HTTP version: %.10s", p);
52 18824b58 2008-08-03 rsc return -1;
53 18824b58 2008-08-03 rsc }
54 18824b58 2008-08-03 rsc q = strchr(p, ' ');
55 18824b58 2008-08-03 rsc if(q == nil){
56 18824b58 2008-08-03 rsc werrstr("invalid HTTP version");
57 18824b58 2008-08-03 rsc return -1;
58 18824b58 2008-08-03 rsc }
59 18824b58 2008-08-03 rsc *q++ = 0;
60 18824b58 2008-08-03 rsc strncpy(hdr->proto, p, sizeof hdr->proto);
61 18824b58 2008-08-03 rsc hdr->proto[sizeof hdr->proto-1] = 0;
62 18824b58 2008-08-03 rsc while(*q == ' ')
63 18824b58 2008-08-03 rsc q++;
64 18824b58 2008-08-03 rsc if(*q < '0' || '9' < *q){
65 18824b58 2008-08-03 rsc werrstr("invalid HTTP response code");
66 18824b58 2008-08-03 rsc return -1;
67 18824b58 2008-08-03 rsc }
68 18824b58 2008-08-03 rsc p = q;
69 18824b58 2008-08-03 rsc q = strchr(p, ' ');
70 18824b58 2008-08-03 rsc if(q == nil)
71 18824b58 2008-08-03 rsc q = p+strlen(p);
72 18824b58 2008-08-03 rsc else
73 18824b58 2008-08-03 rsc *q++ = 0;
74 18824b58 2008-08-03 rsc hdr->code = strtol(p, &p, 10);
75 18824b58 2008-08-03 rsc if(*p != 0)
76 18824b58 2008-08-03 rsc return -1;
77 18824b58 2008-08-03 rsc while(*q == ' ')
78 18824b58 2008-08-03 rsc q++;
79 18824b58 2008-08-03 rsc strncpy(hdr->codedesc, q, sizeof hdr->codedesc);
80 18824b58 2008-08-03 rsc hdr->codedesc[sizeof hdr->codedesc-1] = 0;
81 fa325e9b 2020-01-10 cross continue;
82 18824b58 2008-08-03 rsc }
83 18824b58 2008-08-03 rsc q = strchr(p, ':');
84 18824b58 2008-08-03 rsc if(q == nil)
85 18824b58 2008-08-03 rsc continue;
86 18824b58 2008-08-03 rsc *q++ = 0;
87 18824b58 2008-08-03 rsc while(*q != 0 && (*q == ' ' || *q == '\t'))
88 18824b58 2008-08-03 rsc q++;
89 18824b58 2008-08-03 rsc if(cistrcmp(p, "Content-Type") == 0){
90 18824b58 2008-08-03 rsc strncpy(hdr->contenttype, q, sizeof hdr->contenttype);
91 18824b58 2008-08-03 rsc hdr->contenttype[sizeof hdr->contenttype-1] = 0;
92 18824b58 2008-08-03 rsc continue;
93 18824b58 2008-08-03 rsc }
94 18824b58 2008-08-03 rsc if(cistrcmp(p, "Content-Length") == 0 && '0' <= *q && *q <= '9'){
95 18824b58 2008-08-03 rsc hdr->contentlength = strtoll(q, 0, 10);
96 18824b58 2008-08-03 rsc continue;
97 18824b58 2008-08-03 rsc }
98 18824b58 2008-08-03 rsc }
99 18824b58 2008-08-03 rsc if(nline < 1){
100 18824b58 2008-08-03 rsc werrstr("no header");
101 18824b58 2008-08-03 rsc return -1;
102 18824b58 2008-08-03 rsc }
103 18824b58 2008-08-03 rsc
104 18824b58 2008-08-03 rsc memmove(buf, data, ebuf - data);
105 18824b58 2008-08-03 rsc return ebuf - data;
106 fa325e9b 2020-01-10 cross }
107 18824b58 2008-08-03 rsc
108 18824b58 2008-08-03 rsc static char*
109 18824b58 2008-08-03 rsc genhttp(Protocol *proto, char *host, char *req, HTTPHeader *hdr, int wfd, int rfd, vlong rtotal)
110 18824b58 2008-08-03 rsc {
111 18824b58 2008-08-03 rsc int n, m, total, want;
112 18824b58 2008-08-03 rsc char buf[8192], *data;
113 18824b58 2008-08-03 rsc Pfd *fd;
114 18824b58 2008-08-03 rsc
115 18824b58 2008-08-03 rsc if(chattyhttp > 1){
116 18824b58 2008-08-03 rsc fprint(2, "--HTTP Request:\n");
117 18824b58 2008-08-03 rsc fprint(2, "%s", req);
118 18824b58 2008-08-03 rsc fprint(2, "--\n");
119 18824b58 2008-08-03 rsc }
120 18824b58 2008-08-03 rsc fd = proto->connect(host);
121 18824b58 2008-08-03 rsc if(fd == nil){
122 18824b58 2008-08-03 rsc if(chattyhttp > 0)
123 18824b58 2008-08-03 rsc fprint(2, "connect %s: %r\n", host);
124 18824b58 2008-08-03 rsc return nil;
125 18824b58 2008-08-03 rsc }
126 18824b58 2008-08-03 rsc
127 18824b58 2008-08-03 rsc n = strlen(req);
128 18824b58 2008-08-03 rsc if(proto->write(fd, req, n) != n){
129 18824b58 2008-08-03 rsc if(chattyhttp > 0)
130 18824b58 2008-08-03 rsc fprint(2, "write %s: %r\n", host);
131 18824b58 2008-08-03 rsc proto->close(fd);
132 18824b58 2008-08-03 rsc return nil;
133 18824b58 2008-08-03 rsc }
134 fa325e9b 2020-01-10 cross
135 18824b58 2008-08-03 rsc if(rfd >= 0){
136 18824b58 2008-08-03 rsc while(rtotal > 0){
137 18824b58 2008-08-03 rsc m = sizeof buf;
138 18824b58 2008-08-03 rsc if(m > rtotal)
139 18824b58 2008-08-03 rsc m = rtotal;
140 18824b58 2008-08-03 rsc if((n = read(rfd, buf, m)) <= 0){
141 18824b58 2008-08-03 rsc fprint(2, "read: missing data\n");
142 18824b58 2008-08-03 rsc proto->close(fd);
143 18824b58 2008-08-03 rsc return nil;
144 18824b58 2008-08-03 rsc }
145 18824b58 2008-08-03 rsc if(proto->write(fd, buf, n) != n){
146 18824b58 2008-08-03 rsc fprint(2, "write data: %r\n");
147 18824b58 2008-08-03 rsc proto->close(fd);
148 18824b58 2008-08-03 rsc return nil;
149 18824b58 2008-08-03 rsc }
150 18824b58 2008-08-03 rsc rtotal -= n;
151 18824b58 2008-08-03 rsc }
152 18824b58 2008-08-03 rsc }
153 18824b58 2008-08-03 rsc
154 18824b58 2008-08-03 rsc total = 0;
155 18824b58 2008-08-03 rsc while(!haveheader(buf, total)){
156 18824b58 2008-08-03 rsc n = proto->read(fd, buf+total, sizeof buf-total);
157 18824b58 2008-08-03 rsc if(n <= 0){
158 18824b58 2008-08-03 rsc if(chattyhttp > 0)
159 18824b58 2008-08-03 rsc fprint(2, "read missing header\n");
160 18824b58 2008-08-03 rsc proto->close(fd);
161 18824b58 2008-08-03 rsc return nil;
162 18824b58 2008-08-03 rsc }
163 18824b58 2008-08-03 rsc total += n;
164 18824b58 2008-08-03 rsc }
165 18824b58 2008-08-03 rsc
166 18824b58 2008-08-03 rsc n = parseheader(buf, total, hdr);
167 18824b58 2008-08-03 rsc if(n < 0){
168 18824b58 2008-08-03 rsc fprint(2, "failed response parse: %r\n");
169 18824b58 2008-08-03 rsc proto->close(fd);
170 18824b58 2008-08-03 rsc return nil;
171 18824b58 2008-08-03 rsc }
172 18824b58 2008-08-03 rsc if(hdr->contentlength >= MaxResponse){
173 18824b58 2008-08-03 rsc werrstr("response too long");
174 18824b58 2008-08-03 rsc proto->close(fd);
175 18824b58 2008-08-03 rsc return nil;
176 18824b58 2008-08-03 rsc }
177 18824b58 2008-08-03 rsc if(hdr->contentlength >= 0 && n > hdr->contentlength)
178 18824b58 2008-08-03 rsc n = hdr->contentlength;
179 18824b58 2008-08-03 rsc want = sizeof buf;
180 18824b58 2008-08-03 rsc data = nil;
181 18824b58 2008-08-03 rsc total = 0;
182 18824b58 2008-08-03 rsc goto didread;
183 18824b58 2008-08-03 rsc
184 18824b58 2008-08-03 rsc while(want > 0 && (n = proto->read(fd, buf, want)) > 0){
185 18824b58 2008-08-03 rsc didread:
186 18824b58 2008-08-03 rsc if(wfd >= 0){
187 18824b58 2008-08-03 rsc if(writen(wfd, buf, n) < 0){
188 18824b58 2008-08-03 rsc proto->close(fd);
189 18824b58 2008-08-03 rsc werrstr("write error");
190 18824b58 2008-08-03 rsc return nil;
191 18824b58 2008-08-03 rsc }
192 18824b58 2008-08-03 rsc }else{
193 18824b58 2008-08-03 rsc data = erealloc(data, total+n);
194 18824b58 2008-08-03 rsc memmove(data+total, buf, n);
195 18824b58 2008-08-03 rsc }
196 18824b58 2008-08-03 rsc total += n;
197 18824b58 2008-08-03 rsc if(total > MaxResponse){
198 18824b58 2008-08-03 rsc proto->close(fd);
199 18824b58 2008-08-03 rsc werrstr("response too long");
200 18824b58 2008-08-03 rsc return nil;
201 18824b58 2008-08-03 rsc }
202 18824b58 2008-08-03 rsc if(hdr->contentlength >= 0 && total + want > hdr->contentlength)
203 18824b58 2008-08-03 rsc want = hdr->contentlength - total;
204 18824b58 2008-08-03 rsc }
205 18824b58 2008-08-03 rsc proto->close(fd);
206 18824b58 2008-08-03 rsc
207 18824b58 2008-08-03 rsc if(hdr->contentlength >= 0 && total != hdr->contentlength){
208 18824b58 2008-08-03 rsc werrstr("got wrong content size %d %d", total, hdr->contentlength);
209 18824b58 2008-08-03 rsc return nil;
210 18824b58 2008-08-03 rsc }
211 18824b58 2008-08-03 rsc hdr->contentlength = total;
212 18824b58 2008-08-03 rsc if(wfd >= 0)
213 18824b58 2008-08-03 rsc return (void*)1;
214 18824b58 2008-08-03 rsc else{
215 18824b58 2008-08-03 rsc data = erealloc(data, total+1);
216 18824b58 2008-08-03 rsc data[total] = 0;
217 18824b58 2008-08-03 rsc }
218 18824b58 2008-08-03 rsc return data;
219 18824b58 2008-08-03 rsc }
220 18824b58 2008-08-03 rsc
221 18824b58 2008-08-03 rsc char*
222 18824b58 2008-08-03 rsc httpreq(Protocol *proto, char *host, char *req, HTTPHeader *hdr, int rfd, vlong rlength)
223 18824b58 2008-08-03 rsc {
224 18824b58 2008-08-03 rsc return genhttp(proto, host, req, hdr, -1, rfd, rlength);
225 18824b58 2008-08-03 rsc }
226 18824b58 2008-08-03 rsc
227 18824b58 2008-08-03 rsc int
228 18824b58 2008-08-03 rsc httptofile(Protocol *proto, char *host, char *req, HTTPHeader *hdr, int fd)
229 18824b58 2008-08-03 rsc {
230 18824b58 2008-08-03 rsc if(fd < 0){
231 18824b58 2008-08-03 rsc werrstr("bad fd");
232 18824b58 2008-08-03 rsc return -1;
233 18824b58 2008-08-03 rsc }
234 18824b58 2008-08-03 rsc if(genhttp(proto, host, req, hdr, fd, -1, 0) == nil)
235 18824b58 2008-08-03 rsc return -1;
236 18824b58 2008-08-03 rsc return 0;
237 18824b58 2008-08-03 rsc }