Update HTTP stack.

This commit is contained in:
bossiel 2010-03-05 17:08:03 +00:00
parent 0506a04219
commit 8e7b4e7a88
42 changed files with 2113 additions and 254 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou@yahoo.fr>
*
* 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 <diopmamadou(at)yahoo.fr>
*
* @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_ */

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -75,5 +75,7 @@
#include <stdlib.h>
#endif
/* FIXME */
#define THTTP_NULL 0
#endif // TINYHTTP_CONFIG_H

View File

@ -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

View File

@ -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
{

View File

@ -0,0 +1,164 @@
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou@yahoo.fr>
*
* 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 <diopmamadou(at)yahoo.fr>
*
* @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 <string.h>
/**@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;

View File

@ -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) <pe && !message->Content)
{
message->Content = TSK_BUFFER_CREATE((p+1), clen);

View File

@ -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;
}

View File

@ -0,0 +1,116 @@
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou@yahoo.fr>
*
* 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 <diopmamadou(at)yahoo.fr>
*
* @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;
}

View File

@ -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;

View File

@ -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.

View File

@ -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
{

View File

@ -0,0 +1,321 @@
/* #line 1 "thttp_parser_header_Dummy.rl" */
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou@yahoo.fr>
*
* 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 <diopmamadou(at)yahoo.fr>
*
* @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 <string.h>
/**@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;

View File

@ -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;

View File

@ -2266,4 +2266,4 @@ _again:
533
/* #line 321 "thttp_parser_header.rl" */
) ? 0 : -1;
}
}

View File

@ -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) <pe && !message->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;
}
}

View File

@ -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;
}
}

View File

@ -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 <stdarg.h>
//#include <string.h>
@ -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;

View File

@ -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;

View File

@ -27,4 +27,263 @@
*
* @date Created: Sat Nov 8 16:54:58 2009 mdiop
*/
#include "tinyHTTP/thttp_operation.h"
#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;

View File

@ -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.");

View File

@ -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();

View File

