51,6 → 51,22 |
@@: |
} |
|
macro HTTP_init_buffer buffer, socketnum { |
|
mov eax, buffer |
push socketnum |
popd [eax + http_msg.socket] |
lea esi, [eax + http_msg.data] |
mov [eax + http_msg.flags], 0 |
mov [eax + http_msg.write_ptr], esi |
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_length], 0 |
} |
|
section '.flat' code readable align 16 |
|
;;===========================================================================;; |
108,6 → 124,7 |
sockaddr dd ? |
socketnum dd ? |
buffer dd ? |
port dd ? |
endl |
|
; split the URL into hostname and pageaddr |
121,61 → 138,123 |
cmp [proxyAddr], 0 |
jne .proxy_done |
|
; TODO |
.proxy_done: |
|
; Resolve the hostname |
DEBUGF 1, "Resolving hostname\n" |
push esp ; reserve stack place |
push esp ; fourth parameter |
push 0 ; third parameter |
push 0 ; second parameter |
push [hostname] |
call [getaddrinfo] |
pop esi |
;;;; |
mov [port], 80 ;;;; FIXME |
|
; Connect to the other side. |
stdcall open_connection, [hostname], [port] |
test eax, eax |
jnz .error |
jz .error |
mov [socketnum], eax |
|
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct |
mov esi, [esi + addrinfo.ai_addr] |
mov [sockaddr], esi |
mov eax, [esi + sockaddr_in.sin_addr] |
; Create the HTTP request. |
invoke mem.alloc, BUFFERSIZE |
test eax, eax |
jz .error |
mov [buffer], eax |
mov edi, eax |
DEBUGF 1, "Buffer has been allocated.\n" |
|
DEBUGF 1, "Server ip=%u.%u.%u.%u\n", \ |
[esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \ |
[esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1 |
mov esi, str_get |
copy_till_zero |
|
mov [esi + sockaddr_in.sin_family], AF_INET4 |
mov [esi + sockaddr_in.sin_port], 80 shl 8 ;;; FIXME |
mov esi, [pageaddr] |
copy_till_zero |
|
; Connect to the server. |
mcall socket, AF_INET4, SOCK_STREAM, 0 |
mov esi, str_http11 |
mov ecx, str_http11.length |
rep movsb |
|
mov esi, [hostname] |
copy_till_zero |
|
mov esi, str_close |
mov ecx, str_close.length |
rep movsb |
|
mov byte[edi], 0 |
DEBUGF 1, "Request:\n%s", [buffer] |
|
; Send the request |
mov esi, edi |
sub esi, [buffer] ; length |
xor edi, edi ; flags |
|
mcall send, [socketnum], [buffer] |
test eax, eax |
jz .error |
mov [socketnum], eax |
DEBUGF 1, "Socket: 0x%x\n", eax |
DEBUGF 1, "Request has been sent to server.\n" |
|
mcall connect, [socketnum], [sockaddr], 18 |
HTTP_init_buffer [buffer], [socketnum] |
|
ret ; return buffer ptr |
|
.error: |
DEBUGF 1, "Error!\n" |
xor eax, eax ; return 0 = error |
ret |
|
endp |
|
|
|
;;================================================================================================;; |
proc HTTP_head URL ;///////////////////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _ ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) / buffer ptr ;; |
;;================================================================================================;; |
locals |
hostname dd ? |
pageaddr dd ? |
sockaddr dd ? |
socketnum dd ? |
buffer dd ? |
port dd ? |
endl |
|
; split the URL into hostname and pageaddr |
stdcall parse_url, [URL] |
test eax, eax |
jnz .error |
DEBUGF 1, "Socket is now connected.\n" |
jz .error |
mov [hostname], eax |
mov [pageaddr], ebx |
|
; TODO: free address buffer(s) |
; Do we need to use a proxy? |
cmp [proxyAddr], 0 |
jne .proxy_done |
|
; TODO: set hostname to that of the |
.proxy_done: |
|
;;;; |
mov [port], 80 ;;;; FIXME |
|
; Connect to the other side. |
stdcall open_connection, [hostname], [port] |
test eax, eax |
jz .error |
mov [socketnum], eax |
|
; Create the HTTP request. |
invoke mem.alloc, BUFFERSIZE |
test eax, eax |
jz .error |
mov [buffer], eax |
mov edi, eax |
DEBUGF 1, "Buffer has been allocated.\n" |
|
mov dword[eax], 'GET ' |
lea edi, [eax + 4] |
mov esi, [pageaddr] ; TODO: for proxy use http:// and then full URL |
mov esi, str_head |
copy_till_zero |
|
mov esi, [pageaddr] |
copy_till_zero |
|
mov esi, str_http11 |
mov ecx, str_http11.length |
rep movsb |
190,7 → 269,7 |
mov byte[edi], 0 |
DEBUGF 1, "Request:\n%s", [buffer] |
|
; now send the request |
; Send the request |
mov esi, edi |
sub esi, [buffer] ; length |
xor edi, edi ; flags |
200,20 → 279,118 |
jz .error |
DEBUGF 1, "Request has been sent to server.\n" |
|
; Now that we have sent the request, re-purpose buffer as receive buffer |
mov eax, [buffer] |
push [socketnum] |
popd [eax + http_msg.socket] |
lea esi, [eax + http_msg.data] |
mov [eax + http_msg.flags], 0 |
mov [eax + http_msg.write_ptr], esi |
mov [eax + http_msg.buffer_length], BUFFERSIZE - http_msg.data |
mov [eax + http_msg.chunk_ptr], 0 |
HTTP_init_buffer [buffer], [socketnum] |
|
mov [eax + http_msg.status], 0 |
mov [eax + http_msg.header_length], 0 |
mov [eax + http_msg.content_length], 0 |
ret ; return buffer ptr |
|
.error: |
DEBUGF 1, "Error!\n" |
xor eax, eax ; return 0 = error |
ret |
|
endp |
|
|
;;================================================================================================;; |
proc HTTP_post URL, content, content_type, content_length ;///////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _ ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) / buffer ptr ;; |
;;================================================================================================;; |
locals |
hostname dd ? |
pageaddr dd ? |
sockaddr dd ? |
socketnum dd ? |
buffer dd ? |
port dd ? |
endl |
|
; split the URL into hostname and pageaddr |
stdcall parse_url, [URL] |
test eax, eax |
jz .error |
mov [hostname], eax |
mov [pageaddr], ebx |
|
; Do we need to use a proxy? |
cmp [proxyAddr], 0 |
jne .proxy_done |
|
; TODO: set hostname to that of the |
.proxy_done: |
|
;;;; |
mov [port], 80 ;;;; FIXME |
|
; Connect to the other side. |
stdcall open_connection, [hostname], [port] |
test eax, eax |
jz .error |
mov [socketnum], eax |
|
; Create the HTTP request. |
invoke mem.alloc, BUFFERSIZE |
test eax, eax |
jz .error |
mov [buffer], eax |
mov edi, eax |
DEBUGF 1, "Buffer has been allocated.\n" |
|
mov esi, str_post |
copy_till_zero |
|
mov esi, [pageaddr] |
copy_till_zero |
|
mov esi, str_http11 |
mov ecx, str_http11.length |
rep movsb |
|
mov esi, [hostname] |
copy_till_zero |
|
mov esi, str_post_cl |
mov ecx, str_post_cl.length |
rep movsb |
|
mov eax, [content_length] |
call ascii_dec |
|
mov esi, str_post_ct |
mov ecx, str_post_ct.length |
rep movsb |
|
mov esi, [content_type] |
rep movsb |
|
mov esi, str_close |
mov ecx, str_close.length |
rep movsb |
|
mov byte[edi], 0 |
DEBUGF 1, "Request:\n%s", [buffer] |
|
; Send the request |
mov esi, edi |
sub esi, [buffer] ; length |
xor edi, edi ; flags |
mcall send, [socketnum], [buffer] |
test eax, eax |
jz .error |
DEBUGF 1, "Request has been sent to server.\n" |
|
mcall send, [socketnum], [content], [content_length] |
test eax, eax |
jz .error |
DEBUGF 1, "Data has been sent to server.\n" |
|
HTTP_init_buffer [buffer], [socketnum] |
; mov eax, [buffer] |
|
ret ; return buffer ptr |
|
.error: |
505,7 → 682,6 |
sub eax, http_msg.data |
sub eax, ebp |
mov [ebp + http_msg.content_length], eax |
|
.got_all_data: |
DEBUGF 1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_length] |
or [ebp + http_msg.flags], FLAG_GOT_DATA |
611,7 → 787,81 |
|
; internal procedures start here: |
|
;;================================================================================================;; |
proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _ ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = -1 (error) / 0 ;; |
;;================================================================================================;; |
|
locals |
sockaddr dd ? |
socketnum dd ? |
endl |
|
; Resolve the hostname |
DEBUGF 1, "Resolving hostname\n" |
push esp ; reserve stack place |
push esp ; fourth parameter |
push 0 ; third parameter |
push 0 ; second parameter |
push [hostname] |
call [getaddrinfo] |
pop esi |
test eax, eax |
jnz .error1 |
|
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct |
mov esi, [esi + addrinfo.ai_addr] |
mov [sockaddr], esi |
mov eax, [esi + sockaddr_in.sin_addr] |
test eax, eax |
jz .error2 |
|
DEBUGF 1, "Server ip=%u.%u.%u.%u\n", \ |
[esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \ |
[esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1 |
|
mov [esi + sockaddr_in.sin_family], AF_INET4 |
mov eax, [port] |
xchg al, ah |
mov [esi + sockaddr_in.sin_port], ax |
|
; Connect to the server. |
mcall socket, AF_INET4, SOCK_STREAM, 0 |
test eax, eax |
jz .error2 |
mov [socketnum], eax |
DEBUGF 1, "Socket: 0x%x\n", eax |
|
mcall connect, [socketnum], [sockaddr], 18 |
test eax, eax |
jnz .error2 |
DEBUGF 1, "Socket is now connected.\n" |
|
; free allocated memory |
push [sockaddr] |
call [freeaddrinfo] |
|
mov eax, [socketnum] |
ret |
|
.error2: |
|
; free allocated memory |
push [sockaddr] |
call [freeaddrinfo] |
|
.error1: |
xor eax, eax |
ret |
|
endp |
|
|
;;================================================================================================;; |
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
716,9 → 966,23 |
endp |
|
|
; in: eax = number |
; edi = ptr where to store ascii |
ascii_dec: |
|
mov ecx, 10 |
.loop: |
xor edx, edx |
div ecx |
add dl, '0' |
mov byte[edi], dl |
inc edi |
test eax, eax |
jnz .loop |
|
ret |
|
|
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
759,11 → 1023,11 |
lib_init , 'lib_init' , \ |
0x00010001 , 'version' , \ |
HTTP_get , 'get' , \ |
HTTP_head , 'head' , \ |
HTTP_post , 'post' , \ |
find_header_field , 'find_header_field' , \ |
HTTP_process , 'process' |
|
; HTTP_head , 'head' , \ |
; HTTP_post , 'post' , \ |
; HTTP_put , 'put' , \ |
; HTTP_delete , 'delete' , \ |
; HTTP_trace , 'trace' , \ |
783,6 → 1047,10 |
|
str_http11 db ' HTTP/1.1', 13, 10, 'Host: ' |
.length = $ - str_http11 |
str_post_cl db 13, 10, 'Content-Length: ' |
.length = $ - str_post_cl |
str_post_ct db 13, 10, 'Content-Type: ' |
.length = $ - str_post_ct |
str_close db 13, 10, 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10 |
.length = $ - str_close |
str_proxy_auth db 13, 10, 'Proxy-Authorization: Basic ' |
794,6 → 1062,9 |
str_cl db 'content-length', 0 |
str_slash db '/', 0 |
str_te db 'transfer-encoding', 0 |
str_get db 'GET ', 0 |
str_head db 'HEAD ', 0 |
str_post db 'POST ', 0 |
|
include_debug_strings |
|