Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5533 → Rev 5534

/programs/develop/libraries/http/http.asm
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