Use name unions to overcome C99 limitation.
This commit is contained in:
parent
1c22a0ecf2
commit
b77b4815f2
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue