Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4541 → Rev 4540

/programs/develop/libraries/http/http_en.txt
30,14 → 30,13
As long as the procedure expects more data, -1 is returned and the procedure must be called again.
- When transfer is done, the procedure will return 0.
 
The HTTP header is placed together with some flags and other attributes in the http_msg structure.
All data is placed together with some flags and other attributes in the http_msg structure.
This structure is defined in http.inc (and not copied here because it might still change.)
The identifier used by the functions is actually a pointer to this structure.
In the dword named .flags, the library will set various bit-flags indicating the status of the process.
(When a transfer is done, one should check these bit-flags to find out if the transfer was error-free.)
The HTTP header is placed at the end of this structure. The content is placed in another buffer.
All received data is placed at the end of this structure, including HTTP headers.
The dword .status contains the status code received from the server (e.g. 200 for OK).
In header_length you'll find the length of the header as soon as it has been received.
In content_ptr you'll find a pointer to the actual content.
In content_length you'll find the length of the content.
In content_received, you'll find the number of content bytes already received.
In content_length you'll find the length of the content (not counting headers).
In content_received, you'll find the number of bytes already received (not counting headers).
/programs/develop/libraries/http/http.asm
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; HTTP library for KolibriOS ;;
19,7 → 19,7
 
 
URLMAXLEN = 65535
BUFFERSIZE = 8192
BUFFERSIZE = 4096
TIMEOUT = 1000 ; in 1/100 s
 
__DEBUG__ = 1
59,15 → 59,14
mov eax, buffer
push socketnum
popd [eax + http_msg.socket]
lea esi, [eax + http_msg.http_header]
lea esi, [eax + http_msg.data]
mov [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.buffer_length], BUFFERSIZE - http_msg.data
mov [eax + http_msg.chunk_ptr], 0
 
mov [eax + http_msg.status], 0
mov [eax + http_msg.header_length], 0
mov [eax + http_msg.content_ptr], 0
mov [eax + http_msg.content_length], 0
mov [eax + http_msg.content_received], 0
 
111,13 → 110,16
popa
 
DEBUGF 1, "HTTP library: init OK\n"
 
xor eax, eax
ret
 
.error:
DEBUGF 1, "ERROR loading libraries\n"
 
xor eax, eax
inc eax
 
ret
 
 
164,7 → 166,7
jz .error
mov [buffer], eax
mov edi, eax
DEBUGF 1, "Buffer allocated: 0x%x\n", eax
DEBUGF 1, "Buffer has been allocated.\n"
 
mov esi, str_get
copy_till_zero
242,7 → 244,6
proc HTTP_head URL, 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. ;;
356,8 → 357,7
;;================================================================================================;;
proc HTTP_post URL, add_header, content_type, content_length ;////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Initiates a HTTP connection, using 'POST' method. ;;
;? This method is used to send data to the HTTP server ;;
;? Initiates a HTTP connection, using 'GET' method. ;;
;;------------------------------------------------------------------------------------------------;;
;> URL = pointer to ASCIIZ URL ;;
;> add_header = pointer to additional header parameters (ASCIIZ), or null for none. ;;
535,11 → 535,11
.scan_again:
; eax = total number of bytes received so far
mov eax, [ebp + http_msg.write_ptr]
sub eax, http_msg.http_header
sub eax, http_msg.data
sub eax, ebp
sub eax, [ebp + http_msg.header_length]
; edi is ptr to begin of header
lea edi, [ebp + http_msg.http_header]
lea edi, [ebp + http_msg.data]
add edi, [ebp + http_msg.header_length]
; put it in esi for next proc too
mov esi, edi
557,7 → 557,7
jmp .need_more_data
 
.end_of_header:
add edi, 4 - http_msg.http_header
add edi, 4 - http_msg.data
sub edi, ebp
mov [ebp + http_msg.header_length], edi ; If this isnt the final header, we'll use this as an offset to find real header.
DEBUGF 1, "Header length: %u\n", edi
601,7 → 601,7
; Now, convert all header names to lowercase.
; This way, it will be much easier to find certain header fields, later on.
 
lea esi, [ebp + http_msg.http_header]
lea esi, [ebp + http_msg.data]
mov ecx, [ebp + http_msg.header_length]
.need_newline:
inc esi
634,7 → 634,7
jmp .next_char
.convert_done:
mov byte[esi-1], 0
lea esi, [ebp + http_msg.http_header]
lea esi, [ebp + http_msg.data]
DEBUGF 1, "Header names converted to lowercase:\n%s\n", esi
 
