Use name unions to overcome C99 limitation.

This commit is contained in:
bossiel 2010-05-25 10:10:15 +00:00
parent 1c22a0ecf2
commit b77b4815f2
10 changed files with 92 additions and 68 deletions

View File

@ -98,6 +98,10 @@ typedef enum thttp_stack_param_type_e
pname_tls_certs,
#define THTTP_STACK_SET_TLS_CERTS(CA_FILE_STR, PUB_FILE_STR, PRIV_FILE_STR) pname_tls_certs, (const char*)CA_FILE_STR, (const char*)PUB_FILE_STR, (const char*)PRIV_FILE_STR
/* User Data */
pname_userdata,
#define THHTP_STACK_SET_USERDATA(USERDATA_PTR) pname_userdata, (const void*)USERDATA_PTR
}
thttp_stack_param_type_t;
@ -123,6 +127,8 @@ typedef struct thttp_stack_s
thttp_sessions_L_t* sessions;
const void* userdata;
TSK_DECLARE_SAFEOBJ;
}
thttp_stack_t;
@ -130,6 +136,7 @@ thttp_stack_t;
TINYHTTP_API thttp_stack_handle_t *thttp_stack_create(thttp_stack_callback_f callback, ...);
TINYHTTP_API int thttp_stack_start(thttp_stack_handle_t *self);
TINYHTTP_API int thttp_stack_set(thttp_stack_handle_t *self, ...);
TINYHTTP_API const void* thttp_stack_get_userdata(thttp_stack_handle_t *self);
TINYHTTP_API int thttp_stack_stop(thttp_stack_handle_t *self);
TINYHTTP_GEXTERN const tsk_object_def_t *thttp_stack_def_t;

View File

@ -120,8 +120,8 @@ THTTP_BEGIN_DECLS
* @retval The phrase (const char*).
*/
#define THTTP_RESPONSE_CODE(self) (THTTP_MESSAGE_IS_RESPONSE((self)) ? (self)->status_code : 0)
#define THTTP_RESPONSE_PHRASE(self) ((self)->reason_phrase)
#define THTTP_RESPONSE_CODE(self) (THTTP_MESSAGE_IS_RESPONSE((self)) ? (self)->line.response.status_code : 0)
#define THTTP_RESPONSE_PHRASE(self) ((self)->line.response.reason_phrase)
/**@ingroup thttp_message_group
*@def THTTP_REQUEST_METHOD
@ -135,8 +135,8 @@ THTTP_BEGIN_DECLS
* @param self A pointer to a @ref thttp_request_t object.
* @retval The Url (@ref thttp_url_t).
*/
#define THTTP_REQUEST_METHOD(self) ((self) ? (self)->method : tsk_null)
#define THTTP_REQUEST_URL(self) ((self) ? (self)->url : tsk_null)
#define THTTP_REQUEST_METHOD(self) ((self) ? (self)->line.request.method : tsk_null)
#define THTTP_REQUEST_URL(self) ((self) ? (self)->line.request.url : tsk_null)
/**@ingroup thttp_message_group
*@def THTTP_MESSAGE_CONTENT_LENGTH
@ -190,26 +190,18 @@ typedef struct thttp_message_s
char *http_version; /**< The HTTP version. Only 'HTTP/1.1' is supported. */
thttp_message_type_t type; /**< The type of this HTTP message. */
#if !defined(__C99__) /* C99 does not allow unnamed structs/unions */
union
{
struct
{
#endif
/* Request-Line */
union{
struct{
char *method;
thttp_url_t *url;
#if !defined(__C99__)
};
struct
{
#endif
} request;
struct{
short status_code;
char *reason_phrase;
#if !defined(__C99__)
};
};
} response;
} line;
#endif
/*== MOST COMMON HEADERS. */
thttp_header_Content_Type_t *Content_Type;
thttp_header_Content_Length_t *Content_Length;

View File

