diff --git a/trunk/tinyHTTP/include/thttp.h b/trunk/tinyHTTP/include/thttp.h index be054fdb..83b053ca 100644 --- a/trunk/tinyHTTP/include/thttp.h +++ b/trunk/tinyHTTP/include/thttp.h @@ -32,6 +32,7 @@ #include "tinyhttp_config.h" #include "tinyHTTP/thttp_event.h" +#include "tinyHTTP/thttp_operation.h" THTTP_BEGIN_DECLS @@ -63,11 +64,14 @@ TINYHTTP_API int thttp_global_init(); TINYHTTP_API int thttp_global_deinit(); -TINYHTTP_API thttp_stack_handle_t *thttp_stack_create(thttp_stack_callback callback, ...); +TINYHTTP_API thttp_stack_handle_t *thttp_stack_create(thttp_stack_callback callback, int tls, ...); TINYHTTP_API int thttp_stack_start(thttp_stack_handle_t *self); TINYHTTP_API int thttp_stack_set(thttp_stack_handle_t *self, ...); +int thttp_stack_send(thttp_stack_handle_t *self, thttp_operation_handle_t* op, const struct thttp_message_s* message); TINYHTTP_API int thttp_stack_stop(thttp_stack_handle_t *self); +TINYHTTP_GEXTERN const void *thttp_stack_def_t; + THTTP_END_DECLS #endif /* TINYHTTP_THTTP_H */ \ No newline at end of file diff --git a/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header.h b/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header.h index fdffaf46..00859b2f 100644 --- a/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header.h +++ b/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header.h @@ -62,6 +62,7 @@ typedef enum thttp_header_type_e thttp_htype_Authorization, thttp_htype_Content_Length, thttp_htype_Content_Type, + thttp_htype_Dummy, thttp_htype_Proxy_Authenticate, thttp_htype_Proxy_Authorization, thttp_htype_WWW_Authenticate, @@ -85,6 +86,8 @@ typedef tsk_list_t thttp_headers_L_t; /**< List of @ref thttp_header_t elements. ================================*/ TINYHTTP_API const char *thttp_header_get_name(thttp_header_type_t type); +TINYHTTP_API const char *thttp_header_get_nameex(const thttp_header_t *self); +TINYHTTP_API char thttp_header_get_param_separator(const thttp_header_t *self); TINYHTTP_API int thttp_header_tostring(const thttp_header_t *self, tsk_buffer_t *output); THTTP_END_DECLS diff --git a/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header_Content_Type.h b/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header_Content_Type.h index f44835fb..2be85ab9 100644 --- a/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header_Content_Type.h +++ b/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header_Content_Type.h @@ -39,7 +39,9 @@ THTTP_BEGIN_DECLS * Creates new http 'Content-Type' header. You must call @ref TSK_OBJECT_SAFE_FREE to free the header. * @sa TSK_OBJECT_SAFE_FREE. */ -#define THTTP_HEADER_CONTENT_TYPE_CREATE() tsk_object_new(thttp_header_Content_Type_def_t) +#define THTTP_HEADER_CONTENT_TYPE_VA_ARGS(type) thttp_header_Content_Type_def_t, (const char*)type +#define THTTP_HEADER_CONTENT_TYPE_CREATE(type) tsk_object_new(THTTP_HEADER_CONTENT_TYPE_VA_ARGS(type)) +#define THTTP_HEADER_CONTENT_TYPE_CREATE_NULL() THTTP_HEADER_CONTENT_TYPE_CREATE(THTTP_NULL) //////////////////////////////////////////////////////////////////////////////////////////////////// /// @struct diff --git a/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header_Dummy.h b/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header_Dummy.h new file mode 100644 index 00000000..c12edef2 --- /dev/null +++ b/trunk/tinyHTTP/include/tinyHTTP/headers/thttp_header_Dummy.h @@ -0,0 +1,70 @@ +/* +* Copyright (C) 2009 Mamadou Diop. +* +* Contact: Mamadou Diop +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Dummy.h + * @brief HTTP dummy header. + * + * @author Mamadou Diop + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ +#ifndef _THTTP_HEADER_DUMMY_H_ +#define _THTTP_HEADER_DUMMY_H_ + +#include "tinyhttp_config.h" +#include "tinyhttp/headers/thttp_header.h" + +THTTP_BEGIN_DECLS + +/**@def THTTP_HEADER_DUMMY_CREATE +* Creates new http Dummy header. You must call @ref TSK_OBJECT_SAFE_FREE to free the header. +* @sa TSK_OBJECT_SAFE_FREE. +*/ +#define THTTP_HEADER_DUMMY_VA_ARGS(name, value) thttp_header_Dummy_def_t, (const char*)name, (const char*)value +#define THTTP_HEADER_DUMMY_CREATE(name, value) tsk_object_new(THTTP_HEADER_DUMMY_VA_ARGS(name, value)) +#define THTTP_HEADER_DUMMY_CREATE_NULL() THTTP_HEADER_DUMMY_CREATE(THTTP_NULL, THTTP_NULL) + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// @struct +/// +/// @brief HTTP Dummy header. +/// +/// @par ABNF : token SP* HCOLON SP*<: any* +/// +//////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct thttp_header_Dummy_s +{ + THTTP_DECLARE_HEADER; + + char *name; + char *value; +} +thttp_header_Dummy_t; + +thttp_header_Dummy_t *thttp_header_Dummy_parse(const char *data, size_t size); + +TINYHTTP_GEXTERN const void *thttp_header_Dummy_def_t; + +THTTP_END_DECLS + +#endif /* _THTTP_HEADER_DUMMY_H_ */ + diff --git a/trunk/tinyHTTP/include/tinyHTTP/thttp_message.h b/trunk/tinyHTTP/include/tinyHTTP/thttp_message.h index 360c42c7..d423bb05 100644 --- a/trunk/tinyHTTP/include/tinyHTTP/thttp_message.h +++ b/trunk/tinyHTTP/include/tinyHTTP/thttp_message.h @@ -52,8 +52,9 @@ THTTP_BEGIN_DECLS #define THTTP_MESSAGE_VERSION_10 "HTTP/1.0" +#define THTTP_MESSAGE_VERSION_11 "HTTP/1.1" #define THTTP_MESSAGE_VERSION_20 "HTTP/2.0" -#define THTTP_MESSAGE_VERSION_DEFAULT THTTP_MESSAGE_VERSION_20 +#define THTTP_MESSAGE_VERSION_DEFAULT THTTP_MESSAGE_VERSION_11 #define THTTP_MESSAGE_IS_REQUEST(self) ((self) ? (self)->type == thttp_request : 0) #define THTTP_MESSAGE_IS_RESPONSE(self) ((self) ? (self)->type == thttp_response : 0) @@ -120,7 +121,7 @@ typedef struct thttp_message_s { TSK_DECLARE_OBJECT; - char *http_version; /**< The HTTP version. Only 'HTTP/2.0' is supported. */ + 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 */ @@ -144,14 +145,6 @@ typedef struct thttp_message_s #endif /*== MOST COMMON HEADERS. */ - //thttp_header_Via_t *firstVia; /**< First Via header. */ - //thttp_header_From_t *From; - //thttp_header_To_t *To; - //thttp_header_Contact_t *Contact; - //thttp_header_Call_ID_t *Call_ID; - //thttp_header_CSeq_t *CSeq; - //thttp_header_Expires_t *Expires; - thttp_header_Content_Type_t *Content_Type; thttp_header_Content_Length_t *Content_Length; tsk_buffer_t *Content; @@ -166,41 +159,40 @@ typedef thttp_message_t thttp_response_t; /**< HTTP response message. */ // TINYHTTP_API int thttp_message_add_header(thttp_message_t *self, const thttp_header_t *hdr); -//TINYHTTP_API int thttp_message_add_headers(thttp_message_t *self, const thttp_headers_L_t *headers); -// -//#if !defined(_MSC_VER) || defined(__GNUC__) -//static void THTTP_MESSAGE_ADD_HEADER(thttp_message_t *self, ...) -// { -// va_list ap; -// thttp_header_t *header; -// const tsk_object_def_t *objdef; -// -// va_start(ap, self); -// objdef = va_arg(ap, const tsk_object_def_t*); -// header = tsk_object_new2(objdef, &ap); -// va_end(ap); -// -// thttp_message_add_header(self, header); -// tsk_object_unref(header); -// } -//#else -//#define THTTP_MESSAGE_ADD_HEADER(self, objdef, ...) \ -// { \ -// thttp_header_t *header = tsk_object_new(objdef, __VA_ARGS__); \ -// thttp_message_add_header(self, header); \ -// tsk_object_unref(header); \ -// } -//#endif -// -//TINYHTTP_API const thttp_header_t *thttp_message_get_headerAt(const thttp_message_t *self, thttp_header_type_t type, size_t index); -//TINYHTTP_API const thttp_header_t *thttp_message_get_header(const thttp_message_t *self, thttp_header_type_t type); -// -TINYHTTP_API uint32_t thttp_message_getContent_length(const thttp_message_t *message); -// -//TINYHTTP_API int thttp_message_tostring(const thttp_message_t *self, tsk_buffer_t *output); -// -//TINYHTTP_API thttp_request_t *thttp_request_new(const char* method, const thttp_url_t *request_url, const thttp_url_t *from, const thttp_url_t *to, const char *call_id, int32_t cseq); -//TINYHTTP_API thttp_response_t *thttp_response_new(short status_code, const char* reason_phrase, const thttp_request_t *request); +TINYHTTP_API int thttp_message_add_headers(thttp_message_t *self, const thttp_headers_L_t *headers); + +#if !defined(_MSC_VER) || defined(__GNUC__) +static void THTTP_MESSAGE_ADD_HEADER(thttp_message_t *self, ...) + { + va_list ap; + thttp_header_t *header; + const tsk_object_def_t *objdef; + + va_start(ap, self); + objdef = va_arg(ap, const tsk_object_def_t*); + header = tsk_object_new2(objdef, &ap); + va_end(ap); + + thttp_message_add_header(self, header); + tsk_object_unref(header); + } +#else +#define THTTP_MESSAGE_ADD_HEADER(self, objdef, ...) \ + { \ + thttp_header_t *header = tsk_object_new(objdef, __VA_ARGS__); \ + thttp_message_add_header(self, header); \ + tsk_object_unref(header); \ + } +#endif + +TINYHTTP_API const thttp_header_t *thttp_message_get_headerAt(const thttp_message_t *self, thttp_header_type_t type, size_t index); +TINYHTTP_API const thttp_header_t *thttp_message_get_header(const thttp_message_t *self, thttp_header_type_t type); +TINYHTTP_API const thttp_header_t *thttp_message_get_headerByName(const thttp_message_t *self, const char* name); + +TINYHTTP_API int thttp_message_tostring(const thttp_message_t *self, tsk_buffer_t *output); + +TINYHTTP_API thttp_request_t *thttp_request_new(const char* method, const thttp_url_t *request_url); +TINYHTTP_API thttp_response_t *thttp_response_new(short status_code, const char* reason_phrase, const thttp_request_t *request); TINYHTTP_GEXTERN const void *thttp_message_def_t; diff --git a/trunk/tinyHTTP/include/tinyHTTP/thttp_operation.h b/trunk/tinyHTTP/include/tinyHTTP/thttp_operation.h index ba8081e6..c1dc42fd 100644 --- a/trunk/tinyHTTP/include/tinyHTTP/thttp_operation.h +++ b/trunk/tinyHTTP/include/tinyHTTP/thttp_operation.h @@ -32,8 +32,49 @@ #include "tinyhttp_config.h" +#include "tnet_types.h" + +#include "tsk_object.h" +#include "tsk_list.h" +#include "tsk_params.h" + THTTP_BEGIN_DECLS +//FD +struct thttp_message_s; + +#define THTTP_OPERATION_CREATE(stack, ...) tsk_object_new(thttp_operation_def_t, (thttp_stack_handle_t*)stack, __VA_ARGS__) + +typedef uint64_t thttp_operation_id_t; +#define THTTP_OPERATION_INVALID_ID 0 +#define THTTP_OPERATION_INVALID_HANDLE THTTP_NULL + +typedef enum thttp_operation_param_type_e +{ + optype_param, + optype_header, + optype_null +} +thttp_operation_param_type_t; + +#define THTTP_OPERATION_SET_PARAM(NAME_STR, VALUE_STR) optype_param, (const char*)NAME_STR, (const char*)VALUE_STR +#define THTTP_OPERATION_SET_HEADER(NAME_STR, VALUE_STR) optype_header, (const char*)NAME_STR, (const char*)VALUE_STR +#define THTTP_OPERATION_SET_NULL() optype_null + +typedef void thttp_operation_handle_t; + +TINYHTTP_API int thttp_operation_set(thttp_operation_handle_t *self, ...); +TINYHTTP_API thttp_operation_id_t thttp_operation_get_id(const thttp_operation_handle_t *self); +const tsk_param_t* thttp_operation_get_param(const thttp_operation_handle_t *self, const char* pname); +const tsk_param_t* thttp_operation_get_header(const thttp_operation_handle_t *self, const char* pname); +const tsk_params_L_t* thttp_operation_get_headers(const thttp_operation_handle_t *self); +const tsk_params_L_t* thttp_operation_get_params(const thttp_operation_handle_t *self); +tnet_fd_t thttp_operation_get_fd(const thttp_operation_handle_t *self); +int thttp_operation_set_fd(thttp_operation_handle_t *self, tnet_fd_t fd); +TINYHTTP_API int thttp_operation_perform(thttp_operation_handle_t* self); + +typedef tsk_list_t thttp_operations_L_t; /**< List of @ref thttp_operation_handle_t elements. */ +TINYHTTP_GEXTERN const void *thttp_operation_def_t; THTTP_END_DECLS diff --git a/trunk/tinyHTTP/include/tinyHTTP/thttp_url.h b/trunk/tinyHTTP/include/tinyHTTP/thttp_url.h index be391099..196ee9bb 100644 --- a/trunk/tinyHTTP/include/tinyHTTP/thttp_url.h +++ b/trunk/tinyHTTP/include/tinyHTTP/thttp_url.h @@ -68,8 +68,10 @@ thttp_host_type_t; /// /// @brief HTTP/HTTPS URL. /// -/// @author Mamadou -/// @date 12/6/2009 +/// ABNF (Compact: From RFC 1738): httpurl = "http://" hostport [ "/" hpath [ "?" search ]] +/// hpath = hsegment *[ "/" hsegment ] +/// hsegment = *[ uchar | ";" | ":" | "@" | "&" | "=" ] +/// search = *[ uchar | ";" | ":" | "@" | "&" | "=" ] //////////////////////////////////////////////////////////////////////////////////////////////////// typedef struct thttp_url_s { @@ -78,9 +80,10 @@ typedef struct thttp_url_s thttp_url_type_t type; char *scheme; char *host; /**< Host name. Hostname or IPv4address or IPv6address. */ + char *hpath; + char *search; thttp_host_type_t host_type; /**< IPv4 or IPv6 or domain name. */ uint16_t port; - char *password; } thttp_url_t; diff --git a/trunk/tinyHTTP/include/tinyhttp_config.h b/trunk/tinyHTTP/include/tinyhttp_config.h index a3a49bc2..483084c6 100644 --- a/trunk/tinyHTTP/include/tinyhttp_config.h +++ b/trunk/tinyHTTP/include/tinyhttp_config.h @@ -75,5 +75,7 @@ #include #endif +/* FIXME */ +#define THTTP_NULL 0 #endif // TINYHTTP_CONFIG_H diff --git a/trunk/tinyHTTP/ragel.sh b/trunk/tinyHTTP/ragel.sh index 33468bde..5fdb170e 100644 --- a/trunk/tinyHTTP/ragel.sh +++ b/trunk/tinyHTTP/ragel.sh @@ -22,6 +22,9 @@ ragel.exe $OPTIONS -o ../src/headers/thttp_header_Authorization.c thttp_parser_h # ==Content-Length ragel.exe $OPTIONS -o ../src/headers/thttp_header_Content_Length.c thttp_parser_header_Content_Length.rl +# ==Dummy +ragel.exe $OPTIONS -o ../src/headers/thttp_header_Dummy.c thttp_parser_header_Dummy.rl + # ==Content-Type ragel.exe $OPTIONS -o ../src/headers/thttp_header_Content_Type.c thttp_parser_header_Content_Type.rl diff --git a/trunk/tinyHTTP/ragel/thttp_parser_header_Content_Type.rl b/trunk/tinyHTTP/ragel/thttp_parser_header_Content_Type.rl index d4bf7b3c..23ad2b8e 100644 --- a/trunk/tinyHTTP/ragel/thttp_parser_header_Content_Type.rl +++ b/trunk/tinyHTTP/ragel/thttp_parser_header_Content_Type.rl @@ -102,7 +102,7 @@ thttp_header_Content_Type_t *thttp_header_Content_Type_parse(const char *data, s const char *p = data; const char *pe = p + size; const char *eof = pe; - thttp_header_Content_Type_t *hdr_ctype = THTTP_HEADER_CONTENT_TYPE_CREATE(); + thttp_header_Content_Type_t *hdr_ctype = THTTP_HEADER_CONTENT_TYPE_CREATE_NULL(); const char *tag_start; @@ -137,6 +137,8 @@ static void* thttp_header_Content_Type_create(void *self, va_list * app) { THTTP_HEADER(Content_Type)->type = thttp_htype_Content_Type; THTTP_HEADER(Content_Type)->tostring = thttp_header_Content_Type_tostring; + + Content_Type->type = tsk_strdup( va_arg(*app, const char*) ); } else { diff --git a/trunk/tinyHTTP/ragel/thttp_parser_header_Dummy.rl b/trunk/tinyHTTP/ragel/thttp_parser_header_Dummy.rl new file mode 100644 index 00000000..e9234de2 --- /dev/null +++ b/trunk/tinyHTTP/ragel/thttp_parser_header_Dummy.rl @@ -0,0 +1,164 @@ +/* +* Copyright (C) 2009 Mamadou Diop. +* +* Contact: Mamadou Diop +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Dummy.c + * @brief HTTP DUmmy header. + * + * @author Mamadou Diop + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ +#include "tinyhttp/headers/thttp_header_Dummy.h" + +#include "tinyhttp/parsers/thttp_parser_url.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" + +#include + +/**@defgroup thttp_header_Dummy_group HTTP Dummy header. +*/ + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_header_Dummy; + + # Includes + include thttp_machine_utils "./thttp_machine_utils.rl"; + + action tag + { + tag_start = p; + } + + action parse_name + { + TSK_PARSER_SET_STRING(hdr_Dummy->name); + } + + action parse_value + { + TSK_PARSER_SET_STRING(hdr_Dummy->value); + } + + action eob + { + } + + Dummy = token>tag %parse_name SP* HCOLON SP*<: any*>tag %parse_value; + + # Entry point + main := Dummy :>CRLF @eob; + +}%% + +int thttp_header_Dummy_tostring(const void* header, tsk_buffer_t* output) +{ + if(header) + { + const thttp_header_Dummy_t *Dummy = header; + if(Dummy->value) + { + tsk_buffer_append(output, Dummy->value, strlen(Dummy->value)); + } + return 0; + } + + return -1; +} + +thttp_header_Dummy_t *thttp_header_Dummy_parse(const char *data, size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Dummy_t *hdr_Dummy = THTTP_HEADER_DUMMY_CREATE_NULL(); + + const char *tag_start; + + %%write data; + %%write init; + %%write exec; + + if( cs < %%{ write first_final; }%% ) + { + TSK_OBJECT_SAFE_FREE(hdr_Dummy); + } + + return hdr_Dummy; +} + + + + + + + +//======================================================== +// Dummy header object definition +// + +static void* thttp_header_Dummy_create(void *self, va_list * app) +{ + thttp_header_Dummy_t *Dummy = self; + if(Dummy) + { + THTTP_HEADER(Dummy)->type = thttp_htype_Dummy; + THTTP_HEADER(Dummy)->tostring = thttp_header_Dummy_tostring; + + Dummy->name = tsk_strdup(va_arg(*app, const char*)); + Dummy->value = tsk_strdup(va_arg(*app, const char*)); + } + else + { + TSK_DEBUG_ERROR("Failed to create new Dummy header."); + } + return self; +} + +static void* thttp_header_Dummy_destroy(void *self) +{ + thttp_header_Dummy_t *Dummy = self; + if(Dummy) + { + TSK_FREE(Dummy->name); + TSK_FREE(Dummy->value); + + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Dummy)); + } + else TSK_DEBUG_ERROR("Null Dummy header."); + + return self; +} + +static const tsk_object_def_t thttp_header_Dummy_def_s = +{ + sizeof(thttp_header_Dummy_t), + thttp_header_Dummy_create, + thttp_header_Dummy_destroy, + 0 +}; +const void *thttp_header_Dummy_def_t = &thttp_header_Dummy_def_s; diff --git a/trunk/tinyHTTP/ragel/thttp_parser_message.rl b/trunk/tinyHTTP/ragel/thttp_parser_message.rl index 38fd44a0..e6a0168d 100644 --- a/trunk/tinyHTTP/ragel/thttp_parser_message.rl +++ b/trunk/tinyHTTP/ragel/thttp_parser_message.rl @@ -266,7 +266,7 @@ static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t * if(message) { - uint32_t clen = thttp_message_getContent_length(message); + uint32_t clen = THTTP_MESSAGE_CONTENT_LENGTH(message); if((p+clen) Content) { message->Content = TSK_BUFFER_CREATE((p+1), clen); diff --git a/trunk/tinyHTTP/ragel/thttp_parser_url.rl b/trunk/tinyHTTP/ragel/thttp_parser_url.rl index 771bf4f2..6ed21aae 100644 --- a/trunk/tinyHTTP/ragel/thttp_parser_url.rl +++ b/trunk/tinyHTTP/ragel/thttp_parser_url.rl @@ -54,11 +54,40 @@ action is_http { url->scheme = tsk_strdup("http"), url->type = url_http; } action is_https { url->scheme = tsk_strdup("https"), url->type = url_https; } - action eob - { + #/* Sets HOST type */ + action is_ipv4 { url->host_type = url->host_type = host_ipv4; } + action is_ipv6 { url->host_type = url->host_type = host_ipv6; } + action is_hostname { url->host_type = url->host_type = host_hostname; } + + action parse_host{ + TSK_PARSER_SET_STRING(url->host); } - main := (("http:"i>tag %is_http | "https:"i>tag %is_https) any*) @eob; + action parse_port{ + have_port = 1; + TSK_PARSER_SET_INT(url->port); + } + + action parse_hpath{ + TSK_PARSER_SET_STRING(url->hpath); + } + + action parse_search{ + TSK_PARSER_SET_STRING(url->search); + } + + action eob{ + } + + #// RFC 1738: "http://" hostport [ "/" hpath [ "?" search ]] + #// FIXME: hpath is no optional (see above) but in my def. I use it as opt (any*). + + search = any* >tag %parse_search; + hpath = any* >tag %parse_hpath; + port = DIGIT+ >tag %parse_port; + myhost = ((IPv6reference >is_ipv6) | (IPv4address >is_ipv4) | (hostname >is_hostname)) >tag %parse_host; + hostport = myhost ( ":" port )?; + main := (("http:"i>tag %is_http | "https:"i>tag %is_https) "//" hostport :>("/" hpath :>("?" search)?)? ) @eob; }%% @@ -77,6 +106,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// thttp_url_t *thttp_url_parse(const char *data, size_t size) { + int have_port = 0; int cs = 0; const char *p = data; const char *pe = p + size; @@ -93,11 +123,18 @@ thttp_url_t *thttp_url_parse(const char *data, size_t size) %%write init; %%write exec; - if( cs < %%{ write first_final; }%% ) - { + if( cs < %%{ write first_final; }%% ){ TSK_DEBUG_ERROR("Failed to parse HTTP/HTTPS URL."); TSK_OBJECT_SAFE_FREE(url); } + else if(!have_port){ + if(url->type == url_https){ + url->port = 443; + } + else{ + url->port = 80; + } + } return url; } \ No newline at end of file diff --git a/trunk/tinyHTTP/src/headers/thttp_header.c b/trunk/tinyHTTP/src/headers/thttp_header.c index e69de29b..1aa734fd 100644 --- a/trunk/tinyHTTP/src/headers/thttp_header.c +++ b/trunk/tinyHTTP/src/headers/thttp_header.c @@ -0,0 +1,116 @@ +/* +* Copyright (C) 2009 Mamadou Diop. +* +* Contact: Mamadou Diop +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header.c + * @brief Defines a HTTP header (field-name: field-value). + * + * @author Mamadou Diop + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ +#include "tinyHTTP/headers/thttp_header.h" + +#include "tinyHTTP/headers/thttp_header_Dummy.h" + +const char *thttp_header_get_name(thttp_header_type_t type) +{ + switch(type) + { + case thttp_htype_Authorization: return "Authorization"; + case thttp_htype_Content_Length: return "Content-Length"; + case thttp_htype_Content_Type: return "Content-Type"; + case thttp_htype_Proxy_Authenticate: return "Proxy-Authenticate"; + case thttp_htype_Proxy_Authorization: return "Proxy-Authorization"; + case thttp_htype_WWW_Authenticate: return "WWW-Authenticate"; + + default: return "unknown-header"; + } +} + +const char *thttp_header_get_nameex(const thttp_header_t *self) +{ + if(self){ + if(self->type == thttp_htype_Dummy){ + return ((thttp_header_Dummy_t*)self)->name; + } + else{ + return thttp_header_get_name(self->type); + } + } + return "unknown-header"; +} + +char thttp_header_get_param_separator(const thttp_header_t *self) +{ + if(self) + { + switch(self->type) + { + case thttp_htype_Authorization: + case thttp_htype_Proxy_Authorization: + case thttp_htype_Proxy_Authenticate: + case thttp_htype_WWW_Authenticate: + return ','; + default: + return ';'; + } + } + return 0; +} + +int thttp_header_tostring(const thttp_header_t *self, tsk_buffer_t *output) +{ + int ret = -1; + static const char* hname; + static char separator; + + if(self && THTTP_HEADER(self)->tostring) + { + tsk_list_item_t *item; + + hname = thttp_header_get_nameex(self); + ret = 0; // for empty lists + + /* Header name */ + tsk_buffer_appendEx(output, "%s: ", hname); + + /* Header value.*/ + if((ret = THTTP_HEADER(self)->tostring(self, output))){ + // CHECK all headers return value! + //return ret; + } + + /* Parameters */ + tsk_list_foreach(item, self->params) + { + tsk_param_t* param = item->data; + separator = thttp_header_get_param_separator(self); + if(ret = tsk_buffer_appendEx(output, param->value?"%c%s=%s":"%c%s", separator, param->name, param->value)){ + return ret; + } + } + + /* CRLF */ + tsk_buffer_append(output, "\r\n", 2); + } + return ret; +} \ No newline at end of file diff --git a/trunk/tinyHTTP/src/headers/thttp_header_Authorization.c b/trunk/tinyHTTP/src/headers/thttp_header_Authorization.c index abe3bcfb..33f874c3 100644 --- a/trunk/tinyHTTP/src/headers/thttp_header_Authorization.c +++ b/trunk/tinyHTTP/src/headers/thttp_header_Authorization.c @@ -9765,4 +9765,4 @@ static const tsk_object_def_t thttp_header_Authorization_def_s = thttp_header_Authorization_destroy, 0 }; -const void *thttp_header_Authorization_def_t = &thttp_header_Authorization_def_s; +const void *thttp_header_Authorization_def_t = &thttp_header_Authorization_def_s; \ No newline at end of file diff --git a/trunk/tinyHTTP/src/headers/thttp_header_Content_Length.c b/trunk/tinyHTTP/src/headers/thttp_header_Content_Length.c index 05bb15cc..d8e974a0 100644 --- a/trunk/tinyHTTP/src/headers/thttp_header_Content_Length.c +++ b/trunk/tinyHTTP/src/headers/thttp_header_Content_Length.c @@ -15,7 +15,7 @@ * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. +* GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with DOUBANGO. diff --git a/trunk/tinyHTTP/src/headers/thttp_header_Content_Type.c b/trunk/tinyHTTP/src/headers/thttp_header_Content_Type.c index ac938bd8..c9c32251 100644 --- a/trunk/tinyHTTP/src/headers/thttp_header_Content_Type.c +++ b/trunk/tinyHTTP/src/headers/thttp_header_Content_Type.c @@ -15,7 +15,7 @@ * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. +* GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with DOUBANGO. @@ -63,7 +63,7 @@ thttp_header_Content_Type_t *thttp_header_Content_Type_parse(const char *data, s const char *p = data; const char *pe = p + size; const char *eof = pe; - thttp_header_Content_Type_t *hdr_ctype = THTTP_HEADER_CONTENT_TYPE_CREATE(); + thttp_header_Content_Type_t *hdr_ctype = THTTP_HEADER_CONTENT_TYPE_CREATE_NULL(); const char *tag_start; @@ -387,6 +387,8 @@ static void* thttp_header_Content_Type_create(void *self, va_list * app) { THTTP_HEADER(Content_Type)->type = thttp_htype_Content_Type; THTTP_HEADER(Content_Type)->tostring = thttp_header_Content_Type_tostring; + + Content_Type->type = tsk_strdup( va_arg(*app, const char*) ); } else { diff --git a/trunk/tinyHTTP/src/headers/thttp_header_Dummy.c b/trunk/tinyHTTP/src/headers/thttp_header_Dummy.c new file mode 100644 index 00000000..6e80be54 --- /dev/null +++ b/trunk/tinyHTTP/src/headers/thttp_header_Dummy.c @@ -0,0 +1,321 @@ + +/* #line 1 "thttp_parser_header_Dummy.rl" */ +/* +* Copyright (C) 2009 Mamadou Diop. +* +* Contact: Mamadou Diop +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Dummy.c + * @brief HTTP DUmmy header. + * + * @author Mamadou Diop + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ +#include "tinyhttp/headers/thttp_header_Dummy.h" + +#include "tinyhttp/parsers/thttp_parser_url.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" + +#include + +/**@defgroup thttp_header_Dummy_group HTTP Dummy header. +*/ + +/*********************************** +* Ragel state machine. +*/ + +/* #line 75 "thttp_parser_header_Dummy.rl" */ + + +int thttp_header_Dummy_tostring(const void* header, tsk_buffer_t* output) +{ + if(header) + { + const thttp_header_Dummy_t *Dummy = header; + if(Dummy->value) + { + tsk_buffer_append(output, Dummy->value, strlen(Dummy->value)); + } + return 0; + } + + return -1; +} + +thttp_header_Dummy_t *thttp_header_Dummy_parse(const char *data, size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Dummy_t *hdr_Dummy = THTTP_HEADER_DUMMY_CREATE_NULL(); + + const char *tag_start; + + +/* #line 78 "../src/headers/thttp_header_Dummy.c" */ +static const char _thttp_machine_parser_header_Dummy_actions[] = { + 0, 1, 0, 1, 1, 1, 2, 1, + 3, 2, 0, 2 +}; + +static const char _thttp_machine_parser_header_Dummy_key_offsets[] = { + 0, 0, 14, 31, 34, 37, 38, 39, + 40, 42, 45 +}; + +static const char _thttp_machine_parser_header_Dummy_trans_keys[] = { + 33, 37, 39, 126, 42, 43, 45, 46, + 48, 57, 65, 90, 95, 122, 9, 32, + 33, 37, 39, 58, 126, 42, 43, 45, + 46, 48, 57, 65, 90, 95, 122, 9, + 32, 58, 9, 13, 32, 13, 10, 10, + 9, 32, 9, 13, 32, 0 +}; + +static const char _thttp_machine_parser_header_Dummy_single_lengths[] = { + 0, 4, 7, 3, 3, 1, 1, 1, + 2, 3, 0 +}; + +static const char _thttp_machine_parser_header_Dummy_range_lengths[] = { + 0, 5, 5, 0, 0, 0, 0, 0, + 0, 0, 0 +}; + +static const char _thttp_machine_parser_header_Dummy_index_offsets[] = { + 0, 0, 10, 23, 27, 31, 33, 35, + 37, 40, 44 +}; + +static const char _thttp_machine_parser_header_Dummy_indicies[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 2, 3, 3, 3, 4, + 3, 3, 3, 3, 3, 3, 1, 5, + 5, 6, 1, 6, 8, 6, 7, 10, + 9, 11, 1, 12, 1, 13, 13, 1, + 13, 14, 13, 7, 1, 0 +}; + +static const char _thttp_machine_parser_header_Dummy_trans_targs[] = { + 2, 0, 3, 2, 4, 3, 4, 5, + 7, 5, 6, 10, 8, 9, 6 +}; + +static const char _thttp_machine_parser_header_Dummy_trans_actions[] = { + 1, 0, 3, 0, 3, 0, 0, 1, + 0, 0, 5, 7, 0, 0, 9 +}; + +static const int thttp_machine_parser_header_Dummy_start = 1; +static const int thttp_machine_parser_header_Dummy_first_final = 10; +static const int thttp_machine_parser_header_Dummy_error = 0; + +static const int thttp_machine_parser_header_Dummy_en_main = 1; + + +/* #line 103 "thttp_parser_header_Dummy.rl" */ + +/* #line 141 "../src/headers/thttp_header_Dummy.c" */ + { + cs = thttp_machine_parser_header_Dummy_start; + } + +/* #line 104 "thttp_parser_header_Dummy.rl" */ + +/* #line 148 "../src/headers/thttp_header_Dummy.c" */ + { + int _klen; + unsigned int _trans; + const char *_acts; + unsigned int _nacts; + const char *_keys; + + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _thttp_machine_parser_header_Dummy_trans_keys + _thttp_machine_parser_header_Dummy_key_offsets[cs]; + _trans = _thttp_machine_parser_header_Dummy_index_offsets[cs]; + + _klen = _thttp_machine_parser_header_Dummy_single_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + _klen - 1; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + ((_upper-_lower) >> 1); + if ( (*p) < *_mid ) + _upper = _mid - 1; + else if ( (*p) > *_mid ) + _lower = _mid + 1; + else { + _trans += (_mid - _keys); + goto _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _thttp_machine_parser_header_Dummy_range_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + (_klen<<1) - 2; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( (*p) < _mid[0] ) + _upper = _mid - 2; + else if ( (*p) > _mid[1] ) + _lower = _mid + 2; + else { + _trans += ((_mid - _keys)>>1); + goto _match; + } + } + _trans += _klen; + } + +_match: + _trans = _thttp_machine_parser_header_Dummy_indicies[_trans]; + cs = _thttp_machine_parser_header_Dummy_trans_targs[_trans]; + + if ( _thttp_machine_parser_header_Dummy_trans_actions[_trans] == 0 ) + goto _again; + + _acts = _thttp_machine_parser_header_Dummy_actions + _thttp_machine_parser_header_Dummy_trans_actions[_trans]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) + { + switch ( *_acts++ ) + { + case 0: +/* #line 52 "thttp_parser_header_Dummy.rl" */ + { + tag_start = p; + } + break; + case 1: +/* #line 57 "thttp_parser_header_Dummy.rl" */ + { + TSK_PARSER_SET_STRING(hdr_Dummy->name); + } + break; + case 2: +/* #line 62 "thttp_parser_header_Dummy.rl" */ + { + TSK_PARSER_SET_STRING(hdr_Dummy->value); + } + break; + case 3: +/* #line 67 "thttp_parser_header_Dummy.rl" */ + { + } + break; +/* #line 245 "../src/headers/thttp_header_Dummy.c" */ + } + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + _out: {} + } + +/* #line 105 "thttp_parser_header_Dummy.rl" */ + + if( cs < +/* #line 261 "../src/headers/thttp_header_Dummy.c" */ +10 +/* #line 106 "thttp_parser_header_Dummy.rl" */ + ) + { + TSK_OBJECT_SAFE_FREE(hdr_Dummy); + } + + return hdr_Dummy; +} + + + + + + + +//======================================================== +// Dummy header object definition +// + +static void* thttp_header_Dummy_create(void *self, va_list * app) +{ + thttp_header_Dummy_t *Dummy = self; + if(Dummy) + { + THTTP_HEADER(Dummy)->type = thttp_htype_Dummy; + THTTP_HEADER(Dummy)->tostring = thttp_header_Dummy_tostring; + + Dummy->name = tsk_strdup(va_arg(*app, const char*)); + Dummy->value = tsk_strdup(va_arg(*app, const char*)); + } + else + { + TSK_DEBUG_ERROR("Failed to create new Dummy header."); + } + return self; +} + +static void* thttp_header_Dummy_destroy(void *self) +{ + thttp_header_Dummy_t *Dummy = self; + if(Dummy) + { + TSK_FREE(Dummy->name); + TSK_FREE(Dummy->value); + + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Dummy)); + } + else TSK_DEBUG_ERROR("Null Dummy header."); + + return self; +} + +static const tsk_object_def_t thttp_header_Dummy_def_s = +{ + sizeof(thttp_header_Dummy_t), + thttp_header_Dummy_create, + thttp_header_Dummy_destroy, + 0 +}; +const void *thttp_header_Dummy_def_t = &thttp_header_Dummy_def_s; diff --git a/trunk/tinyHTTP/src/headers/thttp_header_WWW_Authenticate.c b/trunk/tinyHTTP/src/headers/thttp_header_WWW_Authenticate.c index 53e5047d..26e2a5be 100644 --- a/trunk/tinyHTTP/src/headers/thttp_header_WWW_Authenticate.c +++ b/trunk/tinyHTTP/src/headers/thttp_header_WWW_Authenticate.c @@ -6494,4 +6494,4 @@ static const tsk_object_def_t thttp_header_WWW_Authenticate_def_s = thttp_header_WWW_Authenticate_destroy, 0 }; -const void *thttp_header_WWW_Authenticate_def_t = &thttp_header_WWW_Authenticate_def_s; +const void *thttp_header_WWW_Authenticate_def_t = &thttp_header_WWW_Authenticate_def_s; \ No newline at end of file diff --git a/trunk/tinyHTTP/src/parsers/thttp_parser_header.c b/trunk/tinyHTTP/src/parsers/thttp_parser_header.c index a0085c28..1a2c8d91 100644 --- a/trunk/tinyHTTP/src/parsers/thttp_parser_header.c +++ b/trunk/tinyHTTP/src/parsers/thttp_parser_header.c @@ -2266,4 +2266,4 @@ _again: 533 /* #line 321 "thttp_parser_header.rl" */ ) ? 0 : -1; -} +} \ No newline at end of file diff --git a/trunk/tinyHTTP/src/parsers/thttp_parser_message.c b/trunk/tinyHTTP/src/parsers/thttp_parser_message.c index 2f921377..d97c9763 100644 --- a/trunk/tinyHTTP/src/parsers/thttp_parser_message.c +++ b/trunk/tinyHTTP/src/parsers/thttp_parser_message.c @@ -468,7 +468,7 @@ static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t * if(message) { - uint32_t clen = thttp_message_getContent_length(message); + uint32_t clen = THTTP_MESSAGE_CONTENT_LENGTH(message); if((p+clen) Content) { message->Content = TSK_BUFFER_CREATE((p+1), clen); @@ -485,4 +485,4 @@ static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t * state->p = p; state->pe = pe; state->eof = eof; -} +} \ No newline at end of file diff --git a/trunk/tinyHTTP/src/parsers/thttp_parser_url.c b/trunk/tinyHTTP/src/parsers/thttp_parser_url.c index 48ee22fc..4b5d5d33 100644 --- a/trunk/tinyHTTP/src/parsers/thttp_parser_url.c +++ b/trunk/tinyHTTP/src/parsers/thttp_parser_url.c @@ -42,7 +42,7 @@ * Ragel state machine. */ -/* #line 63 "thttp_parser_url.rl" */ +/* #line 92 "thttp_parser_url.rl" */ //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -60,6 +60,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// thttp_url_t *thttp_url_parse(const char *data, size_t size) { + int have_port = 0; int cs = 0; const char *p = data; const char *pe = p + size; @@ -73,71 +74,218 @@ thttp_url_t *thttp_url_parse(const char *data, size_t size) const char *tag_start = 0; -/* #line 77 "../src/parsers/thttp_parser_url.c" */ +/* #line 78 "../src/parsers/thttp_parser_url.c" */ static const char _thttp_machine_parser_url_actions[] = { 0, 1, 0, 1, 1, 1, 2, 1, - 3, 2, 1, 3, 2, 2, 3 + 6, 1, 7, 1, 8, 1, 9, 1, + 10, 2, 0, 4, 2, 0, 8, 2, + 0, 9, 2, 0, 10, 2, 6, 10, + 2, 7, 10, 2, 8, 10, 3, 0, + 3, 5, 3, 0, 5, 10, 3, 0, + 8, 10 }; -static const char _thttp_machine_parser_url_key_offsets[] = { +static const short _thttp_machine_parser_url_key_offsets[] = { 0, 0, 2, 4, 6, 8, 11, 12, - 12, 12 + 13, 20, 28, 35, 43, 49, 56, 58, + 64, 72, 78, 86, 92, 100, 108, 116, + 124, 132, 140, 147, 155, 163, 171, 173, + 180, 189, 191, 194, 196, 199, 201, 204, + 207, 208, 211, 212, 215, 216, 225, 234, + 242, 250, 258, 266, 268, 274, 283, 292, + 301, 303, 306, 309, 310, 311, 312, 313, + 323, 331, 332, 333, 333, 333, 336, 346, + 356, 366 }; static const char _thttp_machine_parser_url_trans_keys[] = { 72, 104, 84, 116, 84, 116, 80, 112, - 58, 83, 115, 58, 0 + 58, 83, 115, 47, 47, 91, 48, 57, + 65, 90, 97, 122, 45, 46, 48, 57, + 65, 90, 97, 122, 45, 48, 57, 65, + 90, 97, 122, 45, 46, 48, 57, 65, + 90, 97, 122, 48, 57, 65, 90, 97, + 122, 45, 48, 57, 65, 90, 97, 122, + 48, 57, 48, 57, 65, 90, 97, 122, + 45, 46, 48, 57, 65, 90, 97, 122, + 48, 57, 65, 90, 97, 122, 45, 46, + 48, 57, 65, 90, 97, 122, 48, 57, + 65, 90, 97, 122, 45, 46, 48, 57, + 65, 90, 97, 122, 45, 46, 48, 57, + 65, 90, 97, 122, 45, 46, 48, 57, + 65, 90, 97, 122, 45, 46, 48, 57, + 65, 90, 97, 122, 45, 46, 48, 57, + 65, 90, 97, 122, 45, 46, 48, 57, + 65, 90, 97, 122, 58, 48, 57, 65, + 70, 97, 102, 58, 93, 48, 57, 65, + 70, 97, 102, 58, 93, 48, 57, 65, + 70, 97, 102, 58, 93, 48, 57, 65, + 70, 97, 102, 58, 93, 58, 48, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 48, 57, 46, + 48, 57, 48, 57, 46, 48, 57, 48, + 57, 93, 48, 57, 93, 48, 57, 93, + 46, 48, 57, 46, 46, 48, 57, 46, + 46, 58, 93, 48, 57, 65, 70, 97, + 102, 46, 58, 93, 48, 57, 65, 70, + 97, 102, 58, 93, 48, 57, 65, 70, + 97, 102, 58, 93, 48, 57, 65, 70, + 97, 102, 58, 93, 48, 57, 65, 70, + 97, 102, 58, 93, 48, 57, 65, 70, + 97, 102, 58, 93, 48, 57, 65, 70, + 97, 102, 46, 58, 93, 48, 57, 65, + 70, 97, 102, 46, 58, 93, 48, 57, + 65, 70, 97, 102, 46, 58, 93, 48, + 57, 65, 70, 97, 102, 48, 57, 46, + 48, 57, 46, 48, 57, 46, 58, 58, + 47, 45, 46, 47, 58, 48, 57, 65, + 90, 97, 122, 47, 58, 48, 57, 65, + 90, 97, 122, 63, 63, 47, 48, 57, + 45, 46, 47, 58, 48, 57, 65, 90, + 97, 122, 45, 46, 47, 58, 48, 57, + 65, 90, 97, 122, 45, 46, 47, 58, + 48, 57, 65, 90, 97, 122, 47, 58, + 0 }; static const char _thttp_machine_parser_url_single_lengths[] = { - 0, 2, 2, 2, 2, 3, 1, 0, - 0, 0 + 0, 2, 2, 2, 2, 3, 1, 1, + 1, 2, 1, 2, 0, 1, 0, 0, + 2, 0, 2, 0, 2, 2, 2, 2, + 2, 2, 1, 2, 2, 2, 2, 1, + 3, 0, 1, 0, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 3, 3, 2, + 2, 2, 2, 2, 0, 3, 3, 3, + 0, 1, 1, 1, 1, 1, 1, 4, + 2, 1, 1, 0, 0, 1, 4, 4, + 4, 2 }; static const char _thttp_machine_parser_url_range_lengths[] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 + 3, 3, 3, 3, 3, 3, 1, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 0, 3, + 3, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 0, 1, 0, 3, 3, 3, + 3, 3, 3, 0, 3, 3, 3, 3, + 1, 1, 1, 0, 0, 0, 0, 3, + 3, 0, 0, 0, 0, 1, 3, 3, + 3, 0 }; -static const char _thttp_machine_parser_url_index_offsets[] = { +static const short _thttp_machine_parser_url_index_offsets[] = { 0, 0, 3, 6, 9, 12, 16, 18, - 19, 20 + 20, 25, 31, 36, 42, 46, 51, 53, + 57, 63, 67, 73, 77, 83, 89, 95, + 101, 107, 113, 118, 124, 130, 136, 139, + 144, 151, 153, 156, 158, 161, 163, 166, + 169, 171, 174, 176, 179, 181, 188, 195, + 201, 207, 213, 219, 222, 226, 233, 240, + 247, 249, 252, 255, 257, 259, 261, 263, + 271, 277, 279, 281, 282, 283, 286, 294, + 302, 310 +}; + +static const char _thttp_machine_parser_url_indicies[] = { + 0, 0, 1, 2, 2, 1, 3, 3, + 1, 4, 4, 1, 5, 6, 6, 1, + 7, 1, 8, 1, 11, 9, 10, 10, + 1, 12, 13, 14, 15, 15, 1, 12, + 15, 15, 15, 1, 12, 16, 15, 15, + 15, 1, 15, 17, 17, 1, 18, 17, + 17, 17, 1, 19, 1, 20, 17, 17, + 1, 12, 21, 22, 15, 15, 1, 23, + 17, 17, 1, 12, 24, 25, 15, 15, + 1, 26, 17, 17, 1, 12, 24, 27, + 15, 15, 1, 12, 24, 15, 15, 15, + 1, 12, 21, 28, 15, 15, 1, 12, + 21, 15, 15, 15, 1, 12, 13, 29, + 15, 15, 1, 12, 13, 15, 15, 15, + 1, 31, 30, 30, 30, 1, 33, 34, + 32, 32, 32, 1, 33, 34, 35, 35, + 35, 1, 33, 34, 36, 36, 36, 1, + 33, 34, 1, 38, 37, 30, 30, 1, + 39, 33, 34, 40, 32, 32, 1, 41, + 1, 42, 43, 1, 44, 1, 45, 46, + 1, 47, 1, 34, 48, 1, 34, 49, + 1, 34, 1, 45, 50, 1, 45, 1, + 42, 51, 1, 42, 1, 39, 33, 34, + 52, 35, 35, 1, 39, 33, 34, 36, + 36, 36, 1, 54, 34, 53, 53, 53, + 1, 56, 34, 55, 55, 55, 1, 56, + 34, 57, 57, 57, 1, 56, 34, 58, + 58, 58, 1, 56, 34, 1, 59, 53, + 53, 1, 39, 56, 34, 60, 55, 55, + 1, 39, 56, 34, 61, 57, 57, 1, + 39, 56, 34, 58, 58, 58, 1, 62, + 1, 39, 63, 1, 39, 64, 1, 39, + 1, 38, 1, 65, 1, 66, 1, 18, + 67, 68, 69, 17, 17, 17, 1, 68, + 69, 15, 17, 17, 1, 71, 70, 73, + 72, 74, 75, 76, 77, 1, 12, 16, + 68, 69, 78, 15, 15, 1, 12, 16, + 68, 69, 79, 15, 15, 1, 12, 16, + 68, 69, 15, 15, 15, 1, 68, 69, + 1, 0 }; static const char _thttp_machine_parser_url_trans_targs[] = { - 2, 2, 0, 3, 3, 0, 4, 4, - 0, 5, 5, 0, 7, 6, 6, 0, - 9, 0, 8, 8, 8, 0 + 2, 0, 3, 4, 5, 6, 61, 7, + 8, 9, 63, 26, 10, 15, 24, 11, + 12, 63, 13, 69, 16, 17, 22, 18, + 19, 20, 70, 21, 23, 25, 27, 60, + 28, 31, 73, 29, 30, 32, 47, 33, + 45, 34, 35, 43, 36, 37, 41, 38, + 39, 40, 42, 44, 46, 48, 56, 49, + 52, 50, 51, 53, 54, 55, 57, 58, + 59, 62, 7, 64, 65, 14, 66, 67, + 66, 67, 68, 68, 65, 69, 71, 72 }; static const char _thttp_machine_parser_url_trans_actions[] = { - 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, - 7, 0, 9, 7, 12, 0 + 1, 0, 0, 0, 0, 0, 0, 3, + 0, 38, 42, 17, 0, 0, 0, 0, + 0, 15, 0, 26, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 15, 29, 7, 26, 46, + 15, 35, 26, 15, 32, 15, 15, 15 }; static const char _thttp_machine_parser_url_eof_actions[] = { - 0, 0, 0, 0, 0, 0, 0, 3, - 0, 5 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, + 7, 20, 11, 23, 13, 9, 7, 7, + 7, 7 }; static const int thttp_machine_parser_url_start = 1; -static const int thttp_machine_parser_url_first_final = 7; +static const int thttp_machine_parser_url_first_final = 63; static const int thttp_machine_parser_url_error = 0; static const int thttp_machine_parser_url_en_main = 1; -/* #line 93 "thttp_parser_url.rl" */ +/* #line 123 "thttp_parser_url.rl" */ -/* #line 134 "../src/parsers/thttp_parser_url.c" */ +/* #line 282 "../src/parsers/thttp_parser_url.c" */ { cs = thttp_machine_parser_url_start; } -/* #line 94 "thttp_parser_url.rl" */ +/* #line 124 "thttp_parser_url.rl" */ -/* #line 141 "../src/parsers/thttp_parser_url.c" */ +/* #line 289 "../src/parsers/thttp_parser_url.c" */ { int _klen; unsigned int _trans; @@ -199,6 +347,7 @@ _resume: } _match: + _trans = _thttp_machine_parser_url_indicies[_trans]; cs = _thttp_machine_parser_url_trans_targs[_trans]; if ( _thttp_machine_parser_url_trans_actions[_trans] == 0 ) @@ -226,10 +375,41 @@ _match: break; case 3: /* #line 58 "thttp_parser_url.rl" */ + { url->host_type = url->host_type = host_ipv4; } + break; + case 4: +/* #line 59 "thttp_parser_url.rl" */ + { url->host_type = url->host_type = host_ipv6; } + break; + case 5: +/* #line 60 "thttp_parser_url.rl" */ + { url->host_type = url->host_type = host_hostname; } + break; + case 6: +/* #line 62 "thttp_parser_url.rl" */ + { + TSK_PARSER_SET_STRING(url->host); + } + break; + case 7: +/* #line 66 "thttp_parser_url.rl" */ + { + have_port = 1; + TSK_PARSER_SET_INT(url->port); + } + break; + case 8: +/* #line 71 "thttp_parser_url.rl" */ + { + TSK_PARSER_SET_STRING(url->hpath); + } + break; + case 10: +/* #line 79 "thttp_parser_url.rl" */ { } break; -/* #line 233 "../src/parsers/thttp_parser_url.c" */ +/* #line 413 "../src/parsers/thttp_parser_url.c" */ } } @@ -245,15 +425,38 @@ _again: unsigned int __nacts = (unsigned int) *__acts++; while ( __nacts-- > 0 ) { switch ( *__acts++ ) { - case 1: -/* #line 54 "thttp_parser_url.rl" */ - { url->scheme = tsk_strdup("http"), url->type = url_http; } + case 0: +/* #line 49 "thttp_parser_url.rl" */ + { + tag_start = p; + } break; - case 2: -/* #line 55 "thttp_parser_url.rl" */ - { url->scheme = tsk_strdup("https"), url->type = url_https; } + case 6: +/* #line 62 "thttp_parser_url.rl" */ + { + TSK_PARSER_SET_STRING(url->host); + } break; -/* #line 257 "../src/parsers/thttp_parser_url.c" */ + case 7: +/* #line 66 "thttp_parser_url.rl" */ + { + have_port = 1; + TSK_PARSER_SET_INT(url->port); + } + break; + case 8: +/* #line 71 "thttp_parser_url.rl" */ + { + TSK_PARSER_SET_STRING(url->hpath); + } + break; + case 9: +/* #line 75 "thttp_parser_url.rl" */ + { + TSK_PARSER_SET_STRING(url->search); + } + break; +/* #line 460 "../src/parsers/thttp_parser_url.c" */ } } } @@ -261,17 +464,24 @@ _again: _out: {} } -/* #line 95 "thttp_parser_url.rl" */ +/* #line 125 "thttp_parser_url.rl" */ if( cs < -/* #line 268 "../src/parsers/thttp_parser_url.c" */ -7 -/* #line 96 "thttp_parser_url.rl" */ - ) - { +/* #line 471 "../src/parsers/thttp_parser_url.c" */ +63 +/* #line 126 "thttp_parser_url.rl" */ + ){ TSK_DEBUG_ERROR("Failed to parse HTTP/HTTPS URL."); TSK_OBJECT_SAFE_FREE(url); } + else if(!have_port){ + if(url->type == url_https){ + url->port = 443; + } + else{ + url->port = 80; + } + } return url; -} +} \ No newline at end of file diff --git a/trunk/tinyHTTP/src/thttp.c b/trunk/tinyHTTP/src/thttp.c index b48c24b0..ee3c2d8d 100644 --- a/trunk/tinyHTTP/src/thttp.c +++ b/trunk/tinyHTTP/src/thttp.c @@ -28,6 +28,7 @@ */ #include "thttp.h" #include "tinyHTTP/thttp_event.h" +#include "tinyHTTP/thttp_message.h" #include "tnet.h" #include "tnet_transport.h" @@ -35,6 +36,9 @@ #include "tsk_runnable.h" #include "tsk_time.h" #include "tsk_debug.h" +#include "tsk_memory.h" +#include "tsk_string.h" +#include "tsk_fsm.h" //#include //#include @@ -51,12 +55,14 @@ // KeepAlive : http://www.io.com/~maus/HttpKeepAlive.html static unsigned __thttp_initialized = 0; -static void *run(void* self); typedef struct thttp_stack_s { TSK_DECLARE_OBJECT; + thttp_stack_callback callback; + tsk_fsm_t *fsm; + /* Identity */ char* username; char* password; @@ -70,10 +76,6 @@ typedef struct thttp_stack_s char* local_ip; int local_port; tnet_transport_t *transport; - - - - unsigned running; } thttp_stack_t; @@ -122,8 +124,19 @@ int __thttp_stack_set(thttp_stack_t *self, va_list values) break; } + + + default: + { + TSK_DEBUG_WARN("Found unknown pname."); + goto bail; + } + }/* switch */ }/* while */ + +bail: + return 0; } int thttp_global_init() @@ -151,39 +164,116 @@ int thttp_global_deinit() return -1; } -thttp_stack_handle_t *thttp_stack_create(thttp_stack_callback callback, ...) +thttp_stack_handle_t *thttp_stack_create(thttp_stack_callback callback, int tls, ...) { + thttp_stack_t* stack = tsk_object_new(thttp_stack_def_t); + va_list params; + if(!stack){ + return 0; + } + stack->local_ip = TNET_SOCKET_HOST_ANY; + stack->local_port = TNET_SOCKET_PORT_ANY; + + stack->callback = callback; + va_start(params, tls); + if(__thttp_stack_set(stack, params)){ + // Delete the stack? + } + va_end(params); + + stack->transport = TNET_TRANSPORT_CREATE(stack->local_ip, stack->local_port, + tls?tnet_socket_type_tls_ipv4:tnet_socket_type_tcp_ipv4, "HTTP/HTTPS transport"); + + return stack; } int thttp_stack_start(thttp_stack_handle_t *self) { + thttp_stack_t *stack = self; + if(!stack){ + return -1; + } + return tnet_transport_start(stack->transport); } int thttp_stack_set(thttp_stack_handle_t *self, ...) { + if(self){ + int ret; + thttp_stack_t *stack = self; + + va_list params; + va_start(params, self); + ret = __thttp_stack_set(stack, params); + va_end(params); + return ret; + } + + return -1; +} +int thttp_stack_send(thttp_stack_handle_t *self, thttp_operation_handle_t* op, const thttp_message_t* message) +{ + int ret = -1; + tsk_buffer_t* output = TSK_BUFFER_CREATE_NULL(); + tnet_socket_type_t type; + thttp_stack_t *stack; + tnet_fd_t fd; + + if(!self || !op || !message->url){ /* Only requests are supported for now. */ + goto bail; + } + + stack = self; + type = tnet_transport_get_type(stack->transport); + + /* Serialize the message and send it */ + if((ret = thttp_message_tostring(message, output))){ + goto bail; + } + else{ + if(message->url->type == url_https){ + TNET_SOCKET_TYPE_SET_TLS(type); + } + else{ + TNET_SOCKET_TYPE_SET_TCP(type); + } + } + + /* Gets the fd associated to this operation */ + fd = thttp_operation_get_fd(op); + + if(fd == TNET_INVALID_FD){ + if((fd = tnet_transport_connectto(stack->transport, message->url->host, message->url->port, type)) == TNET_INVALID_FD){ + goto bail; + } + else{ + thttp_operation_set_fd(op, fd); + } + } + + if(tnet_transport_send(stack->transport, fd, output->data, output->size)){ + ret = 0; + } + else{ + ret = -15; + } + +bail: + TSK_OBJECT_SAFE_FREE(output); + return ret; } int thttp_stack_stop(thttp_stack_handle_t *self) { + thttp_stack_t *stack = self; -} - - -int thttp_stack_start(thttp_stack_handle_t *self) -{ - if(self) - { - int ret; - thttp_stack_t *stack = self; - - TSK_RUNNABLE(stack)->run = run; - if(ret = tsk_runnable_start(TSK_RUNNABLE(stack), thttp_event_def_t)){ - return ret; - } - } + if(!stack){ + return -1; + } + return tnet_transport_start(stack->transport); } @@ -211,3 +301,43 @@ int thttp_stack_start(thttp_stack_handle_t *self) +//======================================================== +// HTTP stack object definition +// +static void* _thttp_stack_create(void * self, va_list * app) +{ + thttp_stack_t *stack = self; + if(stack){ + } + return self; +} + +static void* thttp_stack_destroy(void * self) +{ + thttp_stack_t *stack = self; + if(stack){ + TSK_OBJECT_SAFE_FREE(stack->fsm); + + /* Identity */ + TSK_FREE(stack->username); + TSK_FREE(stack->password); + TSK_FREE(stack->proxy_host); + TSK_FREE(stack->proxy_username); + TSK_FREE(stack->proxy_password); + TSK_FREE(stack->user_agent); + + /* Network */ + TSK_FREE(stack->local_ip); + TSK_OBJECT_SAFE_FREE(stack->transport); + } + return self; +} + +static const tsk_object_def_t thttp_stack_def_s = +{ + sizeof(thttp_stack_t), + _thttp_stack_create, + thttp_stack_destroy, + 0, +}; +const void *thttp_stack_def_t = &thttp_stack_def_s; \ No newline at end of file diff --git a/trunk/tinyHTTP/src/thttp_message.c b/trunk/tinyHTTP/src/thttp_message.c index 210de871..83b4ac83 100644 --- a/trunk/tinyHTTP/src/thttp_message.c +++ b/trunk/tinyHTTP/src/thttp_message.c @@ -30,17 +30,227 @@ */ #include "tinyHTTP/thttp_message.h" +#include "tsk_debug.h" + +static int pred_find_string_by_value(const tsk_list_item_t *item, const void *stringVal) +{ + if(item && item->data) + { + tsk_string_t *string = item->data; + return tsk_stricmp(string->value, stringVal); + } + return -1; +} + +/*== Predicate function to find thttp_header_t object by type. */ +static int pred_find_header_by_type(const tsk_list_item_t *item, const void *thttp_htype) +{ + if(item && item->data) + { + thttp_header_t *header = item->data; + thttp_header_type_t htype = *((thttp_header_type_t*)thttp_htype); + return (header->type - htype); + } + return -1; +} + +/*== Predicate function to find thttp_header_t object by name. */ +static int pred_find_header_by_name(const tsk_list_item_t *item, const void *name) +{ + if(item && item->data) + { + thttp_header_t *header = item->data; + return tsk_stricmp(thttp_header_get_nameex(header), name); + } + return -1; +} int thttp_message_add_header(thttp_message_t *self, const thttp_header_t *hdr) { + #define ADD_HEADER(type, field) \ + case thttp_htype_##type: \ + { \ + if(!self->field) \ + { \ + self->field = (thttp_header_##type##_t*)header; \ + return 0; \ + } \ + break; \ + } + + if(self && hdr) + { + thttp_header_t *header = tsk_object_ref((void*)hdr); + + switch(header->type) + { + ADD_HEADER(Content_Type, Content_Type); + ADD_HEADER(Content_Length, Content_Length); + + default: break; + } + + tsk_list_push_back_data(self->headers, (void**)&header); + + return 0; + } return -1; } -uint32_t thttp_message_getContent_length(const thttp_message_t *message) +int thttp_message_add_headers(thttp_message_t *self, const thttp_headers_L_t *headers) { + tsk_list_item_t *item = 0; + if(self) + { + tsk_list_foreach(item, headers){ + thttp_message_add_header(self, item->data); + } + return 0; + } + return -1; +} + +int thttp_message_add_content(thttp_message_t *self, const char* content_type, const void* content, size_t size) +{ + if(self) + { + if(content_type){ + TSK_OBJECT_SAFE_FREE(self->Content_Type); + } + TSK_OBJECT_SAFE_FREE(self->Content_Length); + TSK_OBJECT_SAFE_FREE(self->Content); + + if(content_type){ + THTTP_MESSAGE_ADD_HEADER(self, THTTP_HEADER_CONTENT_TYPE_VA_ARGS(content_type)); + } + THTTP_MESSAGE_ADD_HEADER(self, THTTP_HEADER_CONTENT_LENGTH_VA_ARGS(size)); + self->Content = TSK_BUFFER_CREATE(content, size); + + return 0; + } + return -1; +} + +const thttp_header_t *thttp_message_get_headerAt(const thttp_message_t *self, thttp_header_type_t type, size_t index) +{ + size_t pos = 0; + tsk_list_item_t *item; + const thttp_header_t* hdr = 0; + + if(self) + { + switch(type) + { + case thttp_htype_Content_Type: + if(index == 0){ + hdr = (const thttp_header_t*)self->Content_Type; + goto bail; + }else pos++; break; + case thttp_htype_Content_Length: + if(index == 0){ + hdr = (const thttp_header_t*)self->Content_Length; + goto bail; + }else pos++; break; + default: + break; + } + + tsk_list_foreach(item, self->headers) + { + if(!pred_find_header_by_type(item, &type)) + { + if(pos++ >= index) + { + hdr = item->data; + break; + } + } + } + } + +bail: + return hdr; +} + +const thttp_header_t *thttp_message_get_header(const thttp_message_t *self, thttp_header_type_t type) +{ + return thttp_message_get_headerAt(self, type, 0); +} + +int thttp_message_tostring(const thttp_message_t *self, tsk_buffer_t *output) +{ + if(!self){ + return -1; + } + + if(THTTP_MESSAGE_IS_REQUEST(self)){ + /*Method SP Request-URI SP HTTP-Version CRLF*/ + /* Method */ + tsk_buffer_appendEx(output, "%s ", self->method); + /* Request URI */ + thttp_url_serialize(self->url, output); + /* HTTP VERSION */ + tsk_buffer_appendEx(output, " %s\r\n", THTTP_MESSAGE_VERSION_DEFAULT); + } + else{ + /*HTTP-Version SP Status-Code SP Reason-Phrase CRLF*/ + tsk_buffer_appendEx(output, "%s %hi %s\r\n", THTTP_MESSAGE_VERSION_DEFAULT, THTTP_RESPONSE_CODE(self), THTTP_RESPONSE_PHRASE(self)); + } + + /* Content-Type */ + if(self->Content_Type){ + thttp_header_tostring(THTTP_HEADER(self->Content_Type), output); + } + /* Content-Length*/ + if(self->Content_Length){ + thttp_header_tostring(THTTP_HEADER(self->Content_Length), output); + } + + /* All other headers */ + { + tsk_list_item_t *item; + tsk_list_foreach(item, self->headers) + { + thttp_header_t *hdr = item->data; + thttp_header_tostring(hdr, output); + } + } + + /* EMPTY LINE */ + tsk_buffer_append(output, "\r\n", 2); + + /* CONTENT */ + if(THTTP_MESSAGE_HAS_CONTENT(self)){ + tsk_buffer_append(output, TSK_BUFFER_TO_STRING(self->Content), TSK_BUFFER_SIZE(self->Content)); + } + return 0; } +thttp_request_t *thttp_request_new(const char* method, const thttp_url_t *request_url) +{ + thttp_request_t* request = 0; + + if((request = THTTP_REQUEST_CREATE(method, request_url))){ + THTTP_MESSAGE_ADD_HEADER(request, THTTP_HEADER_CONTENT_LENGTH_VA_ARGS(0)); + } + return request; +} + +thttp_response_t *thttp_response_new(short status_code, const char* reason_phrase, const thttp_request_t *request) +{ + thttp_response_t *response = 0; + + if(request){ + response = THTTP_RESPONSE_CREATE(request, status_code, reason_phrase); + THTTP_MESSAGE_ADD_HEADER(response, THTTP_HEADER_CONTENT_LENGTH_VA_ARGS(0)); + /* + Copy other headers + */ + } + + return response; +} @@ -50,42 +260,90 @@ uint32_t thttp_message_getContent_length(const thttp_message_t *message) - - - - -//================================================================================================= -// THTTP mesage object definition +//======================================================== +// HTTP message object definition // -static void* thttp_message_create(void * self, va_list * app) + +/**@ingroup thttp_message_group +*/ +static void* thttp_message_create(void *self, va_list * app) { thttp_message_t *message = self; if(message) { + message->type = va_arg(*app, thttp_message_type_t); + message->headers = TSK_LIST_CREATE(); + + switch(message->type) + { + case thttp_unknown: + { + break; + } + + 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*)); + break; + } + + case thttp_response: + { + const thttp_request_t* request = va_arg(*app, const thttp_request_t*); +#if defined(__GNUC__) + message->status_code = (short)va_arg(*app, int); +#else + message->status_code = va_arg(*app, short); +#endif + message->reason_phrase = tsk_strdup(va_arg(*app, const char*)); + break; + } + } + } + else + { + TSK_DEBUG_ERROR("Failed to create new http message."); } return self; } -static void* thttp_message_destroy(void * self) -{ +/**@ingroup thttp_message_group +*/ +static void* thttp_message_destroy(void *self) +{ thttp_message_t *message = self; if(message) { + if(THTTP_MESSAGE_IS_REQUEST(message)) + { + TSK_FREE(message->method); + TSK_OBJECT_SAFE_FREE(message->url); + } + else if(THTTP_MESSAGE_IS_RESPONSE(message)) + { + TSK_FREE(message->reason_phrase); + } + + TSK_FREE(message->http_version); + + TSK_OBJECT_SAFE_FREE(message->Content_Length); + TSK_OBJECT_SAFE_FREE(message->Content_Type); + + TSK_OBJECT_SAFE_FREE(message->Content); + + TSK_OBJECT_SAFE_FREE(message->headers); } + else TSK_DEBUG_ERROR("Null HTTP message."); return self; } -static int thttp_message_cmp(const void *obj1, const void *obj2) -{ - return -1; -} - static const tsk_object_def_t thttp_message_def_s = { sizeof(thttp_message_t), - thttp_message_create, + thttp_message_create, thttp_message_destroy, - thttp_message_cmp, + 0 }; -const void *thttp_message_def_t = &thttp_message_def_s; +const void *thttp_message_def_t = &thttp_message_def_s; \ No newline at end of file diff --git a/trunk/tinyHTTP/src/thttp_operation.c b/trunk/tinyHTTP/src/thttp_operation.c index 3095fad8..eca88a1f 100644 --- a/trunk/tinyHTTP/src/thttp_operation.c +++ b/trunk/tinyHTTP/src/thttp_operation.c @@ -27,4 +27,263 @@ * * @date Created: Sat Nov 8 16:54:58 2009 mdiop */ -#include "tinyHTTP/thttp_operation.h" \ No newline at end of file +#include "tinyHTTP/thttp_operation.h" +#include "thttp.h" + +#include "tinyHTTP/thttp_message.h" +#include "tinyHTTP/parsers/thttp_parser_url.h" + +#include "tinyHTTP/headers/thttp_header_Dummy.h" + +#include "tnet_utils.h" + +#include "tsk_debug.h" + +typedef struct thttp_operation_s +{ + TSK_DECLARE_OBJECT; + + thttp_operation_id_t id; + const thttp_stack_handle_t* stack; + tsk_params_L_t *params; + tsk_params_L_t *headers; + + tnet_fd_t fd; +} +thttp_operation_t; + + +int __thttp_operation_set(thttp_operation_t *self, va_list values) +{ + thttp_operation_param_type_t curr; + + if(!self){ + return -1; + } + + while((curr=va_arg(values, thttp_operation_param_type_t)) != optype_null) + { + switch(curr) + { + case optype_param: + case optype_header: + { + const char* name = va_arg(values, const char *); + const char* value = va_arg(values, const char *); + + if(curr == optype_param){ + tsk_params_add_param(&self->params, name, value); + } else if(curr == optype_header){ + tsk_params_add_param(&self->headers, name, value); + } + break; + } + + default: + { + TSK_DEBUG_ERROR("NOT SUPPORTED."); + goto bail; + } + } + } + +bail: + return 0; +} + +int thttp_operation_set(thttp_operation_handle_t *self, ...) +{ + if(self){ + int ret; + va_list params; + + thttp_operation_t *operation = self; + + if(operation->id == THTTP_OPERATION_INVALID_ID){ + return -2; + } + + va_start(params, self); + ret = __thttp_operation_set(operation, params); + va_end(params); + return ret; + } + + return -1; +} + +thttp_operation_id_t thttp_operation_get_id(const thttp_operation_handle_t *self) +{ + if(self){ + const thttp_operation_t *operation = self; + return operation->id; + } + return THTTP_OPERATION_INVALID_ID; +} + +const tsk_param_t* thttp_operation_get_param(const thttp_operation_handle_t *self, const char* pname) +{ + if(self){ + const thttp_operation_t *operation = self; + return tsk_params_get_param_by_name(operation->params, pname); + } + return THTTP_NULL; +} + +const tsk_param_t* thttp_operation_get_header(const thttp_operation_handle_t *self, const char* hname) +{ + if(self){ + const thttp_operation_t *operation = self; + return tsk_params_get_param_by_name(operation->headers, hname); + } + return THTTP_NULL; +} + +const tsk_params_L_t* thttp_operation_get_headers(const thttp_operation_handle_t *self) +{ + if(self){ + return ((const thttp_operation_t *)self)->headers; + } + return THTTP_NULL; +} + +const tsk_params_L_t* thttp_operation_get_params(const thttp_operation_handle_t *self) +{ + if(self){ + return ((const thttp_operation_t *)self)->params; + } + return THTTP_NULL; +} + +tnet_fd_t thttp_operation_get_fd(const thttp_operation_handle_t *self) +{ + if(self){ + return ((const thttp_operation_t *)self)->fd; + } + return TNET_INVALID_FD; +} + +int thttp_operation_set_fd(thttp_operation_handle_t *self, tnet_fd_t fd) +{ + thttp_operation_t* op; + + if(self){ + op = self; + if(op->fd != TNET_INVALID_FD){ + tnet_sockfd_close(&op->fd); + } + op->fd = fd; + } + return -1; +} + +int thttp_operation_perform(thttp_operation_handle_t* self) +{ + int ret = -1; + thttp_operation_t* op; + thttp_message_t* message = 0; + const tsk_param_t* param; + const tsk_list_item_t* item; + + if(!self){ + goto bail; + } + + op = self; + if((param = tsk_params_get_param_by_name(op->params, "method")) && param->value){ /* REQUEST */ + const char* method = param->value; + thttp_url_t* url = 0; + if((param = tsk_params_get_param_by_name(op->params, "URI")) && param->value && (url = thttp_url_parse(param->value, strlen(param->value)))){ + message = THTTP_REQUEST_CREATE(method, url); + TSK_OBJECT_SAFE_FREE(url); + } + else{ + TSK_DEBUG_ERROR("MUST supply a valid URI."); + ret = -2; + goto bail; + } + } + else{ /* RESPONSE */ + } + + if(!message || !message->url){ /* Only requests are supported in this version. */ + goto bail; + } + + /* Add headers associated to the operation. */ + tsk_list_foreach(item, op->headers) + { + param = (const tsk_param_t*)item->data; + if(!param->tag){ + THTTP_MESSAGE_ADD_HEADER(message, THTTP_HEADER_DUMMY_VA_ARGS(param->name, param->value)); + } + } + + /* Sends the message. */ + ret = thttp_stack_send((thttp_stack_handle_t*)op->stack, op, message); + +bail: + TSK_OBJECT_SAFE_FREE(message); + return ret; +} + + + + + +//======================================================== +// HTTP Operation object definition +// +static void* thttp_operation_create(void * self, va_list * app) +{ + thttp_operation_t *operation = self; + static thttp_operation_id_t unique_id = 0; + if(operation) + { + operation->stack = va_arg(*app, const thttp_stack_handle_t*); + operation->params = TSK_LIST_CREATE(); + operation->headers = TSK_LIST_CREATE(); + operation->fd = TNET_INVALID_FD; + + if(__thttp_operation_set(self, *app)){ + operation->id = THTTP_OPERATION_INVALID_ID; + } + else{ + operation->id = ++unique_id; + } + } + + return self; +} + +static void* thttp_operation_destroy(void * self) +{ + thttp_operation_t *operation = self; + if(operation){ + TSK_OBJECT_SAFE_FREE(operation->params); + TSK_OBJECT_SAFE_FREE(operation->headers); + + tnet_sockfd_close(&operation->fd); + } + return self; +} + +static int thttp_operation_cmp(const void *obj1, const void *obj2) +{ + const thttp_operation_t *operation1 = obj1; + const thttp_operation_t *operation2 = obj2; + + if(operation1 && operation2){ + return (int)(operation1->id-operation2->id); + } + return -1; +} + +static const tsk_object_def_t thttp_operation_def_s = +{ + sizeof(thttp_operation_t), + thttp_operation_create, + thttp_operation_destroy, + thttp_operation_cmp, +}; +const void *thttp_operation_def_t = &thttp_operation_def_s; \ No newline at end of file diff --git a/trunk/tinyHTTP/src/thttp_url.c b/trunk/tinyHTTP/src/thttp_url.c index a00ef622..c64d4478 100644 --- a/trunk/tinyHTTP/src/thttp_url.c +++ b/trunk/tinyHTTP/src/thttp_url.c @@ -40,24 +40,48 @@ /**@defgroup thttp_url_group HTTP URL. */ -int __thttp_url_serialize(const thttp_url_t *url, tsk_buffer_t *output) -{ - return 0; -} - int thttp_url_serialize(const thttp_url_t *url, tsk_buffer_t *output) { - return -1; + /* RFC 1738: "http://" hostport [ "/" hpath [ "?" search ]] */ + return tsk_buffer_appendEx(output, "%s://%s:%u%s%s%s%s", + + url->scheme, + url->host, + url->port, + + url->hpath ? "/" : "", + url->hpath ? url->hpath : "", + + url->search ? "?" : "", + url->search ? url->search : "" + ); } char* thttp_url_tostring(const thttp_url_t *url) { - return 0; + tsk_buffer_t *output = TSK_BUFFER_CREATE_NULL(); + char* ret = 0; + + if(!thttp_url_serialize(url, output)){ + ret = tsk_strndup((const char*)output->data, output->size); + } + else{ + TSK_DEBUG_ERROR("Failed to serialize HTTP URL."); + } + + TSK_OBJECT_SAFE_FREE(output); + return ret; } thttp_url_t *thttp_url_clone(const thttp_url_t *url) { - return 0; + thttp_url_t *newurl = 0; + tsk_buffer_t *output = TSK_BUFFER_CREATE_NULL(); + thttp_url_serialize(url, output); + newurl = thttp_url_parse(output->data, output->size); + TSK_OBJECT_SAFE_FREE(output); + + return newurl; } @@ -76,12 +100,16 @@ thttp_url_t *thttp_url_clone(const thttp_url_t *url) static void* thttp_url_create(void *self, va_list * app) { thttp_url_t *url = self; - if(url) - { + if(url){ url->type = va_arg(*app, thttp_url_type_t); + if(url->type == url_https){ + url->port = 443; + } + else{ + url->port = 80; + } } - else - { + else{ TSK_DEBUG_ERROR("Failed to create new SIP/SIPS/TEL."); } return self; @@ -96,7 +124,8 @@ static void* thttp_url_destroy(void *self) { TSK_FREE(url->scheme); TSK_FREE(url->host); - TSK_FREE(url->password); + TSK_FREE(url->hpath); + TSK_FREE(url->search); } else TSK_DEBUG_ERROR("Null HTTP/HTTPS URL."); diff --git a/trunk/tinyHTTP/test/test.c b/trunk/tinyHTTP/test/test.c index e07b3cd2..15f9c601 100644 --- a/trunk/tinyHTTP/test/test.c +++ b/trunk/tinyHTTP/test/test.c @@ -27,6 +27,7 @@ #include "tsk.h" #include "thttp.h" +#include "tinyHTTP/thttp_operation.h" #include "tinyHTTP/auth/thttp_auth.h" #define LOOP 1 @@ -34,9 +35,11 @@ #define RUN_TEST_ALL 0 #define RUN_TEST_AUTH 0 #define RUN_TEST_STACK 1 +#define RUN_TEST_URL 0 #include "test_auth.h" #include "test_stack.h" +#include "test_url.h" #ifdef _WIN32_WCE @@ -63,6 +66,9 @@ int main() test_stack(); #endif +#if RUN_TEST_URL || RUN_TEST_ALL + test_url(); +#endif } thttp_global_deinit(); diff --git a/trunk/tinyHTTP/test/test_stack.h b/trunk/tinyHTTP/test/test_stack.h index 53cca422..1664f5f7 100644 --- a/trunk/tinyHTTP/test/test_stack.h +++ b/trunk/tinyHTTP/test/test_stack.h @@ -22,9 +22,36 @@ #ifndef _TEST_STACK_H_ #define _TEST_STACK_H_ +int test_stack_callback(const thttp_event_t *httpevent) +{ + return 0; +} + void test_stack() { + thttp_operation_handle_t *op = 0; + thttp_stack_handle_t* stack = thttp_stack_create(test_stack_callback, 0, + THTTP_STACK_SET_NULL()); + if(thttp_stack_start(stack)){ + goto bail; + } + + op = THTTP_OPERATION_CREATE(stack, + THTTP_OPERATION_SET_PARAM("method", "GET"), + THTTP_OPERATION_SET_PARAM("URI", "http://www.google.com"), + + THTTP_OPERATION_SET_HEADER("User-Agent", "IM-client/OMA1.0 doubango/v0.0.0"), + THTTP_OPERATION_SET_HEADER("X-XCAP-Asserted-Identity", "sip:mamadou@ericsson.com"), + + THTTP_OPERATION_SET_NULL()); + + thttp_operation_perform(op); + + + getchar(); +bail: + TSK_OBJECT_SAFE_FREE(stack); } #endif /* _TEST_STACK_H_ */ diff --git a/trunk/tinyHTTP/test/test_url.h b/trunk/tinyHTTP/test/test_url.h new file mode 100644 index 00000000..a2d68057 --- /dev/null +++ b/trunk/tinyHTTP/test/test_url.h @@ -0,0 +1,94 @@ +/* +* Copyright (C) 2009 Mamadou Diop. +* +* Contact: Mamadou Diop +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +#ifndef _TEST_HTTPURL_H +#define _TEST_HTTPURL_H + +#include "tinyhttp/parsers/thttp_parser_url.h" + +const char* urls[] = +{ + + //== HTTP: + "http://www.doubango.org", + "http://www.doubango.org/?p=1", + "http://doubango.org:452/test", + "http://doubango.org:45/test?p=452", + + //== HTTPS: + "https://www.doubango.org", + "https://www.doubango.org/?p=1", + "https://doubango.org:452/test", + "https://doubango.org:45/test?p=452", +}; +#include "tsk_string.h" + +void test_url_tostring(const thttp_url_t *url) +{ + char* ret = thttp_url_tostring(url); + TSK_DEBUG_INFO("url_to_string=%s", ret); + TSK_FREE(ret); +} + +void test_url_parser() +{ + int i; + tsk_list_item_t *item = 0; + + for(i=0; ischeme); + printf("host: %s\n", url->host); + printf("port: %u\n", url->port); + printf("hpath: %s\n", url->hpath); + printf("search: %s\n", url->search); + printf("host-type: %s\n", url->host_type == host_ipv4 ? "IPv4" : (url->host_type == host_ipv6 ? "IPv6" : (url->host_type == host_hostname ? "HOSTNAME" : "UNKNOWN")) ); + + printf("---PARAMS---\n"); + + printf("Is-secure: %s\n", THTTP_URL_IS_SECURE(url) ? "YES" : "NO"); + + test_url_tostring(url); + } + else + { + printf("INVALID HTTP URL.\n"); + } + + printf("\n\n"); + getchar(); + + TSK_OBJECT_SAFE_FREE(url); + } +} + +void test_url() +{ + test_url_parser(); +} + +#endif /* _TEST_HTTPURL_H */ diff --git a/trunk/tinySIP/include/tinysip/headers/tsip_header.h b/trunk/tinySIP/include/tinysip/headers/tsip_header.h index 96f58fe7..3503270f 100644 --- a/trunk/tinySIP/include/tinysip/headers/tsip_header.h +++ b/trunk/tinySIP/include/tinysip/headers/tsip_header.h @@ -169,6 +169,7 @@ typedef tsk_list_t tsip_headers_L_t; /**< List of @ref tsip_header_t elements. * ================================*/ TINYSIP_API const char *tsip_header_get_name(tsip_header_type_t type); +TINYSIP_API const char *tsip_header_get_nameex(const tsip_header_t *self); TINYSIP_API char tsip_header_get_param_separator(const tsip_header_t *self); TINYSIP_API int tsip_header_tostring(const tsip_header_t *self, tsk_buffer_t *output); diff --git a/trunk/tinySIP/include/tinysip/headers/tsip_header_Dummy.h b/trunk/tinySIP/include/tinysip/headers/tsip_header_Dummy.h index 9c58060d..a7422b7a 100644 --- a/trunk/tinySIP/include/tinysip/headers/tsip_header_Dummy.h +++ b/trunk/tinySIP/include/tinysip/headers/tsip_header_Dummy.h @@ -47,8 +47,6 @@ TSIP_BEGIN_DECLS /// @struct /// /// @brief SIP Dummy header. -/// @author Mamadou -/// @date 12/3/2009 /// /// @par ABNF : token SP* HCOLON SP*<: any* /// diff --git a/trunk/tinySIP/ragel/tsip_parser_message.rl b/trunk/tinySIP/ragel/tsip_parser_message.rl index bc827991..a2797575 100644 --- a/trunk/tinySIP/ragel/tsip_parser_message.rl +++ b/trunk/tinySIP/ragel/tsip_parser_message.rl @@ -253,7 +253,7 @@ static void tsip_message_parser_eoh(tsk_ragel_state_t *state, tsip_message_t *me if(extract_content && message) { - uint32_t clen = tsip_message_getContent_length(message); + uint32_t clen = TSIP_MESSAGE_CONTENT_LENGTH(message); if((p+clen) Content) { message->Content = TSK_BUFFER_CREATE((p+1), clen); diff --git a/trunk/tinySIP/src/headers/tsip_header.c b/trunk/tinySIP/src/headers/tsip_header.c index f1d7b6fe..ca7177e1 100644 --- a/trunk/tinySIP/src/headers/tsip_header.c +++ b/trunk/tinySIP/src/headers/tsip_header.c @@ -144,6 +144,19 @@ const char *tsip_header_get_name(tsip_header_type_t type) } } +const char *tsip_header_get_nameex(const tsip_header_t *self) +{ + if(self){ + if(self->type == tsip_htype_Dummy){ + return ((tsip_header_Dummy_t*)self)->name; + } + else{ + return tsip_header_get_name(self->type); + } + } + return "unknown-header"; +} + char tsip_header_get_param_separator(const tsip_header_t *self) { if(self) @@ -177,12 +190,7 @@ int tsip_header_tostring(const tsip_header_t *self, tsk_buffer_t *output) { tsk_list_item_t *item; - if(self->type == tsip_htype_Dummy){ - hname = ((tsip_header_Dummy_t*)self)->name; - } - else{ - hname = tsip_header_get_name(self->type); - } + hname = tsip_header_get_nameex(self); ret = 0; // for empty lists /* Header name */ diff --git a/trunk/tinySIP/src/tsip.c b/trunk/tinySIP/src/tsip.c index 779efe30..5804acdf 100644 --- a/trunk/tinySIP/src/tsip.c +++ b/trunk/tinySIP/src/tsip.c @@ -274,11 +274,13 @@ int __tsip_stack_set(tsip_stack_t *self, va_list values) default: { - return -1; + TSK_DEBUG_WARN("Found unknown pname."); + goto bail; } }/* switch */ }/* while */ +bail: return 0; } @@ -316,7 +318,9 @@ tsip_stack_handle_t* tsip_stack_create(tsip_stack_callback callback, ...) tsip_stack_t *stack = tsk_calloc(1, sizeof(tsip_stack_t)); va_list params; - if(!stack) return 0; + if(!stack){ + return 0; + } /* * Default values @@ -328,8 +332,7 @@ tsip_stack_handle_t* tsip_stack_create(tsip_stack_callback callback, ...) stack->proxy_cscf_type = tnet_socket_type_udp_ipv4; va_start(params, callback); - if(__tsip_stack_set(stack, params)) - { + if(__tsip_stack_set(stack, params)){ // Delete the stack? } va_end(params); diff --git a/trunk/tinySIP/src/tsip_message.c b/trunk/tinySIP/src/tsip_message.c index 47a51150..71b04d80 100644 --- a/trunk/tinySIP/src/tsip_message.c +++ b/trunk/tinySIP/src/tsip_message.c @@ -578,7 +578,6 @@ static void* tsip_message_create(void *self, va_list * app) } message->To = tsk_object_ref((void*)request->To); - // FIXME: What about record routes? break; } } diff --git a/trunk/tinySIP/src/tsip_uri.c b/trunk/tinySIP/src/tsip_uri.c index 5662525d..48632f02 100644 --- a/trunk/tinySIP/src/tsip_uri.c +++ b/trunk/tinySIP/src/tsip_uri.c @@ -115,12 +115,10 @@ char* tsip_uri_tostring(const tsip_uri_t *uri, TSIP_BOOLEAN with_params, TSIP_BO tsk_buffer_t *output = TSK_BUFFER_CREATE_NULL(); char* ret = 0; - if(!tsip_uri_serialize(uri, with_params, quote, output)) - { + if(!tsip_uri_serialize(uri, with_params, quote, output)){ ret = tsk_strndup((const char*)output->data, output->size); } - else - { + else{ TSK_DEBUG_ERROR("Failed to serialize URI."); } @@ -130,7 +128,7 @@ char* tsip_uri_tostring(const tsip_uri_t *uri, TSIP_BOOLEAN with_params, TSIP_BO tsip_uri_t *tsip_uri_clone(const tsip_uri_t *uri, TSIP_BOOLEAN with_params, TSIP_BOOLEAN quote) { - tsip_uri_t *newuri; + tsip_uri_t *newuri = 0; tsk_buffer_t *output = TSK_BUFFER_CREATE_NULL(); tsip_uri_serialize(uri, with_params, quote, output); newuri = tsip_uri_parse(output->data, output->size); diff --git a/trunk/vs_2005/tinyHTTP/test.vcproj b/trunk/vs_2005/tinyHTTP/test.vcproj index fdb16f84..57730017 100644 --- a/trunk/vs_2005/tinyHTTP/test.vcproj +++ b/trunk/vs_2005/tinyHTTP/test.vcproj @@ -47,6 +47,7 @@ RuntimeLibrary="3" UsePrecompiledHeader="0" WarningLevel="3" + WarnAsError="true" DebugInformationFormat="4" CompileAs="1" /> @@ -211,6 +212,14 @@ RelativePath="..\..\tinyHTTP\test\test_auth.h" > + + + + diff --git a/trunk/vs_2005/tinyHTTP/tinyHTTP.vcproj b/trunk/vs_2005/tinyHTTP/tinyHTTP.vcproj index 9ecd44dd..f74d2987 100644 --- a/trunk/vs_2005/tinyHTTP/tinyHTTP.vcproj +++ b/trunk/vs_2005/tinyHTTP/tinyHTTP.vcproj @@ -50,6 +50,7 @@ RuntimeLibrary="3" UsePrecompiledHeader="0" WarningLevel="3" + WarnAsError="true" DebugInformationFormat="4" CompileAs="1" /> @@ -95,84 +96,6 @@ Name="VCPostBuildEventTool" /> - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -362,6 +375,10 @@ + + @@ -374,6 +391,10 @@ RelativePath="..\..\tinyHTTP\src\headers\thttp_header_Content_Type.c" > + + @@ -407,10 +428,22 @@ RelativePath="..\..\tinyHTTP\include\thttp.h" > + + + + + + @@ -446,6 +479,10 @@ RelativePath="..\..\tinyHTTP\include\tinyHTTP\headers\thttp_header_Content_Type.h" > + + @@ -519,6 +556,10 @@ RelativePath="..\..\tinyHTTP\ragel\thttp_parser_header_Content_Type.rl" > + + diff --git a/trunk/vs_2005/tinySIP/tinySIP.vcproj b/trunk/vs_2005/tinySIP/tinySIP.vcproj index d26c84a9..5a5312b7 100644 --- a/trunk/vs_2005/tinySIP/tinySIP.vcproj +++ b/trunk/vs_2005/tinySIP/tinySIP.vcproj @@ -811,6 +811,10 @@ RelativePath="..\..\tinySIP\src\transports\tsip_transport_layer.c" > + + + + + + diff --git a/trunk/website/alexa/7GKOaGQFcCqmeWF73EZ3lPeeRPI.txt b/trunk/website/alexa/7GKOaGQFcCqmeWF73EZ3lPeeRPI.txt new file mode 100644 index 00000000..2040892c --- /dev/null +++ b/trunk/website/alexa/7GKOaGQFcCqmeWF73EZ3lPeeRPI.txt @@ -0,0 +1,2 @@ + + diff --git a/trunk/website/index.html b/trunk/website/index.html index b7682363..3a279da7 100644 --- a/trunk/website/index.html +++ b/trunk/website/index.html @@ -98,6 +98,13 @@ Valid CSS! + + +
+
+ +
+
diff --git a/trunk/website/sourceforge/index.php b/trunk/website/sourceforge/index.php new file mode 100644 index 00000000..70435ec1 --- /dev/null +++ b/trunk/website/sourceforge/index.php @@ -0,0 +1,6 @@ + \ No newline at end of file