; Check for content-length header field.
666,15 → 666,25
mov [ebp + http_msg.content_length], edx
DEBUGF 1, "Content-length: %u\n", edx
 
test edx, edx
jz .got_all_data
; Resize buffer according to content-length.
add edx, [ebp + http_msg.header_length]
add edx, http_msg.data
 
call alloc_contentbuff
test eax, eax
mov ecx, edx
sub ecx, [ebp + http_msg.write_ptr]
mov [ebp + http_msg.buffer_length], ecx
 
invoke mem.realloc, ebp, edx
or eax, eax
jz .no_ram
xor eax, eax
jmp .header_parsed
 
.not_chunked:
mov eax, [ebp + http_msg.write_ptr]
sub eax, [ebp + http_msg.header_length]
sub eax, http_msg.data
sub eax, ebp
jmp .header_parsed ; hooray!
 
.no_content:
DEBUGF 1, "Content-length not found.\n"
 
682,17 → 692,8
; Try to find 'transfer-encoding' header.
stdcall HTTP_find_header_field, ebp, str_te
test eax, eax
jnz .ct_hdr_found
jz .not_chunked
 
.not_chunked:
mov edx, BUFFERSIZE
call alloc_contentbuff
test eax, eax
jz .no_ram
xor eax, eax
jmp .header_parsed
 
.ct_hdr_found:
mov ebx, dword[eax]
or ebx, 0x20202020
cmp ebx, 'chun'
706,19 → 707,16
or [ebp + http_msg.flags], FLAG_CHUNKED
DEBUGF 1, "Transfer type is: chunked\n"
 
mov edx, BUFFERSIZE
call alloc_contentbuff
test eax, eax
jz .no_ram
 
; Set chunk pointer where first chunk should begin.
mov eax, [ebp + http_msg.content_ptr]
lea eax, [ebp + http_msg.data]
add eax, [ebp + http_msg.header_length]
mov [ebp + http_msg.chunk_ptr], eax
 
.chunk_loop:
mov ecx, [ebp + http_msg.write_ptr]
sub ecx, [ebp + http_msg.chunk_ptr]
jb .need_more_data_chunked
jb .need_more_data_chunked ; TODO: use this ecx !!!
 
; Chunkline starts here, convert the ASCII hex number into ebx
mov esi, [ebp + http_msg.chunk_ptr]
xor ebx, ebx
740,57 → 738,47
add bl, al
jmp .chunk_hexloop
.chunk_:
DEBUGF 1, "got chunk of %u bytes\n", ebx
;; cmp esi, [ebp + http_msg.chunk_ptr]
;; je
; If chunk size is 0, all chunks have been received.
test ebx, ebx
jz .got_all_data_chunked ; last chunk, hooray! FIXME: what if it wasnt a valid hex number???
 
; Chunkline ends with a CR, LF or simply LF
dec esi
.end_of_chunkline?:
lodsb
cmp al, 10
je .end_of_chunkline
cmp esi, [ebp + http_msg.write_ptr]
lodsb
cmp edi, [ebp + http_msg.write_ptr]
jb .end_of_chunkline?
jmp .need_more_data
 
.end_of_chunkline:
DEBUGF 1, "Chunk of %u bytes\n", ebx
; If chunk size is 0, all chunks have been received.
test ebx, ebx
jz .got_all_data_chunked
; Calculate how many data bytes we'll need to shift
mov ecx, [ebp + http_msg.write_ptr]
sub ecx, [ebp + http_msg.chunk_ptr]
; Calculate how many bytes we'll need to shift them
sub esi, [ebp + http_msg.chunk_ptr]
; Update write ptr
sub [ebp + http_msg.write_ptr], esi
; Update chunk ptr, and remember old one
mov edi, [ebp + http_msg.chunk_ptr]
add [ebp + http_msg.chunk_ptr], ebx
; Realloc buffer, make it 'chunksize' bigger.
add ebx, [ebp + http_msg.chunk_ptr]
sub ebx, [ebp + http_msg.content_ptr]
add ebx, BUFFERSIZE ; add some space for new chunkline header
DEBUGF 1, "Resizing buffer 0x%x, it will now be %u bytes\n", [ebp + http_msg.content_ptr], ebx
invoke mem.realloc, [ebp + http_msg.content_ptr], ebx
DEBUGF 1, "New buffer = 0x%x\n", eax
mov eax, [ebp + http_msg.buffer_length]
add eax, ebx
invoke mem.realloc, ebp, eax
or eax, eax
jz .no_ram
call recalculate_pointers
; Calculate remaining available buffer size
mov eax, [ebp + http_msg.content_ptr]
add eax, ebx
sub eax, [ebp + http_msg.write_ptr]
mov [ebp + http_msg.buffer_length], eax
; Move all received data to the left (remove chunk header).
mov edi, [ebp + http_msg.chunk_ptr]
add esi, edi
; Update chunk ptr so it points to next chunk
sub ebx, BUFFERSIZE
add [ebp + http_msg.chunk_ptr], ebx
; Update number of received content bytes
add [ebp + http_msg.buffer_length], ebx
 
