Subversion Repositories Kolibri OS

Rev

Rev 4209 | Rev 4212 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4209 Rev 4211
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
5
;;                                                                 ;;
6
;;  HTTP library for KolibriOS                                     ;;
6
;;  HTTP library for KolibriOS                                     ;;
7
;;                                                                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
9
;;                                                                 ;;
10
;;         GNU GENERAL PUBLIC LICENSE                              ;;
10
;;         GNU GENERAL PUBLIC LICENSE                              ;;
11
;;          Version 2, June 1991                                   ;;
11
;;          Version 2, June 1991                                   ;;
12
;;                                                                 ;;
12
;;                                                                 ;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
 
14
 
15
; references:
15
; references:
16
; "HTTP made really easy", http://www.jmarshall.com/easy/http/
16
; "HTTP made really easy", http://www.jmarshall.com/easy/http/
17
; "Hypertext Transfer Protocol -- HTTP/1.1", http://tools.ietf.org/html/rfc2616
17
; "Hypertext Transfer Protocol -- HTTP/1.1", http://tools.ietf.org/html/rfc2616
18
 
18
 
19
 
19
 
20
        URLMAXLEN       = 65535
20
        URLMAXLEN       = 65535
21
        BUFFERSIZE      = 4096
21
        BUFFERSIZE      = 4096
22
        TIMEOUT         = 1000  ; in 1/100 s
22
        TIMEOUT         = 1000  ; in 1/100 s
23
 
23
 
24
        __DEBUG__       = 1
24
        __DEBUG__       = 1
25
        __DEBUG_LEVEL__ = 1
25
        __DEBUG_LEVEL__ = 1
26
 
26
 
27
 
27
 
28
format MS COFF
28
format MS COFF
29
 
29
 
30
public @EXPORT as 'EXPORTS'
30
public @EXPORT as 'EXPORTS'
31
 
31
 
32
include '../../../struct.inc'
32
include '../../../struct.inc'
33
include '../../../proc32.inc'
33
include '../../../proc32.inc'
34
include '../../../macros.inc'
34
include '../../../macros.inc'
35
purge section,mov,add,sub
35
purge section,mov,add,sub
36
include '../../../debug-fdo.inc'
36
include '../../../debug-fdo.inc'
37
 
37
 
38
include '../../../network.inc'
38
include '../../../network.inc'
39
include 'http.inc'
39
include 'http.inc'
40
 
40
 
41
virtual at 0
41
virtual at 0
42
        http_msg http_msg
42
        http_msg http_msg
43
end virtual
43
end virtual
44
 
44
 
45
macro copy_till_zero {
45
macro copy_till_zero {
46
  @@:
46
  @@:
47
        lodsb
47
        lodsb
48
        test    al, al
48
        test    al, al
49
        jz      @f
49
        jz      @f
50
        stosb
50
        stosb
51
        jmp     @r
51
        jmp     @r
52
  @@:
52
  @@:
53
}
53
}
54
 
54
 
55
macro HTTP_init_buffer buffer, socketnum {
55
macro HTTP_init_buffer buffer, socketnum {
56
 
56
 
57
        mov     eax, buffer
57
        mov     eax, buffer
58
        push    socketnum
58
        push    socketnum
59
        popd    [eax + http_msg.socket]
59
        popd    [eax + http_msg.socket]
60
        lea     esi, [eax + http_msg.data]
60
        lea     esi, [eax + http_msg.data]
61
        mov     [eax + http_msg.flags], FLAG_CONNECTED
61
        mov     [eax + http_msg.flags], FLAG_CONNECTED
62
        mov     [eax + http_msg.write_ptr], esi
62
        mov     [eax + http_msg.write_ptr], esi
63
        mov     [eax + http_msg.buffer_length], BUFFERSIZE -  http_msg.data
63
        mov     [eax + http_msg.buffer_length], BUFFERSIZE -  http_msg.data
64
        mov     [eax + http_msg.chunk_ptr], 0
64
        mov     [eax + http_msg.chunk_ptr], 0
65
 
65
 
66
        mov     [eax + http_msg.status], 0
66
        mov     [eax + http_msg.status], 0
67
        mov     [eax + http_msg.header_length], 0
67
        mov     [eax + http_msg.header_length], 0
68
        mov     [eax + http_msg.content_length], 0
68
        mov     [eax + http_msg.content_length], 0
69
        mov     [eax + http_msg.content_received], 0
69
        mov     [eax + http_msg.content_received], 0
70
 
70
 
71
        push    eax ebp
71
        push    eax ebp
72
        mov     ebp, eax
72
        mov     ebp, eax
73
        mcall   29, 9
73
        mcall   29, 9
74
        mov     [ebp + http_msg.timestamp], eax
74
        mov     [ebp + http_msg.timestamp], eax
75
        pop     ebp eax
75
        pop     ebp eax
76
}
76
}
77
 
77
 
78
section '.flat' code readable align 16
78
section '.flat' code readable align 16
79
 
79
 
80
;;===========================================================================;;
80
;;===========================================================================;;
81
lib_init: ;//////////////////////////////////////////////////////////////////;;
81
lib_init: ;//////////////////////////////////////////////////////////////////;;
82
;;---------------------------------------------------------------------------;;
82
;;---------------------------------------------------------------------------;;
83
;? Library entry point (called after library load)                           ;;
83
;? Library entry point (called after library load)                           ;;
84
;;---------------------------------------------------------------------------;;
84
;;---------------------------------------------------------------------------;;
85
;> eax = pointer to memory allocation routine                                ;;
85
;> eax = pointer to memory allocation routine                                ;;
86
;> ebx = pointer to memory freeing routine                                   ;;
86
;> ebx = pointer to memory freeing routine                                   ;;
87
;> ecx = pointer to memory reallocation routine                              ;;
87
;> ecx = pointer to memory reallocation routine                              ;;
88
;> edx = pointer to library loading routine                                  ;;
88
;> edx = pointer to library loading routine                                  ;;
89
;;---------------------------------------------------------------------------;;
89
;;---------------------------------------------------------------------------;;
90
;< eax = 1 (fail) / 0 (ok)                                                   ;;
90
;< eax = 1 (fail) / 0 (ok)                                                   ;;
91
;;===========================================================================;;
91
;;===========================================================================;;
92
        mov     [mem.alloc], eax
92
        mov     [mem.alloc], eax
93
        mov     [mem.free], ebx
93
        mov     [mem.free], ebx
94
        mov     [mem.realloc], ecx
94
        mov     [mem.realloc], ecx
95
        mov     [dll.load], edx
95
        mov     [dll.load], edx
96
 
96
 
97
        invoke  dll.load, @IMPORT
97
        invoke  dll.load, @IMPORT
98
        test    eax, eax
98
        test    eax, eax
99
        jnz     .error
99
        jnz     .error
100
 
100
 
101
; load proxy settings
101
; load proxy settings
102
        invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
102
        invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
103
        invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
103
        invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
104
        mov     [proxyPort], eax
104
        mov     [proxyPort], eax
105
        invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
105
        invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
106
        invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
106
        invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
-
 
107
 
-
 
108
        DEBUGF  1, "HTTP library: init OK"
107
 
109
 
108
        xor     eax, eax
110
        xor     eax, eax
109
        ret
111
        ret
110
 
112
 
111
  .error:
113
  .error:
-
 
114
        DEBUGF  1, "ERROR loading libraries"
-
 
115
 
112
        xor     eax, eax
116
        xor     eax, eax
113
        inc     eax
117
        inc     eax
114
 
118
 
115
        ret
119
        ret
116
 
120
 
117
 
121
 
118
 
122
 
119
 
123
 
120
;;================================================================================================;;
124
;;================================================================================================;;
121
proc HTTP_get URL ;///////////////////////////////////////////////////////////////////////////////;;
125
proc HTTP_get URL ;///////////////////////////////////////////////////////////////////////////////;;
122
;;------------------------------------------------------------------------------------------------;;
126
;;------------------------------------------------------------------------------------------------;;
123
;? Initiates a HTTP connection, using 'GET' method.                                               ;;
127
;? Initiates a HTTP connection, using 'GET' method.                                               ;;
124
;;------------------------------------------------------------------------------------------------;;
128
;;------------------------------------------------------------------------------------------------;;
125
;> URL = pointer to ASCIIZ URL                                                                    ;;
129
;> URL = pointer to ASCIIZ URL                                                                    ;;
126
;;------------------------------------------------------------------------------------------------;;
130
;;------------------------------------------------------------------------------------------------;;
127
;< eax = 0 (error) / buffer ptr                                                                   ;;
131
;< eax = 0 (error) / buffer ptr                                                                   ;;
128
;;================================================================================================;;
132
;;================================================================================================;;
129
locals
133
locals
130
        hostname        dd ?
134
        hostname        dd ?
131
        pageaddr        dd ?
135
        pageaddr        dd ?
132
        sockaddr        dd ?
136
        sockaddr        dd ?
133
        socketnum       dd ?
137
        socketnum       dd ?
134
        buffer          dd ?
138
        buffer          dd ?
135
        port            dd ?
139
        port            dd ?
136
endl
140
endl
137
 
141
 
138
; split the URL into hostname and pageaddr
142
; split the URL into hostname and pageaddr
139
        stdcall parse_url, [URL]
143
        stdcall parse_url, [URL]
140
        test    eax, eax
144
        test    eax, eax
141
        jz      .error
145
        jz      .error
142
        mov     [hostname], eax
146
        mov     [hostname], eax
143
        mov     [pageaddr], ebx
147
        mov     [pageaddr], ebx
144
 
148
 
145
; Do we need to use a proxy?
149
; Do we need to use a proxy?
146
        cmp     [proxyAddr], 0
150
        cmp     [proxyAddr], 0
147
        jne     .proxy_done
151
        jne     .proxy_done
148
 
152
 
149
  .proxy_done:
153
  .proxy_done:
150
 
154
 
151
;;;;
155
;;;;
152
        mov     [port], 80      ;;;; FIXME
156
        mov     [port], 80      ;;;; FIXME
153
 
157
 
154
; Connect to the other side.
158
; Connect to the other side.
155
        stdcall open_connection, [hostname], [port]
159
        stdcall open_connection, [hostname], [port]
156
        test    eax, eax
160
        test    eax, eax
157
        jz      .error
161
        jz      .error
158
        mov     [socketnum], eax
162
        mov     [socketnum], eax
159
 
163
 
160
; Create the HTTP request.
164
; Create the HTTP request.
161
        invoke  mem.alloc, BUFFERSIZE
165
        invoke  mem.alloc, BUFFERSIZE
162
        test    eax, eax
166
        test    eax, eax
163
        jz      .error
167
        jz      .error
164
        mov     [buffer], eax
168
        mov     [buffer], eax
165
        mov     edi, eax
169
        mov     edi, eax
166
        DEBUGF  1, "Buffer has been allocated.\n"
170
        DEBUGF  1, "Buffer has been allocated.\n"
167
 
171
 
168
        mov     esi, str_get
172
        mov     esi, str_get
169
        copy_till_zero
173
        copy_till_zero
170
 
174
 
171
        mov     esi, [pageaddr]
175
        mov     esi, [pageaddr]
172
        copy_till_zero
176
        copy_till_zero
173
 
177
 
174
        mov     esi, str_http11
178
        mov     esi, str_http11
175
        mov     ecx, str_http11.length
179
        mov     ecx, str_http11.length
176
        rep     movsb
180
        rep     movsb
177
 
181
 
178
        mov     esi, [hostname]
182
        mov     esi, [hostname]
179
        copy_till_zero
183
        copy_till_zero
180
 
184
 
181
        mov     esi, str_close
185
        mov     esi, str_close
182
        mov     ecx, str_close.length
186
        mov     ecx, str_close.length
183
        rep     movsb
187
        rep     movsb
184
 
188
 
185
        mov     byte[edi], 0
189
        mov     byte[edi], 0
186
        DEBUGF  1, "Request:\n%s", [buffer]
190
        DEBUGF  1, "Request:\n%s", [buffer]
187
 
191
 
188
; Send the request
192
; Send the request
189
        mov     esi, edi
193
        mov     esi, edi
190
        sub     esi, [buffer]   ; length
194
        sub     esi, [buffer]   ; length
191
        xor     edi, edi        ; flags
195
        xor     edi, edi        ; flags
192
 
196
 
193
        mcall   send, [socketnum], [buffer]
197
        mcall   send, [socketnum], [buffer]
194
        test    eax, eax
198
        test    eax, eax
195
        jz      .error
199
        jz      .error
196
        DEBUGF  1, "Request has been sent to server.\n"
200
        DEBUGF  1, "Request has been sent to server.\n"
197
 
201
 
198
        HTTP_init_buffer [buffer], [socketnum]
202
        HTTP_init_buffer [buffer], [socketnum]
199
 
203
 
200
        ret                     ; return buffer ptr
204
        ret                     ; return buffer ptr
201
 
205
 
202
  .error:
206
  .error:
203
        DEBUGF  1, "Error!\n"
207
        DEBUGF  1, "Error!\n"
204
        xor     eax, eax        ; return 0 = error
208
        xor     eax, eax        ; return 0 = error
205
        ret
209
        ret
206
 
210
 
207
endp
211
endp
208
 
212
 
209
 
213
 
210
 
214
 
211
;;================================================================================================;;
215
;;================================================================================================;;
212
proc HTTP_head URL ;//////////////////////////////////////////////////////////////////////////////;;
216
proc HTTP_head URL ;//////////////////////////////////////////////////////////////////////////////;;
213
;;------------------------------------------------------------------------------------------------;;
217
;;------------------------------------------------------------------------------------------------;;
214
;? Initiates a HTTP connection, using 'HEAD' method.                                              ;;
218
;? Initiates a HTTP connection, using 'HEAD' method.                                              ;;
215
;;------------------------------------------------------------------------------------------------;;
219
;;------------------------------------------------------------------------------------------------;;
216
;> URL = pointer to ASCIIZ URL                                                                    ;;
220
;> URL = pointer to ASCIIZ URL                                                                    ;;
217
;;------------------------------------------------------------------------------------------------;;
221
;;------------------------------------------------------------------------------------------------;;
218
;< eax = 0 (error) / buffer ptr                                                                   ;;
222
;< eax = 0 (error) / buffer ptr                                                                   ;;
219
;;================================================================================================;;
223
;;================================================================================================;;
220
locals
224
locals
221
        hostname        dd ?
225
        hostname        dd ?
222
        pageaddr        dd ?
226
        pageaddr        dd ?
223
        sockaddr        dd ?
227
        sockaddr        dd ?
224
        socketnum       dd ?
228
        socketnum       dd ?
225
        buffer          dd ?
229
        buffer          dd ?
226
        port            dd ?
230
        port            dd ?
227
endl
231
endl
228
 
232
 
229
; split the URL into hostname and pageaddr
233
; split the URL into hostname and pageaddr
230
        stdcall parse_url, [URL]
234
        stdcall parse_url, [URL]
231
        test    eax, eax
235
        test    eax, eax
232
        jz      .error
236
        jz      .error
233
        mov     [hostname], eax
237
        mov     [hostname], eax
234
        mov     [pageaddr], ebx
238
        mov     [pageaddr], ebx
235
 
239
 
236
; Do we need to use a proxy?
240
; Do we need to use a proxy?
237
        cmp     [proxyAddr], 0
241
        cmp     [proxyAddr], 0
238
        jne     .proxy_done
242
        jne     .proxy_done
239
 
243
 
240
        ; TODO: set hostname to that of the
244
        ; TODO: set hostname to that of the
241
  .proxy_done:
245
  .proxy_done:
242
 
246
 
243
;;;;
247
;;;;
244
        mov     [port], 80      ;;;; FIXME
248
        mov     [port], 80      ;;;; FIXME
245
 
249
 
246
; Connect to the other side.
250
; Connect to the other side.
247
        stdcall open_connection, [hostname], [port]
251
        stdcall open_connection, [hostname], [port]
248
        test    eax, eax
252
        test    eax, eax
249
        jz      .error
253
        jz      .error
250
        mov     [socketnum], eax
254
        mov     [socketnum], eax
251
 
255
 
252
; Create the HTTP request.
256
; Create the HTTP request.
253
        invoke  mem.alloc, BUFFERSIZE
257
        invoke  mem.alloc, BUFFERSIZE
254
        test    eax, eax
258
        test    eax, eax
255
        jz      .error
259
        jz      .error
256
        mov     [buffer], eax
260
        mov     [buffer], eax
257
        mov     edi, eax
261
        mov     edi, eax
258
        DEBUGF  1, "Buffer has been allocated.\n"
262
        DEBUGF  1, "Buffer has been allocated.\n"
259
 
263
 
260
        mov     esi, str_head
264
        mov     esi, str_head
261
        copy_till_zero
265
        copy_till_zero
262
 
266
 
263
        mov     esi, [pageaddr]
267
        mov     esi, [pageaddr]
264
        copy_till_zero
268
        copy_till_zero
265
 
269
 
266
        mov     esi, str_http11
270
        mov     esi, str_http11
267
        mov     ecx, str_http11.length
271
        mov     ecx, str_http11.length
268
        rep     movsb
272
        rep     movsb
269
 
273
 
270
        mov     esi, [hostname]
274
        mov     esi, [hostname]
271
        copy_till_zero
275
        copy_till_zero
272
 
276
 
273
        mov     esi, str_close
277
        mov     esi, str_close
274
        mov     ecx, str_close.length
278
        mov     ecx, str_close.length
275
        rep     movsb
279
        rep     movsb
276
 
280
 
277
        mov     byte[edi], 0
281
        mov     byte[edi], 0
278
        DEBUGF  1, "Request:\n%s", [buffer]
282
        DEBUGF  1, "Request:\n%s", [buffer]
279
 
283
 
280
; Send the request
284
; Send the request
281
        mov     esi, edi
285
        mov     esi, edi
282
        sub     esi, [buffer]   ; length
286
        sub     esi, [buffer]   ; length
283
        xor     edi, edi        ; flags
287
        xor     edi, edi        ; flags
284
 
288
 
285
        mcall   send, [socketnum], [buffer]
289
        mcall   send, [socketnum], [buffer]
286
        test    eax, eax
290
        test    eax, eax
287
        jz      .error
291
        jz      .error
288
        DEBUGF  1, "Request has been sent to server.\n"
292
        DEBUGF  1, "Request has been sent to server.\n"
289
 
293
 
290
        HTTP_init_buffer [buffer], [socketnum]
294
        HTTP_init_buffer [buffer], [socketnum]
291
 
295
 
292
        ret                     ; return buffer ptr
296
        ret                     ; return buffer ptr
293
 
297
 
294
  .error:
298
  .error:
295
        DEBUGF  1, "Error!\n"
299
        DEBUGF  1, "Error!\n"
296
        xor     eax, eax        ; return 0 = error
300
        xor     eax, eax        ; return 0 = error
297
        ret
301
        ret
298
 
302
 
299
endp
303
endp
300
 
304
 
301
 
305
 
302
;;================================================================================================;;
306
;;================================================================================================;;
303
proc HTTP_post URL, content_type, content_length ;////////////////////////////////////////////////;;
307
proc HTTP_post URL, content_type, content_length ;////////////////////////////////////////////////;;
304
;;------------------------------------------------------------------------------------------------;;
308
;;------------------------------------------------------------------------------------------------;;
305
;? Initiates a HTTP connection, using 'GET' method.                                               ;;
309
;? Initiates a HTTP connection, using 'GET' method.                                               ;;
306
;;------------------------------------------------------------------------------------------------;;
310
;;------------------------------------------------------------------------------------------------;;
307
;> URL                  = pointer to ASCIIZ URL                                                   ;;
311
;> URL                  = pointer to ASCIIZ URL                                                   ;;
308
;> content_type         = pointer to ASCIIZ string containing content type                        ;;
312
;> content_type         = pointer to ASCIIZ string containing content type                        ;;
309
;> content_length       = length of content (in bytes)                                            ;;
313
;> content_length       = length of content (in bytes)                                            ;;
310
;;------------------------------------------------------------------------------------------------;;
314
;;------------------------------------------------------------------------------------------------;;
311
;< eax = 0 (error) / buffer ptr                                                                   ;;
315
;< eax = 0 (error) / buffer ptr                                                                   ;;
312
;;================================================================================================;;
316
;;================================================================================================;;
313
locals
317
locals
314
        hostname        dd ?
318
        hostname        dd ?
315
        pageaddr        dd ?
319
        pageaddr        dd ?
316
        sockaddr        dd ?
320
        sockaddr        dd ?
317
        socketnum       dd ?
321
        socketnum       dd ?
318
        buffer          dd ?
322
        buffer          dd ?
319
        port            dd ?
323
        port            dd ?
320
endl
324
endl
321
 
325
 
322
; split the URL into hostname and pageaddr
326
; split the URL into hostname and pageaddr
323
        stdcall parse_url, [URL]
327
        stdcall parse_url, [URL]
324
        test    eax, eax
328
        test    eax, eax
325
        jz      .error
329
        jz      .error
326
        mov     [hostname], eax
330
        mov     [hostname], eax
327
        mov     [pageaddr], ebx
331
        mov     [pageaddr], ebx
328
 
332
 
329
; Do we need to use a proxy?
333
; Do we need to use a proxy?
330
        cmp     [proxyAddr], 0
334
        cmp     [proxyAddr], 0
331
        jne     .proxy_done
335
        jne     .proxy_done
332
 
336
 
333
        ; TODO: set hostname to that of the
337
        ; TODO: set hostname to that of the
334
  .proxy_done:
338
  .proxy_done:
335
 
339
 
336
;;;;
340
;;;;
337
        mov     [port], 80      ;;;; FIXME
341
        mov     [port], 80      ;;;; FIXME
338
 
342
 
339
; Connect to the other side.
343
; Connect to the other side.
340
        stdcall open_connection, [hostname], [port]
344
        stdcall open_connection, [hostname], [port]
341
        test    eax, eax
345
        test    eax, eax
342
        jz      .error
346
        jz      .error
343
        mov     [socketnum], eax
347
        mov     [socketnum], eax
344
 
348
 
345
; Create the HTTP request.
349
; Create the HTTP request.
346
        invoke  mem.alloc, BUFFERSIZE
350
        invoke  mem.alloc, BUFFERSIZE
347
        test    eax, eax
351
        test    eax, eax
348
        jz      .error
352
        jz      .error
349
        mov     [buffer], eax
353
        mov     [buffer], eax
350
        mov     edi, eax
354
        mov     edi, eax
