1 18824b58 2008-08-03 rsc #include "a.h"
4 18824b58 2008-08-03 rsc haveheader(char *buf, int n)
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;
20 18824b58 2008-08-03 rsc parseheader(char *buf, int n, HTTPHeader *hdr)
23 18824b58 2008-08-03 rsc char *data, *ebuf, *p, *q, *next;
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)
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");
40 18824b58 2008-08-03 rsc for(p=buf; *p; p=next, nline++){
41 18824b58 2008-08-03 rsc q = strchr(p, '\n');
45 18824b58 2008-08-03 rsc if(q > p && q[-1] == '\r')
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);
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");
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 == ' ')
64 18824b58 2008-08-03 rsc if(*q < '0' || '9' < *q){
65 18824b58 2008-08-03 rsc werrstr("invalid HTTP response code");
69 18824b58 2008-08-03 rsc q = strchr(p, ' ');
71 18824b58 2008-08-03 rsc q = p+strlen(p);
74 18824b58 2008-08-03 rsc hdr->code = strtol(p, &p, 10);
77 18824b58 2008-08-03 rsc while(*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;
83 18824b58 2008-08-03 rsc q = strchr(p, ':');
87 18824b58 2008-08-03 rsc while(*q != 0 && (*q == ' ' || *q == '\t'))
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;
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);
99 18824b58 2008-08-03 rsc if(nline < 1){
100 18824b58 2008-08-03 rsc werrstr("no header");
104 18824b58 2008-08-03 rsc memmove(buf, data, ebuf - data);
105 18824b58 2008-08-03 rsc return ebuf - data;
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)
111 18824b58 2008-08-03 rsc int n, m, total, want;
112 18824b58 2008-08-03 rsc char buf[8192], *data;
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");
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);
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);
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)
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);
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);
150 18824b58 2008-08-03 rsc rtotal -= n;
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);
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);
166 18824b58 2008-08-03 rsc n = parseheader(buf, total, hdr);
168 18824b58 2008-08-03 rsc fprint(2, "failed response parse: %r\n");
169 18824b58 2008-08-03 rsc proto->close(fd);
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);
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;
182 18824b58 2008-08-03 rsc goto didread;
184 18824b58 2008-08-03 rsc while(want > 0 && (n = proto->read(fd, buf, want)) > 0){
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");
193 18824b58 2008-08-03 rsc data = erealloc(data, total+n);
194 18824b58 2008-08-03 rsc memmove(data+total, buf, 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");
202 18824b58 2008-08-03 rsc if(hdr->contentlength >= 0 && total + want > hdr->contentlength)
203 18824b58 2008-08-03 rsc want = hdr->contentlength - total;
205 18824b58 2008-08-03 rsc proto->close(fd);
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);
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;
215 18824b58 2008-08-03 rsc data = erealloc(data, total+1);
216 18824b58 2008-08-03 rsc data[total] = 0;
218 18824b58 2008-08-03 rsc return data;
222 18824b58 2008-08-03 rsc httpreq(Protocol *proto, char *host, char *req, HTTPHeader *hdr, int rfd, vlong rlength)
224 18824b58 2008-08-03 rsc return genhttp(proto, host, req, hdr, -1, rfd, rlength);
228 18824b58 2008-08-03 rsc httptofile(Protocol *proto, char *host, char *req, HTTPHeader *hdr, int fd)
231 18824b58 2008-08-03 rsc werrstr("bad fd");
234 18824b58 2008-08-03 rsc if(genhttp(proto, host, req, hdr, fd, -1, 0) == nil)