From d52d41e20d8006ef2bc16dd53ef60f549912bd6d Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Fri, 20 Mar 2015 12:04:14 +0000 Subject: [PATCH] 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 --- programs/cmm/browser/WebView.c | 4 +- programs/cmm/browser/downloader.h | 4 +- programs/cmm/downloader/Downloader.c | 4 +- programs/cmm/lib/obj/http.h | 17 +- .../libraries/http/examples/downloader.asm | 106 +++++------ .../develop/libraries/http/examples/pasta.asm | 17 +- programs/develop/libraries/http/http.asm | 178 ++++++++++++++---- programs/develop/libraries/http/http.inc | 11 +- programs/develop/libraries/http/http_en.txt | 12 +- 9 files changed, 242 insertions(+), 111 deletions(-) diff --git a/programs/cmm/browser/WebView.c b/programs/cmm/browser/WebView.c index b014b2cbc8..db6876c315 100644 --- a/programs/cmm/browser/WebView.c +++ b/programs/cmm/browser/WebView.c @@ -220,7 +220,7 @@ void main() case evNetwork: if (http_transfer > 0) { - http_process stdcall (http_transfer); + http_receive stdcall (http_transfer); $push EAX ESI = http_transfer; wv_progress_bar.max = ESI.http_msg.content_length; @@ -618,7 +618,7 @@ void OpenPage() 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); - http_get stdcall (#URL, #accept_language); + http_get stdcall (#URL, 0, 0, #accept_language); http_transfer = EAX; if (http_transfer == 0) { diff --git a/programs/cmm/browser/downloader.h b/programs/cmm/browser/downloader.h index d5d9c52a09..0af589bbcd 100644 --- a/programs/cmm/browser/downloader.h +++ b/programs/cmm/browser/downloader.h @@ -88,7 +88,7 @@ void Downloader() default: if (DL_Form.width==0) || (DL_http_transfer <= 0) break; - http_process stdcall (DL_http_transfer); + http_receive stdcall (DL_http_transfer); $push EAX ESI = DL_http_transfer; DL_progress_bar.max = ESI.http_msg.content_length; @@ -220,7 +220,7 @@ void StartDownloading() { download_state = STATE_IN_PROGRESS; 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_progress_bar.value = 0; DL_Draw_Window(); diff --git a/programs/cmm/downloader/Downloader.c b/programs/cmm/downloader/Downloader.c index 83fb470516..bbc75bf453 100644 --- a/programs/cmm/downloader/Downloader.c +++ b/programs/cmm/downloader/Downloader.c @@ -96,7 +96,7 @@ void main() default: if (Form.width==0) break; if (http_transfer <= 0) break; - http_process stdcall (http_transfer); + http_receive stdcall (http_transfer); if (EAX == 0) { ESI = http_transfer; bufpointer = ESI.http_msg.content_ptr; @@ -222,7 +222,7 @@ void StartDownloading() if (strncmp(#URL,"http:",5)==0) { 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; Draw_Window(); if (http_transfer == 0) diff --git a/programs/cmm/lib/obj/http.h b/programs/cmm/lib/obj/http.h index 69c9854abc..4a9eb05b17 100644 --- a/programs/cmm/lib/obj/http.h +++ b/programs/cmm/lib/obj/http.h @@ -8,9 +8,10 @@ dword http_get = #aHTTPget; dword http_head = #aHTTPhead; dword http_post = #aHTTPpost; 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_stop = #aHTTPstop; dword uri_escape = #aURIescape; dword uri_unescape = #aURIunescape; $DD 2 dup 0 @@ -20,12 +21,14 @@ char aHTTPget[4] = "get\0"; char aHTTPhead[5] = "head\0"; char aHTTPpost[5] = "post\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 aHTTPstop[5] = "stop\0"; char aURIescape[7] = "escape\0"; char aURIunescape[9] = "unescape\0"; +// status flags #define FLAG_HTTP11 1 << 0 #define FLAG_GOT_HEADER 1 << 1 #define FLAG_GOT_ALL_DATA 1 << 2 @@ -33,7 +36,11 @@ char aURIunescape[9] = "unescape\0"; #define FLAG_CHUNKED 1 << 4 #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_NO_RAM 1 << 17 #define FLAG_SOCKET_ERROR 1 << 18 diff --git a/programs/develop/libraries/http/examples/downloader.asm b/programs/develop/libraries/http/examples/downloader.asm index b254e6d5da..9ecfccfed4 100644 --- a/programs/develop/libraries/http/examples/downloader.asm +++ b/programs/develop/libraries/http/examples/downloader.asm @@ -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 ;; ;; ;; ;; downloader.asm - HTTP client for KolibriOS ;; @@ -63,13 +63,13 @@ START: test eax, eax jnz exit ;--------------------------------------------------------------------- - mov edi,filename_area - mov esi,start_temp_file_name - call copy_file_name_path + mov edi,filename_area + mov esi,start_temp_file_name + call copy_file_name_path - mov edi,fname_buf - mov esi,start_file_path - call copy_file_name_path + mov edi,fname_buf + mov esi,start_file_path + call copy_file_name_path ;OpenDialog initialisation push dword OpenDialog_data @@ -86,7 +86,7 @@ START: inc [silently] download: - call download_1 + call download_1 test [silently], 0xff jnz save @@ -151,7 +151,7 @@ button: cmp ah, 1 ; button id=1 ? je exit - call download_1 + call download_1 jmp save ;--------------------------------------------------------------------- mouse: @@ -168,16 +168,16 @@ fail: download_1: DEBUGF 1, "Starting download\n" - invoke HTTP_get, params, 0 + invoke HTTP_get, 0, 0, params, 0 test eax, eax jz fail mov [identifier], eax .loop: - invoke HTTP_process, [identifier] + invoke HTTP_receive, [identifier] test eax, eax jnz .loop - ret + ret ;--------------------------------------------------------------------- save: mov ebp, [identifier] @@ -199,14 +199,14 @@ save: jmp still ;--------------------------------------------------------------------- copy_file_name_path: - xor eax,eax - cld + xor eax,eax + cld @@: - lodsb - stosb - test eax,eax - jnz @r - ret + lodsb + stosb + test eax,eax + jnz @r + ret ;--------------------------------------------------------------------- ; ********************************************* ; ******* WINDOW DEFINITIONS AND DRAW ******** @@ -225,23 +225,23 @@ draw_window: mcall 0, <50, 370>, <350, 170>, , 0, title ;----------------------------------- ; draw frames - mov [frame_data.x],dword frame_1.x shl 16+frame_1.width - mov [frame_data.y],dword frame_1.y shl 16+frame_1.height - mov [frame_data.text_pointer],dword select_addr_text - mov eax,[sc.work] - mov [frame_data.font_backgr_color],eax - mov eax,[sc.work_text] - mov [frame_data.font_color],eax - - push dword frame_data - call [Frame_draw] + mov [frame_data.x],dword frame_1.x shl 16+frame_1.width + mov [frame_data.y],dword frame_1.y shl 16+frame_1.height + mov [frame_data.text_pointer],dword select_addr_text + mov eax,[sc.work] + mov [frame_data.font_backgr_color],eax + mov eax,[sc.work_text] + mov [frame_data.font_color],eax + + push dword frame_data + call [Frame_draw] ;----------------------------------- - mov [frame_data.x],dword frame_2.x shl 16+frame_2.width - mov [frame_data.y],dword frame_2.y shl 16+frame_2.height - mov [frame_data.text_pointer],dword select_path_text + mov [frame_data.x],dword frame_2.x shl 16+frame_2.width + mov [frame_data.y],dword frame_2.y shl 16+frame_2.height + mov [frame_data.text_pointer],dword select_path_text - push dword frame_data - call [Frame_draw] + push dword frame_data + call [Frame_draw] ;----------------------------------- ; draw "url:" text mov ecx, [sc.work_text] @@ -255,7 +255,7 @@ draw_window: ; draw buttons mcall 8,,,22,[sc.work_button] ; reload mcall ,,, 24 ; stop - + mcall , ,,26 ; save ;----------------------------------- ; draw buttons text @@ -264,11 +264,11 @@ draw_window: mcall 4, , , button_text.1 mcall , , , button_text.2 mcall , , , button_text.3 - + mcall 13,,,0xffffff push dword PathShow_data_1 call [PathShow_draw] - + mcall 12, 2 ; end window redraw ret @@ -283,8 +283,8 @@ library lib_http, 'http.obj', \ proc_lib, 'proc_lib.obj' import lib_http, \ - HTTP_get , 'get' , \ - HTTP_process , 'process' ,\ + HTTP_get , 'get', \ + HTTP_receive , 'receive', \ HTTP_free , 'free' import box_lib, \ @@ -330,22 +330,22 @@ select_addr_text db ' NETWORK ADDRESS: ',0 select_path_text db ' PATH TO SAVE FILE: ',0 ;--------------------------------------------------------------------- frame_data: -.type dd 0 ;+0 +.type dd 0 ;+0 .x: -.x_size dw 0 ;+4 -.x_start dw 0 ;+6 +.x_size dw 0 ;+4 +.x_start dw 0 ;+6 .y: -.y_size dw 0 ;+8 -.y_start dw 0 ;+10 -.ext_fr_col dd 0x0 ;+12 -.int_fr_col dd 0xffffff ;+16 -.draw_text_flag dd 1 ;+20 -.text_pointer dd 0 ;+24 -.text_position dd 0 ;+28 -.font_number dd 0 ;+32 -.font_size_y dd 9 ;+36 -.font_color dd 0x0 ;+40 -.font_backgr_color dd 0xffffff ;+44 +.y_size dw 0 ;+8 +.y_start dw 0 ;+10 +.ext_fr_col dd 0x0 ;+12 +.int_fr_col dd 0xffffff ;+16 +.draw_text_flag dd 1 ;+20 +.text_pointer dd 0 ;+24 +.text_position dd 0 ;+28 +.font_number dd 0 ;+32 +.font_size_y dd 9 ;+36 +.font_color dd 0x0 ;+40 +.font_backgr_color dd 0xffffff ;+44 ;--------------------------------------------------------------------- PathShow_data_1: .type dd 0 ;+0 diff --git a/programs/develop/libraries/http/examples/pasta.asm b/programs/develop/libraries/http/examples/pasta.asm index 20d61250a7..9869342291 100644 --- a/programs/develop/libraries/http/examples/pasta.asm +++ b/programs/develop/libraries/http/examples/pasta.asm @@ -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 ;; ;; ;; ;; pasta.asm - Paste something to paste.kolibrios.org using POST ;; @@ -42,13 +42,13 @@ START: test eax, eax jnz exit - invoke HTTP_get, sz_url, 0 + invoke HTTP_get, sz_url, 0, 0, 0 test eax, eax jz error mov [identifier], eax .again: - invoke HTTP_process, [identifier] + invoke HTTP_receive, [identifier] test eax, eax jnz .again @@ -78,7 +78,7 @@ START: 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 jz error mov [identifier], eax @@ -87,7 +87,7 @@ START: mcall 75, 6, , sz_paste, sz_paste.length, 0 .again2: - invoke HTTP_process, [identifier] + invoke HTTP_receive, [identifier] test eax, eax jnz .again2 @@ -142,11 +142,10 @@ library lib_http, 'http.obj' import lib_http, \ HTTP_get, 'get', \ - HTTP_process, 'process', \ - HTTP_free, 'free', \ - HTTP_stop, 'stop', \ 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 diff --git a/programs/develop/libraries/http/http.asm b/programs/develop/libraries/http/http.asm index d74c3ac279..24ac4d5c0e 100644 --- a/programs/develop/libraries/http/http.asm +++ b/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 @@ local .copyloop, .copydone .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,25 +178,30 @@ proc HTTP_free identifier ;///////////////////////////////////////////////////// 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. ;; +;> URL = pointer to ASCIIZ URL ;; +;> 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 ;; ;;================================================================================================;; 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,13 +212,24 @@ endl 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 mov [socketnum], eax ; Create the HTTP request. + .send_request: invoke mem.alloc, BUFFERSIZE test eax, eax jz .error @@ -256,6 +274,11 @@ endl 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 @@ endl 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,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. ;; ;? 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. ;; +;> URL = pointer to ASCIIZ URL ;; +;> 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 ;; ;;================================================================================================;; 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,13 +354,24 @@ endl 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 mov [socketnum], eax ; Create the HTTP request. + .send_request: invoke mem.alloc, BUFFERSIZE test eax, eax jz .error @@ -371,12 +416,16 @@ endl 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,11 +440,19 @@ endl 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" @@ -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. ;; ;? 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,13 +497,24 @@ endl 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 mov [socketnum], eax ; Create the HTTP request. + .send_request: invoke mem.alloc, BUFFERSIZE test eax, eax jz .error @@ -502,6 +573,11 @@ endl 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,11 +597,22 @@ endl 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" @@ -555,7 +642,22 @@ proc HTTP_receive identifier ;////////////////////////////////////////////////// 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 @@ proc HTTP_receive identifier ;////////////////////////////////////////////////// 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 @@ proc HTTP_receive identifier ;////////////////////////////////////////////////// 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 @@ proc HTTP_receive identifier ;////////////////////////////////////////////////// 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 @@ proc HTTP_receive identifier ;////////////////////////////////////////////////// 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 @@ 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 ;; ;< 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 @@ 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] 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,7 +1878,9 @@ str_post_ct db 13, 10, 'Content-Type: ' .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 diff --git a/programs/develop/libraries/http/http.inc b/programs/develop/libraries/http/http.inc index 56042c295c..fb7b7910ca 100644 --- a/programs/develop/libraries/http/http.inc +++ b/programs/develop/libraries/http/http.inc @@ -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 ;; ;; ;; ;; HTTP library for KolibriOS ;; @@ -14,13 +14,20 @@ ; Bitflags for http_msg.flags + +; status FLAG_HTTP11 = 1 shl 0 FLAG_GOT_HEADER = 1 shl 1 FLAG_GOT_ALL_DATA = 1 shl 2 FLAG_CONTENT_LENGTH = 1 shl 3 FLAG_CHUNKED = 1 shl 4 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_NO_RAM = 1 shl 17 FLAG_SOCKET_ERROR = 1 shl 18 diff --git a/programs/develop/libraries/http/http_en.txt b/programs/develop/libraries/http/http_en.txt index a5093b562d..5a9bd219c8 100644 --- a/programs/develop/libraries/http/http_en.txt +++ b/programs/develop/libraries/http/http_en.txt @@ -1,20 +1,26 @@ -get(*url, *add_header); +get(*url, identifier, flags, *add_header); *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. Every additional parameter must end with CR LF bytes, including the last line. Initiates a HTTP connection, using 'GET' method. - returns 0 on error, identifier otherwise. -head(*url, *add_header); +head(*url, identifier, flags, *add_header); *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. Every additional parameter must end with CR LF bytes, including the last line. Initiate a HTTP connection, using 'HEAD' method. - 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 + 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. Every additional parameter must end with CR LF bytes, including the last line. *content-type = pointer to ASCIIZ string containing content type.