351
        DEBUGF  1, "Buffer has been allocated.\n"
355
        DEBUGF  1, "Buffer has been allocated.\n"
352
 
356
 
353
        mov     esi, str_post
357
        mov     esi, str_post
354
        copy_till_zero
358
        copy_till_zero
355
 
359
 
356
        mov     esi, [pageaddr]
360
        mov     esi, [pageaddr]
357
        copy_till_zero
361
        copy_till_zero
358
 
362
 
359
        mov     esi, str_http11
363
        mov     esi, str_http11
360
        mov     ecx, str_http11.length
364
        mov     ecx, str_http11.length
361
        rep     movsb
365
        rep     movsb
362
 
366
 
363
        mov     esi, [hostname]
367
        mov     esi, [hostname]
364
        copy_till_zero
368
        copy_till_zero
365
 
369
 
366
        mov     esi, str_post_cl
370
        mov     esi, str_post_cl
367
        mov     ecx, str_post_cl.length
371
        mov     ecx, str_post_cl.length
368
        rep     movsb
372
        rep     movsb
369
 
373
 
370
        mov     eax, [content_length]
374
        mov     eax, [content_length]
371
        call    ascii_dec
375
        call    ascii_dec
372
 
376
 
373
        mov     esi, str_post_ct
377
        mov     esi, str_post_ct
374
        mov     ecx, str_post_ct.length
378
        mov     ecx, str_post_ct.length
375
        rep     movsb
379
        rep     movsb
376
 
380
 
377
        mov     esi, [content_type]
381
        mov     esi, [content_type]
378
        rep     movsb
382
        rep     movsb
379
 
383
 
380
        mov     esi, str_close
384
        mov     esi, str_close
381
        mov     ecx, str_close.length
385
        mov     ecx, str_close.length
382
        rep     movsb
386
        rep     movsb
383
 
387
 
384
        mov     byte[edi], 0
388
        mov     byte[edi], 0
385
        DEBUGF  1, "Request:\n%s", [buffer]
389
        DEBUGF  1, "Request:\n%s", [buffer]
386
 
390
 
387
; Send the request
391
; Send the request
388
        mov     esi, edi
392
        mov     esi, edi
389
        sub     esi, [buffer]   ; length
393
        sub     esi, [buffer]   ; length
390
        xor     edi, edi        ; flags
394
        xor     edi, edi        ; flags
391
        mcall   send, [socketnum], [buffer]
395
        mcall   send, [socketnum], [buffer]
392
        test    eax, eax
396
        test    eax, eax
393
        jz      .error
397
        jz      .error
394
        DEBUGF  1, "Request has been sent to server.\n"
398
        DEBUGF  1, "Request has been sent to server.\n"
395
 
399
 
396
        HTTP_init_buffer [buffer], [socketnum]
400
        HTTP_init_buffer [buffer], [socketnum]
397
 
401
 
398
;        mov     eax, [buffer]
402
;        mov     eax, [buffer]
399
 
403
 
400
        ret                     ; return buffer ptr
404
        ret                     ; return buffer ptr
401
 
405
 
402
  .error:
406
  .error:
403
        DEBUGF  1, "Error!\n"
407
        DEBUGF  1, "Error!\n"
404
        xor     eax, eax        ; return 0 = error
408
        xor     eax, eax        ; return 0 = error
405
        ret
409
        ret
406
 
410
 
407
endp
411
endp
408
 
412
 
409
 
413
 
410
 
414
 
411
;;================================================================================================;;
415
;;================================================================================================;;
412
proc HTTP_process identifier ;////////////////////////////////////////////////////////////////////;;
416
proc HTTP_process identifier ;////////////////////////////////////////////////////////////////////;;
413
;;------------------------------------------------------------------------------------------------;;
417
;;------------------------------------------------------------------------------------------------;;
414
;? Receive data from the server, parse headers and put data in receive buffer.                    ;;
418
;? Receive data from the server, parse headers and put data in receive buffer.                    ;;
415
;? To complete a transfer, this procedure must be called over and over again untill it returns 0. ;;
419
;? To complete a transfer, this procedure must be called over and over again untill it returns 0. ;;
416
;;------------------------------------------------------------------------------------------------;;
420
;;------------------------------------------------------------------------------------------------;;
417
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
421
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
418
;;------------------------------------------------------------------------------------------------;;
422
;;------------------------------------------------------------------------------------------------;;
419
;< eax = -1 (not finished) / 0 finished                                                           ;;
423
;< eax = -1 (not finished) / 0 finished                                                           ;;
420
;;================================================================================================;;
424
;;================================================================================================;;
421
        pusha
425
        pusha
422
        mov     ebp, [identifier]
426
        mov     ebp, [identifier]
423
 
427
 
424
; If the connection is closed, return immediately
428
; If the connection is closed, return immediately
425
        test    [ebp + http_msg.flags], FLAG_CONNECTED
429
        test    [ebp + http_msg.flags], FLAG_CONNECTED
426
        jz      .connection_closed
430
        jz      .connection_closed
427
 
431
 
428
; Receive some data
432
; Receive some data
429
        mcall   recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \
433
        mcall   recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \
430
                      [ebp + http_msg.buffer_length], MSG_DONTWAIT
434
                      [ebp + http_msg.buffer_length], MSG_DONTWAIT
431
        cmp     eax, 0xffffffff
435
        cmp     eax, 0xffffffff
432
        je      .check_socket
436
        je      .check_socket
433
        DEBUGF  1, "Received %u bytes\n", eax
437
        DEBUGF  1, "Received %u bytes\n", eax
434
 
438
 
435
; Update timestamp
439
; Update timestamp
436
        push    eax
440
        push    eax
437
        mcall   29, 9
441
        mcall   29, 9
438
        mov     [ebp + http_msg.timestamp], eax
442
        mov     [ebp + http_msg.timestamp], eax
439
        pop     eax
443
        pop     eax
440
 
444
 
441
; Update pointers
445
; Update pointers
442
        mov     edi, [ebp + http_msg.write_ptr]
446
        mov     edi, [ebp + http_msg.write_ptr]
443
        add     [ebp + http_msg.write_ptr], eax
447
        add     [ebp + http_msg.write_ptr], eax
444
        sub     [ebp + http_msg.buffer_length], eax
448
        sub     [ebp + http_msg.buffer_length], eax
445
        jz      .got_all_data
449
        jz      .got_all_data
446
 
450
 
447
; If data is chunked, combine chunks into contiguous data.
451
; If data is chunked, combine chunks into contiguous data.
448
        test    [ebp + http_msg.flags], FLAG_CHUNKED
452
        test    [ebp + http_msg.flags], FLAG_CHUNKED
449
        jnz     .chunk_loop
453
        jnz     .chunk_loop
450
 
454
 
451
; Did we detect the header yet?
455
; Did we detect the header yet?
452
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
456
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
453
        jnz     .header_parsed
457
        jnz     .header_parsed
454
 
458
 
455
        push    eax
459
        push    eax
456
 
460
 
457
; We havent found the header yet, search for it..
461
; We havent found the header yet, search for it..
458
        sub     eax, 4
462
        sub     eax, 4
459
        jl      .need_more_data_pop
463
        jl      .need_more_data_pop
460
        inc     eax
464
        inc     eax
461
  .scan:
465
  .scan:
462
        ; scan for end of header (empty line)
466
        ; scan for end of header (empty line)
463
        cmp     dword[edi], 0x0a0d0a0d                  ; end of header
467
        cmp     dword[edi], 0x0a0d0a0d                  ; end of header
464
        je      .end_of_header
468
        je      .end_of_header
465
        cmp     word[edi+2], 0x0a0a
469
        cmp     word[edi+2], 0x0a0a
466
        je      .end_of_header
470
        je      .end_of_header
467
        inc     edi
471
        inc     edi
468
        dec     eax
472
        dec     eax
469
        jnz     .scan
473
        jnz     .scan
470
        jmp     .need_more_data_pop
474
        jmp     .need_more_data_pop
471
 
475
 
472
  .end_of_header:
476
  .end_of_header:
473
        add     edi, 4 - http_msg.data
477
        add     edi, 4 - http_msg.data
474
        sub     edi, ebp
478
        sub     edi, ebp
475
        mov     [ebp + http_msg.header_length], edi
479
        mov     [ebp + http_msg.header_length], edi
476
        or      [ebp + http_msg.flags], FLAG_GOT_HEADER
480
        or      [ebp + http_msg.flags], FLAG_GOT_HEADER
477
        DEBUGF  1, "Header length: %u\n", edi
481
        DEBUGF  1, "Header length: %u\n", edi
478
 
482
 
479
; Ok, we have found header:
483
; Ok, we have found header:
480
        cmp     dword[ebp + http_msg.data], 'HTTP'
484
        cmp     dword[ebp + http_msg.data], 'HTTP'
481
        jne     .invalid_header
485
        jne     .invalid_header
482
        cmp     dword[ebp + http_msg.data+4], '/1.0'
486
        cmp     dword[ebp + http_msg.data+4], '/1.0'
483
        je      .http_1.0
487
        je      .http_1.0
484
        cmp     dword[ebp + http_msg.data+4], '/1.1'
488
        cmp     dword[ebp + http_msg.data+4], '/1.1'
485
        jne     .invalid_header
489
        jne     .invalid_header
486
        or      [ebp + http_msg.flags], FLAG_HTTP11
490
        or      [ebp + http_msg.flags], FLAG_HTTP11
487
  .http_1.0:
491
  .http_1.0:
488
        cmp     byte[ebp + http_msg.data+8], ' '
492
        cmp     byte[ebp + http_msg.data+8], ' '
489
        jne     .invalid_header
493
        jne     .invalid_header
490
        DEBUGF  1, "Header seems valid.\n"
494
        DEBUGF  1, "Header seems valid.\n"
491
 
495
 
492
        lea     esi, [ebp + http_msg.data+9]
496
        lea     esi, [ebp + http_msg.data+9]
493
        xor     eax, eax
497
        xor     eax, eax
494
        xor     ebx, ebx
498
        xor     ebx, ebx
495
        mov     ecx, 3
499
        mov     ecx, 3
496
  .statusloop:
500
  .statusloop:
497
        lodsb
501
        lodsb
498
        sub     al, '0'
502
        sub     al, '0'
499
        jb      .invalid_header
503
        jb      .invalid_header
500
        cmp     al, 9
504
        cmp     al, 9
501
        ja      .invalid_header
505
        ja      .invalid_header
502
        lea     ebx, [ebx + 4*ebx]
506
        lea     ebx, [ebx + 4*ebx]
503
        shl     ebx, 1
507
        shl     ebx, 1
504
        add     ebx, eax
508
        add     ebx, eax
505
        dec     ecx
509
        dec     ecx
506
        jnz     .statusloop
510
        jnz     .statusloop
507
        mov     [ebp + http_msg.status], ebx
511
        mov     [ebp + http_msg.status], ebx
508
        DEBUGF  1, "Status: %u\n", ebx
512
        DEBUGF  1, "Status: %u\n", ebx
509
 
513
 
510
; Now, convert all header names to lowercase.
514
; Now, convert all header names to lowercase.
511
; This way, it will be much easier to find certain header fields, later on.
515
; This way, it will be much easier to find certain header fields, later on.
512
 
516
 
513
        lea     esi, [ebp + http_msg.data]
517
        lea     esi, [ebp + http_msg.data]
