In the latest sources, http_RequestAndResponse and other methods that

use connect() are broken. More specifically, connect() in these methods
is returning with an EINVAL. The programatic cause is that the address_len
argument passed to connect() is different in IPV4 vs IPV6 (as described in:
http://www.opengroup.org/onlinepubs/009695399/functions/connect.html).
The current code always uses the IPV6 size. The fix modifies each use of
connect() to use the correct size based on the address family being used.

Patch submitted by Chandra (inactiveneurons).
This commit is contained in:
Marcelo Roberto Jimenez 2010-09-07 21:34:16 -03:00
parent 97af8b6fdb
commit 21660334e4
2 changed files with 355 additions and 379 deletions

View File

@ -2,6 +2,17 @@
Version 1.6.7
*******************************************************************************
2010-09-07 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
In the latest sources, http_RequestAndResponse and other methods that
use connect() are broken. More specifically, connect() in these methods
is returning with an EINVAL. The programatic cause is that the address_len
argument passed to connect() is different in IPV4 vs IPV6 (as described in:
http://www.opengroup.org/onlinepubs/009695399/functions/connect.html).
The current code always uses the IPV6 size. The fix modifies each use of
connect() to use the correct size based on the address family being used.
Patch submitted by Chandra (inactiveneurons).
2010-09-07 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
Fix compilation error in upnp/src/gena/gena_ctrlpt.c (this is most
likely an error on all platforms).

View File

@ -176,31 +176,35 @@ http_FixStrUrl( IN const char *urlstr,
* UPNP_E_OUTOF_SOCKET
* UPNP_E_SOCKET_CONNECT on error
************************************************************************/
int
http_Connect( IN uri_type * destination_url,
OUT uri_type * url )
int http_Connect(
IN uri_type *destination_url,
OUT uri_type *url)
{
int connfd;
int connfd;
int sockaddr_len;
int ret_connect;
http_FixUrl( destination_url, url );
http_FixUrl(destination_url, url);
connfd = socket( url->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( connfd == -1 ) {
return UPNP_E_OUTOF_SOCKET;
}
if( connect( connfd, ( struct sockaddr * )&url->hostport.IPaddress,
sizeof( url->hostport.IPaddress ) ) == -1 ) {
connfd = socket(url->hostport.IPaddress.ss_family, SOCK_STREAM, 0);
if (connfd == -1) {
return UPNP_E_OUTOF_SOCKET;
}
sockaddr_len = url->hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
ret_connect = connect(connfd,
(struct sockaddr *)&url->hostport.IPaddress, sockaddr_len);
if (ret_connect == -1) {
#ifdef WIN32
UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
"connect error: %d\n", WSAGetLastError());
UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
"connect error: %d\n", WSAGetLastError());
#endif
shutdown( connfd, SD_BOTH );
UpnpCloseSocket( connfd );
return UPNP_E_SOCKET_CONNECT;
}
shutdown(connfd, SD_BOTH);
UpnpCloseSocket(connfd);
return UPNP_E_SOCKET_CONNECT;
}
return connfd;
return connfd;
}
@ -536,55 +540,57 @@ end:
* Error Codes returned by http_SendMessage
* Error Codes returned by http_RecvMessage
************************************************************************/
int
http_RequestAndResponse( IN uri_type * destination,
IN const char *request,
IN size_t request_length,
IN http_method_t req_method,
IN int timeout_secs,
OUT http_parser_t * response )
int http_RequestAndResponse(
IN uri_type *destination,
IN const char *request,
IN size_t request_length,
IN http_method_t req_method,
IN int timeout_secs,
OUT http_parser_t *response)
{
int tcp_connection;
int ret_code;
int http_error_code;
SOCKINFO info;
int tcp_connection;
int ret_code;
int sockaddr_len;
int http_error_code;
SOCKINFO info;
tcp_connection = socket( destination->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( tcp_connection == -1 ) {
parser_response_init( response, req_method );
return UPNP_E_SOCKET_ERROR;
}
if( sock_init( &info, tcp_connection ) != UPNP_E_SUCCESS )
{
sock_destroy( &info, SD_BOTH );
parser_response_init( response, req_method );
return UPNP_E_SOCKET_ERROR;
}
// connect
ret_code = connect( info.socket,
( struct sockaddr * )&destination->hostport.
IPaddress, sizeof( struct sockaddr_storage ) );
tcp_connection = socket(
destination->hostport.IPaddress.ss_family, SOCK_STREAM, 0);
if (tcp_connection == -1) {
parser_response_init(response, req_method);
return UPNP_E_SOCKET_ERROR;
}
if (sock_init(&info, tcp_connection) != UPNP_E_SUCCESS) {
parser_response_init(response, req_method);
ret_code = UPNP_E_SOCKET_ERROR;
goto end_function;
}
/* connect */
sockaddr_len = destination->hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
ret_code = connect(info.socket,
(struct sockaddr *)&(destination->hostport.IPaddress), sockaddr_len);
if (ret_code == -1) {
parser_response_init(response, req_method);
ret_code = UPNP_E_SOCKET_CONNECT;
goto end_function;
}
/* send request */
ret_code = http_SendMessage(&info, &timeout_secs, "b",
request, request_length);
if (ret_code != 0) {
parser_response_init(response, req_method);
goto end_function;
}
/* recv response */
ret_code = http_RecvMessage(&info, response, req_method,
&timeout_secs, &http_error_code);
if( ret_code == -1 ) {
sock_destroy( &info, SD_BOTH );
parser_response_init( response, req_method );
return UPNP_E_SOCKET_CONNECT;
}
// send request
ret_code = http_SendMessage( &info, &timeout_secs, "b",
request, request_length );
if( ret_code != 0 ) {
sock_destroy( &info, SD_BOTH );
parser_response_init( response, req_method );
return ret_code;
}
// recv response
ret_code = http_RecvMessage( &info, response, req_method,
&timeout_secs, &http_error_code );
end_function:
/* should shutdown completely */
sock_destroy(&info, SD_BOTH);
sock_destroy( &info, SD_BOTH ); //should shutdown completely
return ret_code;
return ret_code;
}
@ -1000,73 +1006,67 @@ http_CloseHttpPost( IN void *Handle,
* UPNP_E_SOCKET_ERROR
* UPNP_E_SOCKET_CONNECT
************************************************************************/
int
http_OpenHttpPost( IN const char *url_str,
IN OUT void **Handle,
IN const char *contentType,
IN int contentLength,
IN int timeout )
int http_OpenHttpPost(
IN const char *url_str,
IN OUT void **Handle,
IN const char *contentType,
IN int contentLength,
IN int timeout)
{
int ret_code;
int tcp_connection;
membuffer request;
http_post_handle_t *handle = NULL;
uri_type url;
int ret_code;
int sockaddr_len;
int tcp_connection;
membuffer request;
http_post_handle_t *handle = NULL;
uri_type url;
if( ( !url_str ) || ( !Handle ) || ( !contentType ) ) {
return UPNP_E_INVALID_PARAM;
}
if ( !url_str || !Handle || !contentType) {
return UPNP_E_INVALID_PARAM;
}
( *Handle ) = handle;
*Handle = handle;
if( ( ret_code =
MakePostMessage( url_str, &request, &url, contentLength,
contentType ) ) != UPNP_E_SUCCESS ) {
return ret_code;
}
ret_code = MakePostMessage(url_str, &request, &url,
contentLength, contentType);
if (ret_code != UPNP_E_SUCCESS) {
return ret_code;
}
handle = (http_post_handle_t *) malloc(sizeof(http_post_handle_t));
if (!handle) {
return UPNP_E_OUTOF_MEMORY;
}
handle->contentLength = contentLength;
tcp_connection = socket(url.hostport.IPaddress.ss_family, SOCK_STREAM, 0);
if (tcp_connection == -1) {
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
if (sock_init(&handle->sock_info, tcp_connection) != UPNP_E_SUCCESS) {
sock_destroy( &handle->sock_info, SD_BOTH );
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
sockaddr_len = url.hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
ret_code = connect(handle->sock_info.socket,
(struct sockaddr *)&(url.hostport.IPaddress), sockaddr_len);
if (ret_code == -1) {
sock_destroy(&handle->sock_info, SD_BOTH);
ret_code = UPNP_E_SOCKET_CONNECT;
goto errorHandler;
}
/* send request */
ret_code = http_SendMessage(&handle->sock_info, &timeout, "b",
request.buf, request.length);
if (ret_code != 0) {
sock_destroy(&handle->sock_info, SD_BOTH);
}
handle =
( http_post_handle_t * ) malloc( sizeof( http_post_handle_t ) );
errorHandler:
membuffer_destroy(&request);
*Handle = handle;
if( handle == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
handle->contentLength = contentLength;
tcp_connection = socket( url.hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( tcp_connection == -1 ) {
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
if( sock_init( &handle->sock_info, tcp_connection ) != UPNP_E_SUCCESS )
{
sock_destroy( &handle->sock_info, SD_BOTH );
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
ret_code = connect( handle->sock_info.socket,
( struct sockaddr * )&url.hostport.IPaddress,
sizeof( struct sockaddr_storage ) );
if( ret_code == -1 ) {
sock_destroy( &handle->sock_info, SD_BOTH );
ret_code = UPNP_E_SOCKET_CONNECT;
goto errorHandler;
}
// send request
ret_code = http_SendMessage( &handle->sock_info, &timeout, "b",
request.buf, request.length );
if( ret_code != 0 ) {
sock_destroy( &handle->sock_info, SD_BOTH );
}
errorHandler:
membuffer_destroy( &request );
( *Handle ) = handle;
return ret_code;
return ret_code;
}
typedef struct HTTPGETHANDLE {
@ -1565,133 +1565,119 @@ http_OpenHttpGet( IN const char *url_str,
* UPNP_E_SOCKET_ERROR
* UPNP_E_BAD_RESPONSE
************************************************************************/
int
http_OpenHttpGetProxy( IN const char *url_str,
IN const char *proxy_str,
IN OUT void **Handle,
IN OUT char **contentType,
OUT int *contentLength,
OUT int *httpStatus,
IN int timeout )
int http_OpenHttpGetProxy(
IN const char *url_str,
IN const char *proxy_str,
IN OUT void **Handle,
IN OUT char **contentType,
OUT int *contentLength,
OUT int *httpStatus,
IN int timeout)
{
int ret_code;
int http_error_code;
memptr ctype;
int tcp_connection;
membuffer request;
http_get_handle_t *handle = NULL;
uri_type url;
uri_type proxy;
uri_type *peer;
parse_status_t status;
int ret_code;
int sockaddr_len;
int http_error_code;
memptr ctype;
int tcp_connection;
membuffer request;
http_get_handle_t *handle = NULL;
uri_type url;
uri_type proxy;
uri_type *peer;
parse_status_t status;
if( ( !url_str ) || ( !Handle ) || ( !contentType )
|| ( !httpStatus ) ) {
return UPNP_E_INVALID_PARAM;
}
if (!url_str || !Handle || !contentType || !httpStatus ) {
return UPNP_E_INVALID_PARAM;
}
( *httpStatus ) = 0;
( *Handle ) = handle;
( *contentType ) = NULL;
( *contentLength ) = 0;
*httpStatus = 0;
*Handle = handle;
*contentType = NULL;
*contentLength = 0;
if( ( ret_code =
MakeGetMessage( url_str, proxy_str, &request, &url ) ) != UPNP_E_SUCCESS ) {
return ret_code;
}
if( proxy_str ) {
ret_code = http_FixStrUrl( ( char * )proxy_str, strlen( proxy_str ), &proxy );
peer = &proxy;
} else {
peer = &url;
}
ret_code = MakeGetMessage(url_str, proxy_str, &request, &url);
if (ret_code != UPNP_E_SUCCESS) {
return ret_code;
}
if (proxy_str) {
ret_code = http_FixStrUrl((char *)proxy_str, strlen(proxy_str), &proxy);
peer = &proxy;
} else {
peer = &url;
}
handle = (http_get_handle_t *)malloc(sizeof(http_get_handle_t));
if (!handle) {
return UPNP_E_OUTOF_MEMORY;
}
handle->entity_offset = 0;
handle->cancel = 0;
parser_response_init(&handle->response, HTTPMETHOD_GET);
tcp_connection = socket(peer->hostport.IPaddress.ss_family, SOCK_STREAM, 0);
if (tcp_connection == -1) {
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
if (sock_init(&handle->sock_info, tcp_connection) != UPNP_E_SUCCESS) {
sock_destroy(&handle->sock_info, SD_BOTH);
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
sockaddr_len = peer->hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
ret_code = connect(handle->sock_info.socket,
(struct sockaddr *)&(peer->hostport.IPaddress), sockaddr_len);
if (ret_code == -1) {
sock_destroy(&handle->sock_info, SD_BOTH);
ret_code = UPNP_E_SOCKET_CONNECT;
goto errorHandler;
}
/* send request */
ret_code = http_SendMessage(&handle->sock_info, &timeout, "b",
request.buf, request.length);
if (ret_code) {
sock_destroy(&handle->sock_info, SD_BOTH);
goto errorHandler;
}
handle = ( http_get_handle_t * ) malloc( sizeof( http_get_handle_t ) );
status = ReadResponseLineAndHeaders(&handle->sock_info,
&handle->response, &timeout, &http_error_code);
if (status != PARSE_OK) {
ret_code = UPNP_E_BAD_RESPONSE;
goto errorHandler;
}
status = parser_get_entity_read_method(&handle->response);
if (status != PARSE_CONTINUE_1 && status != PARSE_SUCCESS) {
ret_code = UPNP_E_BAD_RESPONSE;
goto errorHandler;
}
if( handle == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
*httpStatus = handle->response.msg.status_code;
ret_code = UPNP_E_SUCCESS;
handle->entity_offset = 0;
handle->cancel = 0;
parser_response_init( &handle->response, HTTPMETHOD_GET );
if (!httpmsg_find_hdr(&handle->response.msg, HDR_CONTENT_TYPE, &ctype)) {
/* no content-type */
*contentType = NULL;
} else {
*contentType = ctype.buf;
}
tcp_connection = socket( peer->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( tcp_connection == -1 ) {
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
if (handle->response.position == POS_COMPLETE) {
*contentLength = 0;
} else if (handle->response.ent_position == ENTREAD_USING_CHUNKED) {
*contentLength = UPNP_USING_CHUNKED;
} else if (handle->response.ent_position == ENTREAD_USING_CLEN) {
*contentLength = handle->response.content_length;
} else if (handle->response.ent_position == ENTREAD_UNTIL_CLOSE) {
*contentLength = UPNP_UNTIL_CLOSE;
}
if( sock_init( &handle->sock_info, tcp_connection ) != UPNP_E_SUCCESS )
{
sock_destroy( &handle->sock_info, SD_BOTH );
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
ret_code = connect( handle->sock_info.socket,
( struct sockaddr * )&peer->hostport.IPaddress,
sizeof( struct sockaddr_storage ) );
if( ret_code == -1 ) {
sock_destroy( &handle->sock_info, SD_BOTH );
ret_code = UPNP_E_SOCKET_CONNECT;
goto errorHandler;
}
// send request
ret_code = http_SendMessage( &handle->sock_info, &timeout, "b",
request.buf, request.length );
if( ret_code != 0 ) {
sock_destroy( &handle->sock_info, SD_BOTH );
goto errorHandler;
}
status =
ReadResponseLineAndHeaders( &handle->sock_info, &handle->response,
&timeout, &http_error_code );
if( status != PARSE_OK ) {
ret_code = UPNP_E_BAD_RESPONSE;
goto errorHandler;
}
status = parser_get_entity_read_method( &handle->response );
if( ( status != PARSE_CONTINUE_1 ) && ( status != PARSE_SUCCESS ) ) {
ret_code = UPNP_E_BAD_RESPONSE;
goto errorHandler;
}
( *httpStatus ) = handle->response.msg.status_code;
ret_code = UPNP_E_SUCCESS;
if( httpmsg_find_hdr( &handle->response.msg, HDR_CONTENT_TYPE, &ctype )
== NULL ) {
*contentType = NULL; // no content-type
} else {
*contentType = ctype.buf;
}
if( handle->response.position == POS_COMPLETE ) {
( *contentLength ) = 0;
} else if( handle->response.ent_position == ENTREAD_USING_CHUNKED ) {
( *contentLength ) = UPNP_USING_CHUNKED;
} else if( handle->response.ent_position == ENTREAD_USING_CLEN ) {
( *contentLength ) = handle->response.content_length;
} else if( handle->response.ent_position == ENTREAD_UNTIL_CLOSE ) {
( *contentLength ) = UPNP_UNTIL_CLOSE;
}
errorHandler:
( *Handle ) = handle;
membuffer_destroy( &request );
if( ret_code != UPNP_E_SUCCESS ) {
httpmsg_destroy( &handle->response.msg );
}
return ret_code;
errorHandler:
*Handle = handle;
membuffer_destroy(&request);
if (ret_code != UPNP_E_SUCCESS) {
httpmsg_destroy(&handle->response.msg);
}
return ret_code;
}
/************************************************************************
@ -2201,149 +2187,128 @@ MakeGetMessageEx( const char *url_str,
* UPNP_E_SOCKET_ERROR
* UPNP_E_BAD_RESPONSE
************************************************************************/
int
http_OpenHttpGetEx( IN const char *url_str,
IN OUT void **Handle,
IN OUT char **contentType,
OUT int *contentLength,
OUT int *httpStatus,
IN int lowRange,
IN int highRange,
IN int timeout )
int http_OpenHttpGetEx(
IN const char *url_str,
IN OUT void **Handle,
IN OUT char **contentType,
OUT int *contentLength,
OUT int *httpStatus,
IN int lowRange,
IN int highRange,
IN int timeout)
{
int http_error_code;
memptr ctype;
int tcp_connection;
membuffer request;
http_get_handle_t *handle = NULL;
uri_type url;
parse_status_t status;
int errCode = UPNP_E_SUCCESS;
int http_error_code;
memptr ctype;
int tcp_connection;
int sockaddr_len;
membuffer request;
http_get_handle_t *handle = NULL;
uri_type url;
parse_status_t status;
int errCode = UPNP_E_SUCCESS;
/* char rangeBuf[SIZE_RANGE_BUFFER]; */
struct SendInstruction rangeBuf;
// char rangeBuf[SIZE_RANGE_BUFFER];
struct SendInstruction rangeBuf;
do {
/* Checking Input parameters */
if (!url_str || !Handle || !contentType || !httpStatus ) {
errCode = UPNP_E_INVALID_PARAM;
break;
}
do {
// Checking Input parameters
if( ( !url_str ) || ( !Handle ) ||
( !contentType ) || ( !httpStatus ) ) {
errCode = UPNP_E_INVALID_PARAM;
break;
}
// Initialize output parameters
( *httpStatus ) = 0;
( *Handle ) = handle;
( *contentType ) = NULL;
( *contentLength ) = 0;
/* Initialize output parameters */
*httpStatus = 0;
*Handle = handle;
*contentType = NULL;
*contentLength = 0;
if( lowRange > highRange ) {
errCode = UPNP_E_INTERNAL_ERROR;
break;
}
if (lowRange > highRange) {
errCode = UPNP_E_INTERNAL_ERROR;
break;
}
memset(&rangeBuf, 0, sizeof(rangeBuf));
sprintf(rangeBuf.RangeHeader,
"Range: bytes=%d-%d\r\n", lowRange, highRange);
membuffer_init(&request);
errCode = MakeGetMessageEx(url_str, &request, &url, &rangeBuf);
if (errCode != UPNP_E_SUCCESS) {
break;
}
handle = (http_get_handle_t *)malloc(sizeof(http_get_handle_t));
if (!handle) {
errCode = UPNP_E_OUTOF_MEMORY;
break;
}
memset(handle, 0, sizeof(*handle));
handle->entity_offset = 0;
parser_response_init(&handle->response, HTTPMETHOD_GET);
tcp_connection = socket(url.hostport.IPaddress.ss_family, SOCK_STREAM, 0);
if (tcp_connection == -1) {
errCode = UPNP_E_SOCKET_ERROR;
free(handle);
break;
}
if (sock_init(&handle->sock_info, tcp_connection) != UPNP_E_SUCCESS) {
sock_destroy(&handle->sock_info, SD_BOTH);
errCode = UPNP_E_SOCKET_ERROR;
free(handle);
break;
}
sockaddr_len = url.hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
errCode = connect(handle->sock_info.socket,
(struct sockaddr *)&(url.hostport.IPaddress), sockaddr_len);
if (errCode == -1) {
sock_destroy(&handle->sock_info, SD_BOTH);
errCode = UPNP_E_SOCKET_CONNECT;
free(handle);
break;
}
/* send request */
errCode = http_SendMessage(&handle->sock_info, &timeout,
"b", request.buf, request.length);
if (errCode != UPNP_E_SUCCESS) {
sock_destroy(&handle->sock_info, SD_BOTH);
free(handle);
break;
}
status = ReadResponseLineAndHeaders(&handle->sock_info,
&handle->response, &timeout, &http_error_code);
if (status != PARSE_OK) {
errCode = UPNP_E_BAD_RESPONSE;
free(handle);
break;
}
status = parser_get_entity_read_method(&handle->response);
if (status != PARSE_CONTINUE_1 && status != PARSE_SUCCESS) {
errCode = UPNP_E_BAD_RESPONSE;
free(handle);
break;
}
*httpStatus = handle->response.msg.status_code;
errCode = UPNP_E_SUCCESS;
memset( &rangeBuf, 0, sizeof( rangeBuf ) );
sprintf( rangeBuf.RangeHeader, "Range: bytes=%d-%d\r\n",
lowRange, highRange );
if (!httpmsg_find_hdr(&handle->response.msg, HDR_CONTENT_TYPE, &ctype)) {
/* no content-type */
*contentType = NULL;
} else {
*contentType = ctype.buf;
}
if (handle->response.position == POS_COMPLETE) {
*contentLength = 0;
} else if(handle->response.ent_position == ENTREAD_USING_CHUNKED) {
*contentLength = UPNP_USING_CHUNKED;
} else if(handle->response.ent_position == ENTREAD_USING_CLEN) {
*contentLength = handle->response.content_length;
} else if(handle->response.ent_position == ENTREAD_UNTIL_CLOSE) {
*contentLength = UPNP_UNTIL_CLOSE;
}
*Handle = handle;
} while (0);
membuffer_init( &request );
membuffer_destroy(&request);
if( ( errCode = MakeGetMessageEx( url_str,
&request, &url, &rangeBuf ) )
!= UPNP_E_SUCCESS ) {
break;
}
handle =
( http_get_handle_t * ) malloc( sizeof( http_get_handle_t ) );
if( handle == NULL ) {
errCode = UPNP_E_OUTOF_MEMORY;
break;
}
memset( handle, 0, sizeof( *handle ) );
handle->entity_offset = 0;
parser_response_init( &handle->response, HTTPMETHOD_GET );
tcp_connection = socket( url.hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( tcp_connection == -1 ) {
errCode = UPNP_E_SOCKET_ERROR;
free( handle );
break;
}
if( sock_init( &handle->sock_info, tcp_connection ) !=
UPNP_E_SUCCESS ) {
sock_destroy( &handle->sock_info, SD_BOTH );
errCode = UPNP_E_SOCKET_ERROR;
free( handle );
break;
}
errCode = connect( handle->sock_info.socket,
( struct sockaddr * )&url.hostport.IPaddress,
sizeof( struct sockaddr_storage ) );
if( errCode == -1 ) {
sock_destroy( &handle->sock_info, SD_BOTH );
errCode = UPNP_E_SOCKET_CONNECT;
free( handle );
break;
}
// send request
errCode = http_SendMessage( &handle->sock_info,
&timeout,
"b", request.buf, request.length );
if( errCode != UPNP_E_SUCCESS ) {
sock_destroy( &handle->sock_info, SD_BOTH );
free( handle );
break;
}
status = ReadResponseLineAndHeaders( &handle->sock_info,
&handle->response,
&timeout, &http_error_code );
if( status != PARSE_OK ) {
errCode = UPNP_E_BAD_RESPONSE;
free( handle );
break;
}
status = parser_get_entity_read_method( &handle->response );
if( ( status != PARSE_CONTINUE_1 ) && ( status != PARSE_SUCCESS ) ) {
errCode = UPNP_E_BAD_RESPONSE;
free( handle );
break;
}
( *httpStatus ) = handle->response.msg.status_code;
errCode = UPNP_E_SUCCESS;
if( httpmsg_find_hdr( &handle->response.msg,
HDR_CONTENT_TYPE, &ctype ) == NULL ) {
*contentType = NULL; // no content-type
} else {
*contentType = ctype.buf;
}
if( handle->response.position == POS_COMPLETE ) {
( *contentLength ) = 0;
} else if( handle->response.ent_position == ENTREAD_USING_CHUNKED ) {
( *contentLength ) = UPNP_USING_CHUNKED;
} else if( handle->response.ent_position == ENTREAD_USING_CLEN ) {
( *contentLength ) = handle->response.content_length;
} else if( handle->response.ent_position == ENTREAD_UNTIL_CLOSE ) {
( *contentLength ) = UPNP_UNTIL_CLOSE;
}
( *Handle ) = handle;
} while( 0 );
membuffer_destroy( &request );
return errCode;
return errCode;
}