@ -70,7 +70,7 @@ typedef enum thttp_session_param_type_e
httpp_option,
httpp_cred,
httpp_header,
httpp_context,
httpp_userdata,
}
thttp_session_param_type_t;
@ -134,7 +134,7 @@ thttp_session_set(session,
* @endcode
*/
/**@ingroup thttp_session_group
* @def THTTP_SESSION_SET_CONTEXT
* @def THTTP_SESSION_SET_USERDATA
* Sets user data (context). Will be return to the application layer each time the callback function is called.
* This is a helper macro for @ref thttp_session_create and @ref thttp_session_set.
* @param CTX_PTR A pointer to the data(const void*).
@ -142,7 +142,7 @@ thttp_session_set(session,
* @code
// session = thttp_session_create(stack,
thttp_session_set(session,
THTTP_SESSION_SET_CONTEXT(ctx),
THTTP_SESSION_SET_USERDATA(ctx),
THTTP_SESSION_SET_NULL());
* @endcode
*/
@ -154,7 +154,7 @@ thttp_session_set(session,
#define THTTP_SESSION_SET_CRED(USERNAME_STR, PASSWORD_STR) httpp_cred, (const char*)USERNAME_STR, (const char*)PASSWORD_STR
#define THTTP_SESSION_SET_HEADER(NAME_STR, VALUE_STR) httpp_header, (const char*)NAME_STR, (const char*)VALUE_STR
#define THTTP_SESSION_UNSET_HEADER(NAME_STR) THTTP_SESSION_SET_HEADER(NAME_STR, (const char*)-1)
#define THTTP_SESSION_SET_CONTEXT(CTX_PTR) httpp_context, (const void*)CTX_PTR
#define THTTP_SESSION_SET_USERDATA(USERDATA_PTR) httpp_userdata, (const void*)USERDATA_PTR
#define THTTP_SESSION_SET_NULL() httpp_null
typedef struct thttp_session_s
@ -163,7 +163,7 @@ typedef struct thttp_session_s
thttp_session_id_t id;
const struct thttp_stack_s* stack;
const void* context; // user's context
const void* userdata; // user's context
tsk_options_L_t *options;
tsk_params_L_t *headers;
@ -191,7 +191,7 @@ typedef void thttp_stack_handle_t;
TINYHTTP_API thttp_session_handle_t* thttp_session_create(const thttp_stack_handle_t* stack, ...);
TINYHTTP_API int thttp_session_set(thttp_session_handle_t *self, ...);
TINYHTTP_API thttp_session_id_t thttp_session_get_id(const thttp_session_handle_t *self);
TINYHTTP_API const void* thttp_session_get_context(const thttp_session_handle_t *self);
TINYHTTP_API const void* thttp_session_get_userdata(const thttp_session_handle_t *self);
int thttp_session_update_challenges(thttp_session_t *self, const thttp_response_t* response, tsk_bool_t answered);
int thttp_session_signal_closed(thttp_session_t *self);

View File

@ -58,9 +58,9 @@ static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t *
if(message->type == thttp_unknown){
message->type = thttp_request;
if(!message->method){
message->method = tsk_calloc(1, len+1);
memcpy(message->method, state->tag_start, len);
if(!message->line.request.method){
message->line.request.method = tsk_calloc(1, len+1);
memcpy(message->line.request.method, state->tag_start, len);
}
}
else{
@ -74,8 +74,8 @@ static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t *
state->tag_end = p;
len = (int)(state->tag_end - state->tag_start);
if(!message->url){
message->url = thttp_url_parse(state->tag_start, (tsk_size_t)len);
if(!message->line.request.url){
message->line.request.url = thttp_url_parse(state->tag_start, (tsk_size_t)len);
}
}
@ -99,7 +99,7 @@ static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t *
if(message->type == thttp_unknown){
message->type = thttp_response;
message->status_code = atoi(state->tag_start);
message->line.response.status_code = atoi(state->tag_start);
}
else{
state->cs = thttp_machine_parser_message_error;
@ -112,9 +112,9 @@ static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t *
state->tag_end = p;
len = (int)(state->tag_end - state->tag_start);
if(!message->reason_phrase){
message->reason_phrase = tsk_calloc(1, len+1);
memcpy(message->reason_phrase, state->tag_start, len);
if(!message->line.response.reason_phrase){
message->line.response.reason_phrase = tsk_calloc(1, len+1);
memcpy(message->line.response.reason_phrase, state->tag_start, len);
}
}

View File

@ -147,12 +147,12 @@ thttp_header_t *thttp_challenge_create_header_authorization(thttp_challenge_t *s
char *uristring = tsk_null;
thttp_header_t *header = 0;
if(!self || !request || !request->url){
if(!self || !request || !request->line.request.url){
goto bail;
}
/* Sets URI: hpath do not start with / ==> append a '/'*/
tsk_sprintf(&uristring, "/%s", request->url->hpath ? request->url->hpath : "");
tsk_sprintf(&uristring, "/%s", request->line.request.url->hpath ? request->line.request.url->hpath : "");
/* We compute the nc here because @ref thttp_challenge_get_response function will increment it's value. */
if(self->nc){
@ -161,7 +161,7 @@ thttp_header_t *thttp_challenge_create_header_authorization(thttp_challenge_t *s
/* Computes the response (Basic and Digest)*/
if(THTTP_CHALLENGE_IS_DIGEST(self)){
if(thttp_challenge_get_digest_response(self, username, password, request->method, uristring, request->Content, &response)){
if(thttp_challenge_get_digest_response(self, username, password, request->line.request.method, uristring, request->Content, &response)){
goto bail;
}
response_size = (TSK_MD5_DIGEST_SIZE*2);

View File

@ -329,9 +329,9 @@ _match:
if(message->type == thttp_unknown){
message->type = thttp_request;
if(!message->method){
message->method = tsk_calloc(1, len+1);
memcpy(message->method, state->tag_start, len);
if(!message->line.request.method){
message->line.request.method = tsk_calloc(1, len+1);
memcpy(message->line.request.method, state->tag_start, len);
}
}
else{
@ -346,8 +346,8 @@ _match:
state->tag_end = p;
len = (int)(state->tag_end - state->tag_start);
if(!message->url){
message->url = thttp_url_parse(state->tag_start, (tsk_size_t)len);
if(!message->line.request.url){
message->line.request.url = thttp_url_parse(state->tag_start, (tsk_size_t)len);
}
}
break;
@ -373,7 +373,7 @@ _match:
if(message->type == thttp_unknown){
message->type = thttp_response;
message->status_code = atoi(state->tag_start);
message->line.response.status_code = atoi(state->tag_start);
}
else{
state->cs = thttp_machine_parser_message_error;
@ -387,9 +387,9 @@ _match:
state->tag_end = p;
len = (int)(state->tag_end - state->tag_start);
if(!message->reason_phrase){
message->reason_phrase = tsk_calloc(1, len+1);
memcpy(message->reason_phrase, state->tag_start, len);
if(!message->line.response.reason_phrase){
message->line.response.reason_phrase = tsk_calloc(1, len+1);
memcpy(message->line.response.reason_phrase, state->tag_start, len);
}
}
break;

View File

@ -415,6 +415,14 @@ int __thttp_stack_set(thttp_stack_t *self, va_list* app)
break;
}
//
// Userdata
//
case pname_userdata:
{ /* (const void*)USERDATA_PTR */
self->userdata = va_arg(*app, const void*);
break;
}
default:
{
@ -524,8 +532,24 @@ int thttp_stack_set(thttp_stack_handle_t *self, ...)
va_end(ap);
return ret;
}
else{
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
}
return -1;
/**@ingroup thttp_stack_group
*/
const void* thttp_stack_get_userdata(thttp_stack_handle_t *self)
{
thttp_stack_t *stack = self;
if(stack){
return stack->userdata;
}
else{
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
}
/**@ingroup thttp_stack_group
@ -539,6 +563,7 @@ int thttp_stack_stop(thttp_stack_handle_t *self)
thttp_stack_t *stack = self;
if(!stack){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
return tnet_transport_shutdown(stack->transport);

View File

@ -317,7 +317,7 @@ int thttp_dialog_send_request(thttp_dialog_t *self)
goto bail;
}
else{
if(request->url->type == url_https){
if(request->line.request.url->type == url_https){
TNET_SOCKET_TYPE_SET_TLS(type);
}
else{
@ -327,8 +327,8 @@ int thttp_dialog_send_request(thttp_dialog_t *self)
/* connect to the server not already done */
if(self->session->fd == TNET_INVALID_FD){
if((self->session->fd = tnet_transport_connectto(self->session->stack->transport, request->url->host, request->url->port, type)) == TNET_INVALID_FD){
TSK_DEBUG_ERROR("Failed to connect to %s:%d.", request->url->host, request->url->port);
if((self->session->fd = tnet_transport_connectto(self->session->stack->transport, request->line.request.url->host, request->line.request.url->port, type)) == TNET_INVALID_FD){
TSK_DEBUG_ERROR("Failed to connect to %s:%d.", request->line.request.url->host, request->line.request.url->port);
goto bail;
}
/* Wait for the socket for writability */

View File

@ -317,17 +317,17 @@ int thttp_message_serialize(const thttp_message_t *self, tsk_buffer_t *output)
if(THTTP_MESSAGE_IS_REQUEST(self)){
/*Method SP Request-URI SP HTTP-Version CRLF*/
/* Method */
tsk_buffer_append_2(output, "%s ", self->method);
tsk_buffer_append_2(output, "%s ", self->line.request.method);
/* Request URI: hpath?search */
tsk_buffer_append_2(output, "/%s%s%s ",
self->url->hpath ? self->url->hpath : "",
self->url->search ? "?" : "",
self->url->search ? self->url->search : ""
self->line.request.url->hpath ? self->line.request.url->hpath : "",
self->line.request.url->search ? "?" : "",
self->line.request.url->search ? self->line.request.url->search : ""
);
/* HTTP VERSION */
tsk_buffer_append_2(output, "%s\r\n", THTTP_MESSAGE_VERSION_DEFAULT);
/* HOST */
tsk_buffer_append_2(output, "Host: %s:%u\r\n", self->url->host, self->url->port);
tsk_buffer_append_2(output, "Host: %s:%u\r\n", self->line.request.url->host, self->line.request.url->port);
}
else{
/*HTTP-Version SP Status-Code SP Reason-Phrase CRLF*/
@ -439,8 +439,8 @@ static tsk_object_t* thttp_message_ctor(tsk_object_t *self, va_list * app)
case thttp_request:
{
message->method = tsk_strdup(va_arg(*app, const char*));
message->url = tsk_object_ref((void*)va_arg(*app, const thttp_url_t*));
message->line.request.method = tsk_strdup(va_arg(*app, const char*));
message->line.request.url = tsk_object_ref((void*)va_arg(*app, const thttp_url_t*));
break;
}
@ -448,11 +448,11 @@ static tsk_object_t* thttp_message_ctor(tsk_object_t *self, va_list * app)
{
/*const thttp_request_t* request =*/ va_arg(*app, const thttp_request_t*);
#if defined(__GNUC__)
message->status_code = (short)va_arg(*app, int);
message->line.response.status_code = (short)va_arg(*app, int);
#else
message->status_code = va_arg(*app, short);
message->line.response.status_code = va_arg(*app, short);
#endif
message->reason_phrase = tsk_strdup(va_arg(*app, const char*));
message->line.response.reason_phrase = tsk_strdup(va_arg(*app, const char*));
break;
}
}
@ -470,11 +470,11 @@ static tsk_object_t* thttp_message_dtor(tsk_object_t *self)
thttp_message_t *message = self;
if(message){
if(THTTP_MESSAGE_IS_REQUEST(message)){
TSK_FREE(message->method);
TSK_OBJECT_SAFE_FREE(message->url);
TSK_FREE(message->line.request.method);
TSK_OBJECT_SAFE_FREE(message->line.request.url);
}
else if(THTTP_MESSAGE_IS_RESPONSE(message)){
TSK_FREE(message->reason_phrase);
TSK_FREE(message->line.response.reason_phrase);
}
TSK_FREE(message->http_version);

View File

@ -80,9 +80,9 @@ int __thttp_session_set(thttp_session_t *self, va_list* app)
break;
}
case httpp_context:
{ /* (const void*)CTX_PTR */
self->context = va_arg(*app, const void *);
case httpp_userdata:
{ /* (const void*)USERDATA_PTR */
self->userdata = va_arg(*app, const void *);
break;
}
@ -202,10 +202,10 @@ thttp_session_id_t thttp_session_get_id(const thttp_session_handle_t *self)
* @retval A pointer to the context. Previously defined by using @ref THTTP_SESSION_SET_CONTEXT() macro.
* @sa @ref THTTP_SESSION_SET_CONTEXT
*/
const void* thttp_session_get_context(const thttp_session_handle_t *self)
const void* thttp_session_get_userdata(const thttp_session_handle_t *self)
{
if(self){
return ((const thttp_session_t*)self)->context;
return ((const thttp_session_t*)self)->userdata;
}
return tsk_null;
}