514
        mov     ecx, [ebp + http_msg.header_length]
518
        mov     ecx, [ebp + http_msg.header_length]
515
  .need_newline:
519
  .need_newline:
516
        inc     esi
520
        inc     esi
517
        dec     ecx
521
        dec     ecx
518
        jz      .convert_done
522
        jz      .convert_done
519
        cmp     byte[esi], 10
523
        cmp     byte[esi], 10
520
        jne     .need_newline
524
        jne     .need_newline
521
; Ok, we have a newline, a line beginning with space or tabs has no header fields.
525
; Ok, we have a newline, a line beginning with space or tabs has no header fields.
522
 
526
 
523
        inc     esi
527
        inc     esi
524
        dec     ecx
528
        dec     ecx
525
        jz      .convert_done
529
        jz      .convert_done
526
        cmp     byte[esi], ' '
530
        cmp     byte[esi], ' '
527
        je      .need_newline
531
        je      .need_newline
528
        cmp     byte[esi], 9    ; horizontal tab
532
        cmp     byte[esi], 9    ; horizontal tab
529
        je      .need_newline
533
        je      .need_newline
530
        jmp     .convert_loop
534
        jmp     .convert_loop
531
  .next_char:
535
  .next_char:
532
        inc     esi
536
        inc     esi
533
        dec     ecx
537
        dec     ecx
534
        jz      .convert_done
538
        jz      .convert_done
535
  .convert_loop:
539
  .convert_loop:
536
        cmp     byte[esi], ':'
540
        cmp     byte[esi], ':'
537
        je      .need_newline
541
        je      .need_newline
538
        cmp     byte[esi], 'A'
542
        cmp     byte[esi], 'A'
539
        jb      .next_char
543
        jb      .next_char
540
        cmp     byte[esi], 'Z'
544
        cmp     byte[esi], 'Z'
541
        ja      .next_char
545
        ja      .next_char
542
        or      byte[esi], 0x20 ; convert to lowercase
546
        or      byte[esi], 0x20 ; convert to lowercase
543
        jmp     .next_char
547
        jmp     .next_char
544
  .convert_done:
548
  .convert_done:
545
        mov     byte[esi-1], 0
549
        mov     byte[esi-1], 0
546
        lea     esi, [ebp + http_msg.data]
550
        lea     esi, [ebp + http_msg.data]
547
        DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
551
        DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
548
 
552
 
549
; Check for content-length header field.
553
; Check for content-length header field.
550
        stdcall find_header_field, ebp, str_cl
554
        stdcall find_header_field, ebp, str_cl
551
        test    eax, eax
555
        test    eax, eax
552
        jz      .no_content
556
        jz      .no_content
553
        or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
557
        or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
554
 
558
 
555
        xor     edx, edx
559
        xor     edx, edx
556
  .cl_loop:
560
  .cl_loop:
557
        movzx   ebx, byte[eax]
561
        movzx   ebx, byte[eax]
558
        inc     eax
562
        inc     eax
559
        cmp     bl, 10
563
        cmp     bl, 10
560
        je      .cl_ok
564
        je      .cl_ok
561
        cmp     bl, 13
565
        cmp     bl, 13
562
        je      .cl_ok
566
        je      .cl_ok
563
        cmp     bl, ' '
567
        cmp     bl, ' '
564
        je      .cl_ok
568
        je      .cl_ok
565
        sub     bl, '0'
569
        sub     bl, '0'
566
        jb      .invalid_header
570
        jb      .invalid_header
567
        cmp     bl, 9
571
        cmp     bl, 9
568
        ja      .invalid_header
572
        ja      .invalid_header
569
        lea     edx, [edx + edx*4]      ; edx = edx*10
573
        lea     edx, [edx + edx*4]      ; edx = edx*10
570
        shl     edx, 1                  ;
574
        shl     edx, 1                  ;
571
        add     edx, ebx
575
        add     edx, ebx
572
        jmp     .cl_loop
576
        jmp     .cl_loop
573
 
577
 
574
  .cl_ok:
578
  .cl_ok:
575
        mov     [ebp + http_msg.content_length], edx
579
        mov     [ebp + http_msg.content_length], edx
576
        DEBUGF  1, "Content-length: %u\n", edx
580
        DEBUGF  1, "Content-length: %u\n", edx
577
 
581
 
578
; Resize buffer according to content-length.
582
; Resize buffer according to content-length.
579
        add     edx, [ebp + http_msg.header_length]
583
        add     edx, [ebp + http_msg.header_length]
580
        add     edx, http_msg.data
584
        add     edx, http_msg.data
581
 
585
 
582
        mov     ecx, edx
586
        mov     ecx, edx
583
        sub     ecx, [ebp + http_msg.write_ptr]
587
        sub     ecx, [ebp + http_msg.write_ptr]
584
        mov     [ebp + http_msg.buffer_length], ecx
588
        mov     [ebp + http_msg.buffer_length], ecx
585
 
589
 
586
        invoke  mem.realloc, ebp, edx
590
        invoke  mem.realloc, ebp, edx
587
        or      eax, eax
591
        or      eax, eax
588
        jz      .no_ram_pop
592
        jz      .no_ram_pop
589
 
593
 
590
        pop     eax
594
        pop     eax
591
        sub     eax, [ebp + http_msg.header_length]
595
        sub     eax, [ebp + http_msg.header_length]
592
        jmp     .header_parsed  ; hooray!
596
        jmp     .header_parsed  ; hooray!
593
 
597
 
594
  .no_content:
598
  .no_content:
595
        DEBUGF  1, "Content-length not found.\n"
599
        DEBUGF  1, "Content-length not found.\n"
596
 
600
 
597
; We didnt find 'content-length', maybe server is using chunked transfer encoding?
601
; We didnt find 'content-length', maybe server is using chunked transfer encoding?
598
; Try to find 'transfer-encoding' header.
602
; Try to find 'transfer-encoding' header.
599
        stdcall find_header_field, ebp, str_te
603
        stdcall find_header_field, ebp, str_te
600
        test    eax, eax
604
        test    eax, eax
601
        jz      .invalid_header
605
        jz      .invalid_header
602
 
606
 
603
        mov     ebx, dword[eax]
607
        mov     ebx, dword[eax]
604
        or      ebx, 0x20202020
608
        or      ebx, 0x20202020
605
        cmp     ebx, 'chun'
609
        cmp     ebx, 'chun'
606
        jne     .invalid_header
610
        jne     .invalid_header
607
        mov     ebx, dword[eax+4]
611
        mov     ebx, dword[eax+4]
608
        or      ebx, 0x00202020
612
        or      ebx, 0x00202020
609
        and     ebx, 0x00ffffff
613
        and     ebx, 0x00ffffff
610
        cmp     ebx, 'ked'
614
        cmp     ebx, 'ked'
611
        jne     .invalid_header
615
        jne     .invalid_header
612
 
616
 
613
        or      [ebp + http_msg.flags], FLAG_CHUNKED
617
        or      [ebp + http_msg.flags], FLAG_CHUNKED
614
        DEBUGF  1, "Transfer type is: chunked\n"
618
        DEBUGF  1, "Transfer type is: chunked\n"
615
 
619
 
616
        pop     eax
620
        pop     eax
617
 
621
 
618
; Set chunk pointer where first chunk should begin.
622
; Set chunk pointer where first chunk should begin.
619
        lea     eax, [ebp + http_msg.data]
623
        lea     eax, [ebp + http_msg.data]
620
        add     eax, [ebp + http_msg.header_length]
624
        add     eax, [ebp + http_msg.header_length]
621
        mov     [ebp + http_msg.chunk_ptr], eax
625
        mov     [ebp + http_msg.chunk_ptr], eax
622
 
626
 
623
  .chunk_loop:
627
  .chunk_loop:
624
        mov     ecx, [ebp + http_msg.write_ptr]
628
        mov     ecx, [ebp + http_msg.write_ptr]
625
        sub     ecx, [ebp + http_msg.chunk_ptr]
629
        sub     ecx, [ebp + http_msg.chunk_ptr]
626
        jb      .need_more_data_chunked         ; TODO: use this ecx !!!
630
        jb      .need_more_data_chunked         ; TODO: use this ecx !!!
627
 
631
 
628
; Chunkline starts here, convert the ASCII hex number into ebx
632
; Chunkline starts here, convert the ASCII hex number into ebx
629
        mov     esi, [ebp + http_msg.chunk_ptr]
633
        mov     esi, [ebp + http_msg.chunk_ptr]
630
        xor     ebx, ebx
634
        xor     ebx, ebx
631
  .chunk_hexloop:
635
  .chunk_hexloop:
632
        lodsb
636
        lodsb
633
        sub     al, '0'
637
        sub     al, '0'
634
        jb      .chunk_
638
        jb      .chunk_
635
        cmp     al, 9
639
        cmp     al, 9
636
        jbe     .chunk_hex
640
        jbe     .chunk_hex
637
        sub     al, 'A' - '0' - 10
641
        sub     al, 'A' - '0' - 10
638
        jb      .chunk_
642
        jb      .chunk_
639
        cmp     al, 15
643
        cmp     al, 15
640
        jbe     .chunk_hex
644
        jbe     .chunk_hex
641
        sub     al, 'a' - 'A'
645
        sub     al, 'a' - 'A'
642
        cmp     al, 15
646
        cmp     al, 15
643
        ja      .chunk_
647
        ja      .chunk_
644
  .chunk_hex:
648
  .chunk_hex:
645
        shl     ebx, 4
649
        shl     ebx, 4
646
        add     bl, al
650
        add     bl, al
647
        jmp     .chunk_hexloop
651
        jmp     .chunk_hexloop
648
  .chunk_:
652
  .chunk_:
649
        DEBUGF  1, "got chunk of %u bytes\n", ebx
653
        DEBUGF  1, "got chunk of %u bytes\n", ebx
650
;;        cmp     esi, [ebp + http_msg.chunk_ptr]
654
;;        cmp     esi, [ebp + http_msg.chunk_ptr]
651
;;        je
655
;;        je
652
; If chunk size is 0, all chunks have been received.
656
; If chunk size is 0, all chunks have been received.
653
        test    ebx, ebx
657
        test    ebx, ebx
654
        jz      .got_all_data_chunked           ; last chunk, hooray! FIXME: what if it wasnt a valid hex number???
658
        jz      .got_all_data_chunked           ; last chunk, hooray! FIXME: what if it wasnt a valid hex number???
655
 
659
 
656
; Chunkline ends with a CR, LF or simply LF
660
; Chunkline ends with a CR, LF or simply LF
657
  .end_of_chunkline?:
661
  .end_of_chunkline?:
658
        cmp     al, 10
662
        cmp     al, 10
659
        je      .end_of_chunkline
663
        je      .end_of_chunkline
660
        lodsb
664
        lodsb
661
        cmp     edi, [ebp + http_msg.write_ptr]
665
        cmp     edi, [ebp + http_msg.write_ptr]
662
        jb      .end_of_chunkline?
666
        jb      .end_of_chunkline?
663
        jmp     .need_more_data
667
        jmp     .need_more_data
664
 
668
 
665
  .end_of_chunkline:
669
  .end_of_chunkline:
666
; Update chunk ptr, and remember old one
670
; Update chunk ptr, and remember old one
667
        mov     edi, [ebp + http_msg.chunk_ptr]
671
        mov     edi, [ebp + http_msg.chunk_ptr]
