1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; HTTP library for KolibriOS ;; |
54,13 → 54,15 |
.copydone: |
} |
|
macro HTTP_init_buffer buffer, socketnum { |
macro HTTP_init_buffer buffer, socketnum, flags { |
|
mov eax, buffer |
push socketnum |
popd [eax + http_msg.socket] |
lea esi, [eax + http_msg.http_header] |
mov [eax + http_msg.flags], FLAG_CONNECTED |
push flags |
pop [eax + http_msg.flags] |
or [eax + http_msg.flags], FLAG_CONNECTED |
mov [eax + http_msg.write_ptr], esi |
mov [eax + http_msg.buffer_length], BUFFERSIZE - http_msg.http_header |
mov [eax + http_msg.chunk_ptr], 0 |
176,13 → 178,17 |
|
endp |
|
|
|
;;================================================================================================;; |
proc HTTP_get URL, add_header ;///////////////////////////////////////////////////////////////////;; |
proc HTTP_get URL, identifier, flags, add_header ;////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Initiates a HTTP connection, using 'GET' method. ;; |
;;------------------------------------------------------------------------------------------------;; |
;> URL = pointer to ASCIIZ URL ;; |
;> add_header = pointer to additional header parameters (ASCIIZ), or null for none. ;; |
;> identifier = Identifier of an already open connection, or NULL to create a new one. ;; |
;> flags = Flags indicating how to threat the connection. ;; |
;> add_header = pointer to additional header parameters (ASCIIZ), or NULL for none. ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) / buffer ptr ;; |
;;================================================================================================;; |
189,12 → 195,13 |
locals |
hostname dd ? |
pageaddr dd ? |
sockaddr dd ? |
socketnum dd ? |
buffer dd ? |
port dd ? |
endl |
|
and [flags], FLAG_KEEPALIVE or FLAG_MULTIBUFF ; filter out invalid flags |
|
pusha |
|
; split the URL into hostname and pageaddr |
205,7 → 212,17 |
mov [pageaddr], ebx |
mov [port], ecx |
|
mov eax, [identifier] |
test eax, eax |
jz .open_new |
test [eax + http_msg.flags], FLAG_CONNECTED |
jz .error |
mov eax, [eax + http_msg.socket] |
mov [socketnum], eax |
jmp .send_request |
|
; Connect to the other side. |
.open_new: |
stdcall open_connection, [hostname], [port] |
test eax, eax |
jz .error |
212,6 → 229,7 |
mov [socketnum], eax |
|
; Create the HTTP request. |
.send_request: |
invoke mem.alloc, BUFFERSIZE |
test eax, eax |
jz .error |
256,6 → 274,11 |
|
mov esi, str_close |
mov ecx, str_close.length |
test [flags], FLAG_KEEPALIVE |
jz @f |
mov esi, str_keep |
mov ecx, str_keep.length |
@@: |
rep movsb |
|
mov byte[edi], 0 |
275,12 → 298,20 |
jz .error |
DEBUGF 1, "Request has been sent to server.\n" |
|
HTTP_init_buffer [buffer], [socketnum] |
cmp [identifier], 0 |
jne .old_connection |
HTTP_init_buffer [buffer], [socketnum], [flags] |
|
popa |
mov eax, [buffer] ; return buffer ptr |
ret |
|
.old_connection: |
invoke mem.free, [buffer] |
popa |
mov eax, [identifier] |
ret |
|
.error: |
DEBUGF 1, "Error!\n" |
popa |
292,13 → 323,15 |
|
|
;;================================================================================================;; |
proc HTTP_head URL, add_header ;//////////////////////////////////////////////////////////////////;; |
proc HTTP_head URL, identifier, flags, add_header ;///////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Initiates a HTTP connection, using 'HEAD' method. ;; |
;? This will only return HTTP header and status, no content ;; |
;;------------------------------------------------------------------------------------------------;; |
;> URL = pointer to ASCIIZ URL ;; |
;> add_header = pointer to additional header parameters (ASCIIZ), or null for none. ;; |
;> identifier = Identifier of an already open connection, or NULL to create a new one. ;; |
;> flags = Flags indicating how to threat the connection. ;; |
;> add_header = pointer to additional header parameters (ASCIIZ), or NULL for none. ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) / buffer ptr ;; |
;;================================================================================================;; |
305,12 → 338,13 |
locals |
hostname dd ? |
pageaddr dd ? |
sockaddr dd ? |
socketnum dd ? |
buffer dd ? |
port dd ? |
endl |
|
and [flags], FLAG_KEEPALIVE or FLAG_MULTIBUFF ; filter out invalid flags |
|
pusha |
; split the URL into hostname and pageaddr |
stdcall parse_url, [URL] |
320,7 → 354,17 |
mov [pageaddr], ebx |
mov [port], ecx |
|
mov eax, [identifier] |
test eax, eax |
jz .open_new |
test [eax + http_msg.flags], FLAG_CONNECTED |
jz .error |
mov eax, [eax + http_msg.socket] |
mov [socketnum], eax |
jmp .send_request |
|
; Connect to the other side. |
.open_new: |
stdcall open_connection, [hostname], [port] |
test eax, eax |
jz .error |
327,6 → 371,7 |
mov [socketnum], eax |
|
; Create the HTTP request. |
.send_request: |
invoke mem.alloc, BUFFERSIZE |
test eax, eax |
jz .error |
371,12 → 416,16 |
|
mov esi, str_close |
mov ecx, str_close.length |
test [flags], FLAG_KEEPALIVE |
jz @f |
mov esi, str_keep |
mov ecx, str_keep.length |
@@: |
rep movsb |
|
mov byte[edi], 0 |
DEBUGF 1, "Request:\n%s", [buffer] |
|
|
; Free unused memory |
push edi |
invoke mem.free, [pageaddr] |
391,12 → 440,20 |
jz .error |
DEBUGF 1, "Request has been sent to server.\n" |
|
HTTP_init_buffer [buffer], [socketnum] |
cmp [identifier], 0 |
jne .old_connection |
HTTP_init_buffer [buffer], [socketnum], [flags] |
|
popa |
mov eax, [buffer] |
ret ; return buffer ptr |
mov eax, [buffer] ; return buffer ptr |
ret |
|
.old_connection: |
invoke mem.free, [buffer] |
popa |
mov eax, [identifier] |
ret |
|
.error: |
DEBUGF 1, "Error!\n" |
popa |
407,27 → 464,30 |
|
|
;;================================================================================================;; |
proc HTTP_post URL, add_header, content_type, content_length ;////////////////////////////////////;; |
proc HTTP_post URL, identifier, flags, add_header, content_type, content_length ;/////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Initiates a HTTP connection, using 'POST' method. ;; |
;? This method is used to send data to the HTTP server ;; |
;;------------------------------------------------------------------------------------------------;; |
;> URL = pointer to ASCIIZ URL ;; |
;> add_header = pointer to additional header parameters (ASCIIZ), or null for none. ;; |
;> identifier = Identifier of an already open connection, or NULL to create a new one. ;; |
;> flags = Flags indicating how to threat the connection. ;; |
;> add_header = pointer to additional header parameters (ASCIIZ), or NULL for none. ;; |
;> content_type = pointer to ASCIIZ string containing content type ;; |
;> content_length = length of content (in bytes) ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) / buffer ptr ;; |
;< eax = 0 (error) / buffer ptr (aka Identifier) ;; |
;;================================================================================================;; |
locals |
hostname dd ? |
pageaddr dd ? |
sockaddr dd ? |
socketnum dd ? |
buffer dd ? |
port dd ? |
endl |
|
and [flags], FLAG_KEEPALIVE or FLAG_MULTIBUFF ; filter out invalid flags |
|
pusha |
; split the URL into hostname and pageaddr |
stdcall parse_url, [URL] |
437,7 → 497,17 |
mov [pageaddr], ebx |
mov [port], ecx |
|
mov eax, [identifier] |
test eax, eax |
jz .open_new |
test [eax + http_msg.flags], FLAG_CONNECTED |
jz .error |
mov eax, [eax + http_msg.socket] |
mov [socketnum], eax |
jmp .send_request |
|
; Connect to the other side. |
.open_new: |
stdcall open_connection, [hostname], [port] |
test eax, eax |
jz .error |
444,6 → 514,7 |
mov [socketnum], eax |
|
; Create the HTTP request. |
.send_request: |
invoke mem.alloc, BUFFERSIZE |
test eax, eax |
jz .error |
502,6 → 573,11 |
|
mov esi, str_close |
mov ecx, str_close.length |
test [flags], FLAG_KEEPALIVE |
jz @f |
mov esi, str_keep |
mov ecx, str_keep.length |
@@: |
rep movsb |
|
mov byte[edi], 0 |
521,12 → 597,23 |
jz .error |
DEBUGF 1, "Request has been sent to server.\n" |
|
HTTP_init_buffer [buffer], [socketnum] |
cmp [identifier], 0 |
jne .old_connection |
HTTP_init_buffer [buffer], [socketnum], [flags] |
|
popa |
mov eax, [buffer] |
ret ; return buffer ptr |
mov eax, [buffer] ; return buffer ptr |
ret |
|
.old_connection: |
invoke mem.free, [buffer] |
mov ebx, [flags] |
mov eax, [identifier] |
or [eax + http_msg.flags], ebx |
popa |
mov eax, [identifier] |
ret |
|
.error: |
DEBUGF 1, "Error!\n" |
popa |
555,7 → 642,22 |
test [ebp + http_msg.flags], FLAG_CONNECTED |
jz .connection_closed |
|
; If the buffer is full, allocate a new one |
cmp [ebp + http_msg.buffer_length], 0 |
jne .receive |
|
test [ebp + http_msg.flags], FLAG_MULTIBUFF |
jz .err_header |
|
invoke mem.alloc, BUFFERSIZE |
test eax, eax |
jz .err_no_ram |
mov [ebp + http_msg.content_ptr], eax |
mov [ebp + http_msg.write_ptr], eax |
mov [ebp + http_msg.buffer_length], BUFFERSIZE |
|
; Receive some data |
.receive: |
mcall recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \ |
[ebp + http_msg.buffer_length], MSG_DONTWAIT |
cmp eax, 0xffffffff |
841,6 → 943,8 |
mov edx, esi |
sub edx, [ebp + http_msg.chunk_ptr] ; edx is now length of chunkline |
sub [ebp + http_msg.write_ptr], edx |
test [ebp + http_msg.flags], FLAG_MULTIBUFF |
jnz .dont_resize |
; Realloc buffer, make it 'chunksize' bigger. |
lea edx, [ebx + BUFFERSIZE] |
mov [ebp + http_msg.buffer_length], edx ; remaining space in new buffer |
853,6 → 957,7 |
jz .err_no_ram |
call recalculate_pointers ; Because it's possible that buffer begins on another address now |
add esi, eax ; recalculate esi too! |
.dont_resize: |
; Remove chunk header (aka chunkline) from the buffer by shifting all received data after chunkt_ptr to the left |
mov edi, [ebp + http_msg.chunk_ptr] |
rep movsb |
887,7 → 992,8 |
ret |
|
.buffer_full: |
; Lets make it bigger.. |
test [ebp + http_msg.flags], FLAG_MULTIBUFF |
jnz .multibuff |
mov eax, [ebp + http_msg.write_ptr] |
add eax, BUFFERSIZE |
sub eax, [ebp + http_msg.content_ptr] |
902,6 → 1008,12 |
dec eax |
ret |
|
.multibuff: |
; This buffer is full |
popa |
xor eax, eax |
ret |
|
.need_more_data_for_header: |
cmp [ebp + http_msg.buffer_length], 0 |
je .err_header ; It's just too damn long! |
1151,24 → 1263,22 |
|
|
;;================================================================================================;; |
proc HTTP_escape URI ;////////////////////////////////////////////////////////////////////////////;; |
proc HTTP_escape URI, length ;////////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? ;; |
;;------------------------------------------------------------------------------------------------;; |
;> URI = ptr to ASCIIZ URI ;; |
;> URI = ptr to ASCIIZ URI/data ;; |
;> length = length of URI/data ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) / ptr to ASCIIZ URI/data ;; |
;< ebx = length of escaped URI/data ;; |
;;================================================================================================;; |
|
|
; TODO: instead of static buffer allocation, make it 4096 bytes and larger only if needed |
|
DEBUGF 1, "HTTP_escape: %s\n", [URI] |
|
pusha |
|
invoke mem.alloc, URLMAXLEN |
invoke mem.alloc, URLMAXLEN ; FIXME: use length provided by caller to guess final size. |
test eax, eax |
jz .error |
mov [esp + 7 * 4], eax ; return ptr in eax |
1227,7 → 1337,7 |
|
|
;;================================================================================================;; |
proc HTTP_unescape URI ;//////////////////////////////////////////////////////////////////////////;; |
proc HTTP_unescape URI, length ;//////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? ;; |
;;------------------------------------------------------------------------------------------------;; |
1239,7 → 1349,7 |
DEBUGF 1, "HTTP_unescape: %s\n", [URI] |
pusha |
|
invoke mem.alloc, URLMAXLEN |
invoke mem.alloc, URLMAXLEN ; FIXME: use length provided by caller |
test eax, eax |
jz .error |
mov [esp + 7 * 4], eax ; return ptr in eax |
1768,8 → 1878,10 |
.length = $ - str_post_ct |
str_proxy_auth db 13, 10, 'Proxy-Authorization: Basic ' |
.length = $ - str_proxy_auth |
str_close db 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10 |
str_close db 'User-Agent: KolibriOS libHTTP/1.1', 13, 10, 'Connection: Close', 13, 10, 13, 10 |
.length = $ - str_close |
str_keep db 'User-Agent: KolibriOS libHTTP/1.1', 13, 10, 'Connection: Keepalive', 13, 10, 13, 10 |
.length = $ - str_close |
|
str_http db 'http://', 0 |
|