Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: http.fth | |
4 | \ | |
5 | \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | \ | |
7 | \ - Do no alter or remove copyright notices | |
8 | \ | |
9 | \ - Redistribution and use of this software in source and binary forms, with | |
10 | \ or without modification, are permitted provided that the following | |
11 | \ conditions are met: | |
12 | \ | |
13 | \ - Redistribution of source code must retain the above copyright notice, | |
14 | \ this list of conditions and the following disclaimer. | |
15 | \ | |
16 | \ - Redistribution in binary form must reproduce the above copyright notice, | |
17 | \ this list of conditions and the following disclaimer in the | |
18 | \ documentation and/or other materials provided with the distribution. | |
19 | \ | |
20 | \ Neither the name of Sun Microsystems, Inc. or the names of contributors | |
21 | \ may be used to endorse or promote products derived from this software | |
22 | \ without specific prior written permission. | |
23 | \ | |
24 | \ This software is provided "AS IS," without a warranty of any kind. | |
25 | \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
26 | \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
27 | \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
28 | \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
29 | \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
30 | \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
31 | \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
32 | \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
33 | \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
34 | \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
35 | \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
36 | \ | |
37 | \ You acknowledge that this software is not designed, licensed or | |
38 | \ intended for use in the design, construction, operation or maintenance of | |
39 | \ any nuclear facility. | |
40 | \ | |
41 | \ ========== Copyright Header End ============================================ | |
42 | id: @(#)http.fth 1.1 04/09/07 | |
43 | purpose: HTTP support | |
44 | copyright: Copyright 2004 Sun Microsystems, Inc. All Rights Reserved | |
45 | copyright: Use is subject to license terms. | |
46 | ||
47 | \ RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1 | |
48 | \ RFC 2046: Multipurpose Internet Mail Extensions: Media Types | |
49 | ||
50 | headerless | |
51 | ||
52 | 0 instance value http-sockid | |
53 | /insock instance buffer: http-srv-addr | |
54 | /ip-addr instance buffer: http-server-ip | |
55 | /ip-addr instance buffer: http-proxy-ip | |
56 | 0 instance value http-server-port | |
57 | 0 instance value http-proxy-port | |
58 | ||
59 | \ Register the HTTP server and port. Use port 80 (decimal) as the | |
60 | \ default port. | |
61 | : http-init-server ( server$ -- ) | |
62 | parse-hostport http-server-ip inet-aton drop ( port$ ) | |
63 | $dnumber if IPPORT_HTTP then to http-server-port ( ) | |
64 | ; | |
65 | ||
66 | \ Register the HTTP proxy server and port. Use port 8080 (decimal) as | |
67 | \ the default proxy port. | |
68 | : http-init-proxy ( proxy$ -- ) | |
69 | inaddr-any http-proxy-ip copy-ip-addr ( proxy$ ) | |
70 | dup if ( proxy$ ) | |
71 | 2dup check-htproxy$-form ( proxy$ ) | |
72 | parse-hostport http-proxy-ip inet-aton drop ( port$ ) | |
73 | $dnumber if IPPORT_HTTP_ALT then to http-proxy-port ( ) | |
74 | else ( null$ ) | |
75 | 2drop ( ) | |
76 | then ( ) | |
77 | ; | |
78 | ||
79 | \ Is a proxy server in use? | |
80 | : use-proxy? ( -- flag ) http-proxy-ip inaddr-any? 0= ; | |
81 | ||
82 | \ Issue an HTTP GET request. The absolute URI form must be used if | |
83 | \ the request is being made to a proxy. Since persistent connections | |
84 | \ are the default with HTTP/1.1, we use the "close" connection option | |
85 | \ to signal that a persistent connection is not required. | |
86 | ||
87 | : http-send-request ( url$ -- ) | |
88 | d# 512 dup alloc-mem swap >r >r ( url$ ) ( r: len adr ) | |
89 | r@ 0 ( url$ msg$ ) | |
90 | " GET " strcat ( url$ msg$ ) | |
91 | use-proxy? if ( url$ msg$ ) | |
92 | 2over strcat ( url$ msg$ ) | |
93 | else ( url$ msg$ ) | |
94 | " /" strcat ( url$ msg$ ) | |
95 | 2over parse-http-url 2drop strcat ( url$ msg$ ) | |
96 | then ( url$ msg$ ) | |
97 | " HTTP/1.1"r"n" strcat ( url$ msg$ ) | |
98 | " Host: " strcat ( url$ msg$ ) | |
99 | 2swap parse-http-url 2swap 2drop strcat ( msg$ ) | |
100 | " "r"n" strcat ( msg$ ) | |
101 | " Connection: close"r"n" strcat ( msg$ ) | |
102 | " "r"n" strcat ( msg$ ) | |
103 | http-sockid -rot 0 sosend drop ( ) | |
104 | r> r> free-mem ( ) ( r: ) | |
105 | ; | |
106 | ||
107 | \ Incoming data is buffered before further processing since we may | |
108 | \ need to peek at the data stream to determine the course of action. | |
109 | ||
110 | struct | |
111 | /n field >http-bufadr \ Receive buffer address | |
112 | /l field >http-bufsize \ Buffer size | |
113 | /l field >http-bufstart \ Offset to start of data | |
114 | /l field >http-bufnbytes \ Unread bytes in buffer | |
115 | constant /http-inbuf | |
116 | ||
117 | 0 instance value http-inbuf | |
118 | ||
119 | \ Allocate receive buffer resources | |
120 | : htbuf-alloc ( -- htbuf ) | |
121 | /http-inbuf alloc-mem >r | |
122 | h# 1000 dup alloc-mem r@ >http-bufadr ! | |
123 | r@ >http-bufsize l! | |
124 | 0 r@ >http-bufstart l! | |
125 | 0 r@ >http-bufnbytes l! | |
126 | r> | |
127 | ; | |
128 | ||
129 | \ Get receive buffer address and size | |
130 | : htbuf>adr,size ( htbuf -- adr size ) | |
131 | dup >http-bufadr @ swap >http-bufsize l@ | |
132 | ; | |
133 | ||
134 | \ Get address and size of unread data in receive buffer | |
135 | : htbuf>data,len ( htbuf -- data len ) | |
136 | dup >http-bufadr @ over >http-bufstart l@ ca+ swap >http-bufnbytes l@ | |
137 | ; | |
138 | ||
139 | \ Check if the receive buffer is empty | |
140 | : htbuf-empty? ( htbuf -- empty? ) >http-bufnbytes l@ 0= ; | |
141 | ||
142 | \ Read data arriving on this socket. | |
143 | : http-read-bytes ( adr len -- actual ) http-sockid -rot 0 sorecv ; | |
144 | ||
145 | \ Read data into the buffer. Called only when the buffer is empty. | |
146 | : htbuf-fill ( htbuf -- n ) | |
147 | dup htbuf>adr,size http-read-bytes ( htbuf n ) | |
148 | tuck over >http-bufnbytes l! ( n htbuf ) | |
149 | 0 swap >http-bufstart l! ( n ) | |
150 | ; | |
151 | ||
152 | \ Read data from receive buffer, reading more data into the buffer | |
153 | \ if it is empty. | |
154 | : htbuf-read ( htbuf adr len -- #read ) | |
155 | rot >r ( adr len ) ( r: htbuf ) | |
156 | r@ htbuf-empty? if ( adr len ) | |
157 | r@ htbuf-fill 0= if ( adr len ) | |
158 | 2drop r> drop 0 exit ( 0 ) | |
159 | then ( adr len ) | |
160 | show-progress ( adr len ) | |
161 | then ( adr len ) | |
162 | r@ htbuf>data,len ( adr len data n ) | |
163 | 2swap rot min dup >r move r> ( #read ) | |
164 | r@ >http-bufnbytes 2dup l@ swap - swap l! ( #read ) | |
165 | r> >http-bufstart 2dup l@ + swap l! ( #read ) | |
166 | ; | |
167 | ||
168 | \ Peek at next character in stream | |
169 | : htbuf-peekchar ( htbuf -- char true | false ) | |
170 | dup htbuf-empty? if | |
171 | dup htbuf-fill 0= if drop false exit then | |
172 | then | |
173 | htbuf>data,len drop c@ true | |
174 | ; | |
175 | ||
176 | \ Free receive buffer resources | |
177 | : htbuf-free ( htbuf -- ) | |
178 | dup htbuf>adr,size free-mem /http-inbuf free-mem | |
179 | ; | |
180 | ||
181 | \ Each HTTP header line ends with a CRLF sequence which serves as the | |
182 | \ end-of-line marker. But, HTTP/1.1 header field values can be folded | |
183 | \ onto multiple lines if the continuation line begins with a space | |
184 | \ or horizontal tab. | |
185 | ||
186 | : is-space? ( char -- flag ) dup h# 20 = swap h# 09 = or ; | |
187 | ||
188 | : http-read-hdrline ( adr maxlen -- adr len ) | |
189 | over >r over ca+ swap ( end nxt ) ( r: adr ) | |
190 | begin ( end nxt ) | |
191 | 2dup = if nip r> tuck - exit then ( end nxt ) | |
192 | http-inbuf over 1 htbuf-read 0= if ( end nxt ) | |
193 | nip r> tuck - exit ( adr len ) | |
194 | then ( end nxt ) | |
195 | dup c@ linefeed = if ( end nxt ) | |
196 | http-inbuf htbuf-peekchar if ( end nxt char ) | |
197 | is-space? 0= if ( end nxt ) | |
198 | nip r> tuck - exit ( adr len ) | |
199 | then ( end nxt ) | |
200 | then ( end nxt ) | |
201 | else ( end nxt ) | |
202 | dup c@ carret <> if ca1+ then ( end nxt' ) | |
203 | then | |
204 | again | |
205 | ; | |
206 | ||
207 | \ Return the next HTTP header line token. Words may be separated | |
208 | \ by linear white space, or one of "," ";" or "=". The field value | |
209 | \ may be quoted string. | |
210 | ||
211 | : htnextfield ( $ -- rem$ tok$ ) | |
212 | " "t"r"n,=;" ( $ delim$ ) | |
213 | 2swap 2over string-skipchars dup if ( delim$ $' ) | |
214 | over c@ ascii " = if ( delim$ $' ) | |
215 | 1 /string ascii " left-parse-string ( delim$ rem$ tok$ ) | |
216 | else ( delim$ $' ) | |
217 | 2over strtok ( delim$ rem$ tok$ ) | |
218 | then ( delim$ rem$ tok$ ) | |
219 | else ( delim$ $' ) | |
220 | null$ ( delim$ rem$ null$ ) | |
221 | then ( delim$ rem$ tok$ ) | |
222 | 2rot 2drop ( rem$ tok$ ) | |
223 | ; | |
224 | ||
225 | \ The HTTP response begins with a Status-Line and is followed by | |
226 | \ message headers and a message body. | |
227 | \ | |
228 | \ We expect a 2xx status code in the response status line, and process | |
229 | \ the "Content-Length", "Content-Type" and "Transfer-Encoding" HTTP | |
230 | \ message header fields. The message body may be a multipart message | |
231 | \ and may have the "chunked" transfer encoding applied to it. | |
232 | ||
233 | 0 instance value http-transfer-length \ Total message length | |
234 | false instance value http-is-multipart? \ Multipart message? | |
235 | d# 72 instance buffer: http-part-boundary \ Multipart message boundary | |
236 | 0 instance value http-bodypart-length \ Current bodypart length | |
237 | false instance value http-is-chunked? \ Chunked transfer? | |
238 | ||
239 | \ Process HTTP status line in the response. | |
240 | : http-check-statusline ( $ -- ) | |
241 | " " strtok ( rem$ ver$ ) | |
242 | 2dup " HTTP/1.1" $= >r 2dup " HTTP/1.0" $= r> or 0= if | |
243 | ." HTTP: Bad Version: " type cr -1 throw | |
244 | then 2drop ( rem$ ) | |
245 | " " strtok ( msg$ code$ ) | |
246 | 2dup $dnumber if | |
247 | ." HTTP: Bad Status code: " type cr -1 throw | |
248 | then nip nip ( msg$ code ) | |
249 | dup d# 200 <> if | |
250 | ." HTTP: Bad Response: " .d type cr -1 throw | |
251 | then ( msg$ code ) | |
252 | 3drop ( ) | |
253 | ; | |
254 | ||
255 | \ Get the size of the HTTP message body. | |
256 | : http-content-length ( $ -- ) | |
257 | htnextfield 2swap 2drop $dnumber ( n false | true ) | |
258 | if ." HTTP Content Length Invalid" -1 throw then ( n ) | |
259 | to http-transfer-length ( ) | |
260 | ; | |
261 | ||
262 | \ Process "Content-Type" field of HTTP message header. If this a multipart | |
263 | \ message, get the boundary parameter value. | |
264 | : http-content-type ( $ -- ) | |
265 | htnextfield " multipart/mixed" $case= 0= if 2drop exit then | |
266 | htnextfield " Boundary" $case= 0= if | |
267 | ." Multipart Message Boundary not specified" -1 throw | |
268 | then | |
269 | htnextfield http-part-boundary pack drop 2drop | |
270 | true to http-is-multipart? | |
271 | ; | |
272 | ||
273 | \ Get the transfer encoding applied to the message body. | |
274 | : http-transfer-encoding ( $ -- ) | |
275 | htnextfield 2swap 2drop " chunked" $case= to http-is-chunked? | |
276 | ; | |
277 | ||
278 | \ Token table for HTTP message headers. | |
279 | create http-headers | |
280 | " Content-Length" false ['] http-content-length token-handler, | |
281 | " Content-Type" false ['] http-content-type token-handler, | |
282 | " Transfer-Encoding" false ['] http-transfer-encoding token-handler, | |
283 | null$ 0 0 token-handler, | |
284 | ||
285 | \ Process HTTP message headers. | |
286 | : http-process-headers ( -- ) | |
287 | d# 1000 dup alloc-mem swap ( buf$ ) | |
288 | 2dup http-read-hdrline ( buf$ line$ ) | |
289 | http-check-statusline ( buf$ ) | |
290 | begin ( buf$ ) | |
291 | 2dup http-read-hdrline ( buf$ line$ ) | |
292 | dup while ( buf$ line$ ) | |
293 | ascii : left-parse-string ( buf$ value$ field$ ) | |
294 | http-headers find-token-handler if ( buf$ value$ xt ) | |
295 | execute ( buf$ ) | |
296 | else ( buf$ value$ ) | |
297 | 2drop ( buf$ ) | |
298 | then ( buf$ ) | |
299 | repeat 2drop ( buf$ ) | |
300 | free-mem ( ) | |
301 | ; | |
302 | ||
303 | \ With chunked transfer encoding, the message body is split into one or | |
304 | \ more "chunks". A chunk appears as | |
305 | \ chunk = chunk-size CRLF | |
306 | \ chunk-data CRLF | |
307 | \ The chunk-size field indicates the size (in hexadecimal) of the data | |
308 | \ in that chunk. The last chunk has a size of zero. | |
309 | ||
310 | struct | |
311 | d# 80 field >http-chunkline$ \ Buffer to read chunk-size lines | |
312 | /l field >http-chunk-nleft \ Unread data in current chunk | |
313 | constant /http-chunkinfo | |
314 | ||
315 | 0 instance value http-chunkinfo | |
316 | ||
317 | \ Initialize structures to enable chunk decoding | |
318 | : http-chunk-init ( -- htchunk ) | |
319 | /http-chunkinfo dup alloc-mem tuck swap erase | |
320 | ; | |
321 | ||
322 | \ Free chunking data structures | |
323 | : http-chunk-free ( htchunk -- ) | |
324 | /http-chunkinfo free-mem | |
325 | ; | |
326 | ||
327 | \ Get size of unread data in the current chunk | |
328 | : htchunk-nleft@ ( -- n ) http-chunkinfo >http-chunk-nleft l@ ; | |
329 | ||
330 | \ Update size of unread data in current chunk | |
331 | : htchunk-nleft! ( n -- ) http-chunkinfo >http-chunk-nleft l! ; | |
332 | ||
333 | \ Read chunk line (size of chunk or trailing CRLF) | |
334 | : http-read-chunkline ( -- line$ ) | |
335 | http-chunkinfo >http-chunkline$ d# 80 over 0 2swap bounds ?do | |
336 | http-inbuf i 1 htbuf-read 0= ?leave | |
337 | i c@ linefeed = ?leave | |
338 | i c@ carret <> if 1+ then | |
339 | loop ( adr len ) | |
340 | ; | |
341 | ||
342 | \ Get size of next chunk | |
343 | : http-read-chunksize ( -- n ) | |
344 | http-read-chunkline 2dup $hnumber if | |
345 | ." HTTP: Bad Chunk Size " type cr -1 throw | |
346 | then nip nip ( n ) | |
347 | dup htchunk-nleft! ( n ) | |
348 | ; | |
349 | ||
350 | \ Read chunk data. If all data from the previous chunk has been | |
351 | \ processed, get the size of the new chunk before reading data. | |
352 | \ If all data in the current chunk has been processed as a result | |
353 | \ of this read, process the trailing CRLF as well. | |
354 | ||
355 | : http-read-chunkdata ( adr len -- #read ) | |
356 | htchunk-nleft@ 0= if ( adr len ) | |
357 | http-read-chunksize 0= if ( adr len ) | |
358 | 2drop 0 exit ( 0 ) | |
359 | then ( adr len ) | |
360 | then ( adr len ) | |
361 | http-inbuf -rot htchunk-nleft@ min htbuf-read ( #read ) | |
362 | htchunk-nleft@ over - htchunk-nleft! ( #read ) | |
363 | htchunk-nleft@ 0= if ( #read ) | |
364 | http-read-chunkline 2drop ( #read ) | |
365 | then ( #read ) | |
366 | ; | |
367 | ||
368 | \ Decode the chunked transfer-coding to get the message body contents. | |
369 | : http-chunked-read ( adr len -- #read ) | |
370 | over >r ( adr len ) ( r: adr ) | |
371 | begin dup while ( nxt rem ) | |
372 | 2dup http-read-chunkdata ?dup if ( nxt rem n ) | |
373 | tuck - >r ca+ r> ( nxt' rem' ) | |
374 | else ( nxt rem ) | |
375 | drop r> - exit ( #read ) | |
376 | then ( nxt' rem' ) | |
377 | repeat ( nxt' rem' ) | |
378 | drop r> - ( #read ) | |
379 | ; | |
380 | ||
381 | \ Read contents from an unencoded message body. | |
382 | : http-unencoded-read ( adr len -- #read ) | |
383 | over >r ( adr len ) ( r: adr ) | |
384 | begin dup while ( nxt rem ) | |
385 | 2dup http-inbuf -rot htbuf-read ?dup if ( nxt rem nread ) | |
386 | tuck - >r ca+ r> ( nxt' rem' ) | |
387 | else ( nxt rem ) | |
388 | drop r> - exit ( #read ) | |
389 | then ( nxt' rem' ) | |
390 | repeat ( nxt' rem' ) | |
391 | drop r> - ( #read ) | |
392 | ; | |
393 | ||
394 | \ Read a block of data from the message body. | |
395 | : http-read-body ( adr len -- #read ) | |
396 | http-is-chunked? if http-chunked-read else http-unencoded-read then | |
397 | ; | |
398 | ||
399 | \ Processing body part headers of a multipart message. | |
400 | \ | |
401 | \ Each body part of a multipart message is preceded by a boundary delimiter | |
402 | \ line, and the last one is followed by the closing boundary delimiter | |
403 | \ line. After its boundary delimiter line, the body part consists of a | |
404 | \ header area, a blank line, and a body area. | |
405 | \ | |
406 | \ A boundary delimiter line is of the form "--<boundary>". A closing | |
407 | \ boundary delimiter line is of the form "--<boundary>--". The boundary | |
408 | \ string is specified in the "Content-Type" field in the HTTP header. | |
409 | \ | |
410 | \ The "Content-Length" and "Content-Type" fields in the body part header | |
411 | \ lines provide the length and description of data contained in the | |
412 | \ body part. | |
413 | \ | |
414 | \ Since the HTTP message body (which includes body parts of the multipart | |
415 | \ message) may be chunked, the transfer-coding must be decoded before | |
416 | \ reading body part header lines. | |
417 | ||
418 | : http-part-content-length ( $ -- ) | |
419 | htnextfield 2swap 2drop $dnumber if | |
420 | ." HTTP Bodypart Content Length Invalid" -1 throw | |
421 | then to http-bodypart-length | |
422 | ; | |
423 | ||
424 | : http-part-content-type ( $ -- ) | |
425 | htnextfield 2swap 2drop ( type$ ) | |
426 | 2dup " application/octet-stream" $case= 0= if | |
427 | ." HTTP: Unexpected media type " type cr -1 throw | |
428 | then 2drop | |
429 | ; | |
430 | ||
431 | \ Token table for body part header fields. | |
432 | create http-part-headers | |
433 | " Content-Length" false ['] http-part-content-length token-handler, | |
434 | " Content-Type" false ['] http-part-content-type token-handler, | |
435 | null$ 0 0 token-handler, | |
436 | ||
437 | : http-process-boundary$ ( boundary$ -- closing-boundary? ) | |
438 | over " --" comp 0<> if | |
439 | ." HTTP: Missing Multipart Message Boundary" -1 throw | |
440 | then | |
441 | over 2+ http-part-boundary count comp 0<> if | |
442 | ." HTTP: Multipart Message Boundary Mismatch" -1 throw | |
443 | then | |
444 | drop 2+ http-part-boundary count nip ca+ " --" comp 0= | |
445 | ; | |
446 | ||
447 | \ Read next body part header line. | |
448 | : http-read-part-hdrline ( adr maxlen -- adr len ) | |
449 | over 0 2swap bounds ?do | |
450 | i 1 http-read-body 0= ?leave | |
451 | i c@ linefeed = ?leave | |
452 | i c@ carret <> if 1+ then | |
453 | loop | |
454 | ; | |
455 | ||
456 | \ Process body part header lines. | |
457 | : http-process-part-headers ( -- ) | |
458 | d# 80 dup alloc-mem swap ( buf$ ) | |
459 | 0 to http-bodypart-length ( buf$ ) | |
460 | begin 2dup http-read-part-hdrline dup 0= while ( buf$ line$ ) | |
461 | 2drop ( buf$ ) | |
462 | repeat ( buf$ boundary$ ) | |
463 | http-process-boundary$ 0= if ( buf$ ) | |
464 | begin 2dup http-read-part-hdrline dup while ( buf$ line$ ) | |
465 | ascii : left-parse-string ( buf$ value$ field$ ) | |
466 | http-part-headers find-token-handler if ( buf$ value$ xt ) | |
467 | execute ( buf$ ) | |
468 | else ( buf$ value$ ) | |
469 | 2drop ( buf$ ) | |
470 | then ( buf$ ) | |
471 | repeat 2drop ( buf$ ) | |
472 | then ( buf$ ) | |
473 | free-mem ( ) | |
474 | ; | |
475 | ||
476 | \ Establish a connection with the HTTP server. The server is accessed | |
477 | \ via a proxy server if one was specified. | |
478 | ||
479 | : http-init ( url$ proxy$ -- ) | |
480 | http-init-proxy ( url$ ) | |
481 | 2dup check-httpurl$-form ( url$ ) | |
482 | parse-http-url 2swap 2drop http-init-server ( ) | |
483 | ||
484 | http-srv-addr ( insock ) | |
485 | use-proxy? if ( insock ) | |
486 | http-proxy-ip http-proxy-port ( insock proxyip,port ) | |
487 | else ( insock ) | |
488 | http-server-ip http-server-port ( insock srvip,port ) | |
489 | then ( insock ipaddr,port ) | |
490 | insock-init ( ) | |
491 | ||
492 | AF_INET SOCK_STREAM 0 socreate to http-sockid ( ) | |
493 | http-sockid http-srv-addr /insock soconnect ( 0 | error# ) | |
494 | 0<> if ( ) | |
495 | http-sockid http-srv-addr ( sockid insock ) | |
496 | ." HTTP: Could not connect to " .insock .soerror ( ) | |
497 | -1 throw | |
498 | then ( ) | |
499 | ||
500 | htbuf-alloc to http-inbuf ( ) | |
501 | http-chunk-init to http-chunkinfo ( ) | |
502 | ; | |
503 | ||
504 | \ Close HTTP connection and free resources. | |
505 | : http-close ( -- ) | |
506 | http-sockid soclose ( ) | |
507 | http-inbuf htbuf-free http-chunkinfo http-chunk-free ( ) | |
508 | ; | |
509 | ||
510 | [ifdef] DEBUG | |
511 | : http-load ( adr url$ proxy$ -- ) | |
512 | 2over 2swap http-init ( adr url$ ) | |
513 | http-send-request ( adr ) | |
514 | http-process-headers ( adr ) | |
515 | h# a00000 http-read-body ( size ) | |
516 | http-close ( size ) | |
517 | ; | |
518 | [then] | |
519 | ||
520 | headers |