668
        add     [ebp + http_msg.chunk_ptr], ebx
672
        add     [ebp + http_msg.chunk_ptr], ebx
669
; Realloc buffer, make it 'chunksize' bigger.
673
; Realloc buffer, make it 'chunksize' bigger.
670
        mov     eax, [ebp + http_msg.buffer_length]
674
        mov     eax, [ebp + http_msg.buffer_length]
671
        add     eax, ebx
675
        add     eax, ebx
672
        invoke  mem.realloc, ebp, eax
676
        invoke  mem.realloc, ebp, eax
673
        or      eax, eax
677
        or      eax, eax
674
        jz      .no_ram
678
        jz      .no_ram
675
        add     [ebp + http_msg.buffer_length], ebx
679
        add     [ebp + http_msg.buffer_length], ebx
676
 
680
 
677
; Update write ptr
681
; Update write ptr
678
        mov     eax, esi
682
        mov     eax, esi
679
        sub     eax, edi
683
        sub     eax, edi
680
        sub     [ebp + http_msg.write_ptr], eax
684
        sub     [ebp + http_msg.write_ptr], eax
681
 
685
 
682
; Now move all received data to the left (remove chunk header).
686
; Now move all received data to the left (remove chunk header).
683
; Update content_length accordingly.
687
; Update content_length accordingly.
684
        mov     ecx, [ebp + http_msg.write_ptr]
688
        mov     ecx, [ebp + http_msg.write_ptr]
685
        sub     ecx, esi
689
        sub     ecx, esi
686
        add     [ebp + http_msg.content_received], ecx
690
        add     [ebp + http_msg.content_received], ecx
687
        rep     movsb
691
        rep     movsb
688
        jmp     .chunk_loop
692
        jmp     .chunk_loop
689
 
693
 
690
; Check if we got all the data.
694
; Check if we got all the data.
691
  .header_parsed:
695
  .header_parsed:
692
        add     [ebp + http_msg.content_received], eax
696
        add     [ebp + http_msg.content_received], eax
693
        mov     eax, [ebp + http_msg.content_length]
697
        mov     eax, [ebp + http_msg.content_length]
694
        cmp     eax, [ebp + http_msg.content_received]
698
        cmp     eax, [ebp + http_msg.content_received]
695
        jae     .got_all_data
699
        jae     .got_all_data
696
        jmp     .need_more_data
700
        jmp     .need_more_data
697
  .need_more_data_pop:
701
  .need_more_data_pop:
698
        pop     eax
702
        pop     eax
699
  .need_more_data:
703
  .need_more_data:
700
        popa
704
        popa
701
        xor     eax, eax
705
        xor     eax, eax
702
        dec     eax
706
        dec     eax
703
        ret
707
        ret
704
 
708
 
705
  .need_more_data_chunked:
709
  .need_more_data_chunked:
706
        add     [ebp + http_msg.content_received], eax
710
        add     [ebp + http_msg.content_received], eax
707
        popa
711
        popa
708
        xor     eax, eax
712
        xor     eax, eax
709
        dec     eax
713
        dec     eax
710
        ret
714
        ret
711
 
715
 
712
  .got_all_data_chunked:
716
  .got_all_data_chunked:
713
        mov     eax, [ebp + http_msg.chunk_ptr]
717
        mov     eax, [ebp + http_msg.chunk_ptr]
714
        sub     eax, [ebp + http_msg.header_length]
718
        sub     eax, [ebp + http_msg.header_length]
715
        sub     eax, http_msg.data
719
        sub     eax, http_msg.data
716
        sub     eax, ebp
720
        sub     eax, ebp
717
        mov     [ebp + http_msg.content_length], eax
721
        mov     [ebp + http_msg.content_length], eax
718
        mov     [ebp + http_msg.content_received], eax
722
        mov     [ebp + http_msg.content_received], eax
719
  .got_all_data:
723
  .got_all_data:
720
        DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_length]
724
        DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_length]
721
        or      [ebp + http_msg.flags], FLAG_GOT_ALL_DATA
725
        or      [ebp + http_msg.flags], FLAG_GOT_ALL_DATA
722
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
726
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
723
        mcall   close, [ebp + http_msg.socket]
727
        mcall   close, [ebp + http_msg.socket]
724
        popa
728
        popa
725
        xor     eax, eax
729
        xor     eax, eax
726
        ret
730
        ret
727
 
731
 
728
  .check_socket:
732
  .check_socket:
729
        cmp     ebx, EWOULDBLOCK
733
        cmp     ebx, EWOULDBLOCK
730
        jne     .socket_error
734
        jne     .socket_error
731
 
735
 
732
        mcall   29, 9
736
        mcall   29, 9
733
        sub     eax, TIMEOUT
737
        sub     eax, TIMEOUT
734
        cmp     eax, [ebp + http_msg.timestamp]
738
        cmp     eax, [ebp + http_msg.timestamp]
735
        jb      .need_more_data
739
        jb      .need_more_data
736
        DEBUGF  1, "ERROR: timeout\n"
740
        DEBUGF  1, "ERROR: timeout\n"
