Extended http library API to allow keepalive connections, streaming connections and transfer of large files.

git-svn-id: svn://kolibrios.org@5534 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2015-03-20 12:04:14 +00:00
parent 5080442b18
commit d52d41e20d
9 changed files with 242 additions and 111 deletions

View File

@ -220,7 +220,7 @@ void main()
case evNetwork: case evNetwork:
if (http_transfer > 0) { if (http_transfer > 0) {
http_process stdcall (http_transfer); http_receive stdcall (http_transfer);
$push EAX $push EAX
ESI = http_transfer; ESI = http_transfer;
wv_progress_bar.max = ESI.http_msg.content_length; wv_progress_bar.max = ESI.http_msg.content_length;
@ -618,7 +618,7 @@ void OpenPage()
if (strncmp(#URL,"http:",5)==0) if (strncmp(#URL,"http:",5)==0)
{ {
img_draw stdcall(skin.image, address_box.left+address_box.width+1, address_box.top-2, 17, skin.h, 131, 0); img_draw stdcall(skin.image, address_box.left+address_box.width+1, address_box.top-2, 17, skin.h, 131, 0);
http_get stdcall (#URL, #accept_language); http_get stdcall (#URL, 0, 0, #accept_language);
http_transfer = EAX; http_transfer = EAX;
if (http_transfer == 0) if (http_transfer == 0)
{ {

View File

@ -88,7 +88,7 @@ void Downloader()
default: default:
if (DL_Form.width==0) || (DL_http_transfer <= 0) break; if (DL_Form.width==0) || (DL_http_transfer <= 0) break;
http_process stdcall (DL_http_transfer); http_receive stdcall (DL_http_transfer);
$push EAX $push EAX
ESI = DL_http_transfer; ESI = DL_http_transfer;
DL_progress_bar.max = ESI.http_msg.content_length; DL_progress_bar.max = ESI.http_msg.content_length;
@ -220,7 +220,7 @@ void StartDownloading()
{ {
download_state = STATE_IN_PROGRESS; download_state = STATE_IN_PROGRESS;
DL_address_box.color = DL_address_box.blur_border_color = DL_address_box.focus_border_color = 0xdddDDD; DL_address_box.color = DL_address_box.blur_border_color = DL_address_box.focus_border_color = 0xdddDDD;
http_get stdcall (#DL_URL, #accept_language); http_get stdcall (#DL_URL, 0, 0, #accept_language);
DL_http_transfer = EAX; DL_http_transfer = EAX;
DL_progress_bar.value = 0; DL_progress_bar.value = 0;
DL_Draw_Window(); DL_Draw_Window();

View File

@ -96,7 +96,7 @@ void main()
default: default:
if (Form.width==0) break; if (Form.width==0) break;
if (http_transfer <= 0) break; if (http_transfer <= 0) break;
http_process stdcall (http_transfer); http_receive stdcall (http_transfer);
if (EAX == 0) { if (EAX == 0) {
ESI = http_transfer; ESI = http_transfer;
bufpointer = ESI.http_msg.content_ptr; bufpointer = ESI.http_msg.content_ptr;
@ -222,7 +222,7 @@ void StartDownloading()
if (strncmp(#URL,"http:",5)==0) if (strncmp(#URL,"http:",5)==0)
{ {
address_box.color = address_box.blur_border_color = address_box.focus_border_color = 0xededed; address_box.color = address_box.blur_border_color = address_box.focus_border_color = 0xededed;
http_get stdcall (#URL, #accept_language); http_get stdcall (#URL, 0, 0, #accept_language);
http_transfer = EAX; http_transfer = EAX;
Draw_Window(); Draw_Window();
if (http_transfer == 0) if (http_transfer == 0)

View File

@ -8,9 +8,10 @@ dword http_get = #aHTTPget;
dword http_head = #aHTTPhead; dword http_head = #aHTTPhead;
dword http_post = #aHTTPpost; dword http_post = #aHTTPpost;
dword http_find_header_field = #aFHF; dword http_find_header_field = #aFHF;
dword http_process = #aHTTPprocess; dword http_send = #aHTTPsend;
dword http_receive = #aHTTPreceive;
dword http_disconnect = #aHTTPdisconnect;
dword http_free = #aHTTPfree; dword http_free = #aHTTPfree;
dword http_stop = #aHTTPstop;
dword uri_escape = #aURIescape; dword uri_escape = #aURIescape;
dword uri_unescape = #aURIunescape; dword uri_unescape = #aURIunescape;
$DD 2 dup 0 $DD 2 dup 0
@ -20,12 +21,14 @@ char aHTTPget[4] = "get\0";
char aHTTPhead[5] = "head\0"; char aHTTPhead[5] = "head\0";
char aHTTPpost[5] = "post\0"; char aHTTPpost[5] = "post\0";
char aFHF[18] = "find_header_field\0"; char aFHF[18] = "find_header_field\0";
char aHTTPprocess[8] = "process\0"; char aHTTPsend[5] = "send\0";
char aHTTPreceive[8] = "receive\0";
char aHTTPdisconnect[11] = "disconnect\0";
char aHTTPfree[5] = "free\0"; char aHTTPfree[5] = "free\0";
char aHTTPstop[5] = "stop\0";
char aURIescape[7] = "escape\0"; char aURIescape[7] = "escape\0";
char aURIunescape[9] = "unescape\0"; char aURIunescape[9] = "unescape\0";
// status flags
#define FLAG_HTTP11 1 << 0 #define FLAG_HTTP11 1 << 0
#define FLAG_GOT_HEADER 1 << 1 #define FLAG_GOT_HEADER 1 << 1
#define FLAG_GOT_ALL_DATA 1 << 2 #define FLAG_GOT_ALL_DATA 1 << 2
@ -33,7 +36,11 @@ char aURIunescape[9] = "unescape\0";
#define FLAG_CHUNKED 1 << 4 #define FLAG_CHUNKED 1 << 4
#define FLAG_CONNECTED 1 << 5 #define FLAG_CONNECTED 1 << 5
// error flags go into the upper word // user flags
#define FLAG_KEEPALIVE 1 << 8
#define FLAG_MULTIBUFF 1 << 9
// error flags
#define FLAG_INVALID_HEADER 1 << 16 #define FLAG_INVALID_HEADER 1 << 16
#define FLAG_NO_RAM 1 << 17 #define FLAG_NO_RAM 1 << 17
#define FLAG_SOCKET_ERROR 1 << 18 #define FLAG_SOCKET_ERROR 1 << 18

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2009-2013. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2009-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;; downloader.asm - HTTP client for KolibriOS ;; ;; downloader.asm - HTTP client for KolibriOS ;;
@ -168,13 +168,13 @@ fail:
download_1: download_1:
DEBUGF 1, "Starting download\n" DEBUGF 1, "Starting download\n"
invoke HTTP_get, params, 0 invoke HTTP_get, 0, 0, params, 0
test eax, eax test eax, eax
jz fail jz fail
mov [identifier], eax mov [identifier], eax
.loop: .loop:
invoke HTTP_process, [identifier] invoke HTTP_receive, [identifier]
test eax, eax test eax, eax
jnz .loop jnz .loop
ret ret
@ -283,8 +283,8 @@ library lib_http, 'http.obj', \
proc_lib, 'proc_lib.obj' proc_lib, 'proc_lib.obj'
import lib_http, \ import lib_http, \
HTTP_get , 'get' , \ HTTP_get , 'get', \
HTTP_process , 'process' ,\ HTTP_receive , 'receive', \
HTTP_free , 'free' HTTP_free , 'free'
import box_lib, \ import box_lib, \

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2014. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2014-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;; pasta.asm - Paste something to paste.kolibrios.org using POST ;; ;; pasta.asm - Paste something to paste.kolibrios.org using POST ;;
@ -42,13 +42,13 @@ START:
test eax, eax test eax, eax
jnz exit jnz exit
invoke HTTP_get, sz_url, 0 invoke HTTP_get, sz_url, 0, 0, 0
test eax, eax test eax, eax
jz error jz error
mov [identifier], eax mov [identifier], eax
.again: .again:
invoke HTTP_process, [identifier] invoke HTTP_receive, [identifier]
test eax, eax test eax, eax
jnz .again jnz .again
@ -78,7 +78,7 @@ START:
invoke HTTP_free, [identifier] invoke HTTP_free, [identifier]
invoke HTTP_post, sz_url, sz_cookie, sz_ctype, sz_paste.length invoke HTTP_post, sz_url, 0, 0, sz_cookie, sz_ctype, sz_paste.length
test eax, eax test eax, eax
jz error jz error
mov [identifier], eax mov [identifier], eax
@ -87,7 +87,7 @@ START:
mcall 75, 6, , sz_paste, sz_paste.length, 0 mcall 75, 6, , sz_paste, sz_paste.length, 0
.again2: .again2:
invoke HTTP_process, [identifier] invoke HTTP_receive, [identifier]
test eax, eax test eax, eax
jnz .again2 jnz .again2
@ -142,11 +142,10 @@ library lib_http, 'http.obj'
import lib_http, \ import lib_http, \
HTTP_get, 'get', \ HTTP_get, 'get', \
HTTP_process, 'process', \
HTTP_free, 'free', \
HTTP_stop, 'stop', \
HTTP_post, 'post', \ HTTP_post, 'post', \
HTTP_find_header_field, 'find_header_field' HTTP_receive, 'receive', \
HTTP_find_header_field, 'find_header_field', \
HTTP_free, 'free'
identifier dd 0 identifier dd 0

View File

@ -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 ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;; HTTP library for KolibriOS ;; ;; HTTP library for KolibriOS ;;
@ -54,13 +54,15 @@ local .copyloop, .copydone
.copydone: .copydone:
} }
macro HTTP_init_buffer buffer, socketnum { macro HTTP_init_buffer buffer, socketnum, flags {
mov eax, buffer mov eax, buffer
push socketnum push socketnum
popd [eax + http_msg.socket] popd [eax + http_msg.socket]
lea esi, [eax + http_msg.http_header] 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.write_ptr], esi
mov [eax + http_msg.buffer_length], BUFFERSIZE - http_msg.http_header mov [eax + http_msg.buffer_length], BUFFERSIZE - http_msg.http_header
mov [eax + http_msg.chunk_ptr], 0 mov [eax + http_msg.chunk_ptr], 0
@ -176,25 +178,30 @@ proc HTTP_free identifier ;/////////////////////////////////////////////////////
endp endp
;;================================================================================================;; ;;================================================================================================;;
proc HTTP_get URL, add_header ;///////////////////////////////////////////////////////////////////;; proc HTTP_get URL, identifier, flags, add_header ;////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? Initiates a HTTP connection, using 'GET' method. ;; ;? Initiates a HTTP connection, using 'GET' method. ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> URL = pointer to ASCIIZ URL ;; ;> 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 ;; ;< eax = 0 (error) / buffer ptr ;;
;;================================================================================================;; ;;================================================================================================;;
locals locals
hostname dd ? hostname dd ?
pageaddr dd ? pageaddr dd ?
sockaddr dd ?
socketnum dd ? socketnum dd ?
buffer dd ? buffer dd ?
port dd ? port dd ?
endl endl
and [flags], FLAG_KEEPALIVE or FLAG_MULTIBUFF ; filter out invalid flags
pusha pusha
; split the URL into hostname and pageaddr ; split the URL into hostname and pageaddr
@ -205,13 +212,24 @@ endl
mov [pageaddr], ebx mov [pageaddr], ebx
mov [port], ecx 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. ; Connect to the other side.
.open_new:
stdcall open_connection, [hostname], [port] stdcall open_connection, [hostname], [port]
test eax, eax test eax, eax
jz .error jz .error
mov [socketnum], eax mov [socketnum], eax
; Create the HTTP request. ; Create the HTTP request.
.send_request:
invoke mem.alloc, BUFFERSIZE invoke mem.alloc, BUFFERSIZE
test eax, eax test eax, eax
jz .error jz .error
@ -256,6 +274,11 @@ endl
mov esi, str_close mov esi, str_close
mov ecx, str_close.length mov ecx, str_close.length
test [flags], FLAG_KEEPALIVE
jz @f
mov esi, str_keep
mov ecx, str_keep.length
@@:
rep movsb rep movsb
mov byte[edi], 0 mov byte[edi], 0
@ -275,12 +298,20 @@ endl
jz .error jz .error
DEBUGF 1, "Request has been sent to server.\n" 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 popa
mov eax, [buffer] ; return buffer ptr mov eax, [buffer] ; return buffer ptr
ret ret
.old_connection:
invoke mem.free, [buffer]
popa
mov eax, [identifier]
ret
.error: .error:
DEBUGF 1, "Error!\n" DEBUGF 1, "Error!\n"
popa popa
@ -292,25 +323,28 @@ endp
;;================================================================================================;; ;;================================================================================================;;
proc HTTP_head URL, add_header ;//////////////////////////////////////////////////////////////////;; proc HTTP_head URL, identifier, flags, add_header ;///////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? Initiates a HTTP connection, using 'HEAD' method. ;; ;? Initiates a HTTP connection, using 'HEAD' method. ;;
;? This will only return HTTP header and status, no content ;; ;? This will only return HTTP header and status, no content ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> URL = pointer to ASCIIZ URL ;; ;> 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 ;; ;< eax = 0 (error) / buffer ptr ;;
;;================================================================================================;; ;;================================================================================================;;
locals locals
hostname dd ? hostname dd ?
pageaddr dd ? pageaddr dd ?
sockaddr dd ?
socketnum dd ? socketnum dd ?
buffer dd ? buffer dd ?
port dd ? port dd ?
endl endl
and [flags], FLAG_KEEPALIVE or FLAG_MULTIBUFF ; filter out invalid flags
pusha pusha
; split the URL into hostname and pageaddr ; split the URL into hostname and pageaddr
stdcall parse_url, [URL] stdcall parse_url, [URL]
@ -320,13 +354,24 @@ endl
mov [pageaddr], ebx mov [pageaddr], ebx
mov [port], ecx 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. ; Connect to the other side.
.open_new:
stdcall open_connection, [hostname], [port] stdcall open_connection, [hostname], [port]
test eax, eax test eax, eax
jz .error jz .error
mov [socketnum], eax mov [socketnum], eax
; Create the HTTP request. ; Create the HTTP request.
.send_request:
invoke mem.alloc, BUFFERSIZE invoke mem.alloc, BUFFERSIZE
test eax, eax test eax, eax
jz .error jz .error
@ -371,12 +416,16 @@ endl
mov esi, str_close mov esi, str_close
mov ecx, str_close.length mov ecx, str_close.length
test [flags], FLAG_KEEPALIVE
jz @f
mov esi, str_keep
mov ecx, str_keep.length
@@:
rep movsb rep movsb
mov byte[edi], 0 mov byte[edi], 0
DEBUGF 1, "Request:\n%s", [buffer] DEBUGF 1, "Request:\n%s", [buffer]
; Free unused memory ; Free unused memory
push edi push edi
invoke mem.free, [pageaddr] invoke mem.free, [pageaddr]
@ -391,11 +440,19 @@ endl
jz .error jz .error
DEBUGF 1, "Request has been sent to server.\n" 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 popa
mov eax, [buffer] mov eax, [buffer] ; return buffer ptr
ret ; return buffer ptr ret
.old_connection:
invoke mem.free, [buffer]
popa
mov eax, [identifier]
ret
.error: .error:
DEBUGF 1, "Error!\n" DEBUGF 1, "Error!\n"
@ -407,27 +464,30 @@ endp
;;================================================================================================;; ;;================================================================================================;;
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. ;; ;? Initiates a HTTP connection, using 'POST' method. ;;
;? This method is used to send data to the HTTP server ;; ;? This method is used to send data to the HTTP server ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> URL = pointer to ASCIIZ URL ;; ;> 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_type = pointer to ASCIIZ string containing content type ;;
;> content_length = length of content (in bytes) ;; ;> content_length = length of content (in bytes) ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< eax = 0 (error) / buffer ptr ;; ;< eax = 0 (error) / buffer ptr (aka Identifier) ;;
;;================================================================================================;; ;;================================================================================================;;
locals locals
hostname dd ? hostname dd ?
pageaddr dd ? pageaddr dd ?
sockaddr dd ?
socketnum dd ? socketnum dd ?
buffer dd ? buffer dd ?
port dd ? port dd ?
endl endl
and [flags], FLAG_KEEPALIVE or FLAG_MULTIBUFF ; filter out invalid flags
pusha pusha
; split the URL into hostname and pageaddr ; split the URL into hostname and pageaddr
stdcall parse_url, [URL] stdcall parse_url, [URL]
@ -437,13 +497,24 @@ endl
mov [pageaddr], ebx mov [pageaddr], ebx
mov [port], ecx 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. ; Connect to the other side.
.open_new:
stdcall open_connection, [hostname], [port] stdcall open_connection, [hostname], [port]
test eax, eax test eax, eax
jz .error jz .error
mov [socketnum], eax mov [socketnum], eax
; Create the HTTP request. ; Create the HTTP request.
.send_request:
invoke mem.alloc, BUFFERSIZE invoke mem.alloc, BUFFERSIZE
test eax, eax test eax, eax
jz .error jz .error
@ -502,6 +573,11 @@ endl
mov esi, str_close mov esi, str_close
mov ecx, str_close.length mov ecx, str_close.length
test [flags], FLAG_KEEPALIVE
jz @f
mov esi, str_keep
mov ecx, str_keep.length
@@:
rep movsb rep movsb
mov byte[edi], 0 mov byte[edi], 0
@ -521,11 +597,22 @@ endl
jz .error jz .error
DEBUGF 1, "Request has been sent to server.\n" 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 popa
mov eax, [buffer] mov eax, [buffer] ; return buffer ptr
ret ; 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: .error:
DEBUGF 1, "Error!\n" DEBUGF 1, "Error!\n"
@ -555,7 +642,22 @@ proc HTTP_receive identifier ;//////////////////////////////////////////////////
test [ebp + http_msg.flags], FLAG_CONNECTED test [ebp + http_msg.flags], FLAG_CONNECTED
jz .connection_closed 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 some data
.receive:
mcall recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \ mcall recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \
[ebp + http_msg.buffer_length], MSG_DONTWAIT [ebp + http_msg.buffer_length], MSG_DONTWAIT
cmp eax, 0xffffffff cmp eax, 0xffffffff
@ -841,6 +943,8 @@ proc HTTP_receive identifier ;//////////////////////////////////////////////////
mov edx, esi mov edx, esi
sub edx, [ebp + http_msg.chunk_ptr] ; edx is now length of chunkline sub edx, [ebp + http_msg.chunk_ptr] ; edx is now length of chunkline
sub [ebp + http_msg.write_ptr], edx sub [ebp + http_msg.write_ptr], edx
test [ebp + http_msg.flags], FLAG_MULTIBUFF
jnz .dont_resize
; Realloc buffer, make it 'chunksize' bigger. ; Realloc buffer, make it 'chunksize' bigger.
lea edx, [ebx + BUFFERSIZE] lea edx, [ebx + BUFFERSIZE]
mov [ebp + http_msg.buffer_length], edx ; remaining space in new buffer mov [ebp + http_msg.buffer_length], edx ; remaining space in new buffer
@ -853,6 +957,7 @@ proc HTTP_receive identifier ;//////////////////////////////////////////////////
jz .err_no_ram jz .err_no_ram
call recalculate_pointers ; Because it's possible that buffer begins on another address now call recalculate_pointers ; Because it's possible that buffer begins on another address now
add esi, eax ; recalculate esi too! 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 ; 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] mov edi, [ebp + http_msg.chunk_ptr]
rep movsb rep movsb
@ -887,7 +992,8 @@ proc HTTP_receive identifier ;//////////////////////////////////////////////////
ret ret
.buffer_full: .buffer_full:
; Lets make it bigger.. test [ebp + http_msg.flags], FLAG_MULTIBUFF
jnz .multibuff
mov eax, [ebp + http_msg.write_ptr] mov eax, [ebp + http_msg.write_ptr]
add eax, BUFFERSIZE add eax, BUFFERSIZE
sub eax, [ebp + http_msg.content_ptr] sub eax, [ebp + http_msg.content_ptr]
@ -902,6 +1008,12 @@ proc HTTP_receive identifier ;//////////////////////////////////////////////////
dec eax dec eax
ret ret
.multibuff:
; This buffer is full
popa
xor eax, eax
ret
.need_more_data_for_header: .need_more_data_for_header:
cmp [ebp + http_msg.buffer_length], 0 cmp [ebp + http_msg.buffer_length], 0
je .err_header ; It's just too damn long! je .err_header ; It's just too damn long!
@ -1151,24 +1263,22 @@ endp
;;================================================================================================;; ;;================================================================================================;;
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 ;; ;< eax = 0 (error) / ptr to ASCIIZ URI/data ;;
;< ebx = length of escaped 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] DEBUGF 1, "HTTP_escape: %s\n", [URI]
pusha pusha
invoke mem.alloc, URLMAXLEN invoke mem.alloc, URLMAXLEN ; FIXME: use length provided by caller to guess final size.
test eax, eax test eax, eax
jz .error jz .error
mov [esp + 7 * 4], eax ; return ptr in eax mov [esp + 7 * 4], eax ; return ptr in eax
@ -1227,7 +1337,7 @@ endp
;;================================================================================================;; ;;================================================================================================;;
proc HTTP_unescape URI ;//////////////////////////////////////////////////////////////////////////;; proc HTTP_unescape URI, length ;//////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? ;; ;? ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
@ -1239,7 +1349,7 @@ proc HTTP_unescape URI ;////////////////////////////////////////////////////////
DEBUGF 1, "HTTP_unescape: %s\n", [URI] DEBUGF 1, "HTTP_unescape: %s\n", [URI]
pusha pusha
invoke mem.alloc, URLMAXLEN invoke mem.alloc, URLMAXLEN ; FIXME: use length provided by caller
test eax, eax test eax, eax
jz .error jz .error
mov [esp + 7 * 4], eax ; return ptr in eax mov [esp + 7 * 4], eax ; return ptr in eax
@ -1768,7 +1878,9 @@ str_post_ct db 13, 10, 'Content-Type: '
.length = $ - str_post_ct .length = $ - str_post_ct
str_proxy_auth db 13, 10, 'Proxy-Authorization: Basic ' str_proxy_auth db 13, 10, 'Proxy-Authorization: Basic '
.length = $ - str_proxy_auth .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 .length = $ - str_close
str_http db 'http://', 0 str_http db 'http://', 0

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;; HTTP library for KolibriOS ;; ;; HTTP library for KolibriOS ;;
@ -14,13 +14,20 @@
; Bitflags for http_msg.flags ; Bitflags for http_msg.flags
; status
FLAG_HTTP11 = 1 shl 0 FLAG_HTTP11 = 1 shl 0
FLAG_GOT_HEADER = 1 shl 1 FLAG_GOT_HEADER = 1 shl 1
FLAG_GOT_ALL_DATA = 1 shl 2 FLAG_GOT_ALL_DATA = 1 shl 2
FLAG_CONTENT_LENGTH = 1 shl 3 FLAG_CONTENT_LENGTH = 1 shl 3
FLAG_CHUNKED = 1 shl 4 FLAG_CHUNKED = 1 shl 4
FLAG_CONNECTED = 1 shl 5 FLAG_CONNECTED = 1 shl 5
; ERROR flags go into the upper word
; user options
FLAG_KEEPALIVE = 1 shl 8
FLAG_MULTIBUFF = 1 shl 9
; error
FLAG_INVALID_HEADER = 1 shl 16 FLAG_INVALID_HEADER = 1 shl 16
FLAG_NO_RAM = 1 shl 17 FLAG_NO_RAM = 1 shl 17
FLAG_SOCKET_ERROR = 1 shl 18 FLAG_SOCKET_ERROR = 1 shl 18

View File

@ -1,20 +1,26 @@
get(*url, *add_header); get(*url, identifier, flags, *add_header);
*url = pointer to ASCIIZ URL *url = pointer to ASCIIZ URL
identifier = identified of previously opened connection, or 0 to open a new one
flags = bit flags (see http.inc user flags)
*add_header = pointer to ASCIIZ additional header parameters, or null for none. *add_header = pointer to ASCIIZ additional header parameters, or null for none.
Every additional parameter must end with CR LF bytes, including the last line. Every additional parameter must end with CR LF bytes, including the last line.
Initiates a HTTP connection, using 'GET' method. Initiates a HTTP connection, using 'GET' method.
- returns 0 on error, identifier otherwise. - returns 0 on error, identifier otherwise.
head(*url, *add_header); head(*url, identifier, flags, *add_header);
*url = pointer to ASCIIZ URL *url = pointer to ASCIIZ URL
identifier = identified of previously opened connection, or 0 to open a new one
flags = bit flags (see http.inc user flags)
*add_header = pointer to ASCIIZ additional header parameters, or null for none. *add_header = pointer to ASCIIZ additional header parameters, or null for none.
Every additional parameter must end with CR LF bytes, including the last line. Every additional parameter must end with CR LF bytes, including the last line.
Initiate a HTTP connection, using 'HEAD' method. Initiate a HTTP connection, using 'HEAD' method.
- returns 0 on error, identifier otherwise - returns 0 on error, identifier otherwise
post(*url, *add_header, *content-type, content-length); post(*url, identifier, flags, *add_header, *content-type, content-length);
*url = pointer to ASCIIZ URL *url = pointer to ASCIIZ URL
identifier = identified of previously opened connection, or 0 to open a new one
flags = bit flags (see http.inc user flags)
*add_header = pointer to ASCIIZ additional header parameters, or null for none. *add_header = pointer to ASCIIZ additional header parameters, or null for none.
Every additional parameter must end with CR LF bytes, including the last line. Every additional parameter must end with CR LF bytes, including the last line.
*content-type = pointer to ASCIIZ string containing content type. *content-type = pointer to ASCIIZ string containing content type.