forked from KolibriOS/kolibrios
HTTP lib: added support for HEAD and POST methods
git-svn-id: svn://kolibrios.org@4167 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
71a9f8e4cf
commit
44992ba6df
@ -51,6 +51,22 @@ macro copy_till_zero {
|
|||||||
@@:
|
@@:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
section '.flat' code readable align 16
|
||||||
|
|
||||||
;;===========================================================================;;
|
;;===========================================================================;;
|
||||||
@ -108,6 +124,7 @@ locals
|
|||||||
sockaddr dd ?
|
sockaddr dd ?
|
||||||
socketnum dd ?
|
socketnum dd ?
|
||||||
buffer dd ?
|
buffer dd ?
|
||||||
|
port dd ?
|
||||||
endl
|
endl
|
||||||
|
|
||||||
; split the URL into hostname and pageaddr
|
; split the URL into hostname and pageaddr
|
||||||
@ -121,59 +138,29 @@ endl
|
|||||||
cmp [proxyAddr], 0
|
cmp [proxyAddr], 0
|
||||||
jne .proxy_done
|
jne .proxy_done
|
||||||
|
|
||||||
; TODO
|
|
||||||
.proxy_done:
|
.proxy_done:
|
||||||
|
|
||||||
; Resolve the hostname
|
;;;;
|
||||||
DEBUGF 1, "Resolving hostname\n"
|
mov [port], 80 ;;;; FIXME
|
||||||
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 .error
|
|
||||||
|
|
||||||
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
|
; Connect to the other side.
|
||||||
mov esi, [esi + addrinfo.ai_addr]
|
stdcall open_connection, [hostname], [port]
|
||||||
mov [sockaddr], esi
|
|
||||||
mov eax, [esi + sockaddr_in.sin_addr]
|
|
||||||
test eax, eax
|
|
||||||
jz .error
|
|
||||||
|
|
||||||
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 [esi + sockaddr_in.sin_port], 80 shl 8 ;;; FIXME
|
|
||||||
|
|
||||||
; Connect to the server.
|
|
||||||
mcall socket, AF_INET4, SOCK_STREAM, 0
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .error
|
jz .error
|
||||||
mov [socketnum], eax
|
mov [socketnum], eax
|
||||||
DEBUGF 1, "Socket: 0x%x\n", eax
|
|
||||||
|
|
||||||
mcall connect, [socketnum], [sockaddr], 18
|
|
||||||
test eax, eax
|
|
||||||
jnz .error
|
|
||||||
DEBUGF 1, "Socket is now connected.\n"
|
|
||||||
|
|
||||||
; TODO: free address buffer(s)
|
|
||||||
|
|
||||||
; Create the HTTP request.
|
; Create the HTTP request.
|
||||||
invoke mem.alloc, BUFFERSIZE
|
invoke mem.alloc, BUFFERSIZE
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .error
|
jz .error
|
||||||
mov [buffer], eax
|
mov [buffer], eax
|
||||||
|
mov edi, eax
|
||||||
DEBUGF 1, "Buffer has been allocated.\n"
|
DEBUGF 1, "Buffer has been allocated.\n"
|
||||||
|
|
||||||
mov dword[eax], 'GET '
|
mov esi, str_get
|
||||||
lea edi, [eax + 4]
|
copy_till_zero
|
||||||
mov esi, [pageaddr] ; TODO: for proxy use http:// and then full URL
|
|
||||||
|
mov esi, [pageaddr]
|
||||||
copy_till_zero
|
copy_till_zero
|
||||||
|
|
||||||
mov esi, str_http11
|
mov esi, str_http11
|
||||||
@ -190,7 +177,7 @@ endl
|
|||||||
mov byte[edi], 0
|
mov byte[edi], 0
|
||||||
DEBUGF 1, "Request:\n%s", [buffer]
|
DEBUGF 1, "Request:\n%s", [buffer]
|
||||||
|
|
||||||
; now send the request
|
; Send the request
|
||||||
mov esi, edi
|
mov esi, edi
|
||||||
sub esi, [buffer] ; length
|
sub esi, [buffer] ; length
|
||||||
xor edi, edi ; flags
|
xor edi, edi ; flags
|
||||||
@ -200,19 +187,209 @@ endl
|
|||||||
jz .error
|
jz .error
|
||||||
DEBUGF 1, "Request has been sent to server.\n"
|
DEBUGF 1, "Request has been sent to server.\n"
|
||||||
|
|
||||||
; Now that we have sent the request, re-purpose buffer as receive buffer
|
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
|
ret ; return buffer ptr
|
||||||
mov [eax + http_msg.header_length], 0
|
|
||||||
mov [eax + http_msg.content_length], 0
|
.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
|
||||||
|
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_head
|
||||||
|
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_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"
|
||||||
|
|
||||||
|
HTTP_init_buffer [buffer], [socketnum]
|
||||||
|
|
||||||
|
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
|
ret ; return buffer ptr
|
||||||
|
|
||||||
@ -505,7 +682,6 @@ proc HTTP_process identifier ;//////////////////////////////////////////////////
|
|||||||
sub eax, http_msg.data
|
sub eax, http_msg.data
|
||||||
sub eax, ebp
|
sub eax, ebp
|
||||||
mov [ebp + http_msg.content_length], eax
|
mov [ebp + http_msg.content_length], eax
|
||||||
|
|
||||||
.got_all_data:
|
.got_all_data:
|
||||||
DEBUGF 1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_length]
|
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
|
||||||
@ -611,6 +787,80 @@ endp
|
|||||||
|
|
||||||
; internal procedures start here:
|
; 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 ;//////////////////////////////////////////////////////////////////////////////;;
|
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
|
||||||
@ -716,7 +966,21 @@ endl
|
|||||||
endp
|
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 @@ export \
|
|||||||
lib_init , 'lib_init' , \
|
lib_init , 'lib_init' , \
|
||||||
0x00010001 , 'version' , \
|
0x00010001 , 'version' , \
|
||||||
HTTP_get , 'get' , \
|
HTTP_get , 'get' , \
|
||||||
|
HTTP_head , 'head' , \
|
||||||
|
HTTP_post , 'post' , \
|
||||||
find_header_field , 'find_header_field' , \
|
find_header_field , 'find_header_field' , \
|
||||||
HTTP_process , 'process'
|
HTTP_process , 'process'
|
||||||
|
|
||||||
; HTTP_head , 'head' , \
|
|
||||||
; HTTP_post , 'post' , \
|
|
||||||
; HTTP_put , 'put' , \
|
; HTTP_put , 'put' , \
|
||||||
; HTTP_delete , 'delete' , \
|
; HTTP_delete , 'delete' , \
|
||||||
; HTTP_trace , 'trace' , \
|
; HTTP_trace , 'trace' , \
|
||||||
@ -783,6 +1047,10 @@ key_password db 'password', 0
|
|||||||
|
|
||||||
str_http11 db ' HTTP/1.1', 13, 10, 'Host: '
|
str_http11 db ' HTTP/1.1', 13, 10, 'Host: '
|
||||||
.length = $ - str_http11
|
.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
|
str_close db 13, 10, 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10
|
||||||
.length = $ - str_close
|
.length = $ - str_close
|
||||||
str_proxy_auth db 13, 10, 'Proxy-Authorization: Basic '
|
str_proxy_auth db 13, 10, 'Proxy-Authorization: Basic '
|
||||||
@ -794,6 +1062,9 @@ base64_table db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
|||||||
str_cl db 'content-length', 0
|
str_cl db 'content-length', 0
|
||||||
str_slash db '/', 0
|
str_slash db '/', 0
|
||||||
str_te db 'transfer-encoding', 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
|
include_debug_strings
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user