@ -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_ */

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou@yahoo.fr>
*
* 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; i<sizeof(urls)/sizeof(const char*); i++)
{
thttp_url_t *url = thttp_url_parse(urls[i], strlen(urls[i]));
printf("\n== Parsing {{ %s }} ==\n\n", urls[i]);
if(url)
{
printf("scheme: %s\n", url->scheme);
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 */

View File

@ -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);

View File

@ -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*
///

View File

@ -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) <pe && !message->Content)
{
message->Content = TSK_BUFFER_CREATE((p+1), clen);

View File

@ -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 */

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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"
>
</File>
<File
RelativePath="..\..\tinyHTTP\test\test_stack.h"
>
</File>
<File
RelativePath="..\..\tinyHTTP\test\test_url.h"
>
</File>
</Filter>
</Files>
<Globals>

View File

@ -50,6 +50,7 @@
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
WarnAsError="true"
DebugInformationFormat="4"
CompileAs="1"
/>
@ -95,84 +96,6 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;TINYHTTP_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
OutputDirectory="&quot;$(SolutionDir)$(ConfigurationName)\wce&quot;"
@ -253,6 +176,84 @@
<DebuggerTool
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;TINYHTTP_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
OutputDirectory="$(SolutionDir)Windows Mobile 5.0 Pocket PC SDK (ARMV4I)\$(ConfigurationName)"
@ -343,10 +344,22 @@
RelativePath="..\..\tinyHTTP\src\thttp.c"
>
</File>
<File
RelativePath="..\..\tinyHTTP\src\thttp_event.c"
>
</File>
<File
RelativePath="..\..\tinyHTTP\src\thttp_message.c"
>
</File>
<File
RelativePath="..\..\tinyHTTP\src\thttp_operation.c"
>
</File>
<File
RelativePath="..\..\tinyHTTP\src\thttp_transport.c"
>
</File>
<File
RelativePath="..\..\tinyHTTP\src\thttp_url.c"
>
@ -362,6 +375,10 @@
<Filter
Name="headers"
>
<File
RelativePath="..\..\tinyHTTP\src\headers\thttp_header.c"
>
</File>
<File
RelativePath="..\..\tinyHTTP\src\headers\thttp_header_Authorization.c"
>
@ -374,6 +391,10 @@
RelativePath="..\..\tinyHTTP\src\headers\thttp_header_Content_Type.c"
>
</File>
<File
RelativePath="..\..\tinyHTTP\src\headers\thttp_header_Dummy.c"
>
</File>
<File
RelativePath="..\..\tinyHTTP\src\headers\thttp_header_Proxy_Authenticate.c"
>
@ -407,10 +428,22 @@
RelativePath="..\..\tinyHTTP\include\thttp.h"
>
</File>
<File
RelativePath="..\..\tinyHTTP\include\tinyHTTP\thttp_event.h"
>
</File>
<File
RelativePath="..\..\tinyHTTP\include\tinyHTTP\thttp_message.h"
>
</File>
<File
RelativePath="..\..\tinyHTTP\include\tinyHTTP\thttp_operation.h"
>
</File>
<File
RelativePath="..\..\tinyHTTP\include\tinyHTTP\thttp_transport.h"
>
</File>
<File
RelativePath="..\..\tinyHTTP\include\tinyHTTP\thttp_url.h"
>
@ -446,6 +479,10 @@
RelativePath="..\..\tinyHTTP\include\tinyHTTP\headers\thttp_header_Content_Type.h"
>
</File>
<File
RelativePath="..\..\tinyHTTP\include\tinyHTTP\headers\thttp_header_Dummy.h"
>
</File>
<File
RelativePath="..\..\tinyHTTP\include\tinyHTTP\headers\thttp_header_Proxy_Authenticate.h"
>
@ -519,6 +556,10 @@
RelativePath="..\..\tinyHTTP\ragel\thttp_parser_header_Content_Type.rl"
>
</File>
<File
RelativePath="..\..\tinyHTTP\ragel\thttp_parser_header_Dummy.rl"
>
</File>
<File
RelativePath="..\..\tinyHTTP\ragel\thttp_parser_header_WWW_Authenticate.rl"
>

View File

@ -811,6 +811,10 @@
RelativePath="..\..\tinySIP\src\transports\tsip_transport_layer.c"
>
</File>
<File
RelativePath="..\..\tinySIP\src\transports\tsip_transport_tls.c"
>
</File>
</Filter>
<Filter
Name="dialogs"
@ -1373,6 +1377,10 @@
RelativePath="..\..\tinySIP\include\tinysip\transports\tsip_transport_layer.h"
>
</File>
<File
RelativePath="..\..\tinySIP\include\tinysip\transports\tsip_transport_tls.h"
>
</File>
</Filter>
<Filter
Name="dialogs"
@ -1546,6 +1554,10 @@
RelativePath="..\..\tinySIP\ragel\tsip_parser_header_Date.rl"
>
</File>
<File
RelativePath="..\..\tinySIP\ragel\tsip_parser_header_Dummy.rl"
>
</File>
<File
RelativePath="..\..\tinySIP\ragel\tsip_parser_header_Error_Info.rl"
>

View File

@ -0,0 +1,2 @@
<meta name="alexaVerifyID" content="7GKOaGQFcCqmeWF73EZ3lPeeRPI" />

View File

@ -98,6 +98,13 @@
<a href="http://jigsaw.w3.org/css-validator/check/referer">
<img style="border: 0px" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" /></a>
</div>
<!-- Alexa -->
<div>
<br />
<a href="http://www.alexa.com/siteinfo/www.doubango.org"><script type='text/javascript' language='JavaScript' src='http://xslt.alexa.com/site_stats/js/t/a?url=www.doubango.org'></script></a>
</div>
</div>
<div id="contenttext">

View File

@ -0,0 +1,6 @@
<?php
/* Redirect browser */
header("Location: http://www.doubango.org");
/* Make sure that code below does not get executed when we redirect. */
exit;
?>