• R/O
  • SSH
  • HTTPS

svardos: Commit


Commit MetaInfo

Revision338 (tree)
Time2021-05-20 22:48:57
Authormateuszviste

Log Message

improvement of http headers parsing

Change Summary

Incremental Difference

--- pkgnet/pkgnet.c (revision 337)
+++ pkgnet/pkgnet.c (revision 338)
@@ -34,17 +34,17 @@
3434
3535 #include "net.h"
3636
37-#define PVER "20210514"
37+#define PVER "20210520"
3838 #define PDATE "2021"
3939
4040 #define HOSTADDR "svardos.osdn.io"
4141
4242
43-/* strips http headers and returns new buff len */
44-static int detecthttpheadersend(unsigned char *buff, int len) {
45- static char lastbyteislf = 0; /* static because I must potentially remember it for next packet/call */
46- int i;
47- for (i = 0; i < len; i++) {
43+/* returns length of all http headers, or 0 if uncomplete yet */
44+static unsigned short detecthttpheadersend(const unsigned char *buff) {
45+ char lastbyteislf = 0;
46+ unsigned short i;
47+ for (i = 0; buff[i] != 0; i++) {
4848 if (buff[i] == '\r') continue; /* ignore CR characters */
4949 if (buff[i] != '\n') {
5050 lastbyteislf = 0;
@@ -55,11 +55,8 @@
5555 lastbyteislf = 1;
5656 continue;
5757 }
58- /* end of headers! rewind the buffer and return new len */
59- i += 1; /* add 1 to skip the current \n character */
60- len -= i;
61- if (len > 0) memmove(buff, buff + i, len + 1); /* +1 so I catch the string terminator as well */
62- return(len);
58+ /* end of headers! return length of headers */
59+ return(i + 1); /* add 1 to skip the current \n character */
6360 }
6461 return(0);
6562 }
@@ -107,6 +104,46 @@
107104 }
108105
109106
107+static int htget_headers(unsigned char *buffer, size_t buffersz, struct net_tcpsocket *sock, int *httpcode) {
108+ unsigned char *buffptr = buffer;
109+ unsigned short bufflen = 0;
110+ int byteread;
111+ time_t starttime = time(NULL);
112+ for (;;) {
113+ byteread = net_recv(sock, buffptr, buffersz - (bufflen + 1)); /* -1 because I will append a NULL terminator */
114+
115+ if (byteread > 0) { /* got data */
116+ int hdlen;
117+ bufflen += byteread;
118+ buffptr += byteread;
119+ buffer[bufflen] = 0;
120+ hdlen = detecthttpheadersend(buffer);
121+ if (hdlen > 0) { /* full headers - parse http code and continue processing */
122+ int spc;
123+ /* find the first space (HTTP/1.1 200 OK) */
124+ for (spc = 0; spc < 16; spc++) {
125+ if (buffer[spc] == ' ') break;
126+ if (buffer[spc] == 0) break;
127+ }
128+ if (buffer[spc] != ' ') return(-1);
129+ *httpcode = atoi((char *)(buffer + spc + 1));
130+ /* rewind the buffer */
131+ bufflen -= hdlen;
132+ memmove(buffer, buffer + hdlen, bufflen);
133+ return(bufflen); /* move to body processing now */
134+ }
135+
136+ } else if (byteread < 0) { /* abort on error */
137+ return(-2); /* unexpected end of connection (while waiting for all http headers) */
138+
139+ } else { /* else no data received - look for timeout and release a cpu cycle */
140+ if (time(NULL) - starttime > 20) return(-3); /* TIMEOUT! */
141+ _asm int 28h; /* release a CPU cycle */
142+ }
143+ }
144+}
145+
146+
110147 /* fetch http data from ipaddr using url
111148 * write result to file outfname if not null, or print to stdout otherwise
112149 * fills bsum with the BSD sum of the data
@@ -115,8 +152,8 @@
115152 struct net_tcpsocket *sock;
116153 unsigned char buffer[4096];
117154 time_t lastactivity, lastprogressoutput = 0;
118- int headersdone = 0;
119155 int httpcode = -1;
156+ int byteread;
120157 long flen = 0, lastflen = 0;
121158 FILE *fd = NULL;
122159
@@ -145,57 +182,33 @@
145182 goto SHITQUIT;
146183 }
147184
148- lastactivity = time(NULL);
149- for (;;) {
150- int byteread = net_recv(sock, buffer, sizeof(buffer) - 1); /* -1 because I will append a NULL terminator */
185+ /* receive and process HTTP headers */
186+ byteread = htget_headers(buffer, sizeof(buffer), sock, &httpcode);
151187
152- if (byteread < 0) break; /* end of connection */
188+ /* transmission error? */
189+ if (byteread < 0) {
190+ printf("ERROR: communication error (%d)", byteread);
191+ puts("");
192+ goto SHITQUIT;
193+ }
153194
154- /* */
155- if (byteread == 0) {
156- if (time(NULL) - lastactivity > 20) { /* TIMEOUT! */
157- puts("ERROR: Timeout while waiting for data");
158- goto SHITQUIT;
159- }
160- /* waiting for packets - release a CPU cycle in the meantime */
161- _asm int 28h;
162- /* */
163- continue;
195+ /* open destination file if required and if no server-side error occured */
196+ if ((httpcode == 200) && (*outfname != 0)) {
197+ fd = fopen(outfname, "wb");
198+ if (fd == NULL) {
199+ printf("ERROR: failed to create file %s", outfname);
200+ puts("");
201+ goto SHITQUIT;
164202 }
203+ }
165204
166- if (byteread > 0) {
205+ /* read body of the answer */
206+ lastactivity = time(NULL);
207+ for (;; byteread = net_recv(sock, buffer, sizeof(buffer) - 1)) { /* read 1 byte less because I need to append a NULL terminator */
208+
209+ if (byteread > 0) { /* got data */
167210 buffer[byteread] = 0;
168211 lastactivity = time(NULL);
169- /* are headers done already? */
170- if (headersdone == 0) {
171- if (httpcode < 0) { /* do I know the http code yet? */
172- int spc;
173- /* find the first space (HTTP/1.1 200 OK) */
174- for (spc = 0; spc < 16; spc++) {
175- if (buffer[spc] == ' ') break;
176- if (buffer[spc] == 0) break;
177- }
178- if (buffer[spc] == 0) continue; /* not enough data received */
179- if (buffer[spc] != ' ') {
180- puts("ERROR: server answered with invalid HTTP");
181- goto SHITQUIT;
182- }
183- httpcode = atoi((char *)(buffer + spc + 1));
184- /* on error, the answer should be always printed on screen */
185- if ((httpcode == 200) && (*outfname != 0)) {
186- fd = fopen(outfname, "wb");
187- if (fd == NULL) {
188- printf("ERROR: failed to create file %s", outfname);
189- puts("");
190- goto SHITQUIT;
191- }
192- }
193- }
194- /* skip headers: look for \r\n\r\n or \n\n within the stream */
195- byteread = detecthttpheadersend(buffer, byteread);
196- headersdone = 1; /* assumes ALL headers are contained in the first packet TODO FIXME */
197- if (byteread == 0) continue;
198- }
199212 /* if downloading to file, write stuff to disk */
200213 if (fd != NULL) {
201214 int i;
@@ -223,14 +236,29 @@
223236 } else { /* otherwise dump to screen */
224237 printf("%s", buffer);
225238 }
239+
240+ } else if (byteread < 0) { /* end of connection */
241+ break;
242+
243+ } else { /* check for timeout (byteread == 0) */
244+ if (time(NULL) - lastactivity > 20) { /* TIMEOUT! */
245+ puts("ERROR: Timeout while waiting for data");
246+ goto SHITQUIT;
247+ }
248+ /* waiting for packets - release a CPU cycle in the meantime */
249+ _asm int 28h;
226250 }
227251 }
228- net_close(sock);
229- return(flen);
230252
253+ goto ALLGOOD;
254+
231255 SHITQUIT:
256+ flen = -1;
257+
258+ ALLGOOD:
259+ if (fd != NULL) fclose(fd);
232260 net_close(sock);
233- return(-1);
261+ return(flen);
234262 }
235263
236264
Show on old repository browser