forked from KolibriOS/kolibrios
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:
parent
cb3c960361
commit
5da434be1e
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user