; Update write ptr
mov eax, esi
sub eax, edi
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_received], ecx
DEBUGF 1, "Moving %u bytes from 0x%x to 0x%x\n", ecx, esi, edi
rep movsb
 
xor eax, eax
jmp .chunk_loop
 
;---------------------------------------------------------
; Check if we got all the data.
.header_parsed:
add [ebp + http_msg.content_received], eax
802,15 → 790,12
jmp .need_more_data
 
.need_more_data_and_space:
test [ebp + http_msg.flags], FLAG_GOT_HEADER
jz .invalid_header ; It's just too damn long!
mov eax, [ebp + http_msg.write_ptr]
add eax, BUFFERSIZE
sub eax, [ebp + http_msg.content_ptr]
invoke mem.realloc, [ebp + http_msg.content_ptr], eax
sub eax, ebp
invoke mem.realloc, ebp, eax
or eax, eax
jz .no_ram
call recalculate_pointers
mov [ebp + http_msg.buffer_length], BUFFERSIZE
 
.need_more_data:
828,7 → 813,9
 
.got_all_data_chunked:
mov eax, [ebp + http_msg.chunk_ptr]
sub eax, [ebp + http_msg.content_ptr]
sub eax, [ebp + http_msg.header_length]
sub eax, http_msg.data
sub eax, ebp
mov [ebp + http_msg.content_length], eax
mov [ebp + http_msg.content_received], eax
.got_all_data:
847,7 → 834,7
mcall 29, 9
sub eax, TIMEOUT
cmp eax, [ebp + http_msg.timestamp]
jl .need_more_data
jb .need_more_data
DEBUGF 1, "ERROR: timeout\n"
or [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
jmp .disconnect
890,57 → 877,8
endp
 
 
alloc_contentbuff:
 
; Allocate content buffer
invoke mem.alloc, edx
or eax, eax
jz .no_ram
 
DEBUGF 1, "Content buffer allocated: 0x%x\n", eax
 
; Copy already received content into content buffer
mov edi, eax
lea esi, [ebp + http_msg.http_header]
add esi, [ebp + http_msg.header_length]
mov ecx, [ebp + http_msg.write_ptr]
sub ecx, esi
mov ebx, ecx
rep movsb
 
; Update pointers to point to new buffer
mov [ebp + http_msg.content_ptr], eax
mov [ebp + http_msg.content_received], ebx
sub edx, ebx
mov [ebp + http_msg.buffer_length], edx
add eax, ebx
mov [ebp + http_msg.write_ptr], eax
 
; Shrink header buffer
mov eax, http_msg.http_header
add eax, [ebp + http_msg.header_length]
invoke mem.realloc, ebp, eax
or eax, eax
.no_ram:
 
ret
 
 
 
recalculate_pointers:
 
sub eax, [ebp + http_msg.content_ptr]
jz .done
add [ebp + http_msg.content_ptr], eax
add [ebp + http_msg.write_ptr], eax
add [ebp + http_msg.chunk_ptr], eax
 
.done:
ret
 
 
 
 
;;================================================================================================;;
proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
950,7 → 888,7
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
DEBUGF 1, "HTTP_free: 0x%x\n", [identifier]
 
pusha
mov ebp, [identifier]
 
1011,7 → 949,7
test [ebx + http_msg.flags], FLAG_GOT_HEADER
jz .fail
 
lea edx, [ebx + http_msg.http_header]
lea edx, [ebx + http_msg.data]
mov ecx, edx
add ecx, [ebx + http_msg.header_length]
 
/programs/develop/libraries/http/http.inc
35,13 → 35,10
.buffer_length dd ? ; internal use only (number of available bytes in buffer)
.chunk_ptr dd ? ; internal use only (where the next chunk begins)
.timestamp dd ? ; internal use only (when last data was received)
 
.status dd ? ; HTTP status
.header_length dd ? ; length of HTTP header
.content_ptr dd ? ; ptr to content
.content_length dd ? ; total length of HTTP content
.content_length dd ? ; length of HTTP content
.content_received dd ? ; number of currently received content bytes
.data:
 
.http_header:
 
}