HTTP lib now also supports chunked content encoding.

git-svn-id: svn://kolibrios.org@4162 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2013-11-04 18:41:15 +00:00
parent cb3c960361
commit 5da434be1e

View File

@ -236,21 +236,31 @@ proc HTTP_process identifier ;//////////////////////////////////////////////////
;;================================================================================================;; ;;================================================================================================;;
pusha pusha
mov ebp, [identifier] mov ebp, [identifier]
; Receive some data
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
je .check_socket je .check_socket
DEBUGF 1, "Received %u bytes\n", eax DEBUGF 1, "Received %u bytes\n", eax
; Update pointers
mov edi, [ebp + http_msg.write_ptr] mov edi, [ebp + http_msg.write_ptr]
add [ebp + http_msg.write_ptr], eax add [ebp + http_msg.write_ptr], eax
sub [ebp + http_msg.buffer_length], eax sub [ebp + http_msg.buffer_length], eax
jz .got_all_data jz .got_all_data
; If data is chunked, combine chunks into contiguous data.
test [ebp + http_msg.flags], FLAG_CHUNKED
jnz .chunk_loop
; Did we detect the header yet?
test [ebp + http_msg.flags], FLAG_GOT_HEADER test [ebp + http_msg.flags], FLAG_GOT_HEADER
jnz .header_parsed jnz .header_parsed
; We havent found the header yet, search for it..
sub eax, 4 sub eax, 4
jl .no_header jl .need_more_data
.scan: .scan:
; scan for end of header (empty line) ; scan for end of header (empty line)
cmp dword[edi], 0x0a0d0a0d ; end of header cmp dword[edi], 0x0a0d0a0d ; end of header
@ -261,12 +271,6 @@ proc HTTP_process identifier ;//////////////////////////////////////////////////
dec eax dec eax
jnz .scan jnz .scan
.no_header:
popa
xor eax, eax
dec eax
ret
.end_of_header: .end_of_header:
add edi, 4 - http_msg.data add edi, 4 - http_msg.data
sub edi, ebp sub edi, ebp
@ -397,34 +401,29 @@ proc HTTP_process identifier ;//////////////////////////////////////////////////
jz .invalid_header jz .invalid_header
mov ebx, dword[eax] mov ebx, dword[eax]
or eax, 0x20202020 or ebx, 0x20202020
cmp ebx, 'chun' cmp ebx, 'chun'
jne .invalid_header jne .invalid_header
mov ebx, dword[eax+4] mov ebx, dword[eax+4]
or eax, 0x00202020 or ebx, 0x00202020
and eax, 0x00ffffff and ebx, 0x00ffffff
cmp ebx, 'ked' cmp ebx, 'ked'
jne .invalid_header jne .invalid_header
or [ebp + http_msg.flags], FLAG_CHUNKED or [ebp + http_msg.flags], FLAG_CHUNKED
DEBUGF 1, "Transfer type is: chunked\n" DEBUGF 1, "Transfer type is: chunked\n"
; Set chunk pointer where first chunk should begin. ; Set chunk pointer where first chunk should begin.
mov eax, [ebp + http_msg.header_length] lea eax, [ebp + http_msg.data]
add eax, http_msg.data add eax, [ebp + http_msg.header_length]
mov [ebp + http_msg.chunk_ptr], eax mov [ebp + http_msg.chunk_ptr], eax
.header_parsed: .chunk_loop:
; If data is chunked, combine chunks into contiguous data if so.
test [ebp + http_msg.flags], FLAG_CHUNKED
jz .not_chunked
.chunkloop:
mov ecx, [ebp + http_msg.write_ptr] mov ecx, [ebp + http_msg.write_ptr]
sub ecx, [ebp + http_msg.chunk_ptr] sub ecx, [ebp + http_msg.chunk_ptr]
jb .not_finished jb .need_more_data_chunked
; TODO: make sure we have the complete chunkline header
mov esi, [ebp + http_msg.chunk_ptr] mov esi, [ebp + http_msg.chunk_ptr]
xor ebx, ebx xor ebx, ebx
.chunk_hexloop: .chunk_hexloop:
@ -433,12 +432,12 @@ proc HTTP_process identifier ;//////////////////////////////////////////////////
jb .chunk_ jb .chunk_
cmp al, 9 cmp al, 9
jbe .chunk_hex jbe .chunk_hex
sub al, 'A' - '0' sub al, 'A' - '0' - 10
jb .chunk_ jb .chunk_
cmp al, 5 cmp al, 15
jbe .chunk_hex jbe .chunk_hex
sub al, 'a' - 'A' sub al, 'a' - 'A'
cmp al, 5 cmp al, 15
ja .chunk_ ja .chunk_
.chunk_hex: .chunk_hex:
shl ebx, 4 shl ebx, 4
@ -448,7 +447,8 @@ proc HTTP_process identifier ;//////////////////////////////////////////////////
DEBUGF 1, "got chunk of %u bytes\n", ebx DEBUGF 1, "got chunk of %u bytes\n", ebx
; If chunk size is 0, all chunks have been received. ; If chunk size is 0, all chunks have been received.
test ebx, ebx test ebx, ebx
jz .got_all_data ; last chunk, hooray! FIXME: what if it wasnt a valid hex number??? jz .got_all_data_chunked ; last chunk, hooray! FIXME: what if it wasnt a valid hex number???
mov edi, [ebp + http_msg.chunk_ptr] ; we'll need this in about 25 lines...
add [ebp + http_msg.chunk_ptr], ebx add [ebp + http_msg.chunk_ptr], ebx
; Chunkline ends with a CR, LF or simply LF ; Chunkline ends with a CR, LF or simply LF
@ -459,34 +459,55 @@ proc HTTP_process identifier ;//////////////////////////////////////////////////
jmp .end_of_chunkline? jmp .end_of_chunkline?
.end_of_chunkline: .end_of_chunkline:
; Now move all received data to the left (remove chunk header). ; Realloc buffer, make it 'chunksize' bigger.
; Meanwhile, update write_ptr and content_length accordingly. mov eax, [ebp + http_msg.buffer_length]
mov edi, [ebp + http_msg.chunk_ptr] add eax, ebx
mov ecx, [ebp + http_msg.write_ptr] invoke mem.realloc, ebp, eax
sub ecx, esi or eax, eax
jz .no_ram
add [ebp + http_msg.buffer_length], ebx
; Update write ptr
mov eax, esi mov eax, esi
sub eax, edi sub eax, edi
sub [ebp + http_msg.write_ptr], eax sub [ebp + http_msg.write_ptr], eax
; Now move all received data to the left (remove chunk header).
; Update content_length accordingly.
mov ecx, [ebp + http_msg.write_ptr]
sub ecx, esi
add [ebp + http_msg.content_length], ecx add [ebp + http_msg.content_length], ecx
rep movsb rep movsb
jmp .chunkloop jmp .chunk_loop
.not_chunked:
; Check if we got all the data. ; Check if we got all the data.
.header_parsed:
mov eax, [ebp + http_msg.header_length] mov eax, [ebp + http_msg.header_length]
add eax, [ebp + http_msg.content_length] add eax, [ebp + http_msg.content_length]
cmp eax, [ebp + http_msg.buffer_length] cmp eax, [ebp + http_msg.buffer_length]
je .got_all_data je .got_all_data
.need_more_data:
.not_finished:
; DEBUGF 1, "Needs more processing...\n"
popa popa
xor eax, eax xor eax, eax
dec eax dec eax
ret ret
.need_more_data_chunked:
add [ebp + http_msg.content_length], eax
popa
xor eax, eax
dec eax
ret
.got_all_data_chunked:
mov eax, [ebp + http_msg.chunk_ptr]
sub eax, [ebp + http_msg.header_length]
sub eax, http_msg.data
sub eax, ebp
mov [ebp + http_msg.content_length], eax
.got_all_data: .got_all_data:
DEBUGF 1, "We got all the data!\n" DEBUGF 1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_length]
or [ebp + http_msg.flags], FLAG_GOT_DATA or [ebp + http_msg.flags], FLAG_GOT_DATA
mcall close, [ebp + http_msg.socket] mcall close, [ebp + http_msg.socket]
popa popa
@ -495,7 +516,7 @@ proc HTTP_process identifier ;//////////////////////////////////////////////////
.check_socket: .check_socket:
cmp ebx, EWOULDBLOCK cmp ebx, EWOULDBLOCK
je .not_finished je .need_more_data
DEBUGF 1, "ERROR: socket error %u\n", ebx DEBUGF 1, "ERROR: socket error %u\n", ebx
or [ebp + http_msg.flags], FLAG_SOCKET_ERROR or [ebp + http_msg.flags], FLAG_SOCKET_ERROR