737
        or      [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
741
        or      [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
738
        jmp     .disconnect
742
        jmp     .disconnect
739
 
743
 
740
  .invalid_header:
744
  .invalid_header:
741
        pop     eax
745
        pop     eax
742
        DEBUGF  1, "ERROR: invalid header\n"
746
        DEBUGF  1, "ERROR: invalid header\n"
743
        or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
747
        or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
744
        jmp     .disconnect
748
        jmp     .disconnect
745
 
749
 
746
  .no_ram_pop:
750
  .no_ram_pop:
747
        pop     eax
751
        pop     eax
748
  .no_ram:
752
  .no_ram:
749
        DEBUGF  1, "ERROR: out of RAM\n"
753
        DEBUGF  1, "ERROR: out of RAM\n"
750
        or      [ebp + http_msg.flags], FLAG_NO_RAM
754
        or      [ebp + http_msg.flags], FLAG_NO_RAM
751
        jmp     .disconnect
755
        jmp     .disconnect
752
 
756
 
753
  .socket_error:
757
  .socket_error:
754
        DEBUGF  1, "ERROR: socket error %u\n", ebx
758
        DEBUGF  1, "ERROR: socket error %u\n", ebx
755
        or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
759
        or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
756
  .disconnect:
760
  .disconnect:
757
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
761
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
758
        mcall   close, [ebp + http_msg.socket]
762
        mcall   close, [ebp + http_msg.socket]
759
  .connection_closed:
763
  .connection_closed:
760
        popa
764
        popa
761
        xor     eax, eax
765
        xor     eax, eax
762
        ret
766
        ret
763
 
767
 
764
endp
768
endp
765
 
769
 
766
 
770
 
767
 
771
 
768
 
772
 
769
;;================================================================================================;;
773
;;================================================================================================;;
770
proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
774
proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
771
;;------------------------------------------------------------------------------------------------;;
775
;;------------------------------------------------------------------------------------------------;;
772
;? Free the http_msg structure                                                                    ;;
776
;? Free the http_msg structure                                                                    ;;
773
;;------------------------------------------------------------------------------------------------;;
777
;;------------------------------------------------------------------------------------------------;;
774
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
778
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
775
;;------------------------------------------------------------------------------------------------;;
779
;;------------------------------------------------------------------------------------------------;;
776
;< none                                                                                           ;;
780
;< none                                                                                           ;;
777
;;================================================================================================;;
781
;;================================================================================================;;
778
 
782
 
779
        pusha
783
        pusha
780
        mov     ebp, [identifier]
784
        mov     ebp, [identifier]
781
 
785
 
782
        test    [ebp + http_msg.flags], FLAG_CONNECTED
786
        test    [ebp + http_msg.flags], FLAG_CONNECTED
783
        jz      .not_connected
787
        jz      .not_connected
784
 
788
 
785
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
789
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
786
        mcall   close, [ebp + http_msg.socket]
790
        mcall   close, [ebp + http_msg.socket]
787
 
791
 
788
  .not_connected:
792
  .not_connected:
789
        invoke  mem.free, ebp
793
        invoke  mem.free, ebp
790
 
794
 
791
        popa
795
        popa
792
        ret
796
        ret
793
 
797
 
794
endp
798
endp
795
 
799
 
796
 
800
 
797
 
801
 
798
;;================================================================================================;;
802
;;================================================================================================;;
799
proc HTTP_stop identifier ;///////////////////////////////////////////////////////////////////////;;
803
proc HTTP_stop identifier ;///////////////////////////////////////////////////////////////////////;;
800
;;------------------------------------------------------------------------------------------------;;
804
;;------------------------------------------------------------------------------------------------;;
801
;? Stops the open connection                                                                      ;;
805
;? Stops the open connection                                                                      ;;
802
;;------------------------------------------------------------------------------------------------;;
806
;;------------------------------------------------------------------------------------------------;;
803
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
807
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
804
;;------------------------------------------------------------------------------------------------;;
808
;;------------------------------------------------------------------------------------------------;;
805
;< none                                                                                           ;;
809
;< none                                                                                           ;;
806
;;================================================================================================;;
810
;;================================================================================================;;
807
 
811
 
808
        pusha
812
        pusha
809
        mov     ebp, [identifier]
813
        mov     ebp, [identifier]
810
 
814
 
811
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
815
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
812
        mcall   close, [ebp + http_msg.socket]
816
        mcall   close, [ebp + http_msg.socket]
813
 
817
 
814
        popa
818
        popa
815
        ret
819
        ret
816
 
820
 
817
endp
821
endp
818
 
822
 
819
 
823
 
820
 
824
 
821
;;================================================================================================;;
825
;;================================================================================================;;
822
proc find_header_field identifier, headername ;///////////////////////////////////////////////////;;
826
proc find_header_field identifier, headername ;///////////////////////////////////////////////////;;
823
;;------------------------------------------------------------------------------------------------;;
827
;;------------------------------------------------------------------------------------------------;;
824
;? Find a header field in the received HTTP header                                                ;;
828
;? Find a header field in the received HTTP header                                                ;;
825
;;------------------------------------------------------------------------------------------------;;
829
;;------------------------------------------------------------------------------------------------;;
826
;> identifier   = ptr to http_msg struct                                                          ;;
830
;> identifier   = ptr to http_msg struct                                                          ;;
827
;> headername   = ptr to ASCIIZ string containg field you want to find (must be in lowercase)     ;;
831
;> headername   = ptr to ASCIIZ string containg field you want to find (must be in lowercase)     ;;
828
;;------------------------------------------------------------------------------------------------;;
832
;;------------------------------------------------------------------------------------------------;;
829
;< eax = 0 (error) / ptr to content of the HTTP header field                                      ;;
833
;< eax = 0 (error) / ptr to content of the HTTP header field                                      ;;
830
;;================================================================================================;;
834
;;================================================================================================;;
831
        push    ebx ecx edx esi edi
835
        push    ebx ecx edx esi edi
832
 
836
 
833
        DEBUGF  1, "Find header field: %s\n", [headername]
837
        DEBUGF  1, "Find header field: %s\n", [headername]
834
 
838
 
835
        mov     ebx, [identifier]
839
        mov     ebx, [identifier]
836
        test    [ebx + http_msg.flags], FLAG_GOT_HEADER
840
        test    [ebx + http_msg.flags], FLAG_GOT_HEADER
837
        jz      .fail
841
        jz      .fail
838
 
842
 
839
        lea     edx, [ebx + http_msg.data]
843
        lea     edx, [ebx + http_msg.data]
840
        mov     ecx, edx
844
        mov     ecx, edx
841
        add     ecx, [ebx + http_msg.header_length]
845
        add     ecx, [ebx + http_msg.header_length]
842
 
846
 
843
  .restart:
847
  .restart:
844
        mov     esi, [headername]
848
        mov     esi, [headername]
845
        mov     edi, edx
849
        mov     edi, edx
846
  .loop:
850
  .loop:
847
        cmp     edi, ecx
851
        cmp     edi, ecx
848
        jae     .fail
852
        jae     .fail
849
        lodsb
853
        lodsb
850
        scasb
854
        scasb
851
        je      .loop
855
        je      .loop
852
        test    al, al
856
        test    al, al
853
        jz      .done?
857
        jz      .done?
854
  .next:
858
  .next:
855
        inc     edx
859
        inc     edx
856
        jmp     .restart
860
        jmp     .restart
857
 
861
 
858
  .not_done:
862
  .not_done:
859
        inc     edi
863
        inc     edi
860
  .done?:
864
  .done?:
861
        cmp     byte[edi-1], ':'
865
        cmp     byte[edi-1], ':'
862
        je      .almost_done
866
        je      .almost_done
863
        cmp     byte[edi-1], ' '
867
        cmp     byte[edi-1], ' '
864
        je      .not_done
868
        je      .not_done
865
        cmp     byte[edi-1], 9  ; tab
869
        cmp     byte[edi-1], 9  ; tab
866
        je      .not_done
870
        je      .not_done
867
 
871
 
868
        jmp     .next
872
        jmp     .next
869
 
873
 
870
  .almost_done:                 ; FIXME: buffer overflow?
874
  .almost_done:                 ; FIXME: buffer overflow?
871
        dec     edi
875
        dec     edi
872
        DEBUGF  1, "Found header field\n"
876
        DEBUGF  1, "Found header field\n"
873
  .spaceloop:
877
  .spaceloop:
874
        inc     edi
878
        inc     edi
875
        cmp     byte[edi], ' '
879
        cmp     byte[edi], ' '
876
        je      .spaceloop
880
        je      .spaceloop
877
        cmp     byte[edi], 9    ; tab
881
        cmp     byte[edi], 9    ; tab
878
        je      .spaceloop
882
        je      .spaceloop
879
 
883
 
880
        mov     eax, edi
884
        mov     eax, edi
881
        pop     edi esi edx ecx ebx
885
        pop     edi esi edx ecx ebx
882
        ret
886
        ret
883
 
887
 
884
  .fail:
888
  .fail:
885
        pop     edi esi edx ecx ebx
889
        pop     edi esi edx ecx ebx
886
        xor     eax, eax
890
        xor     eax, eax
887
        ret
891
        ret
888
 
892
 
889
endp
893
endp
890
 
894
 
891
 
895
 
892
 
896
 
893
;;================================================================================================;;
897
;;================================================================================================;;
894
proc URI_escape URI ;/////////////////////////////////////////////////////////////////////////////;;
898
proc URI_escape URI ;/////////////////////////////////////////////////////////////////////////////;;
895
;;------------------------------------------------------------------------------------------------;;
899
;;------------------------------------------------------------------------------------------------;;
896
;?                                                                                                ;;
900
;?                                                                                                ;;
897
;;------------------------------------------------------------------------------------------------;;
901
;;------------------------------------------------------------------------------------------------;;
898
;> URI = ptr to ASCIIZ URI                                                                        ;;
902
;> URI = ptr to ASCIIZ URI                                                                        ;;
899
;;------------------------------------------------------------------------------------------------;;
903
;;------------------------------------------------------------------------------------------------;;
900
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
904
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
901
;;================================================================================================;;
905
;;================================================================================================;;
902
 
906
 
903
        pusha
907
        pusha
904
 
908
 
905
        invoke  mem.alloc, URLMAXLEN
909
        invoke  mem.alloc, URLMAXLEN
906
        test    eax, eax
910
        test    eax, eax
907
        jz      .error
911
        jz      .error
908
        mov     [esp + 7 * 4], eax              ; return ptr in eax
912
        mov     [esp + 7 * 4], eax              ; return ptr in eax
909
        mov     esi, [URI]
913
        mov     esi, [URI]
910
        mov     edi, eax
914
        mov     edi, eax
911
        xor     ebx, ebx
915
        xor     ebx, ebx
912
        xor     ecx, ecx
916
        xor     ecx, ecx
913
  .loop:
917
  .loop:
914
        lodsb
918
        lodsb
915
        test    al, al
919
        test    al, al
916
        jz      .done
920
        jz      .done
917
 
921
 
918
        mov     cl, al
922
        mov     cl, al
919
        and     cl, 0x1f
923
        and     cl, 0x1f
920
        mov     bl, al
924
        mov     bl, al
921
        shr     bl, 5
925
        shr     bl, 5
922
        bt      dword[bits_must_escape + ebx], ecx
926
        bt      dword[bits_must_escape + ebx], ecx
923
        jc      .escape
927
        jc      .escape
924
 
928
 
925
        stosb
929
        stosb
926
        jmp     .loop
930
        jmp     .loop
927
 
931
 
928
  .escape:
932
  .escape:
929
        mov     al, '%'
933
        mov     al, '%'
930
        stosb
934
        stosb
931
        mov     bl, byte[esi-1]
935
        mov     bl, byte[esi-1]
932
        shr     bl, 4
936
        shr     bl, 4
933
        mov     al, byte[str_hex + ebx]
937
        mov     al, byte[str_hex + ebx]
934
        stosb
938
        stosb
935
        mov     bl, byte[esi-1]
939
        mov     bl, byte[esi-1]
936
        and     bl, 0x0f
940
        and     bl, 0x0f
937
        mov     al, byte[str_hex + ebx]
941
        mov     al, byte[str_hex + ebx]
938
        stosb
942
        stosb
939
        jmp     .loop
943
        jmp     .loop
940
 
944
 
941
 
945
 
942
  .done:
946
  .done:
943
        stosb
947
        stosb
944
 
948
 
945
        popa
949
        popa
946
        ret
950
        ret
947
 
951
 
948
  .error:
952
  .error:
949
        popa
953
        popa
950
        xor     eax, eax
954
        xor     eax, eax
951
        ret
955
        ret
952
 
956
 
953
endp
957
endp
954
 
958
 
955
 
959
 
956
 
960
 
957
;;================================================================================================;;
961
;;================================================================================================;;
958
proc URI_unescape URI ;///////////////////////////////////////////////////////////////////////////;;
962
proc URI_unescape URI ;///////////////////////////////////////////////////////////////////////////;;
959
;;------------------------------------------------------------------------------------------------;;
963
;;------------------------------------------------------------------------------------------------;;
960
;?                                                                                                ;;
964
;?                                                                                                ;;
961
;;------------------------------------------------------------------------------------------------;;
965
;;------------------------------------------------------------------------------------------------;;
962
;> URI = ptr to ASCIIZ URI                                                                        ;;
966
;> URI = ptr to ASCIIZ URI                                                                        ;;
963
;;------------------------------------------------------------------------------------------------;;
967
;;------------------------------------------------------------------------------------------------;;
964
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
968
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
965
;;================================================================================================;;
969
;;================================================================================================;;
966
 
970
 
967
        pusha
971
        pusha
968
 
972
 
969
        invoke  mem.alloc, URLMAXLEN
973
        invoke  mem.alloc, URLMAXLEN
970
        test    eax, eax
974
        test    eax, eax
971
        jz      .error
975
        jz      .error
972
        mov     [esp + 7 * 4], eax              ; return ptr in eax
976
        mov     [esp + 7 * 4], eax              ; return ptr in eax
973
        mov     esi, [URI]
977
        mov     esi, [URI]
974
        mov     edi, eax
978
        mov     edi, eax
975
  .loop:
979
  .loop:
976
        lodsb
980
        lodsb
977
        test    al, al
981
        test    al, al
978
        jz      .done
982
        jz      .done
979
 
983
 
980
        cmp     al, '%'
984
        cmp     al, '%'
981
        je      .unescape
985
        je      .unescape
982
 
986
 
983
        stosb
987
        stosb
984
        jmp     .loop
988
        jmp     .loop
985
 
989
 
986
  .unescape:
990
  .unescape:
987
        xor     ebx, ebx
991
        xor     ebx, ebx
988
        xor     ecx, ecx
992
        xor     ecx, ecx
989
  .unescape_nibble:
993
  .unescape_nibble:
990
        lodsb
994
        lodsb
991
        sub     al, '0'
995
        sub     al, '0'
992
        jb      .fail
996
        jb      .fail
993
        cmp     al, 9
997
        cmp     al, 9
994
        jbe     .nibble_ok
998
        jbe     .nibble_ok
995
        sub     al, 'A' - '0' - 10
999
        sub     al, 'A' - '0' - 10
996
        jb      .fail
1000
        jb      .fail
997
        cmp     al, 15
1001
        cmp     al, 15
998
        jbe     .nibble_ok
1002
        jbe     .nibble_ok
999
        sub     al, 'a' - 'A'
1003
        sub     al, 'a' - 'A'
1000
        cmp     al, 15
1004
        cmp     al, 15
1001
        ja      .fail
1005
        ja      .fail
1002
  .nibble_ok:
1006
  .nibble_ok:
1003
        shl     bl, 8
1007
        shl     bl, 8
1004
        or      bl, al
1008
        or      bl, al
1005
        dec     ecx
1009
        dec     ecx
1006
        jc      .unescape_nibble
1010
        jc      .unescape_nibble
1007
        mov     al, bl
1011
        mov     al, bl
1008
        stosb
1012
        stosb
1009
        jmp     .loop
1013
        jmp     .loop
1010
 
1014
 
1011
  .fail:
1015
  .fail:
1012
        DEBUGF  1, "ERROR: invalid URI!\n"
1016
        DEBUGF  1, "ERROR: invalid URI!\n"
1013
        jmp     .loop
1017
        jmp     .loop
1014
 
1018
 
1015
  .done:
1019
  .done:
1016
        stosb
1020
        stosb
1017
 
1021
 
1018
        popa
1022
        popa
1019
        ret
1023
        ret
1020
 
1024
 
1021
  .error:
1025
  .error:
1022
        popa
1026
        popa
1023
        xor     eax, eax
1027
        xor     eax, eax
1024
        ret
1028
        ret
1025
 
1029
 
1026
endp
1030
endp
1027
 
1031
 
1028
 
1032
 
1029
 
1033
 
1030
 
1034
 
1031
 
1035
 
1032
;;================================================================================================;;
1036
;;================================================================================================;;
1033
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1037
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1034
;;================================================================================================;;
1038
;;================================================================================================;;
1035
;! Internal procedures section                                                                    ;;
1039
;! Internal procedures section                                                                    ;;
1036
;;================================================================================================;;
1040
;;================================================================================================;;
1037
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1041
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1038
;;================================================================================================;;
1042
;;================================================================================================;;
1039
 
1043
 
1040
 
1044
 
1041
 
1045
 
1042
 
1046
 
1043
;;================================================================================================;;
1047
;;================================================================================================;;
1044
proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;;
1048
proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;;
1045
;;------------------------------------------------------------------------------------------------;;
1049
;;------------------------------------------------------------------------------------------------;;
1046
;? Connects to a HTTP server                                                                      ;;
1050
;? Connects to a HTTP server                                                                      ;;
1047
;;------------------------------------------------------------------------------------------------;;
1051
;;------------------------------------------------------------------------------------------------;;
1048
;> hostname     = ptr to ASCIIZ hostname                                                          ;;
1052
;> hostname     = ptr to ASCIIZ hostname                                                          ;;
1049
;> port         = port (x86 byte order)                                                           ;;
1053
;> port         = port (x86 byte order)                                                           ;;
1050
;;------------------------------------------------------------------------------------------------;;
1054
;;------------------------------------------------------------------------------------------------;;
1051
;< eax = 0 (error) / socketnum                                                                    ;;
1055
;< eax = 0 (error) / socketnum                                                                    ;;
1052
;;================================================================================================;;
1056
;;================================================================================================;;
1053
 
1057
 
1054
locals
1058
locals
1055
        sockaddr        dd ?
1059
        sockaddr        dd ?
1056
        socketnum       dd ?
1060
        socketnum       dd ?
1057
endl
1061
endl
1058
 
1062
 
1059
; Resolve the hostname
1063
; Resolve the hostname
1060
        DEBUGF  1, "Resolving hostname\n"
1064
        DEBUGF  1, "Resolving hostname\n"
1061
        push    esp     ; reserve stack place
1065
        push    esp     ; reserve stack place
1062
        push    esp     ; fourth parameter
1066
        push    esp     ; fourth parameter
1063
        push    0       ; third parameter
1067
        push    0       ; third parameter
1064
        push    0       ; second parameter
1068
        push    0       ; second parameter
1065
        push    [hostname]
1069
        push    [hostname]
1066
        call    [getaddrinfo]
1070
        call    [getaddrinfo]
1067
        pop     esi
1071
        pop     esi
1068
        test    eax, eax
1072
        test    eax, eax
1069
        jnz     .error1
1073
        jnz     .error1
1070
 
1074
 
1071
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
1075
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
1072
        mov     esi, [esi + addrinfo.ai_addr]
1076
        mov     esi, [esi + addrinfo.ai_addr]
1073
        mov     [sockaddr], esi
1077
        mov     [sockaddr], esi
1074
        mov     eax, [esi + sockaddr_in.sin_addr]
1078
        mov     eax, [esi + sockaddr_in.sin_addr]
1075
        test    eax, eax
1079
        test    eax, eax
1076
        jz      .error2
1080
        jz      .error2
1077
 
1081
 
1078
        DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
1082
        DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
1079
        [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
1083
        [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
1080
        [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
1084
        [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
1081
 
1085
 
1082
        mov     [esi + sockaddr_in.sin_family], AF_INET4
1086
        mov     [esi + sockaddr_in.sin_family], AF_INET4
1083
        mov     eax, [port]
1087
        mov     eax, [port]
1084
        xchg    al, ah
1088
        xchg    al, ah
1085
        mov     [esi + sockaddr_in.sin_port], ax
1089
        mov     [esi + sockaddr_in.sin_port], ax
1086
 
1090
 
1087
; Connect to the server.
1091
; Connect to the server.
1088
        mcall   socket, AF_INET4, SOCK_STREAM, 0
1092
        mcall   socket, AF_INET4, SOCK_STREAM, 0
1089
        test    eax, eax
1093
        test    eax, eax
1090
        jz      .error2
1094
        jz      .error2
1091
        mov     [socketnum], eax
1095
        mov     [socketnum], eax
1092
        DEBUGF  1, "Socket: 0x%x\n", eax
1096
        DEBUGF  1, "Socket: 0x%x\n", eax
1093
 
1097
 
1094
        mcall   connect, [socketnum], [sockaddr], 18
1098
        mcall   connect, [socketnum], [sockaddr], 18
1095
        test    eax, eax
1099
        test    eax, eax
1096
        jnz     .error2
1100
        jnz     .error2
1097
        DEBUGF  1, "Socket is now connected.\n"
1101
        DEBUGF  1, "Socket is now connected.\n"
1098
 
1102
 
1099
; free allocated memory
1103
; free allocated memory
1100
        push    [sockaddr]
1104
        push    [sockaddr]
1101
        call    [freeaddrinfo]
1105
        call    [freeaddrinfo]
1102
 
1106
 
1103
        mov     eax, [socketnum]
1107
        mov     eax, [socketnum]
1104
        ret
1108
        ret
1105
 
1109
 
1106
  .error2:
1110
  .error2:
1107
 
1111
 
1108
; free allocated memory
1112
; free allocated memory
1109
        push    [sockaddr]
1113
        push    [sockaddr]
1110
        call    [freeaddrinfo]
1114
        call    [freeaddrinfo]
1111
 
1115
 
1112
  .error1:
1116
  .error1:
1113
        xor     eax, eax
1117
        xor     eax, eax
1114
        ret
1118
        ret
1115
 
1119
 
1116
endp
1120
endp
1117
 
1121
 
1118
 
1122
 
1119
;;================================================================================================;;
1123
;;================================================================================================;;
1120
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
1124
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
1121
;;------------------------------------------------------------------------------------------------;;
1125
;;------------------------------------------------------------------------------------------------;;
1122
;? Split a given URL into hostname and pageaddr                                                   ;;
1126
;? Split a given URL into hostname and pageaddr                                                   ;;
1123
;;------------------------------------------------------------------------------------------------;;
1127
;;------------------------------------------------------------------------------------------------;;
1124
;> URL = ptr to ASCIIZ URL                                                                        ;;
1128
;> URL = ptr to ASCIIZ URL                                                                        ;;
1125
;;------------------------------------------------------------------------------------------------;;
1129
;;------------------------------------------------------------------------------------------------;;
1126
;< eax = 0 (error) / ptr to ASCIIZ hostname                                                       ;;
1130
;< eax = 0 (error) / ptr to ASCIIZ hostname                                                       ;;
1127
;< ebx = ptr to ASCIIZ pageaddr                                                                   ;;
1131
;< ebx = ptr to ASCIIZ pageaddr                                                                   ;;
1128
;;================================================================================================;;
1132
;;================================================================================================;;
1129
 
1133
 
1130
locals
1134
locals
1131
        urlsize         dd ?
1135
        urlsize         dd ?
1132
        hostname        dd ?
1136
        hostname        dd ?
1133
        pageaddr        dd ?
1137
        pageaddr        dd ?
1134
endl
1138
endl
1135
 
1139
 
1136
        DEBUGF  1, "parsing URL: %s\n", [URL]
1140
        DEBUGF  1, "parsing URL: %s\n", [URL]
1137
 
1141
 
1138
; remove any leading protocol text
1142
; remove any leading protocol text
1139
        mov     esi, [URL]
1143
        mov     esi, [URL]
1140
        mov     ecx, URLMAXLEN
1144
        mov     ecx, URLMAXLEN
1141
        mov     ax, '//'
1145
        mov     ax, '//'
1142
  .loop1:
1146
  .loop1:
1143
        cmp     byte[esi], 0            ; end of URL?
1147
        cmp     byte[esi], 0            ; end of URL?
1144
        je      .url_ok                 ; yep, so not found
1148
        je      .url_ok                 ; yep, so not found
1145
        cmp     [esi], ax
1149
        cmp     [esi], ax
1146
        je      .skip_proto
1150
        je      .skip_proto
1147
        inc     esi
1151
        inc     esi
1148
        dec     ecx
1152
        dec     ecx
1149
        jnz     .loop1
1153
        jnz     .loop1
1150
 
1154
 
1151
        DEBUGF  1, "Invalid URL\n"
1155
        DEBUGF  1, "Invalid URL\n"
1152
        xor     eax, eax
1156
        xor     eax, eax
1153
        ret
1157
        ret
1154
 
1158
 
1155
  .skip_proto:
1159
  .skip_proto:
1156
        inc     esi                     ; skip the two '/'
1160
        inc     esi                     ; skip the two '/'
1157
        inc     esi
1161
        inc     esi
1158
        mov     [URL], esi              ; update pointer so it skips protocol
1162
        mov     [URL], esi              ; update pointer so it skips protocol
1159
        jmp     .loop1                  ; we still need to find the length of the URL
1163
        jmp     .loop1                  ; we still need to find the length of the URL
1160
 
1164
 
1161
  .url_ok:
1165
  .url_ok:
1162
        sub     esi, [URL]              ; calculate total length of URL
1166
        sub     esi, [URL]              ; calculate total length of URL
1163
        mov     [urlsize], esi
1167
        mov     [urlsize], esi
1164
 
1168
 
1165
 
1169
 
1166
; now look for page delimiter - it's a '/' character
1170
; now look for page delimiter - it's a '/' character
1167
        mov     ecx, esi                ; URL length
1171
        mov     ecx, esi                ; URL length
1168
        mov     edi, [URL]
1172
        mov     edi, [URL]
1169
        mov     al, '/'
1173
        mov     al, '/'
1170
        repne   scasb
1174
        repne   scasb
1171
        jne     @f
1175
        jne     @f
1172
        dec     edi                     ; return one char, '/' must be part of the pageaddr
1176
        dec     edi                     ; return one char, '/' must be part of the pageaddr
1173
        inc     ecx                     ;
1177
        inc     ecx                     ;
1174
  @@:
1178
  @@:
1175
        push    ecx edi                 ; remember the pointer and length of pageaddr
1179
        push    ecx edi                 ; remember the pointer and length of pageaddr
1176
 
1180
 
1177
        mov     ecx, edi
1181
        mov     ecx, edi
1178
        sub     ecx, [URL]
1182
        sub     ecx, [URL]
1179
        inc     ecx                     ; we will add a 0 byte at the end
1183
        inc     ecx                     ; we will add a 0 byte at the end
1180
        invoke  mem.alloc, ecx
1184
        invoke  mem.alloc, ecx
1181
        or      eax, eax
1185
        or      eax, eax
1182
        jz      .no_mem
1186
        jz      .no_mem
1183
 
1187
 
1184
        mov     [hostname], eax         ; copy hostname to buffer
1188
        mov     [hostname], eax         ; copy hostname to buffer
1185
        mov     edi, eax
1189
        mov     edi, eax
1186
        mov     esi, [URL]
1190
        mov     esi, [URL]
1187
        dec     ecx
1191
        dec     ecx
1188
        rep     movsb
1192
        rep     movsb
1189
        xor     al, al
1193
        xor     al, al
1190
        stosb
1194
        stosb
1191
 
1195
 
1192
        mov     [pageaddr], str_slash   ; assume there is no pageaddr
1196
        mov     [pageaddr], str_slash   ; assume there is no pageaddr
1193
        pop     esi ecx
1197
        pop     esi ecx
1194
        test    ecx, ecx
1198
        test    ecx, ecx
1195
        jz      .no_page
1199
        jz      .no_page
1196
        inc     ecx                     ; we will add a 0 byte at the end
1200
        inc     ecx                     ; we will add a 0 byte at the end
1197
        invoke  mem.alloc, ecx
1201
        invoke  mem.alloc, ecx
1198
        or      eax, eax
1202
        or      eax, eax
1199
        jz      .no_mem
1203
        jz      .no_mem
1200
 
1204
 
1201
        mov     [pageaddr], eax         ; copy pageaddr to buffer
1205
        mov     [pageaddr], eax         ; copy pageaddr to buffer
1202
        mov     edi, eax
1206
        mov     edi, eax
1203
        dec     ecx
1207
        dec     ecx
1204
        rep     movsb
1208
        rep     movsb
1205
        xor     al, al
1209
        xor     al, al
1206
        stosb
1210
        stosb
1207
  .no_page:
1211
  .no_page:
1208
 
1212
 
1209
        mov     eax, [hostname]
1213
        mov     eax, [hostname]
1210
        mov     ebx, [pageaddr]
1214
        mov     ebx, [pageaddr]
1211
 
1215
 
1212
        DEBUGF  1, "hostname: %s\n", eax
1216
        DEBUGF  1, "hostname: %s\n", eax
1213
        DEBUGF  1, "pageaddr: %s\n", ebx
1217
        DEBUGF  1, "pageaddr: %s\n", ebx
1214
 
1218
 
1215
        ret
1219
        ret
1216
 
1220
 
1217
  .no_mem:
1221
  .no_mem:
1218
        xor     eax, eax
1222
        xor     eax, eax
1219
        ret
1223
        ret
1220
 
1224
 
1221
endp
1225
endp
1222
 
1226
 
1223
 
1227
 
1224
;;================================================================================================;;
1228
;;================================================================================================;;
1225
proc ascii_dec ;//////////////////////////////////////////////////////////////////////////////////;;
1229
proc ascii_dec ;//////////////////////////////////////////////////////////////////////////////////;;
1226
;;------------------------------------------------------------------------------------------------;;
1230
;;------------------------------------------------------------------------------------------------;;
1227
;? Convert eax to ASCII decimal number                                                            ;;
1231
;? Convert eax to ASCII decimal number                                                            ;;
1228
;;------------------------------------------------------------------------------------------------;;
1232
;;------------------------------------------------------------------------------------------------;;
1229
;> eax = number                                                                                   ;;
1233
;> eax = number                                                                                   ;;
1230
;> edi = ptr where to write ASCII decimal number                                                  ;;
1234
;> edi = ptr where to write ASCII decimal number                                                  ;;
1231
;;------------------------------------------------------------------------------------------------;;
1235
;;------------------------------------------------------------------------------------------------;;
1232
;< /                                                                                              ;;
1236
;< /                                                                                              ;;
1233
;;================================================================================================;;
1237
;;================================================================================================;;
1234
 
1238
 
1235
        push    -'0'
1239
        push    -'0'
1236
        mov     ecx, 10
1240
        mov     ecx, 10
1237
  .loop:
1241
  .loop:
1238
        xor     edx, edx
1242
        xor     edx, edx
1239
        div     ecx
1243
        div     ecx
1240
        add     dl, '0'
1244
        add     dl, '0'
1241
        push    edx
1245
        push    edx
1242
        test    eax, eax
1246
        test    eax, eax
1243
        jnz     .loop
1247
        jnz     .loop
1244
 
1248
 
1245
  .loop2:
1249
  .loop2:
1246
        pop     eax
1250
        pop     eax
1247
        add     al, '0'
1251
        add     al, '0'
1248
        jz      .done
1252
        jz      .done
1249
        stosb
1253
        stosb
1250
        jmp     .loop2
1254
        jmp     .loop2
1251
  .done:
1255
  .done:
1252
 
1256
 
1253
        ret
1257
        ret
1254
 
1258
 
1255
endp
1259
endp
1256
 
1260
 
1257
 
1261
 
1258
;;================================================================================================;;
1262
;;================================================================================================;;
1259
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1263
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1260
;;================================================================================================;;
1264
;;================================================================================================;;
1261
;! Imported functions section                                                                     ;;
1265
;! Imported functions section                                                                     ;;
1262
;;================================================================================================;;
1266
;;================================================================================================;;
1263
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1267
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1264
;;================================================================================================;;
1268
;;================================================================================================;;
1265
 
1269
 
1266
 
1270
 
1267
align 16
1271
align 16
1268
@IMPORT:
1272
@IMPORT:
1269
 
1273
 
1270
library \
1274
library \
1271
        libini, 'libini.obj', \
1275
        libini, 'libini.obj', \
1272
        network, 'network.obj'
1276
        network, 'network.obj'
1273
 
1277
 
1274
import  libini, \
1278
import  libini, \
1275
        ini.get_str, 'ini_get_str', \
1279
        ini.get_str, 'ini_get_str', \
1276
        ini.get_int, 'ini_get_int'
1280
        ini.get_int, 'ini_get_int'
1277
 
1281
 
1278
import  network,\
1282
import  network,\
1279
        getaddrinfo, 'getaddrinfo',\
1283
        getaddrinfo, 'getaddrinfo',\
1280
        freeaddrinfo,  'freeaddrinfo',\
1284
        freeaddrinfo,  'freeaddrinfo',\
1281
        inet_ntoa, 'inet_ntoa'
1285
        inet_ntoa, 'inet_ntoa'
1282
 
1286
 
1283
;;===========================================================================;;
1287
;;===========================================================================;;
1284
;;///////////////////////////////////////////////////////////////////////////;;
1288
;;///////////////////////////////////////////////////////////////////////////;;
1285
;;===========================================================================;;
1289
;;===========================================================================;;
1286
;! Exported functions section                                                ;;
1290
;! Exported functions section                                                ;;
1287
;;===========================================================================;;
1291
;;===========================================================================;;
1288
;;///////////////////////////////////////////////////////////////////////////;;
1292
;;///////////////////////////////////////////////////////////////////////////;;
1289
;;===========================================================================;;
1293
;;===========================================================================;;
1290
 
1294
 
1291
 
1295
 
1292
align 4
1296
align 4
1293
@EXPORT:
1297
@EXPORT:
1294
export  \
1298
export  \
1295
        lib_init                , 'lib_init'            , \
1299
        lib_init                , 'lib_init'            , \
1296
        0x00010001              , 'version'             , \
1300
        0x00010001              , 'version'             , \
1297
        HTTP_get                , 'get'                 , \
1301
        HTTP_get                , 'get'                 , \
1298
        HTTP_head               , 'head'                , \
1302
        HTTP_head               , 'head'                , \
1299
        HTTP_post               , 'post'                , \
1303
        HTTP_post               , 'post'                , \
1300
        find_header_field       , 'find_header_field'   , \
1304
        find_header_field       , 'find_header_field'   , \
1301
        HTTP_process            , 'process'             , \
1305
        HTTP_process            , 'process'             , \
1302
        HTTP_free               , 'free'                , \
1306
        HTTP_free               , 'free'                , \
1303
        HTTP_stop               , 'stop'                , \
1307
        HTTP_stop               , 'stop'                , \
1304
        URI_escape              , 'escape'              , \
1308
        URI_escape              , 'escape'              , \
1305
        URI_unescape            , 'unescape'
1309
        URI_unescape            , 'unescape'
1306
 
1310
 
1307
;        HTTP_put                , 'put'                 , \
1311
;        HTTP_put                , 'put'                 , \
1308
;        HTTP_delete             , 'delete'              , \
1312
;        HTTP_delete             , 'delete'              , \
1309
;        HTTP_trace              , 'trace'               , \
1313
;        HTTP_trace              , 'trace'               , \
1310
;        HTTP_connect            , 'connect'             , \
1314
;        HTTP_connect            , 'connect'             , \
1311
 
1315
 
1312
 
1316
 
1313
 
1317
 
1314
section '.data' data readable writable align 16
1318
section '.data' data readable writable align 16
1315
 
1319
 
1316
inifile         db '/sys/settings/network.ini', 0
1320
inifile         db '/sys/settings/network.ini', 0
1317
 
1321
 
1318
sec_proxy:
1322
sec_proxy:
1319
key_proxy       db 'proxy', 0
1323
key_proxy       db 'proxy', 0
1320
key_proxyport   db 'port', 0
1324
key_proxyport   db 'port', 0
1321
key_user        db 'user', 0
1325
key_user        db 'user', 0
1322
key_password    db 'password', 0
1326
key_password    db 'password', 0
1323
 
1327
 
1324
str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
1328
str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
1325
  .length       = $ - str_http11
1329
  .length       = $ - str_http11
1326
str_post_cl     db 13, 10, 'Content-Length: '
1330
str_post_cl     db 13, 10, 'Content-Length: '
1327
  .length       = $ - str_post_cl
1331
  .length       = $ - str_post_cl
1328
str_post_ct     db 13, 10, 'Content-Type: '
1332
str_post_ct     db 13, 10, 'Content-Type: '
1329
  .length       = $ - str_post_ct
1333
  .length       = $ - str_post_ct
1330
str_close       db 13, 10, 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10
1334
str_close       db 13, 10, 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10
1331
  .length       = $ - str_close
1335
  .length       = $ - str_close
1332
str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
1336
str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
1333
  .length       = $ - str_proxy_auth
1337
  .length       = $ - str_proxy_auth
1334
 
1338
 
1335
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
1339
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
1336
                db '0123456789+/'
1340
                db '0123456789+/'
1337
 
1341
 
1338
str_cl          db 'content-length', 0
1342
str_cl          db 'content-length', 0
1339
str_slash       db '/', 0
1343
str_slash       db '/', 0
1340
str_te          db 'transfer-encoding', 0
1344
str_te          db 'transfer-encoding', 0
1341
str_get         db 'GET ', 0
1345
str_get         db 'GET ', 0
1342
str_head        db 'HEAD ', 0
1346
str_head        db 'HEAD ', 0
1343
str_post        db 'POST ', 0
1347
str_post        db 'POST ', 0
1344
 
1348
 
1345
bits_must_escape:
1349
bits_must_escape:
1346
dd      0xffffffff                                                      ; 00-1F
1350
dd      0xffffffff                                                      ; 00-1F
1347
dd      1 shl 0 + 1 shl 2 + 1 shl 3 + 1 shl 5 + 1 shl 28 + 1 shl 30     ; "#%<>
1351
dd      1 shl 0 + 1 shl 2 + 1 shl 3 + 1 shl 5 + 1 shl 28 + 1 shl 30     ; "#%<>
1348
dd      1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 30                       ;[\]^
1352
dd      1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 30                       ;[\]^
1349
dd      1 shl 0 + 1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 31             ;`{|} DEL
1353
dd      1 shl 0 + 1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 31             ;`{|} DEL
1350
 
1354
 
1351
dd      0xffffffff
1355
dd      0xffffffff
1352
dd      0xffffffff
1356
dd      0xffffffff
1353
dd      0xffffffff
1357
dd      0xffffffff
1354
dd      0xffffffff
1358
dd      0xffffffff
1355
 
1359
 
1356
str_hex:
1360
str_hex:
1357
db '0123456789ABCDEF'
1361
db '0123456789ABCDEF'
1358
 
1362
 
1359
include_debug_strings
1363
include_debug_strings
1360
 
1364
 
1361
; uninitialized data
1365
; uninitialized data
1362
mem.alloc       dd ?
1366
mem.alloc       dd ?
1363
mem.free        dd ?
1367
mem.free        dd ?
1364
mem.realloc     dd ?
1368
mem.realloc     dd ?
1365
dll.load        dd ?
1369
dll.load        dd ?
1366
 
1370
 
1367
proxyAddr       rb 256
1371
proxyAddr       rb 256
1368
proxyUser       rb 256
1372
proxyUser       rb 256
1369
proxyPassword   rb 256
1373
proxyPassword   rb 256
1370
proxyPort       dd ?
1374
proxyPort       dd ?