diff --git a/examples/hello-world.c b/examples/hello-world.c index 34184e1..f0f486f 100644 --- a/examples/hello-world.c +++ b/examples/hello-world.c @@ -24,14 +24,14 @@ static void -hello_world(aisl_evt_t const evt, void * p_ctx) +hello_world(const struct aisl_evt *evt, void *p_ctx) { if (evt->code != AISL_EVENT_STREAM_REQUEST) return; - aisl_status_t status; + AislStatus status; - aisl_stream_t s = evt->source; + AislStream s = evt->source; const char html[] = "" @@ -44,11 +44,11 @@ hello_world(aisl_evt_t const evt, void * p_ctx) "" ""; - status = aisl_response(s, AISL_HTTP_OK, sizeof(html)-1); + status = aisl_response(s, AISL_HTTP_OK, sizeof (html)-1); if (status == AISL_SUCCESS) { - if (aisl_write(s, html, sizeof(html)-1) != -1) + if (aisl_write(s, html, sizeof (html)-1) != -1) { aisl_flush(s); } @@ -63,8 +63,8 @@ hello_world(aisl_evt_t const evt, void * p_ctx) int main(int argc, char ** argv) { - aisl_t aisl; /**< AISL instance pointer */ - aisl_status_t status; /**< AISL status code */ + AislInstance aisl; /**< AISL instance pointer */ + AislStatus status; /**< AISL status code */ struct aisl_cfg cfg = AISL_CFG_DEFAULT; struct aisl_cfg_srv srv = { .host = "0.0.0.0", diff --git a/include/aisl/aisl.h b/include/aisl/aisl.h index 798c134..e649d55 100644 --- a/include/aisl/aisl.h +++ b/include/aisl/aisl.h @@ -1,10 +1,16 @@ -/* - * +/****************************************************************************** * - * Copyright (c) 2017-2019 by Löwenware Ltd. + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information * - * Project homepage: https://lowenware.com/aisl/ + ******************************************************************************/ + +/** + * @file aisl/aisl.h + * @author Ilja Kartašov + * @brief Meta header file of AISL * + * @see https://lowenware.com/aisl/ */ #ifndef AISL_H_17EF1616_A00F_49C9_92B6_273AB13BF279 diff --git a/include/aisl/client.h b/include/aisl/client.h index f7dd37a..ffc6178 100644 --- a/include/aisl/client.h +++ b/include/aisl/client.h @@ -1,10 +1,16 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + /** * @file aisl/client.h + * @author Ilja Kartašov + * @brief Declarations of #AislCLient functions * - * Copyright (c) 2017-2019 by Löwenware Ltd. - * - * Project homepage: https://lowenware.com/aisl/ - * + * @see https://lowenware.com/aisl/ */ #ifndef AISL_CLIENT_H_A6C37DCF_2183_4F22_A5A0_668311757A08 @@ -14,50 +20,50 @@ /** - * @brief Gets #aisl_server_t instance associated with client. - * @param client an #aisl_client_t instance pointer. - * @return an associated #aisl_server_t pointer. + * @brief Gets #AislServer instance associated with client. + * @param client an #AislClient instance pointer. + * @return an associated #AislServer pointer. */ -aisl_server_t -aisl_client_get_server(aisl_client_t client); +AislServer +aisl_client_get_server(AislClient client); /** * @brief Gets security connection status. - * @param client an #aisl_client_t instance pointer. + * @param client an #AislClient instance pointer. * @return true if SSL is enabled and false if disabled. */ bool -aisl_client_is_secure(aisl_client_t client); +aisl_client_is_secure(AislClient client); /** * @brief Gets client's connection state. - * @param client an #aisl_client_t instance pointer. + * @param client an #AislClient instance pointer. * @return true if client is online and false if is offline. */ bool -aisl_client_is_online(aisl_client_t client); +aisl_client_is_online(AislClient client); /** * @brief Forcefully closes client's connection. - * @param client an #aisl_client_t instance pointer. + * @param client an #AislClient instance pointer. */ void -aisl_client_disconnect(aisl_client_t client); +aisl_client_disconnect(AislClient client); /** * @brief Gets HTTP protocol version. - * @param client an #aisl_client_t instance pointer. + * @param client an #AislClient instance pointer. * @return HTTP protocol version */ -aisl_http_version_t -aisl_client_get_http_version(aisl_client_t client); +AislHttpVersion +aisl_client_get_http_version(AislClient client); void -aisl_client_get_address( aisl_client_t client, struct sockaddr_in * address); +aisl_client_get_address(AislClient client, struct sockaddr_in *address); #endif /* !AISL_CLIENT_H */ diff --git a/include/aisl/config.h b/include/aisl/config.h index 1ecf61a..3826a9e 100644 --- a/include/aisl/config.h +++ b/include/aisl/config.h @@ -1,10 +1,16 @@ -/* - * +/****************************************************************************** * - * Copyright (c) 2017-2019 by Löwenware Ltd. + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information * - * Project homepage: https://lowenware.com/aisl/ + ******************************************************************************/ + +/** + * @file aisl/config.h + * @author Ilja Kartašov + * @brief Declarations of AISL configuration structures * + * @see https://lowenware.com/aisl/ */ #ifndef AISL_CONFIG_H_DB67A89B_5CAF_4A5F_AEB1_6DB9F84827D6 @@ -12,59 +18,49 @@ #include -#define AISL_CFG_DEFAULT \ -{ \ - .callback = NULL \ - , .p_ctx = NULL \ - , .srv = NULL \ - , .ssl = NULL \ - , .srv_cnt = 0 \ - , .ssl_cnt = 0 \ - , .client_spool_size = 32 \ - , .initial_buffer_size = 16536 \ - , .client_accept_limit = 1024 \ - , .client_silence_timeout = 30 \ +#define AISL_CFG_DEFAULT { \ + .callback = NULL \ + , .p_ctx = NULL \ + , .srv = NULL \ + , .ssl = NULL \ + , .srv_cnt = 0 \ + , .ssl_cnt = 0 \ + , .client_spool_size = 32 \ + , .initial_buffer_size = 16536 \ + , .client_accept_limit = 1024 \ + , .client_silence_timeout = 30 \ } \ -struct aisl_cfg_srv -{ - const char * host; - uint16_t port; - bool secure; +struct aisl_cfg_srv { + const char * host; + uint16_t port; + bool secure; }; -typedef struct aisl_cfg_srv * aisl_cfg_srv_t; - - -struct aisl_cfg_ssl -{ - const char * host; - const char * key_file; - const char * crt_file; +struct aisl_cfg_ssl { + const char * host; + const char * key_file; + const char * crt_file; }; -typedef struct aisl_cfg_ssl * aisl_cfg_ssl_t; - struct aisl_cfg { - /* event handlers */ - aisl_callback_t callback; - void * p_ctx; + /* event handlers */ + AislCallback callback; + void *p_ctx; - aisl_cfg_srv_t srv; - aisl_cfg_ssl_t ssl; + struct aisl_cfg_srv *srv; + struct aisl_cfg_ssl *ssl; - int srv_cnt; - int ssl_cnt; + int srv_cnt; + int ssl_cnt; - int client_spool_size; - int initial_buffer_size; - int client_accept_limit; - int client_silence_timeout; + int client_spool_size; + int initial_buffer_size; + int client_accept_limit; + int client_silence_timeout; }; -typedef struct aisl_cfg * aisl_cfg_t; - #endif /* !AISL_CONFIG_H */ diff --git a/include/aisl/instance.h b/include/aisl/instance.h index 54a85b7..3785d4a 100644 --- a/include/aisl/instance.h +++ b/include/aisl/instance.h @@ -1,10 +1,17 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + /** * @file aisl/instance.h + * @author Ilja Kartašov + * @brief Declarations of #AislInstance functions * - * Copyright (c) 2017-2019 by Löwenware Ltd. - * - * Project homepage: https://lowenware.com/aisl/ - * + * @see https://lowenware.com/aisl/ + */ #ifndef AISL_INSTANCE_H_60576F41_454C_4189_B91A_F40501132230 @@ -21,39 +28,39 @@ * @brief Allocates new AISL instance. * * @param cfg a pointer to #aisl_cfg_t structure. - * @return an #aisl_t instance pointer. + * @return an #AislInstance instance pointer. */ -aisl_t -aisl_new( aisl_cfg_t cfg ); +AislInstance +aisl_new(const struct aisl_cfg *cfg); /** * @brief Frees previously allocated pointer of AISL instance. - * @param instance a pointer to #aisl_t instance. + * @param instance a pointer to #AislInstance instance. */ void -aisl_free( aisl_t instance ); +aisl_free(AislInstance instance); /** * @brief A core function doing all the library routines. * Designed to be called inside application main loop - * @param instance a pointer to #aisl_t instance. - * @return #aisl_status_t code. + * @param instance a pointer to #AislInstance instance. + * @return #AislStatus code. */ -aisl_status_t -aisl_run_cycle( aisl_t instance ); +AislStatus +aisl_run_cycle(AislInstance instance); /** * @brief Function to sleep CPU if nothing to do. * Calls select on all the opened sockets inside. - * @param instance a pointer to #aisl_t instance. + * @param instance a pointer to #AislInstance instance. * @param usec a number of miliseconds to wait for any data on sockets. - * @return #aisl_status_t code. + * @return #AislStatus code. */ -aisl_status_t -aisl_sleep( aisl_t instance, uint32_t usec ); +AislStatus +aisl_sleep(AislInstance instance, uint32_t usec); #endif /* !AISL_INSTANCE_H */ diff --git a/include/aisl/server.h b/include/aisl/server.h index a23da30..c0233d9 100644 --- a/include/aisl/server.h +++ b/include/aisl/server.h @@ -1,10 +1,16 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + /** * @file aisl/server.h + * @author Ilja Kartašov + * @brief Declarations of #AislServer functions * - * Copyright (c) 2017-2019 by Löwenware Ltd. - * - * Project homepage: https://lowenware.com/aisl/ - * + * @see https://lowenware.com/aisl/ */ #ifndef AISL_SERVER_H_CC564608_7A05_4B31_9E7E_32750BC60768 @@ -15,28 +21,28 @@ /** * @brief Function to get appropriate AISL instance pointer from server pointer. - * @param server an #aisl_server_t pointer. - * @return an #aisl_t instance pointer. + * @param server an #AislServer pointer. + * @return an #AislInstance instance pointer. */ -aisl_t -aisl_server_get_instance( aisl_server_t server ); +AislInstance +aisl_server_get_instance(AislServer server); /** * @brief Copies server listen address information to sockaddr_in structure. - * @param server an #aisl_server_t pointer. + * @param server an #AislServer pointer. * @param address a pointer to sockaddr_in structure. */ void -aisl_server_get_address( aisl_server_t server, struct sockaddr_in * address); +aisl_server_get_address(AislServer server, struct sockaddr_in *address); /** - * @brief Function to get on and off status of SSL for the #aisl_server_t. - * @param server an #aisl_server_t pointer. + * @brief Function to get on and off status of SSL for the #AislServer. + * @param server an #AislServer pointer. * @return a boolean value representing SSL enabled/disabled state. */ bool -aisl_server_get_ssl( aisl_server_t server ); +aisl_server_get_ssl(AislServer server); #endif /* !AISL_SERVER_H */ diff --git a/include/aisl/stream.h b/include/aisl/stream.h index 484921e..6cf7d1a 100644 --- a/include/aisl/stream.h +++ b/include/aisl/stream.h @@ -1,12 +1,17 @@ -/* - * +/****************************************************************************** * - * Copyright (c) 2017-2019 by Löwenware Ltd. + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information * - * Project homepage: https://lowenware.com/aisl/ - * - */ + ******************************************************************************/ +/** + * @file aisl/stream.h + * @author Ilja Kartašov + * @brief Declarations of #AislStream functions + * + * @see https://lowenware.com/aisl/ + */ #ifndef AISL_STREAM_H_4D8EB622_3CE0_4F1B_AC1F_B27CCB5C2EDC #define AISL_STREAM_H_4D8EB622_3CE0_4F1B_AC1F_B27CCB5C2EDC @@ -15,96 +20,87 @@ #include - -/* Stream helpers */ - bool -aisl_is_secure( aisl_stream_t stream ); +aisl_is_secure(AislStream stream); -aisl_client_t -aisl_get_client( aisl_stream_t stream ); +AislClient +aisl_get_client(AislStream stream); -aisl_server_t -aisl_get_server( aisl_stream_t stream ); +AislServer +aisl_get_server(AislStream stream); -aisl_http_version_t -aisl_get_http_version( aisl_stream_t stream ); +AislHttpVersion +aisl_get_http_version(AislStream stream); -aisl_t -aisl_stream_get_instance( aisl_stream_t s ); +AislInstance +aisl_stream_get_instance(AislStream s); -/* Context functions */ - void * -aisl_get_context( aisl_stream_t stream ); +aisl_get_context(AislStream stream); void -aisl_set_context( aisl_stream_t stream, void * context ); +aisl_set_context(AislStream stream, void *context); -/* Stream control functions */ - -aisl_status_t -aisl_flush( aisl_stream_t stream ); +AislStatus +aisl_flush(AislStream stream); void -aisl_reject( aisl_stream_t stream ); +aisl_reject(AislStream stream); -/* Response functions */ - -aisl_status_t -aisl_response( aisl_stream_t stream, - aisl_http_response_t status_code, - uint64_t content_length ); +AislStatus +aisl_response(AislStream stream, + AislHttpResponse status_code, + uint64_t content_length); int -aisl_header( aisl_stream_t stream, const char *key, const char *value ); +aisl_header(AislStream stream, const char *key, const char *value ); int -aisl_header_printf( aisl_stream_t stream, - const char * key, - const char * format, - ... ); +aisl_header_printf(AislStream stream, + const char *key, + const char *format, + ... ); int -aisl_header_vprintf( aisl_stream_t stream, - const char * key, - const char * format, - va_list args ); +aisl_header_vprintf(AislStream stream, + const char *key, + const char *format, + va_list args ); int -aisl_printf( aisl_stream_t stream, const char * format, ... ); +aisl_printf(AislStream stream, const char *format, ...); int -aisl_vprintf( aisl_stream_t stream, const char * format, va_list args ); +aisl_vprintf(AislStream stream, const char *format, va_list args); int -aisl_write( aisl_stream_t stream, const char * data, int d_len ); +aisl_write(AislStream stream, const char *data, int d_len); int -aisl_puts( const char * str_data, aisl_stream_t stream ); +aisl_puts(const char *str_data, AislStream stream); void -aisl_set_output_event(aisl_stream_t stream, bool value); +aisl_set_output_event(AislStream stream, bool value); bool -aisl_get_output_event(aisl_stream_t stream); +aisl_get_output_event(AislStream stream); #endif /* !AISL_STREAM_H */ diff --git a/include/aisl/types.h b/include/aisl/types.h index 9d44861..0e468df 100644 --- a/include/aisl/types.h +++ b/include/aisl/types.h @@ -1,10 +1,16 @@ -/* - * +/****************************************************************************** * - * Copyright (c) 2017-2019 by Löwenware Ltd. + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information * - * Project homepage: https://lowenware.com/aisl/ + ******************************************************************************/ + +/** + * @file aisl/types.h + * @author Ilja Kartašov + * @brief Declarations of AISL types * + * @see https://lowenware.com/aisl/ */ #ifndef AISL_TYPES_H_86A9DBA7_C0E6_4CF4_8A64_DAAD4A81031B @@ -20,206 +26,182 @@ #define AISL_AUTO_LENGTH (~0) -/* type casts */ -#define AISL_CALLBACK(x) ((aisl_callback_t) x) +/** type casts */ +#define AISL_CALLBACK(x) ((AislCallback) x) -/* AISL Instance */ -typedef struct aisl * aisl_t; +/** AISL Instance */ +typedef struct aisl_instance * AislInstance; -/* HTTP(s) Server */ -typedef struct aisl_server * aisl_server_t; +/** HTTP(s) Server */ +typedef struct aisl_server * AislServer; -/* HTTP(s) Client */ -typedef struct aisl_client * aisl_client_t; +/** HTTP(s) Client */ +typedef struct aisl_client * AislClient; -/* Server<->Client Stream */ -typedef struct aisl_stream * aisl_stream_t; +/** Server<->Client Stream */ +typedef struct aisl_stream * AislStream; -/* status return codes */ -typedef enum -{ - AISL_INPUT_ERROR = -4 - , AISL_EXTCALL_ERROR = -3 - , AISL_SYSCALL_ERROR = -2 - , AISL_MALLOC_ERROR = -1 +/** status return codes */ +typedef enum { + AISL_INPUT_ERROR = -4 + , AISL_EXTCALL_ERROR = -3 + , AISL_SYSCALL_ERROR = -2 + , AISL_MALLOC_ERROR = -1 - , AISL_SUCCESS = 0 - , AISL_IDLE = 1 - -} aisl_status_t; + , AISL_SUCCESS = 0 + , AISL_IDLE = 1 +} AislStatus; #ifndef WITHOUT_STRINGIFIERS const char * -aisl_status_to_string(aisl_status_t status); +aisl_status_to_string(AislStatus status); #endif -/* Generic HTTP Enumerations */ - -typedef enum -{ - AISL_HTTP_0_9 = 0x0009 - , AISL_HTTP_1_0 = 0x0100 - , AISL_HTTP_1_1 = 0x0101 - , AISL_HTTP_2_0 = 0x0200 - -} aisl_http_version_t; +/** Generic HTTP Enumerations */ +typedef enum { + AISL_HTTP_0_9 = 0x0009 + , AISL_HTTP_1_0 = 0x0100 + , AISL_HTTP_1_1 = 0x0101 + , AISL_HTTP_2_0 = 0x0200 +} AislHttpVersion; const char * -aisl_http_version_to_string( aisl_http_version_t version ); +aisl_http_version_to_string(AislHttpVersion version); -typedef enum -{ - AISL_HTTP_METHOD_UNKNOWN - , AISL_HTTP_GET - , AISL_HTTP_PUT - , AISL_HTTP_POST - , AISL_HTTP_HEAD - , AISL_HTTP_TRACE - , AISL_HTTP_DELETE - , AISL_HTTP_OPTIONS - , AISL_HTTP_CONNECT - - , AISL_HTTP_PRI - -} aisl_http_method_t; +typedef enum { + AISL_HTTP_METHOD_UNKNOWN + , AISL_HTTP_GET + , AISL_HTTP_PUT + , AISL_HTTP_POST + , AISL_HTTP_HEAD + , AISL_HTTP_TRACE + , AISL_HTTP_DELETE + , AISL_HTTP_OPTIONS + , AISL_HTTP_CONNECT + , AISL_HTTP_PRI +} AislHttpMethod; const char * -aisl_http_method_to_string( aisl_http_method_t method ); +aisl_http_method_to_string( AislHttpMethod method ); -typedef enum -{ - AISL_HTTP_CONTINUE = 100 - , AISL_HTTP_SWITCHING_PROTOCOLS +typedef enum { + AISL_HTTP_CONTINUE = 100 + , AISL_HTTP_SWITCHING_PROTOCOLS - , AISL_HTTP_OK = 200 - , AISL_HTTP_CREATED - , AISL_HTTP_ACCEPTED - , AISL_HTTP_NON_AUTHORITATIVE_INFORMATION - , AISL_HTTP_NO_CONTENT - , AISL_HTTP_RESET_CONTENT - , AISL_HTTP_PARTIAL_CONTENT + , AISL_HTTP_OK = 200 + , AISL_HTTP_CREATED + , AISL_HTTP_ACCEPTED + , AISL_HTTP_NON_AUTHORITATIVE_INFORMATION + , AISL_HTTP_NO_CONTENT + , AISL_HTTP_RESET_CONTENT + , AISL_HTTP_PARTIAL_CONTENT - , AISL_HTTP_MULTIPLE_CHOICES = 300 - , AISL_HTTP_MOVED_PERMANENTLY - , AISL_HTTP_FOUND - , AISL_HTTP_SEE_OTHER - , AISL_HTTP_NOT_MODIFIED - , AISL_HTTP_USE_PROXY - , AISL_HTTP_UNUSED - , AISL_HTTP_TEMPORARY_REDIRECT + , AISL_HTTP_MULTIPLE_CHOICES = 300 + , AISL_HTTP_MOVED_PERMANENTLY + , AISL_HTTP_FOUND + , AISL_HTTP_SEE_OTHER + , AISL_HTTP_NOT_MODIFIED + , AISL_HTTP_USE_PROXY + , AISL_HTTP_UNUSED + , AISL_HTTP_TEMPORARY_REDIRECT - , AISL_HTTP_BAD_REQUEST = 400 - , AISL_HTTP_UNAUTHORIZED - , AISL_HTTP_PAYMENT_REQUIRED - , AISL_HTTP_FORBIDDEN - , AISL_HTTP_NOT_FOUND - , AISL_HTTP_METHOD_NOT_ALLOWED - , AISL_HTTP_NOT_ACCEPTABLE - , AISL_HTTP_PROXY_AUTHENTICATION_REQUIRED - , AISL_HTTP_REQUEST_TIMEOUT - , AISL_HTTP_CONFLICT - , AISL_HTTP_GONE - , AISL_HTTP_LENGTH_REQUIRED - , AISL_HTTP_PRECONDITION_FAILED - , AISL_HTTP_REQUEST_ENTITY_TOO_LARGE - , AISL_HTTP_REQUEST_URI_TOO_LONG - , AISL_HTTP_UNSUPPORTED_MEDIA_TYPE - , AISL_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE - , AISL_HTTP_EXPECTATION_FAILED + , AISL_HTTP_BAD_REQUEST = 400 + , AISL_HTTP_UNAUTHORIZED + , AISL_HTTP_PAYMENT_REQUIRED + , AISL_HTTP_FORBIDDEN + , AISL_HTTP_NOT_FOUND + , AISL_HTTP_METHOD_NOT_ALLOWED + , AISL_HTTP_NOT_ACCEPTABLE + , AISL_HTTP_PROXY_AUTHENTICATION_REQUIRED + , AISL_HTTP_REQUEST_TIMEOUT + , AISL_HTTP_CONFLICT + , AISL_HTTP_GONE + , AISL_HTTP_LENGTH_REQUIRED + , AISL_HTTP_PRECONDITION_FAILED + , AISL_HTTP_REQUEST_ENTITY_TOO_LARGE + , AISL_HTTP_REQUEST_URI_TOO_LONG + , AISL_HTTP_UNSUPPORTED_MEDIA_TYPE + , AISL_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE + , AISL_HTTP_EXPECTATION_FAILED - , AISL_HTTP_INTERNAL_SERVER_ERROR = 500 - , AISL_HTTP_NOT_IMPLEMENTED - , AISL_HTTP_BAD_GATEWAY - , AISL_HTTP_SERVICE_UNAVAILABLE - , AISL_HTTP_GATEWAY_TIMEOUT - , AISL_HTTP_VERSION_NOT_SUPPORTED - -} aisl_http_response_t; + , AISL_HTTP_INTERNAL_SERVER_ERROR = 500 + , AISL_HTTP_NOT_IMPLEMENTED + , AISL_HTTP_BAD_GATEWAY + , AISL_HTTP_SERVICE_UNAVAILABLE + , AISL_HTTP_GATEWAY_TIMEOUT + , AISL_HTTP_VERSION_NOT_SUPPORTED +} AislHttpResponse; const char * -aisl_http_response_to_string( aisl_http_response_t code ); +aisl_http_response_to_string( AislHttpResponse code ); -/* Events */ +/** Codes of AISL events */ +typedef enum { + AISL_EVENT_SERVER_READY = 100 + , AISL_EVENT_SERVER_ERROR = 190 -typedef enum -{ - AISL_EVENT_SERVER_OPEN = 100 - , AISL_EVENT_SERVER_ERROR = 190 + , AISL_EVENT_CLIENT_CONNECT = 200 + , AISL_EVENT_CLIENT_DISCONNECT = 210 - , AISL_EVENT_CLIENT_CONNECT = 200 - , AISL_EVENT_CLIENT_DISCONNECT = 210 - - , AISL_EVENT_STREAM_OPEN = 300 - , AISL_EVENT_STREAM_HEADER = 310 - , AISL_EVENT_STREAM_INPUT = 320 - , AISL_EVENT_STREAM_REQUEST = 330 - , AISL_EVENT_STREAM_OUTPUT = 340 - , AISL_EVENT_STREAM_CLOSE = 350 - , AISL_EVENT_STREAM_ERROR = 390 - -} aisl_evt_code_t; + , AISL_EVENT_STREAM_OPEN = 300 + , AISL_EVENT_STREAM_HEADER = 310 + , AISL_EVENT_STREAM_INPUT = 320 + , AISL_EVENT_STREAM_REQUEST = 330 + , AISL_EVENT_STREAM_OUTPUT = 340 + , AISL_EVENT_STREAM_CLOSE = 350 + , AISL_EVENT_STREAM_ERROR = 390 +} AislEvent; -struct aisl_evt -{ - void * source; - aisl_evt_code_t code; - aisl_status_t status; +struct aisl_evt { + void *source; + AislEvent code; + AislStatus status; }; -typedef struct aisl_evt * aisl_evt_t; - /* void type event callback */ typedef void -(* aisl_callback_t) (aisl_evt_t const evt, void * p_ctx); +(* AislCallback) (const struct aisl_evt *evt, void *ctx); -struct aisl_evt_stream_open -{ - struct aisl_evt evt; - const char * path; - const char * query; - aisl_http_method_t http_method; +struct aisl_evt_open { + struct aisl_evt evt; + const char *path; + const char *query; + AislHttpMethod http_method; }; -typedef struct aisl_evt_stream_open * aisl_evt_stream_open_t; - -struct aisl_evt_stream_header -{ - struct aisl_evt evt; - const char * key; - const char * value; +struct aisl_evt_header { + struct aisl_evt evt; + const char *key; + const char *value; }; -typedef struct aisl_evt_stream_header * aisl_evt_stream_header_t; - -struct aisl_evt_stream_input -{ - struct aisl_evt evt; - const char * data; - int32_t size; +struct aisl_evt_input { + struct aisl_evt evt; + const char *data; + int32_t size; }; -typedef struct aisl_evt_stream_input * aisl_evt_stream_input_t; #ifndef WITHOUT_STRINGIFIERS const char * -aisl_evt_code_to_string( aisl_evt_code_t evt_code ); +aisl_event_to_string(AislEvent evt); #endif diff --git a/src/) b/src/) new file mode 100644 index 0000000..2a5d491 --- /dev/null +++ b/src/) @@ -0,0 +1,539 @@ +#include +#include +#include +#include +#include +#include +#include + +#ifndef AISL_WITHOUT_SSL +#include +#endif + +#include +#include "debug.h" +#include "stream.h" +#include "http.h" +#include "server.h" +#include "instance.h" +#include "client.h" + +#define FLAG_KEEPALIVE (1<<0) +#define FLAG_HANDSHAKE (1<<1) +#define FLAG_CAN_READ (1<<2) +#define FLAG_CAN_WRITE (1<<3) + +#define BUFFER_SIZE (16*1024) + + +static void +aisl_client_close(AislClient client, AislStatus status) +{ + if (client->fd != -1) + { + aisl_raise( + client->server->instance + , (void *)client + , AISL_EVENT_CLIENT_DISCONNECT + , status + ); + + close(client->fd); + shutdown(client->fd, SHUT_RDWR); + client->fd = -1; + } +} + + +static AislStatus +aisl_client_parse(AislClient client, char * data, int32_t size) +{ + AislStatus result = AISL_SUCCESS; + AislStream s = client->stream; + ParserStatus p = HTTP_PARSER_SUCCESS; + + + int32_t bytes_left = size; + + switch (client->http_version) + { + case AISL_HTTP_0_9: + case AISL_HTTP_1_0: + case AISL_HTTP_1_1: + + /* s = client->stream; */ + + while ( p == HTTP_PARSER_SUCCESS ) + { + + switch ( aisl_stream_get_state(s) ) + { + case AISL_STREAM_STATE_IDLE: + p = http_10_parse_request(data, &size, client->stream); + break; + + case AISL_STREAM_STATE_WAIT_HEADER: + p = http_10_parse_header(data, &size, client->stream); + break; + + case AISL_STREAM_STATE_WAIT_BODY: + p = http_10_parse_body(data, &size, client->stream); + break; + + default: /* has input data, but request was already parsed */ + p = HTTP_PARSER_ERROR; + continue; + } + // size now has number of parsed bytes + data += size; + bytes_left -= size; + size = bytes_left; + } + + + + break; + + case AISL_HTTP_2_0: + + break; + } + + switch(p) + { + case HTTP_PARSER_READY: + client->flags &= ~FLAG_CAN_READ; + client->flags |= FLAG_CAN_WRITE; + + aisl_raise( + client->server->instance + , (void *) s + , AISL_EVENT_STREAM_REQUEST + , result + ); + break; + + case HTTP_PARSER_ERROR: + /* reply Bad Request here */ + client->stream->http_response = AISL_HTTP_BAD_REQUEST; + + aisl_raise( + client->server->instance + , (void *) s + , AISL_EVENT_STREAM_ERROR + , result + ); + + aisl_client_close(client, result); + + return result; + + default: + break; + } + + if (size) + buffer_shift(&client->in, client->in.used - size); /* reset buffer */ + + return result; +} + + +/* In HTTP 2.0 client->stream will be NULL if stream related data was completely + * parsed. If it is not NULL, then stream expects additional data -> same like + * in mono stream HTTP 1.0 + */ +static AislStatus +aisl_client_input(AislClient client) +{ + int l; + + char * data = &client->in.data[ client->in.used ]; + int32_t size = client->in.size - client->in.used; + + #ifndef AISL_WITHOUT_SSL + if (client->ssl) + { + DPRINTF("SSL_read"); + if ( !(client->flags & FLAG_HANDSHAKE) ) + { + if ( (l = SSL_accept(client->ssl)) != 1 ) + { + l = SSL_get_error(client->ssl, l); + + if (l == SSL_ERROR_WANT_READ || l == SSL_ERROR_WANT_WRITE) + return AISL_IDLE; + + DPRINTF("SSL handshake fail: %s\n", ERR_error_string(l, NULL) ); + + aisl_client_close(client, AISL_EXTCALL_ERROR); + return AISL_EXTCALL_ERROR; + } + + client->flags &= ~FLAG_HANDSHAKE; + } + + l = SSL_read(client->ssl, data, size) ; + } + else + #endif + l = recv( client->fd, data, size, 0); + + if (l > 0) + { + DPRINTF("%d bytes received from client", l); + + data = client->in.data; + size = client->in.used + l; + + client->in.used = size; + + return aisl_client_parse(client, data, size); + } + else if (l<0) + { + #ifndef AISL_WITHOUT_SSL + if (client->ssl) + { + if (SSL_get_error(client->ssl, l) == SSL_ERROR_WANT_READ) + return AISL_IDLE; + } + else + #endif + { + if(errno == EWOULDBLOCK) + return AISL_IDLE; + + DPRINTF("client - %s", strerror(errno)); + } + } + + /* both: client disconnect + on read error */ + /* todo: raise client error here */ + aisl_client_close(client, AISL_SYSCALL_ERROR); + + return AISL_SYSCALL_ERROR; +} + + +static AislStatus +aisl_client_output(AislClient client) +{ + int l; + char * data; + + AislStream s = client->stream; + + /* while stream is not flushed, we should raise event */ + if( aisl_get_output_event(s) ) + { + /* in case of chunked output ( subscription for AISL_STREAM_OUTPUT event ) + * stream buffer will be initialized with OUTPUT_BUFFER_SIZE size, but + * buffer->size will be used to carry amount of stored bytes + * */ + l = aisl_stream_get_buffer_space(s); + + /* + if (bsz < OUTPUT_BUFFER_SIZE) + { + if (buffer_clear(s->buffer, OUTPUT_BUFFER_SIZE) == 0) + return false; + + s->buffer->size = bsz; + bsz = OUTPUT_BUFFER_SIZE; + } + */ + + if ( !(l < aisl_stream_get_buffer_size(s) / 2) ) + { + aisl_raise( + client->server->instance + , (void*)s + , AISL_EVENT_STREAM_OUTPUT + , AISL_SUCCESS + ); + } + } + + data = aisl_stream_get_data(s, &l); + + if ( !l ) + return AISL_IDLE; + + #ifdef AISL_WITHOUT_SSL + l = send( client->fd, data, l, 0); + #else + l = (client->ssl) ? + SSL_write(client->ssl, data, l) : + send( client->fd, data, l, 0); + #endif + + if (l > 0) + { + aisl_stream_shift(s, l); + + /* + if (s->state == STREAM_RESPONSE_READY && / * flushed * / + s->buffer->size == 0) / * all sent * / + */ + if ( aisl_stream_is_done(s) ) + { + /* buffer_clear(s->buffer, 0); */ + + /* data has been sent */ + + if (client->flags & FLAG_KEEPALIVE) + { + aisl_stream_free(s); + + client->stream = aisl_stream_new(client, client->next_id++); + if (client->stream != NULL ) + return AISL_SUCCESS; + + /* in case of malloc error it will not be error as long as request was + * handled and we just close the connection. + */ + } + + aisl_client_close(client, AISL_SUCCESS); + } + + return AISL_SUCCESS; + } + + /* l < 0 */ + #ifndef AISL_WITHOUT_SSL + if (client->ssl) + { + if ( SSL_get_error(client->ssl, l) == SSL_ERROR_WANT_WRITE ) + return AISL_IDLE; + } + else + #endif + { + if (errno == EWOULDBLOCK) + return AISL_IDLE; + } + + aisl_client_close(client, AISL_SYSCALL_ERROR); + + return AISL_SYSCALL_ERROR; +} + + +AislClient +aisl_client_new( AislServer server, + int fd, + struct sockaddr_in * addr ) +{ + AislClient client; + AislStream stream; + + if ( (client = calloc(1, sizeof (struct aisl_client))) != NULL ) + { + DPRINTF("client alocated"); + memcpy(&client->address, addr, sizeof (struct sockaddr_in)); + client->server = server; + client->fd = fd; + client->next_id = 2; + client->http_version = AISL_HTTP_1_0; + client->timestamp = time(NULL); + client->flags = FLAG_KEEPALIVE | FLAG_HANDSHAKE | FLAG_CAN_READ; + + if (buffer_init(&client->in, 2*BUFFER_SIZE) != -1) + { + DPRINTF("client buffer alocated"); + memcpy(&client->out, &client->in, sizeof (struct buffer)); + + stream = aisl_stream_new(client, 0); + + if (stream != NULL) + { + client->stream = stream; + + DPRINTF("client stream alocated"); + + #ifdef AISL_WITHOUT_SSL + + return client; + + #else + + SSL_CTX * ssl_ctx; + + if ( !server->ssl ) + return client; + + ssl_ctx = aisl_get_ssl_ctx(server->instance, NULL); + + if ((client->ssl = SSL_new(ssl_ctx)) != NULL ) + { + SSL_set_fd(client->ssl, fd); + return client; + } + + #endif + } + } + aisl_client_free(client); + + } + + return NULL; +} + + +void +aisl_client_free(AislClient client) +{ + aisl_client_close(client, AISL_SUCCESS); + + #ifndef AISL_WITHOUT_SSL + if (client->ssl) + SSL_free(client->ssl); + #endif + + if (client->in.data) + free(client->in.data); + + /* out buffer is a shared part of input buffer, so no need to free it */ + + if (client->stream) + aisl_stream_free(client->stream); + + free(client); +} + + +AislStatus +AislClientouch(AislClient client, int32_t timeout) +{ + AislStatus result = AISL_IDLE, + status = AISL_IDLE; + + /* input */ + if (client->flags & FLAG_CAN_READ) + { + if ( (result = aisl_client_input(client)) < 0 ) + return result; + } + + /* output */ + if (client->flags & FLAG_CAN_WRITE) + { + if ( (status = aisl_client_output(client)) < 0 ) + return status; + } + + + /* + if ((client->http_version==AISL_HTTP_2_0 || s->statestreams, client->ostream); + + if ( s->flags & (STREAM_FLAG_OUTPUT_READY | STREAM_FLAG_OUTPUT_CHUNKED) ) + result = client_output(client); + */ + /* update timestamp */ + + if (result == AISL_IDLE) + result = status; + + if (result == AISL_SUCCESS) + client->timestamp = time(NULL); + else + { + time_t now; + time(&now); + + if ( !(now - client->timestamp < timeout) ) + { + aisl_client_close(client, result); + } + } + + + return result; +} + + +int +aisl_client_get_socket(AislClient client) +{ + return client->fd; +} + + +bool +aisl_client_get_keepalive(AislClient client) +{ + return (client->flags & FLAG_KEEPALIVE); +} + + +void +aisl_client_set_keepalive(AislClient client, bool value) +{ + if (value) + client->flags |= FLAG_KEEPALIVE; + else + client->flags &= ~FLAG_KEEPALIVE; +} + + + +/* API Level ---------------------------------------------------------------- */ + +__attribute__ ((visibility ("default") )) +AislServer +aisl_client_get_server(AislClient client) +{ + return client->server; +} + + +__attribute__ ((visibility ("default") )) +bool +aisl_client_is_secure(AislClient client) +{ + #ifdef AISL_WITHOUT_SSL + return false; + #else + return (client->ssl == NULL) ? false : true; + #endif +} + + +__attribute__ ((visibility ("default") )) +bool +aisl_client_is_online(AislClient client) +{ + return (client->fd == -1) ? false : true; +} + + +__attribute__ ((visibility ("default") )) +void +aisl_client_disconnect(AislClient client) +{ + aisl_client_close(client, AISL_SUCCESS); +} + + +__attribute__ ((visibility ("default") )) +AislHttpVersion +aisl_client_get_http_version(AislClient client) +{ + return client->http_version; +} + + +__attribute__ ((visibility ("default") )) +void +aisl_client_get_address( AislClient client, struct sockaddr_in * address) +{ + memcpy(address, &client->address, sizeof (struct sockaddr_in)); +} diff --git a/src/buffer.c b/src/buffer.c index 2aef473..765d2eb 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -19,169 +19,157 @@ static int32_t -buffer_set_size(buffer_t buffer, int32_t new_size) +buffer_set_size(struct buffer *buffer, int32_t new_size) { - if ( new_size != buffer->size ) - { - if (new_size) - { - int32_t s = new_size / 1024; + if (new_size != buffer->size) { + char *data; - if ( new_size % 1024 ) - { - new_size = (s+1) * 1024; - } - } - else - new_size = 16*1024; + if (new_size) { + int32_t s = new_size / 1024; - char * data = realloc(buffer->data, new_size); + if ( new_size % 1024 ) { + new_size = (s+1) * 1024; + } + } else { + new_size = 16*1024; + } - if (data) - { - buffer->data = data; - buffer->size = new_size; - } - else - new_size = -1; - } + if ((data = realloc(buffer->data, new_size)) != NULL) { + buffer->data = data; + buffer->size = new_size; + } else { + new_size = -1; + } + } - return new_size; + return new_size; } int32_t -buffer_init( buffer_t buffer, int32_t size ) +buffer_init(struct buffer *buffer, int32_t size) { - if ( (size = buffer_set_size(buffer, size)) != -1) - buffer->used = 0; + if ( (size = buffer_set_size(buffer, size)) != -1) + buffer->used = 0; - return size; + return size; } void -buffer_release( buffer_t buffer ) +buffer_release(struct buffer *buffer) { - if (buffer->data) - { - free(buffer->data); - buffer->data = NULL; - } + if (buffer->data) { + free(buffer->data); + buffer->data = NULL; + } - buffer->used = 0; - buffer->size = 0; + buffer->used = 0; + buffer->size = 0; } static int32_t -buffer_move_offset( buffer_t buffer, int32_t offset, int32_t size ) +buffer_move_offset(struct buffer *buffer, int32_t offset, int32_t size) { - int32_t to_move = buffer->used - offset; + int32_t to_move = buffer->used - offset; - if (to_move < 0) - return -1; - else if (to_move) - memmove(&buffer->data[offset+size], &buffer->data[offset], to_move); + if (to_move < 0) { + return -1; + } else if (to_move) { + memmove(&buffer->data[offset+size], &buffer->data[offset], to_move); + } - return size; + return size; } int32_t -buffer_insert( buffer_t buffer - , int32_t offset - , const char * data - , int32_t size ) +buffer_insert(struct buffer *buffer, + int32_t offset, + const char *data, + int32_t size) { - int32_t result; + int32_t result; - if ( (result = buffer_set_size(buffer, size)) != -1) - { - if ((result = buffer_move_offset(buffer, offset, size)) != -1) - { - memcpy(&buffer->data[offset], data, size); - buffer->used += result; - } - } + if ( (result = buffer_set_size(buffer, size)) != -1) { + if ((result = buffer_move_offset(buffer, offset, size)) != -1) { + memcpy(&buffer->data[offset], data, size); + buffer->used += result; + } + } - return result; + return result; } int32_t -buffer_append_printf( buffer_t buffer, const char * format, ... ) +buffer_append_printf(struct buffer *buffer, const char *format, ...) { - int32_t result; - va_list args; + int32_t result; + va_list args; - va_start(args, format); - result = buffer_append_vprintf( buffer, format, args); - va_end(args); + va_start(args, format); + result = buffer_append_vprintf(buffer, format, args); + va_end(args); - return result; + return result; } int32_t -buffer_append_vprintf( buffer_t buffer, const char * format, va_list args ) +buffer_append_vprintf(struct buffer *buffer, const char *format, va_list args) { - int32_t space = buffer->size - buffer->used, - result; + int32_t space, result; + va_list cp_args; - va_list cp_args; - va_copy(cp_args, args); + va_copy(cp_args, args); + space = buffer->size - buffer->used, + result = vsnprintf(&buffer->data[buffer->used], space, format, args); - result = vsnprintf( &buffer->data[buffer->used], space, format, args ); + if (result < space) { /* enough space */ + buffer->used += result; + } else { + result = buffer_set_size(buffer, buffer->size + result - space); + if (result != -1) + result = buffer_append_vprintf(buffer, format, cp_args); + } + va_end(cp_args); - if ( result < space ) /* enough space */ - { - buffer->used += result; - } - else - { - if ((result = buffer_set_size(buffer, buffer->size + result - space)) != -1) - result = buffer_append_vprintf(buffer, format, cp_args); - } - va_end(cp_args); - - return result; + return result; } int32_t -buffer_append( buffer_t buffer, const char * data, int32_t size ) +buffer_append(struct buffer *buffer, const char *data, int32_t size) { - int32_t used = buffer->used, - space = buffer->size - used; + int32_t used, space; + + used = buffer->used, + space = buffer->size - used; - if ( size > space ) /* enough space */ - { - if ( buffer_set_size(buffer, buffer->size + size - space) == -1) - return -1; - } + if (size > space) { /* enough space */ + if (buffer_set_size(buffer, buffer->size + size - space) == -1) + return -1; + } - memcpy(&buffer->data[used], data, size); - buffer->used += size; + memcpy(&buffer->data[used], data, size); + buffer->used += size; - return size; + return size; } int32_t -buffer_shift( buffer_t buffer, int32_t offset ) +buffer_shift(struct buffer *buffer, int32_t offset) { - int32_t used = buffer->used - offset; + int32_t used = buffer->used - offset; - if (offset > 0) - { - if (offset < used) - { - memmove(buffer->data, &buffer->data[offset], used); - } - else - used = 0; - - buffer->used = used; - } - - return used; + if (offset > 0) { + if (offset < used) { + memmove(buffer->data, &buffer->data[offset], used); + } else { + used = 0; + } + buffer->used = used; + } + return used; } diff --git a/src/buffer.h b/src/buffer.h index 81854f5..e86e34d 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -6,9 +6,9 @@ ******************************************************************************/ /** - * @file buffer.h + * @file src/buffer.h * @author Ilja Kartašov - * @brief Buffer module header file + * @brief Declarations of struct buffer and functions * * @see https://lowenware.com/aisl/ */ @@ -20,42 +20,39 @@ #include -struct buffer -{ - char * data; - int32_t size; - int32_t used; +struct buffer { + char *data; + int32_t size; + int32_t used; }; -typedef struct buffer * buffer_t; - int32_t -buffer_init( buffer_t buffer, int32_t size ); +buffer_init(struct buffer *bs, int32_t size); void -buffer_release( buffer_t buffer ); +buffer_release(struct buffer *bs ); int32_t -buffer_insert(buffer_t buffer, int32_t offset, const char * data, int32_t size); +buffer_insert(struct buffer *bs, int32_t offset, const char *data, int32_t size); int32_t -buffer_append_printf( buffer_t buffer, const char * format, ... ); +buffer_append_printf(struct buffer *bs, const char *format, ...); int32_t -buffer_append_vprintf( buffer_t buffer, const char * format, va_list args ); +buffer_append_vprintf(struct buffer *bs, const char *format, va_list args); int32_t -buffer_append( buffer_t buffer, const char * data, int32_t size ); +buffer_append(struct buffer *bs, const char *data, int32_t size); int32_t -buffer_shift( buffer_t buffer, int32_t size ); +buffer_shift(struct buffer *bs, int32_t size); diff --git a/src/client.c b/src/client.c index 0afae31..8d9152f 100644 --- a/src/client.c +++ b/src/client.c @@ -27,115 +27,87 @@ static void -aisl_client_close(aisl_client_t client, aisl_status_t status) +aisl_client_close(AislClient client, AislStatus status) { - if (client->fd != -1) - { - aisl_raise( - client->server->instance - , (void *)client - , AISL_EVENT_CLIENT_DISCONNECT - , status - ); + if (client->fd != -1) { + aisl_raise(client->server->instance, (void *)client, + AISL_EVENT_CLIENT_DISCONNECT, status ); - close(client->fd); - shutdown(client->fd, SHUT_RDWR); - client->fd = -1; - } + close(client->fd); + shutdown(client->fd, SHUT_RDWR); + client->fd = -1; + } } -static aisl_status_t -aisl_client_parse(aisl_client_t client, char * data, int32_t size) +static AislStatus +aisl_client_parse(AislClient client, char *data, int32_t size) { - aisl_status_t result = AISL_SUCCESS; - aisl_stream_t s = client->stream; - http_parser_t p = HTTP_PARSER_SUCCESS; + AislStatus result = AISL_SUCCESS; + AislStream s = client->stream; + ParserStatus p = HTTP_PARSER_SUCCESS; + int32_t bytes_left = size; - int32_t bytes_left = size; + switch (client->http_version) { + case AISL_HTTP_0_9: + case AISL_HTTP_1_0: + case AISL_HTTP_1_1: + while (p == HTTP_PARSER_SUCCESS) { + switch (aisl_stream_get_state(s)) { + case AISL_STREAM_STATE_IDLE: + p = http_10_parse_request(data, &size, client->stream); + break; - switch (client->http_version) - { - case AISL_HTTP_0_9: - case AISL_HTTP_1_0: - case AISL_HTTP_1_1: + case AISL_STREAM_STATE_WAIT_HEADER: + p = http_10_parse_header(data, &size, client->stream); + break; - /* s = client->stream; */ + case AISL_STREAM_STATE_WAIT_BODY: + p = http_10_parse_body(data, &size, client->stream); + break; - while ( p == HTTP_PARSER_SUCCESS ) - { + default: /* has input data, but request was already parsed */ + p = HTTP_PARSER_ERROR; + continue; + } + // size now has number of parsed bytes + data += size; + bytes_left -= size; + size = bytes_left; + } + break; - switch ( aisl_stream_get_state(s) ) - { - case AISL_STREAM_STATE_IDLE: - p = http_10_parse_request(data, &size, client->stream); - break; + case AISL_HTTP_2_0: + break; + } - case AISL_STREAM_STATE_WAIT_HEADER: - p = http_10_parse_header(data, &size, client->stream); - break; + switch(p) { + case HTTP_PARSER_READY: + client->flags &= ~FLAG_CAN_READ; + client->flags |= FLAG_CAN_WRITE; - case AISL_STREAM_STATE_WAIT_BODY: - p = http_10_parse_body(data, &size, client->stream); - break; + aisl_raise(client->server->instance, (void *)s, AISL_EVENT_STREAM_REQUEST, + result); + break; - default: /* has input data, but request was already parsed */ - p = HTTP_PARSER_ERROR; - continue; - } - // size now has number of parsed bytes - data += size; - bytes_left -= size; - size = bytes_left; - } + case HTTP_PARSER_ERROR: + /* reply Bad Request here */ + client->stream->http_response = AISL_HTTP_BAD_REQUEST; + aisl_raise(client->server->instance, (void *)s, AISL_EVENT_STREAM_ERROR, + result); + aisl_client_close(client, result); + return result; + default: + break; + } - break; + if (size) + buffer_shift(&client->in, client->in.used - size); /* reset buffer */ - case AISL_HTTP_2_0: - - break; - } - - switch(p) - { - case HTTP_PARSER_READY: - client->flags &= ~FLAG_CAN_READ; - client->flags |= FLAG_CAN_WRITE; - - aisl_raise( - client->server->instance - , (void *) s - , AISL_EVENT_STREAM_REQUEST - , result - ); - break; - - case HTTP_PARSER_ERROR: - /* reply Bad Request here */ - client->stream->http_response = AISL_HTTP_BAD_REQUEST; - - aisl_raise( - client->server->instance - , (void *) s - , AISL_EVENT_STREAM_ERROR - , result - ); - - aisl_client_close(client, result); - - return result; - - default: - break; - } - - if (size) - buffer_shift(&client->in, client->in.used - size); /* reset buffer */ - - return result; + return result; } @@ -143,344 +115,279 @@ aisl_client_parse(aisl_client_t client, char * data, int32_t size) * parsed. If it is not NULL, then stream expects additional data -> same like * in mono stream HTTP 1.0 */ -static aisl_status_t -aisl_client_input(aisl_client_t client) +static AislStatus +aisl_client_input(AislClient client) { - int l; + int l; + char *data = &client->in.data[ client->in.used ]; + int32_t size = client->in.size - client->in.used; - char * data = &client->in.data[ client->in.used ]; - int32_t size = client->in.size - client->in.used; + #ifndef AISL_WITHOUT_SSL + if (client->ssl) { + DPRINTF("SSL_read"); + if (!(client->flags & FLAG_HANDSHAKE)) { + if ( (l = SSL_accept(client->ssl)) != 1 ) { + l = SSL_get_error(client->ssl, l); - #ifndef AISL_WITHOUT_SSL - if (client->ssl) - { - DPRINTF("SSL_read"); - if ( !(client->flags & FLAG_HANDSHAKE) ) - { - if ( (l = SSL_accept(client->ssl)) != 1 ) - { - l = SSL_get_error(client->ssl, l); + if (l == SSL_ERROR_WANT_READ || l == SSL_ERROR_WANT_WRITE) + return AISL_IDLE; - if (l == SSL_ERROR_WANT_READ || l == SSL_ERROR_WANT_WRITE) - return AISL_IDLE; + DPRINTF("SSL handshake fail: %s\n", ERR_error_string(l, NULL) ); - DPRINTF("SSL handshake fail: %s\n", ERR_error_string(l, NULL) ); + aisl_client_close(client, AISL_EXTCALL_ERROR); + return AISL_EXTCALL_ERROR; + } + client->flags &= ~FLAG_HANDSHAKE; + } + l = SSL_read(client->ssl, data, size); + } else + #endif + { + l = recv( client->fd, data, size, 0); + } - aisl_client_close(client, AISL_EXTCALL_ERROR); - return AISL_EXTCALL_ERROR; - } + if (l > 0) { + DPRINTF("%d bytes received from client", l); - client->flags &= ~FLAG_HANDSHAKE; - } + data = client->in.data; + size = client->in.used + l; + client->in.used = size; + return aisl_client_parse(client, data, size); + } else if (l<0) { - l = SSL_read(client->ssl, data, size) ; - } - else - #endif - l = recv( client->fd, data, size, 0); + #ifndef AISL_WITHOUT_SSL + if (client->ssl) { + if (SSL_get_error(client->ssl, l) == SSL_ERROR_WANT_READ) + return AISL_IDLE; + } else + #endif + { - if (l > 0) - { - DPRINTF("%d bytes received from client", l); + if(errno == EWOULDBLOCK) + return AISL_IDLE; + DPRINTF("client - %s", strerror(errno)); + } + } - data = client->in.data; - size = client->in.used + l; + /* both: client disconnect + on read error */ + /* todo: raise client error here */ + aisl_client_close(client, AISL_SYSCALL_ERROR); - client->in.used = size; - - return aisl_client_parse(client, data, size); - } - else if (l<0) - { - #ifndef AISL_WITHOUT_SSL - if (client->ssl) - { - if (SSL_get_error(client->ssl, l) == SSL_ERROR_WANT_READ) - return AISL_IDLE; - } - else - #endif - { - if(errno == EWOULDBLOCK) - return AISL_IDLE; - - DPRINTF("client - %s", strerror(errno)); - } - } - - /* both: client disconnect + on read error */ - /* todo: raise client error here */ - aisl_client_close(client, AISL_SYSCALL_ERROR); - - return AISL_SYSCALL_ERROR; + return AISL_SYSCALL_ERROR; } -static aisl_status_t -aisl_client_output(aisl_client_t client) +static AislStatus +aisl_client_output(AislClient client) { - int l; - char * data; + int l; + char *data; - aisl_stream_t s = client->stream; + AislStream s = client->stream; - /* while stream is not flushed, we should raise event */ - if( aisl_get_output_event(s) ) - { - /* in case of chunked output ( subscription for AISL_STREAM_OUTPUT event ) - * stream buffer will be initialized with OUTPUT_BUFFER_SIZE size, but - * buffer->size will be used to carry amount of stored bytes - * */ - l = aisl_stream_get_buffer_space(s); + /* while stream is not flushed, we should raise event */ + if(aisl_get_output_event(s)) { + /* in case of chunked output ( subscription for AISL_STREAM_OUTPUT event ) + * stream buffer will be initialized with OUTPUT_BUFFER_SIZE size, but + * buffer->size will be used to carry amount of stored bytes + * */ + l = aisl_stream_get_buffer_space(s); - /* - if (bsz < OUTPUT_BUFFER_SIZE) - { - if (buffer_clear(s->buffer, OUTPUT_BUFFER_SIZE) == 0) - return false; + /* + if (bsz < OUTPUT_BUFFER_SIZE) + { + if (buffer_clear(s->buffer, OUTPUT_BUFFER_SIZE) == 0) + return false; - s->buffer->size = bsz; - bsz = OUTPUT_BUFFER_SIZE; - } - */ + s->buffer->size = bsz; + bsz = OUTPUT_BUFFER_SIZE; + } + */ - if ( !(l < aisl_stream_get_buffer_size(s) / 2) ) - { - aisl_raise( - client->server->instance - , (void*)s - , AISL_EVENT_STREAM_OUTPUT - , AISL_SUCCESS - ); - } - } + if (!(l < aisl_stream_get_buffer_size(s) / 2)) { + aisl_raise(client->server->instance, (void*)s, AISL_EVENT_STREAM_OUTPUT, + AISL_SUCCESS); + } + } - data = aisl_stream_get_data(s, &l); + data = aisl_stream_get_data(s, &l); - if ( !l ) - return AISL_IDLE; + if ( !l ) + return AISL_IDLE; - #ifdef AISL_WITHOUT_SSL - l = send( client->fd, data, l, 0); - #else - l = (client->ssl) ? - SSL_write(client->ssl, data, l) : - send( client->fd, data, l, 0); - #endif + #ifdef AISL_WITHOUT_SSL + l = send( client->fd, data, l, 0); + #else + l = (client->ssl) ? + SSL_write(client->ssl, data, l) : + send( client->fd, data, l, 0); + #endif - if (l > 0) - { - aisl_stream_shift(s, l); + if (l > 0) { + aisl_stream_shift(s, l); + if ( aisl_stream_is_done(s) ) { + /* data has been sent */ + if (client->flags & FLAG_KEEPALIVE) { + aisl_stream_free(s); - /* - if (s->state == STREAM_RESPONSE_READY && / * flushed * / - s->buffer->size == 0) / * all sent * / - */ - if ( aisl_stream_is_done(s) ) - { - /* buffer_clear(s->buffer, 0); */ + client->stream = aisl_stream_new(client, client->next_id++); + if (client->stream != NULL ) + return AISL_SUCCESS; - /* data has been sent */ + /* in case of malloc error it will not be error as long as request was + * handled and we just close the connection. + */ + } - if (client->flags & FLAG_KEEPALIVE) - { - aisl_stream_free(s); + aisl_client_close(client, AISL_SUCCESS); + } - client->stream = aisl_stream_new(client, client->next_id++); - if (client->stream != NULL ) - return AISL_SUCCESS; + return AISL_SUCCESS; + } - /* in case of malloc error it will not be error as long as request was - * handled and we just close the connection. - */ - } + /* l < 0 */ + #ifndef AISL_WITHOUT_SSL + if (client->ssl) { + if (SSL_get_error(client->ssl, l) == SSL_ERROR_WANT_WRITE) + return AISL_IDLE; + } else + #endif + { + if (errno == EWOULDBLOCK) + return AISL_IDLE; + } + aisl_client_close(client, AISL_SYSCALL_ERROR); - aisl_client_close(client, AISL_SUCCESS); - } - - return AISL_SUCCESS; - } - - /* l < 0 */ - #ifndef AISL_WITHOUT_SSL - if (client->ssl) - { - if ( SSL_get_error(client->ssl, l) == SSL_ERROR_WANT_WRITE ) - return AISL_IDLE; - } - else - #endif - { - if (errno == EWOULDBLOCK) - return AISL_IDLE; - } - - aisl_client_close(client, AISL_SYSCALL_ERROR); - - return AISL_SYSCALL_ERROR; + return AISL_SYSCALL_ERROR; } -aisl_client_t -aisl_client_new( aisl_server_t server, - int fd, - struct sockaddr_in * addr ) +AislClient +aisl_client_new(AislServer server, int fd, struct sockaddr_in *addr) { - aisl_client_t client; - aisl_stream_t stream; + AislClient client; + AislStream stream; - if ( (client = calloc(1, sizeof(struct aisl_client))) != NULL ) - { - DPRINTF("client alocated"); - memcpy(&client->address, addr, sizeof(struct sockaddr_in)); - client->server = server; - client->fd = fd; - client->next_id = 2; - client->http_version = AISL_HTTP_1_0; - client->timestamp = time(NULL); - client->flags = FLAG_KEEPALIVE | FLAG_HANDSHAKE | FLAG_CAN_READ; + if ((client = calloc(1, sizeof (struct aisl_client))) != NULL) { + DPRINTF("client alocated"); + memcpy(&client->address, addr, sizeof (struct sockaddr_in)); + client->server = server; + client->fd = fd; + client->next_id = 2; + client->http_version = AISL_HTTP_1_0; + client->timestamp = time(NULL); + client->flags = FLAG_KEEPALIVE | FLAG_HANDSHAKE | FLAG_CAN_READ; - if (buffer_init(&client->in, 2*BUFFER_SIZE) != -1) - { - DPRINTF("client buffer alocated"); - memcpy(&client->out, &client->in, sizeof(struct buffer)); + if (buffer_init(&client->in, 2*BUFFER_SIZE) != -1) { + DPRINTF("client buffer alocated"); + memcpy(&client->out, &client->in, sizeof (struct buffer)); - stream = aisl_stream_new(client, 0); + stream = aisl_stream_new(client, 0); - if (stream != NULL) - { - client->stream = stream; + if (stream != NULL) { + client->stream = stream; + DPRINTF("client stream alocated"); - DPRINTF("client stream alocated"); + #ifndef AISL_WITHOUT_SSL + if (server->ssl) { + SSL_CTX * ssl_ctx = aisl_get_ssl_ctx(server->instance, NULL); - #ifdef AISL_WITHOUT_SSL - - return client; - - #else - - SSL_CTX * ssl_ctx; - - if ( !server->ssl ) - return client; - - ssl_ctx = aisl_get_ssl_ctx(server->instance, NULL); - - if ((client->ssl = SSL_new(ssl_ctx)) != NULL ) - { - SSL_set_fd(client->ssl, fd); - return client; - } - - #endif - } - } - aisl_client_free(client); - - } - - return NULL; + if ((client->ssl = SSL_new(ssl_ctx)) != NULL ) { + SSL_set_fd(client->ssl, fd); + return client; + } + } else { + return client; + } + #else + return client; + #endif + } + } + aisl_client_free(client); + } + return NULL; } void -aisl_client_free(aisl_client_t client) +aisl_client_free(AislClient client) { - aisl_client_close(client, AISL_SUCCESS); + aisl_client_close(client, AISL_SUCCESS); - #ifndef AISL_WITHOUT_SSL - if (client->ssl) - SSL_free(client->ssl); - #endif + #ifndef AISL_WITHOUT_SSL + if (client->ssl) + SSL_free(client->ssl); + #endif - if (client->in.data) - free(client->in.data); + if (client->in.data) + free(client->in.data); - /* out buffer is a shared part of input buffer, so no need to free it */ + if (client->stream) + aisl_stream_free(client->stream); - if (client->stream) - aisl_stream_free(client->stream); - - free(client); + free(client); } -aisl_status_t -aisl_client_touch(aisl_client_t client, int32_t timeout) +AislStatus +aisl_client_touch(AislClient client, int32_t timeout) { - aisl_status_t result = AISL_IDLE, - status = AISL_IDLE; + AislStatus result, status; + + result = AISL_IDLE; + status = AISL_IDLE; - /* input */ - if (client->flags & FLAG_CAN_READ) - { - if ( (result = aisl_client_input(client)) < 0 ) - return result; - } + /* input */ + if (client->flags & FLAG_CAN_READ) { + if ( (result = aisl_client_input(client)) < 0 ) + return result; + } - /* output */ - if (client->flags & FLAG_CAN_WRITE) - { - if ( (status = aisl_client_output(client)) < 0 ) - return status; - } + /* output */ + if (client->flags & FLAG_CAN_WRITE) { + if ( (status = aisl_client_output(client)) < 0 ) + return status; + } + if (result == AISL_IDLE) + result = status; - /* - if ((client->http_version==AISL_HTTP_2_0 || s->statestreams, client->ostream); + if (result != AISL_SUCCESS) { + time_t now; + time(&now); - if ( s->flags & (STREAM_FLAG_OUTPUT_READY | STREAM_FLAG_OUTPUT_CHUNKED) ) - result = client_output(client); - */ - /* update timestamp */ - - if (result == AISL_IDLE) - result = status; - - if (result == AISL_SUCCESS) - client->timestamp = time(NULL); - else - { - time_t now; - time(&now); - - if ( !(now - client->timestamp < timeout) ) - { - aisl_client_close(client, result); - } - } - - - return result; + if (!(now - client->timestamp < timeout)) { + aisl_client_close(client, result); + } + } else { + client->timestamp = time(NULL); + } + return result; } int -aisl_client_get_socket(aisl_client_t client) +aisl_client_get_socket(AislClient client) { - return client->fd; + return client->fd; } bool -aisl_client_get_keepalive(aisl_client_t client) +aisl_client_get_keepalive(AislClient client) { - return (client->flags & FLAG_KEEPALIVE); + return (client->flags & FLAG_KEEPALIVE); } void -aisl_client_set_keepalive(aisl_client_t client, bool value) +aisl_client_set_keepalive(AislClient client, bool value) { - if (value) - client->flags |= FLAG_KEEPALIVE; - else - client->flags &= ~FLAG_KEEPALIVE; + if (value) + client->flags |= FLAG_KEEPALIVE; + else + client->flags &= ~FLAG_KEEPALIVE; } @@ -488,52 +395,52 @@ aisl_client_set_keepalive(aisl_client_t client, bool value) /* API Level ---------------------------------------------------------------- */ __attribute__ ((visibility ("default") )) -aisl_server_t -aisl_client_get_server(aisl_client_t client) +AislServer +aisl_client_get_server(AislClient client) { - return client->server; + return client->server; } __attribute__ ((visibility ("default") )) bool -aisl_client_is_secure(aisl_client_t client) +aisl_client_is_secure(AislClient client) { - #ifdef AISL_WITHOUT_SSL - return false; - #else - return (client->ssl == NULL) ? false : true; - #endif + #ifdef AISL_WITHOUT_SSL + return false; + #else + return (client->ssl == NULL) ? false : true; + #endif } __attribute__ ((visibility ("default") )) bool -aisl_client_is_online(aisl_client_t client) +aisl_client_is_online(AislClient client) { - return (client->fd == -1) ? false : true; + return (client->fd == -1) ? false : true; } __attribute__ ((visibility ("default") )) void -aisl_client_disconnect(aisl_client_t client) +aisl_client_disconnect(AislClient client) { - aisl_client_close(client, AISL_SUCCESS); + aisl_client_close(client, AISL_SUCCESS); } __attribute__ ((visibility ("default") )) -aisl_http_version_t -aisl_client_get_http_version(aisl_client_t client) +AislHttpVersion +aisl_client_get_http_version(AislClient client) { - return client->http_version; + return client->http_version; } __attribute__ ((visibility ("default") )) void -aisl_client_get_address( aisl_client_t client, struct sockaddr_in * address) +aisl_client_get_address(AislClient client, struct sockaddr_in *address) { - memcpy(address, &client->address, sizeof(struct sockaddr_in)); + memcpy(address, &client->address, sizeof (struct sockaddr_in)); } diff --git a/src/client.h b/src/client.h index 4aa2728..e452e11 100644 --- a/src/client.h +++ b/src/client.h @@ -1,3 +1,17 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file client.h + * @author Ilja Kartašov + * @brief Declarations of aisl_client structure and functions + * + * @see https://lowenware.com/aisl/ + */ #ifndef AISL_CLIENT_H_164FE6B2_E5D4_4968_B50F_823E30E8F777 #define AISL_CLIENT_H_164FE6B2_E5D4_4968_B50F_823E30E8F777 @@ -6,86 +20,83 @@ #include #include "buffer.h" -#define AISL_CLIENT(x) ((aisl_client_t) x) +#define AISL_CLIENT(x) ((AislClient) x) -struct aisl_client -{ - struct sockaddr_in address; /**< Client's address structure. */ - aisl_server_t server; /**< Server instance. */ - struct buffer in; /**< Client's input buffer. */ - struct buffer out; /**< Client's output buffer. */ - #ifndef AISL_WITHOUT_SSL - SSL * ssl; /**< SSL pointer for HTTPS. */ - #endif - time_t timestamp; /**< Last communication timestamp. */ - - aisl_stream_t stream; /**< Pending client's stream. */ - int next_id; /**< Stream id generator (even). */ - int flags; /**< Client's flag bitmask. */ - int fd; /**< Client's socket descriptor. */ - - aisl_http_version_t http_version; /**< Client's http_version version. */ +struct aisl_client { + struct sockaddr_in address; /**< Client's address structure. */ + struct buffer in; /**< Client's input buffer. */ + struct buffer out; /**< Client's output buffer. */ + AislServer server; /**< Server instance. */ + AislStream stream; /**< Pending client's stream. */ + #ifndef AISL_WITHOUT_SSL + SSL *ssl; /**< SSL pointer for HTTPS. */ + #endif + time_t timestamp; /**< Last communication timestamp. */ + int next_id; /**< Stream id generator (even). */ + int flags; /**< Client's flag bitmask. */ + int fd; /**< Client's socket descriptor. */ + AislHttpVersion http_version; /**< Client's http_version version. */ }; /** - * @brief Constructor for #aisl_client_t instance. - * @param server an #aisl_server_t instance pointer. + * @brief Constructor for #AislClient instance. + * @param server an #AislServer instance pointer. * @param fd a client socket descriptor. * @param addr a pointer to client's address structure. * @param ssl_ctx a pointer to SSL context or NULL if encryption is disabled */ -aisl_client_t -aisl_client_new( aisl_server_t server, - int fd, - struct sockaddr_in * addr ); +AislClient +aisl_client_new(AislServer server, + int fd, + struct sockaddr_in *addr ); /** - * @brief Destructor for #aisl_client_t instance. - * @param client an #aisl_client_t instance pointer. + * @brief Destructor for #AislClient instance. + * @param client an #AislClient instance pointer. */ void -aisl_client_free(aisl_client_t client); +aisl_client_free(AislClient client); /** * @brief Does all HTTP client routines. * Reads and parses requests, writes responses. - * @param client an #aisl_client_t instance pointer. + * @param client an #AislClient instance pointer. * @param timeout an allowed client silence time in seconds. - * @return #aisl_status_t code. + * @return #AislStatus code. */ -aisl_status_t -aisl_client_touch(aisl_client_t client, int32_t timeout); +AislStatus +aisl_client_touch(AislClient client, int32_t timeout); /** * @Brief Checks if client is about to keep connection alive. - * @param client an #aisl_client_t instance pointer. + * @param client an #AislClient instance pointer. * @return true if keepalive mode is on, otherwise false. */ bool -aisl_client_get_keepalive(aisl_client_t client); +aisl_client_get_keepalive(AislClient client); /** * @Brief Sets if connection with client must be kept alive. - * @param client an #aisl_client_t instance pointer. + * @param client an #AislClient instance pointer. * @param value a true to enable keepalive mode, false to disable. */ void -aisl_client_set_keepalive(aisl_client_t client, bool value); +aisl_client_set_keepalive(AislClient client, bool value); /** - * @brief Gets socket descriptor associated with #aisl_client_t instance. - * @param client an #aisl_client_t instance pointer. + * @brief Gets socket descriptor associated with #AislClient instance. + * @param client an #AislClient instance pointer. * @return a client socket descriptor. */ int -aisl_client_get_socket(aisl_client_t client); +aisl_client_get_socket(AislClient client); #endif /* !AISL_CLIENT_H */ diff --git a/src/http.c b/src/http.c index df57c19..181a9c4 100644 --- a/src/http.c +++ b/src/http.c @@ -20,319 +20,277 @@ #include "debug.h" #include "http.h" -struct http_request + +static AislHttpMethod +http_method_from_string(const char *method, int32_t length) { - char * method; - char * schema; - char * host; - char * port; - char * path; - char * version; - char * newline; - int32_t method_len; - int32_t schema_len; - int32_t host_len; - int32_t port_len; - int32_t path_len; - int32_t version_len; -}; + int i; + AislHttpMethod methods[3] = {0, 0, 0}; -typedef struct http_request * http_request_t; + switch(length) { + case 3: + methods[0] = AISL_HTTP_GET; + methods[1] = AISL_HTTP_PUT; + methods[2] = AISL_HTTP_PRI; + break; -static aisl_http_method_t -http_method_from_string( const char * method, int32_t length ) -{ - int i; - aisl_http_method_t methods[3] = {0, 0, 0}; + case 4: + methods[0] = AISL_HTTP_POST; + methods[1] = AISL_HTTP_HEAD; + break; - switch(length) - { - case 3: - methods[0] = AISL_HTTP_GET; - methods[1] = AISL_HTTP_PUT; - methods[2] = AISL_HTTP_PRI; - break; + case 5: + methods[0] = AISL_HTTP_TRACE; + break; - case 4: - methods[0] = AISL_HTTP_POST; - methods[1] = AISL_HTTP_HEAD; - break; + case 6: + methods[0] = AISL_HTTP_DELETE; + break; - case 5: - methods[0] = AISL_HTTP_TRACE; - break; + case 7: + methods[0] = AISL_HTTP_OPTIONS; + methods[1] = AISL_HTTP_CONNECT; + break; + } - case 6: - methods[0] = AISL_HTTP_DELETE; - break; + for (i=0; i host) - { - path = data; - if (!uri) - uri = path; - } - else if (version && data-version != 4) - return HTTP_PARSER_ERROR; - break; + case '/': + if (!path && data > host) { + path = data; + if (!uri) + uri = path; + } else if (version && data-version != 4) { + return HTTP_PARSER_ERROR; + } + break; - case '?': - if (!query) - query = data+1; - else if (version) - return HTTP_PARSER_ERROR; - break; + case '?': + if (!query) + query = data+1; + else if (version) + return HTTP_PARSER_ERROR; + break; - case '\n': - newline = data; - break; + case '\n': + newline = data; + break; - case '\r': - if (!version) - return HTTP_PARSER_ERROR; - break; + case '\r': + if (!version) + return HTTP_PARSER_ERROR; + break; - default: - if (!uri && method_end) - uri = data; - else if (!version && uri_end) - version = data; - else if (version && data-version > 7) - return HTTP_PARSER_ERROR; + default: + if (!uri && method_end) + uri = data; + else if (!version && uri_end) + version = data; + else if (version && data-version > 7) + return HTTP_PARSER_ERROR; + } + data++; + } - } - data++; - } + /* STEP 2. Verifly splitting was completed */ + /* Was request sent? */ + if (!newline) + return HTTP_PARSER_HUNGRY; - /* STEP 2. Verifly splitting was completed */ + /* Check mandatory parts presence */ + if (!method_end || !path || !uri_end || !version) + return HTTP_PARSER_ERROR; - /* Was request sent? */ - if (!newline) - return HTTP_PARSER_HUNGRY; + *method_end = 0; + *newline = 0; + *uri_end = 0; + http_method = http_method_from_string(method, method_end - method); + if (http_method == AISL_HTTP_METHOD_UNKNOWN) + return HTTP_PARSER_ERROR; - /* Check mandatory parts presence */ - if (!method_end || !path || !uri_end || !version) - return HTTP_PARSER_ERROR; + if ((http_version = http_version_from_string(version))==0) + return HTTP_PARSER_ERROR; - *method_end = 0; - *newline = 0; - *uri_end = 0; + if (query) { + *(query-1)=0; + } else { + query = uri_end; + } - http_method = http_method_from_string(method, method_end - method); - if (http_method == AISL_HTTP_METHOD_UNKNOWN) - return HTTP_PARSER_ERROR; + if (host) { + if (strncmp(uri, "http://", 7) || strncmp(uri, "https://", 8)) + return HTTP_PARSER_ERROR; + + if (port) + *(port-1)=0; + } - if ((http_version = http_version_from_string(version))==0) - return HTTP_PARSER_ERROR; + stream->client->http_version = http_version; + aisl_stream_set_request(stream, http_method, path, query); - if (query) - { - *(query-1)=0; - } - else - query = uri_end; - - if (host) - { - if (strncmp(uri, "http://", 7) || strncmp(uri, "https://", 8)) - return HTTP_PARSER_ERROR; - - if (port) - *(port-1)=0; - } - - stream->client->http_version = http_version; - - aisl_stream_set_request(stream, http_method, path, query); - - if (host) - aisl_stream_set_header(stream, "host", host); - - /* how many characters has been read */ - *(p_size)-=size; - return HTTP_PARSER_SUCCESS; + if (host) + aisl_stream_set_header(stream, "host", host); + /* how many characters has been read */ + *(p_size)-=size; + return HTTP_PARSER_SUCCESS; } -http_parser_t -http_10_parse_header(char * data, int32_t * p_size, aisl_stream_t stream) +ParserStatus +http_10_parse_header(char *data, int32_t *p_size, AislStream stream) { - int32_t size = *p_size; - char * key = data, - * colon = NULL, - * val = NULL, - * val_end = NULL, - * newline = NULL; + int32_t size = *p_size; + char *key = data, + *colon = NULL, + *val = NULL, + *val_end = NULL, + *newline = NULL; - while(!newline && size-- ) - { - switch(*data) - { - case ' ': - if (val && !val_end) - val_end = data; - break; + while(!newline && size-- ) { + switch(*data) { + case ' ': + if (val && !val_end) + val_end = data; + break; - case ':': - if (!colon) - { - if (colon == key) - return HTTP_PARSER_ERROR; + case ':': + if (!colon) { + if (colon == key) + return HTTP_PARSER_ERROR; - colon = data; - } - break; + colon = data; + } + break; - case '\n': - newline = data; + case '\n': + newline = data; - case '\r': - if (!val_end && val) - val_end = data; - break; + case '\r': + if (!val_end && val) + val_end = data; + break; - default: - if (!colon) - { - *data = tolower(*data); - } - else if (!val) - { - if (colon) - val = data; - } + default: + if (!colon) { + *data = tolower(*data); + } else if (!val) { + if (colon) + val = data; + } - if (val_end) - val_end = NULL; + if (val_end) + val_end = NULL; + } + data++; + } - } - data++; - } + if (!newline) + return HTTP_PARSER_HUNGRY; - if (!newline) - return HTTP_PARSER_HUNGRY; - - if (colon && val && val_end) - { - *colon = 0; - *val_end = 0; - - aisl_stream_set_header(stream, key, val); - - *p_size -= size; - - return HTTP_PARSER_SUCCESS; - } - else if (newline == key || (newline == key+1 && *key == '\r')) - { - return (aisl_stream_set_end_of_headers(stream) == 0) ? HTTP_PARSER_READY : - HTTP_PARSER_SUCCESS; - } - - return HTTP_PARSER_ERROR; + if (colon && val && val_end) { + *colon = 0; + *val_end = 0; + aisl_stream_set_header(stream, key, val); + *p_size -= size; + return HTTP_PARSER_SUCCESS; + } else if (newline == key || (newline == key+1 && *key == '\r')) { + return (aisl_stream_set_end_of_headers(stream) == 0) ? + HTTP_PARSER_READY : HTTP_PARSER_SUCCESS; + } + return HTTP_PARSER_ERROR; } -http_parser_t -http_10_parse_body(char * data, int32_t * p_size, aisl_stream_t stream) +ParserStatus +http_10_parse_body(char *data, int32_t *p_size, AislStream stream) { - switch (aisl_stream_set_body(stream, data, *p_size)) - { - case 0: return HTTP_PARSER_READY; - case -1: return HTTP_PARSER_ERROR; - default: return HTTP_PARSER_SUCCESS; - } + switch (aisl_stream_set_body(stream, data, *p_size)) { + case 0: + return HTTP_PARSER_READY; + case -1: + return HTTP_PARSER_ERROR; + default: + return HTTP_PARSER_SUCCESS; + } } @@ -340,102 +298,94 @@ http_10_parse_body(char * data, int32_t * p_size, aisl_stream_t stream) __attribute__ ((visibility ("default") )) const char * -aisl_http_version_to_string(aisl_http_version_t version) +aisl_http_version_to_string(AislHttpVersion version) { - switch (version) - { - case AISL_HTTP_0_9: return "HTTP/0.9"; - case AISL_HTTP_1_0: return "HTTP/1.0"; - case AISL_HTTP_1_1: return "HTTP/1.1"; - case AISL_HTTP_2_0: return "HTTP/2.0"; - } - return ""; + switch (version) { + case AISL_HTTP_0_9: + return "HTTP/0.9"; + case AISL_HTTP_1_0: + return "HTTP/1.0"; + case AISL_HTTP_1_1: + return "HTTP/1.1"; + case AISL_HTTP_2_0: + return "HTTP/2.0"; + } + return ""; } __attribute__ ((visibility ("default") )) const char * -aisl_http_response_to_string(aisl_http_response_t code) +aisl_http_response_to_string(AislHttpResponse code) { - switch (code) - { - /* most common for faster behavior */ - case AISL_HTTP_OK: return "OK"; - case AISL_HTTP_MOVED_PERMANENTLY: return "Moved Permanently"; - - /* informational */ - case AISL_HTTP_CONTINUE: return "Continue"; - case AISL_HTTP_SWITCHING_PROTOCOLS: return "Switching Protocols"; - /* Successful */ - case AISL_HTTP_CREATED: return "Created"; - case AISL_HTTP_ACCEPTED: return "Accepted"; - case AISL_HTTP_NON_AUTHORITATIVE_INFORMATION: return "Non-Authoritative Information"; - case AISL_HTTP_NO_CONTENT: return "No Content"; - case AISL_HTTP_RESET_CONTENT: return "Reset Content"; - case AISL_HTTP_PARTIAL_CONTENT: return "Partial Content"; - /* redirection */ - case AISL_HTTP_MULTIPLE_CHOICES: return "Multiple Choices"; - case AISL_HTTP_FOUND: return "Found"; - case AISL_HTTP_SEE_OTHER: return "See other"; - case AISL_HTTP_NOT_MODIFIED: return "Not Modified"; - case AISL_HTTP_USE_PROXY: return "Use Proxy"; - case AISL_HTTP_UNUSED: return "(unused)"; - case AISL_HTTP_TEMPORARY_REDIRECT: return "Temporary Redirect"; - /* client error */ - case AISL_HTTP_BAD_REQUEST: return "Bad Request"; - case AISL_HTTP_UNAUTHORIZED: return "Unauthorized"; - case AISL_HTTP_PAYMENT_REQUIRED: return "Payment Required"; - case AISL_HTTP_FORBIDDEN: return "Forbidden"; - case AISL_HTTP_NOT_FOUND: return "Not Found"; - case AISL_HTTP_METHOD_NOT_ALLOWED: return "Method Not Allowed"; - case AISL_HTTP_NOT_ACCEPTABLE: return "Not Acceptable"; - case AISL_HTTP_PROXY_AUTHENTICATION_REQUIRED: return "Proxy Authentication Required"; - case AISL_HTTP_REQUEST_TIMEOUT: return "Request Timeout"; - case AISL_HTTP_CONFLICT: return "Conflict"; - case AISL_HTTP_GONE: return "Gone"; - case AISL_HTTP_LENGTH_REQUIRED: return "Length Required"; - case AISL_HTTP_PRECONDITION_FAILED: return "Precondition Failed"; - case AISL_HTTP_REQUEST_ENTITY_TOO_LARGE: return "Request Entity Too Large"; - case AISL_HTTP_REQUEST_URI_TOO_LONG: return "Request-URI Too Long"; - case AISL_HTTP_UNSUPPORTED_MEDIA_TYPE: return "Unsupported Media Type"; - case AISL_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE: return "Requested Range Not Satisfiable"; - case AISL_HTTP_EXPECTATION_FAILED: return "Expectation Failed"; - /* server error */ - case AISL_HTTP_INTERNAL_SERVER_ERROR: return "Internal Server Error"; - case AISL_HTTP_NOT_IMPLEMENTED: return "Not Implemented"; - case AISL_HTTP_BAD_GATEWAY: return "Bad Gateway"; - case AISL_HTTP_SERVICE_UNAVAILABLE: return "Service Unavailable"; - case AISL_HTTP_GATEWAY_TIMEOUT: return "Gateway Timeout"; - case AISL_HTTP_VERSION_NOT_SUPPORTED: return "HTTP Version Not Supported"; - - } - return ""; - + switch (code) { + /* most common for faster behavior */ + case AISL_HTTP_OK: return "OK"; + case AISL_HTTP_MOVED_PERMANENTLY: return "Moved Permanently"; + /* informational */ + case AISL_HTTP_CONTINUE: return "Continue"; + case AISL_HTTP_SWITCHING_PROTOCOLS: return "Switching Protocols"; + /* Successful */ + case AISL_HTTP_CREATED: return "Created"; + case AISL_HTTP_ACCEPTED: return "Accepted"; + case AISL_HTTP_NON_AUTHORITATIVE_INFORMATION: return "Non-Authoritative Information"; + case AISL_HTTP_NO_CONTENT: return "No Content"; + case AISL_HTTP_RESET_CONTENT: return "Reset Content"; + case AISL_HTTP_PARTIAL_CONTENT: return "Partial Content"; + /* redirection */ + case AISL_HTTP_MULTIPLE_CHOICES: return "Multiple Choices"; + case AISL_HTTP_FOUND: return "Found"; + case AISL_HTTP_SEE_OTHER: return "See other"; + case AISL_HTTP_NOT_MODIFIED: return "Not Modified"; + case AISL_HTTP_USE_PROXY: return "Use Proxy"; + case AISL_HTTP_UNUSED: return "(unused)"; + case AISL_HTTP_TEMPORARY_REDIRECT: return "Temporary Redirect"; + /* client error */ + case AISL_HTTP_BAD_REQUEST: return "Bad Request"; + case AISL_HTTP_UNAUTHORIZED: return "Unauthorized"; + case AISL_HTTP_PAYMENT_REQUIRED: return "Payment Required"; + case AISL_HTTP_FORBIDDEN: return "Forbidden"; + case AISL_HTTP_NOT_FOUND: return "Not Found"; + case AISL_HTTP_METHOD_NOT_ALLOWED: return "Method Not Allowed"; + case AISL_HTTP_NOT_ACCEPTABLE: return "Not Acceptable"; + case AISL_HTTP_PROXY_AUTHENTICATION_REQUIRED: return "Proxy Authentication Required"; + case AISL_HTTP_REQUEST_TIMEOUT: return "Request Timeout"; + case AISL_HTTP_CONFLICT: return "Conflict"; + case AISL_HTTP_GONE: return "Gone"; + case AISL_HTTP_LENGTH_REQUIRED: return "Length Required"; + case AISL_HTTP_PRECONDITION_FAILED: return "Precondition Failed"; + case AISL_HTTP_REQUEST_ENTITY_TOO_LARGE: return "Request Entity Too Large"; + case AISL_HTTP_REQUEST_URI_TOO_LONG: return "Request-URI Too Long"; + case AISL_HTTP_UNSUPPORTED_MEDIA_TYPE: return "Unsupported Media Type"; + case AISL_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE: return "Requested Range Not Satisfiable"; + case AISL_HTTP_EXPECTATION_FAILED: return "Expectation Failed"; + /* server error */ + case AISL_HTTP_INTERNAL_SERVER_ERROR: return "Internal Server Error"; + case AISL_HTTP_NOT_IMPLEMENTED: return "Not Implemented"; + case AISL_HTTP_BAD_GATEWAY: return "Bad Gateway"; + case AISL_HTTP_SERVICE_UNAVAILABLE: return "Service Unavailable"; + case AISL_HTTP_GATEWAY_TIMEOUT: return "Gateway Timeout"; + case AISL_HTTP_VERSION_NOT_SUPPORTED: return "HTTP Version Not Supported"; + } + return ""; } __attribute__ ((visibility ("default") )) const char * -aisl_http_method_to_string( aisl_http_method_t method ) +aisl_http_method_to_string( AislHttpMethod method ) { - switch(method) - { - case AISL_HTTP_GET: return "GET"; - case AISL_HTTP_PUT: return "PUT"; - case AISL_HTTP_POST: return "POST"; - case AISL_HTTP_HEAD: return "HEAD"; - case AISL_HTTP_TRACE: return "TRACE"; - case AISL_HTTP_DELETE: return "DELETE"; - case AISL_HTTP_OPTIONS: return "OPTIONS"; - case AISL_HTTP_CONNECT: return "CONNECT"; - - case AISL_HTTP_PRI: return "PRI"; - - case AISL_HTTP_METHOD_UNKNOWN: break; - } - - return ""; + switch(method) { + case AISL_HTTP_GET: return "GET"; + case AISL_HTTP_PUT: return "PUT"; + case AISL_HTTP_POST: return "POST"; + case AISL_HTTP_HEAD: return "HEAD"; + case AISL_HTTP_TRACE: return "TRACE"; + case AISL_HTTP_DELETE: return "DELETE"; + case AISL_HTTP_OPTIONS: return "OPTIONS"; + case AISL_HTTP_CONNECT: return "CONNECT"; + case AISL_HTTP_PRI: return "PRI"; + case AISL_HTTP_METHOD_UNKNOWN: break; + } + return ""; } - - - diff --git a/src/http.h b/src/http.h index c6069e5..75da224 100644 --- a/src/http.h +++ b/src/http.h @@ -18,26 +18,24 @@ #include -typedef enum -{ - HTTP_PARSER_SUCCESS - , HTTP_PARSER_READY - , HTTP_PARSER_HUNGRY - , HTTP_PARSER_ERROR - -} http_parser_t; +typedef enum { + HTTP_PARSER_SUCCESS + , HTTP_PARSER_READY + , HTTP_PARSER_HUNGRY + , HTTP_PARSER_ERROR +} ParserStatus; -http_parser_t -http_10_parse_request(char * data, int32_t * size, aisl_stream_t stream); +ParserStatus +http_10_parse_request(char *data, int32_t *size, AislStream stream); -http_parser_t -http_10_parse_header(char * data, int32_t * size, aisl_stream_t stream); +ParserStatus +http_10_parse_header(char *data, int32_t *size, AislStream stream); -http_parser_t -http_10_parse_body(char * data, int32_t * size, aisl_stream_t stream); +ParserStatus +http_10_parse_body(char *data, int32_t *size, AislStream stream); #endif /* !AISL_HTTP_H */ diff --git a/src/instance.c b/src/instance.c index 116285c..580246a 100644 --- a/src/instance.c +++ b/src/instance.c @@ -22,10 +22,8 @@ #include "debug.h" #include "str-utils.h" #include "buffer.h" - #include "client.h" #include "server.h" -//#include "globals.h" #include "stream.h" #include "instance.h" @@ -34,42 +32,35 @@ static uint32_t m_instances = 0; - -static const aisl_ssl_t -aisl_new_ssl( aisl_t instance, const aisl_cfg_ssl_t cfg_ssl) +static struct aisl_ssl * +aisl_new_ssl(AislInstance instance, const struct aisl_cfg_ssl *cfg_ssl) { - SSL_CTX * ssl_ctx = NULL; - aisl_ssl_t * list = instance->ssl, - ssl; + SSL_CTX *ssl_ctx = NULL; + struct aisl_ssl **list, *ssl; + + list = instance->ssl; - /* lookup for existing contexts */ - while( (ssl = *list) ) - { - if (ssl->key_file && strcmp(ssl->key_file, cfg_ssl->key_file)==0 && - ssl->crt_file && strcmp(ssl->crt_file, cfg_ssl->crt_file)==0 ) - { - ssl_ctx = ssl->ctx; - break; - } + /* lookup for existing contexts */ + while ((ssl = *list)) { + if (ssl->key_file && strcmp(ssl->key_file, cfg_ssl->key_file)==0 && + ssl->crt_file && strcmp(ssl->crt_file, cfg_ssl->crt_file)==0 + ) { + ssl_ctx = ssl->ctx; + break; + } + list++; + } - list++; - } + ssl = aisl_ssl_new(cfg_ssl->host, cfg_ssl->key_file, cfg_ssl->crt_file, + ssl_ctx); - ssl = aisl_ssl_new( cfg_ssl->host, - cfg_ssl->key_file, - cfg_ssl->crt_file, - ssl_ctx ); - - if (ssl) - { - if ( !ssl_ctx && !aisl_ssl_get_ctx(ssl, (void*) instance)) - { - aisl_ssl_free(ssl); - ssl = NULL; - } - } - - return ssl; + if (ssl) { + if (!ssl_ctx && !aisl_ssl_get_ctx(ssl, (void*) instance)) { + aisl_ssl_free(ssl); + ssl = NULL; + } + } + return ssl; } #endif @@ -78,265 +69,233 @@ aisl_new_ssl( aisl_t instance, const aisl_cfg_ssl_t cfg_ssl) /* Initialization functions */ __attribute__ ((visibility ("default") )) -aisl_t -aisl_new( aisl_cfg_t cfg ) +AislInstance +aisl_new(const struct aisl_cfg *cfg) { - aisl_t instance; + int i; + AislInstance instance; - /* allocate root structure */ - if ( !(instance = calloc(1, sizeof(struct aisl))) ) - goto finally; + /* allocate root structure */ + if (!(instance = calloc(1, sizeof (struct aisl_instance)))) + goto finally; - /* allocate servers */ - if ( !(instance->srv = calloc(cfg->srv_cnt+1, sizeof(aisl_server_t))) ) - goto release; + /* allocate servers */ + if (!(instance->srv = calloc(cfg->srv_cnt+1, sizeof (AislServer)))) + goto release; - for (int i=0; isrv_cnt; i++) - { - DPRINTF("new srv %d", i); - if (!(instance->srv[i] = aisl_server_new(&cfg->srv[i], instance))) - goto release; - } + for (i = 0; i < cfg->srv_cnt; i++) { + DPRINTF("new srv %d", i); + if (!(instance->srv[i] = aisl_server_new(&cfg->srv[i], instance))) + goto release; + } - #ifndef AISL_WITHOUT_SSL - if ((m_instances++) == 0) - { - SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); - } + #ifndef AISL_WITHOUT_SSL + if ((m_instances++) == 0) { + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); + } - if ( !(instance->ssl = calloc(cfg->ssl_cnt+1, sizeof(aisl_ssl_t))) ) - goto release; + if (!(instance->ssl = calloc(cfg->ssl_cnt+1, sizeof (struct aisl_ssl)))) + goto release; - for (int i=0; issl_cnt; i++) - { - DPRINTF("new ssl %d", i); - if (!(instance->ssl[i] = aisl_new_ssl(instance, &cfg->ssl[i]))) - goto release; - } - #endif + for (i=0; issl_cnt; i++) { + DPRINTF("new ssl %d", i); + if (!(instance->ssl[i] = aisl_new_ssl(instance, &cfg->ssl[i]))) + goto release; + } + #endif - if ( list_init(&instance->client_spool, cfg->client_spool_size) == -1 ) - goto release; + if (list_init(&instance->client_spool, cfg->client_spool_size) == -1) + goto release; - instance->accept_limit = cfg->client_accept_limit; - instance->silence_timeout = cfg->client_silence_timeout; - instance->callback = cfg->callback; - instance->p_ctx = cfg->p_ctx; + instance->accept_limit = cfg->client_accept_limit; + instance->silence_timeout = cfg->client_silence_timeout; + instance->callback = cfg->callback; + instance->p_ctx = cfg->p_ctx; - goto finally; + goto finally; release: - aisl_free(instance); - instance = NULL; + aisl_free(instance); + instance = NULL; finally: - return instance; + return instance; } __attribute__ ((visibility ("default") )) void -aisl_free( aisl_t instance ) +aisl_free(AislInstance instance) { - if (instance->srv) - { - aisl_server_t * srv = instance->srv; + if (instance->srv) { + AislServer * srv = instance->srv; - while (*srv) - { - aisl_server_free(*srv); - srv++; - } + while (*srv) { + aisl_server_free(*(srv++)); + } - free(instance->srv); - } + free(instance->srv); + } - list_release(&instance->client_spool, (list_destructor_t) aisl_client_free ); + list_release(&instance->client_spool, (list_destructor_t)aisl_client_free); - #ifndef AISL_WITHOUT_SSL - if (instance->ssl) - { - aisl_ssl_t * ssl = instance->ssl; + #ifndef AISL_WITHOUT_SSL + if (instance->ssl) { + struct aisl_ssl **ssl = instance->ssl; - while (*ssl) - { - aisl_ssl_free(*ssl); - ssl++; - } + while (*ssl) { + aisl_ssl_free(*(ssl++)); + } + free(instance->ssl); + } - free(instance->ssl); - } + if ((--m_instances) == 0) { + EVP_cleanup(); + } + #endif - if ((--m_instances) == 0) - { - EVP_cleanup(); - } - - #endif - - free(instance); + free(instance); } #ifndef AISL_WITHOUT_SSL SSL_CTX * -aisl_get_ssl_ctx( aisl_t instance, const char * host ) +aisl_get_ssl_ctx(AislInstance instance, const char * host) { - aisl_ssl_t * list = instance->ssl, - ssl; + struct aisl_ssl **list, *ssl; + + list = instance->ssl; - if (host) - { - while ( (ssl = *list) ) - { - if (str_cmpi(ssl->host, host) == 0) - { - return ssl->ctx; - } - - list++; - } - } - - return NULL; + if (host) { + while ((ssl = *list)) { + if (str_cmpi(ssl->host, host) == 0) { + return ssl->ctx; + } + list++; + } + } + return NULL; } #endif void -aisl_raise_evt( aisl_t instance, aisl_evt_t const evt ) +aisl_raise_evt(AislInstance instance, const struct aisl_evt *evt) { - #ifdef AISL_WITHOUT_STRINGIFIERS - DPRINTF("! %d", evt->code); - #else - DPRINTF("! %s", aisl_evt_code_to_string(evt->code)); - #endif + #ifdef AISL_WITHOUT_STRINGIFIERS + DPRINTF("! %d", evt->code); + #else + DPRINTF("! %s", aisl_event_to_string(evt->code)); + #endif - if (instance->callback) - instance->callback(evt, instance->p_ctx); + if (instance->callback) + instance->callback(evt, instance->p_ctx); } void -aisl_raise( aisl_t instance, - void * source, - aisl_evt_code_t code, - aisl_status_t status ) +aisl_raise(AislInstance instance, + void *source, + AislEvent code, + AislStatus status) { - struct aisl_evt evt; + struct aisl_evt evt; - evt.source = source; - evt.code = code; - evt.status = status; + evt.source = source; + evt.code = code; + evt.status = status; - aisl_raise_evt(instance, &evt); + aisl_raise_evt(instance, &evt); } __attribute__ ((visibility ("default") )) -aisl_status_t -aisl_run_cycle( aisl_t instance ) +AislStatus +aisl_run_cycle(AislInstance instance) { - aisl_status_t result = AISL_IDLE; + AislStatus result = AISL_IDLE; + AislServer *list, srv; + AislClient cli; + int32_t i; - aisl_server_t * list = instance->srv, - srv; - aisl_client_t cli; + list = instance->srv; - while ( (srv = *list) ) - { - cli = NULL; + while ((srv = *list)) { + cli = NULL; - if (aisl_server_touch(srv, &cli) != AISL_IDLE) - result = AISL_SUCCESS; + if (aisl_server_touch(srv, &cli) != AISL_IDLE) + result = AISL_SUCCESS; - if (cli) - { - DPRINTF("Accepted %p", (void*)cli); - if ( list_append(&instance->client_spool, cli) == -1 ) - aisl_client_free(cli); - } + if (cli) { + DPRINTF("Accepted %p", (void*)cli); + if (list_append(&instance->client_spool, cli) == -1) + aisl_client_free(cli); + } + list++; + } - list++; - } + for (i=0; i < instance->client_spool.count; i++) { + cli = LIST_INDEX(instance->client_spool, i); - for (int32_t i=0; i < instance->client_spool.count; i++) - { - cli = LIST_INDEX(instance->client_spool, i); + if (aisl_client_touch(cli, instance->silence_timeout) != AISL_IDLE) + result = AISL_SUCCESS; - if (aisl_client_touch(cli, instance->silence_timeout) != AISL_IDLE) - result = AISL_SUCCESS; - - /* if (aisl_client_is_timed_out( c, instance->silence_timeout ) ) - aisl_raise( instance, c, AISL_EVENT_CLIENT_TIMEOUT ); - */ - - if ( !aisl_client_is_online(cli) ) - { - aisl_client_free( cli ); - list_remove_index(&instance->client_spool, i); - } - } - - return result; + if (!aisl_client_is_online(cli)) { + aisl_client_free( cli ); + list_remove_index(&instance->client_spool, i); + } + } + return result; } __attribute__ ((visibility ("default") )) -aisl_status_t -aisl_sleep( aisl_t instance, uint32_t usec ) +AislStatus +aisl_sleep(AislInstance instance, uint32_t usec) { - int maxfd=0, - sd; - size_t i; - struct timeval timeout = {0,usec}; + AislServer *list, srv; + int sd, maxfd = 0; + size_t i; + struct timeval timeout = {0,usec}; - memset(&timeout, 0, sizeof(struct timeval)); - timeout.tv_usec = usec; + memset(&timeout, 0, sizeof (struct timeval)); + timeout.tv_usec = usec; - fd_set fs; - FD_ZERO (&fs); + fd_set fs; + FD_ZERO (&fs); - aisl_server_t * list = instance->srv, - srv; + list = instance->srv; - while ( (srv = *list) ) - { - sd = aisl_server_get_socket(srv); + while ((srv = *list)) { + sd = aisl_server_get_socket(srv); - if (sd != -1) - { - FD_SET(sd, &fs); - if (sd > maxfd) maxfd = sd; - } + if (sd != -1) { + FD_SET(sd, &fs); + if (sd > maxfd) maxfd = sd; + } + list++; + } - list++; - } + for (i=0; iclient_spool.count; i++) { + AislClient c = LIST_INDEX(instance->client_spool, i); + sd = aisl_client_get_socket(c); + if (sd != -1) { + FD_SET(sd, &fs); + if (sd > maxfd) maxfd = sd; + } + } - for (i=0; iclient_spool.count; i++) - { - aisl_client_t c = LIST_INDEX(instance->client_spool, i); - sd = aisl_client_get_socket(c); - if (sd != -1) - { - FD_SET(sd, &fs); - if (sd > maxfd) maxfd = sd; - } - } + switch (select(maxfd+1, &fs, NULL, NULL, &timeout)) { + case -1: + return AISL_SYSCALL_ERROR; - switch ( select(maxfd+1, &fs, NULL, NULL, &timeout) ) - { - case -1: - return AISL_SYSCALL_ERROR; + case 0: + return AISL_IDLE; - case 0: - return AISL_IDLE; - - default: - return AISL_SUCCESS; - } + default: + return AISL_SUCCESS; + } } - diff --git a/src/instance.h b/src/instance.h index 2ef5b46..617d7f7 100644 --- a/src/instance.h +++ b/src/instance.h @@ -1,10 +1,16 @@ -/* - * src/instance.h +/****************************************************************************** * - * Copyright (C) 2019 Ilja Kartašov + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information * - * Project homepage: https://lowenware.com/aisl/ + ******************************************************************************/ + +/** + * @file src/instance.h + * @author Ilja Kartašov + * @brief Declarations of aisl_instance structure and functions * + * @see https://lowenware.com/aisl/ */ #ifndef AISL_INSTANCE_H_814CF474_A646_45B7_B6B2_3F4C7BEFA484 @@ -19,47 +25,46 @@ #include "list.h" -struct aisl -{ - aisl_server_t * srv; - #ifndef AISL_WITHOUT_SSL - aisl_ssl_t * ssl; - #endif - struct list client_spool; - aisl_callback_t callback; - void * p_ctx; +struct aisl_instance { + AislServer *srv; + #ifndef AISL_WITHOUT_SSL + struct aisl_ssl * *ssl; + #endif + struct list client_spool; + AislCallback callback; + void *p_ctx; - uint32_t accept_limit; - uint32_t silence_timeout; - uint32_t buffer_size; + uint32_t accept_limit; + uint32_t silence_timeout; + uint32_t buffer_size; }; #ifndef AISL_WITHOUT_SSL /** * @brief Gets SSL context for appropriate server name. - * @param instance a pointer to #aisl_t instance. + * @param instance a pointer to #AislInstance instance. * @param server_name a null-terminated string with server name or NULL. * @return a pointer to SSL context */ SSL_CTX * -aisl_get_ssl_ctx( aisl_t instance, const char * server_name ); +aisl_get_ssl_ctx(AislInstance instance, const char *server_name); #endif /** * @brief Raises event from source. - * @param instance a pointer to #aisl_t instance. + * @param instance a pointer to #AislInstance instance. * @param evt a pointer to event structure. */ void -aisl_raise_evt( aisl_t instance, aisl_evt_t const evt ); +aisl_raise_evt(AislInstance instance, const struct aisl_evt *evt); void -aisl_raise( aisl_t instance, - void * source, - aisl_evt_code_t code, - aisl_status_t status ); +aisl_raise(AislInstance instance, + void *source, + AislEvent code, + AislStatus status); #endif /* !AISL_INSTANCE_H */ diff --git a/src/list.c b/src/list.c index 980935c..ad20426 100644 --- a/src/list.c +++ b/src/list.c @@ -18,87 +18,80 @@ #include "list.h" int32_t -list_init(list_t list, int32_t size) +list_init(struct list *list, int32_t size) { - if ((list->data = calloc(size, sizeof(void*))) != NULL) - { - list->size = size; - list->count = 0; - return 0; - } - - return -1; + if ((list->data = calloc(size, sizeof (void*))) != NULL) { + list->size = size; + list->count = 0; + return 0; + } + return -1; } void -list_release(list_t list, list_destructor_t destructor) +list_release(struct list *list, list_destructor_t destructor) { - if (list->data) - { - if (destructor) - { - int32_t i; - for (i=0; icount; i++) - { - void * ptr; + if (list->data) { + if (destructor) { + int32_t i; - if ( (ptr = list->data[i]) != NULL) - destructor( list->data[i] ); - } - } - free(list->data); - } + for (i=0; icount; i++) { + void *ptr; + + if ((ptr = list->data[i]) != NULL) + destructor(list->data[i]); + } + } + free(list->data); + } } int32_t -list_append(list_t list, void * entry) +list_append(struct list *list, void *entry) { - int32_t pos = list->count; + int32_t pos = list->count; - DPRINTF("pos = %d", pos); + DPRINTF("pos = %d", pos); - if ( !(pos < list->size) ) - { - DPRINTF("extending, size = %d", list->size); - void ** new_list; - int32_t new_size = pos + 1; + if (!(pos < list->size)) { + DPRINTF("extending, size = %d", list->size); + void **new_list; + int32_t new_size = pos + 1; - DPRINTF("extending, ptr = %p", (void*)list->data); - if ( (new_list = realloc( list->data, new_size*sizeof(void*) )) == NULL ) - return -1; + DPRINTF("extending, ptr = %p", (void*)list->data); + if ((new_list = realloc( list->data, new_size*sizeof (void*) )) == NULL) + return -1; - list->data = new_list; - list->size = new_size; - } + list->data = new_list; + list->size = new_size; + } - list->data[pos]=entry; - list->count++; + list->data[pos]=entry; + list->count++; - return pos; + return pos; } void * -list_remove_index(list_t list, int32_t index) +list_remove_index(struct list *list, int32_t index) { - void * result; + void *result; - if (index < list->count) - { - int32_t i, c = --list->count; + if (index < list->count) { + int32_t i, c = --list->count; - result = list->data[index]; + result = list->data[index]; - for (i=index; idata[i]=list->data[i+1]; - } - } - else - result = NULL; + for (i = index; idata[i]=list->data[i+1]; + } + } + else + result = NULL; - return result; + return result; } diff --git a/src/list.h b/src/list.h index b571d03..403295e 100644 --- a/src/list.h +++ b/src/list.h @@ -6,11 +6,11 @@ ******************************************************************************/ /** - * @file list.h + * @file src/list.h * @author Ilja Kartašov * @brief List module header file * - * @see https://lowenware.com/ + * @see https://lowenware.com/aisl/ */ #ifndef AISL_LIST_H_21495B65_111D_40F7_840F_CC50D9D324A1 @@ -21,34 +21,31 @@ #define LIST_INDEX(L, I) ( L.data[ I ] ) -struct list -{ - void ** data; - int32_t size; - int32_t count; +struct list { + void **data; + int32_t size; + int32_t count; }; -typedef struct list * list_t; - typedef void -(* list_destructor_t)(void * list_item); +(* list_destructor_t)(void *list_item); int32_t -list_init(list_t list, int32_t size); +list_init(struct list *lst, int32_t size); void -list_release(list_t list, list_destructor_t destructor); +list_release(struct list *lst, list_destructor_t destructor); int32_t -list_append(list_t list, void * entry); +list_append(struct list *lst, void * entry); void * -list_remove_index(list_t list, int32_t index); +list_remove_index(struct list *lst, int32_t index); #endif /* !AISL_LIST_H */ diff --git a/src/server.c b/src/server.c index 8e4e411..a5187d3 100644 --- a/src/server.c +++ b/src/server.c @@ -6,15 +6,12 @@ #include #include #include +#include #ifdef __APPLE__ - #include - #endif -#include - #include "debug.h" #include "str-utils.h" #include "instance.h" @@ -24,151 +21,128 @@ /** * @brief Creates TCP server socket, binds to address and starts to listen. - * @param server a pointer to #aisl_server_t instance. - * @return #aisl_status_t code. + * @param server a pointer to #AislServer instance. + * @return #AislStatus code. */ -static aisl_status_t -aisl_server_open(aisl_server_t server) +static AislStatus +aisl_server_open(AislServer server) { - int fd, s_opt = 1; + int fd, s_opt = 1; - fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); - if (fd != -1) - { - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&s_opt, sizeof(int)); + if (fd != -1) { + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&s_opt, + sizeof (int)); - #ifdef __APPLE__ - ioctl(fd, FIONBIO, (char *)&s_opt); - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); - #endif + #ifdef __APPLE__ + ioctl(fd, FIONBIO, (char *)&s_opt); + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + #endif - s_opt = sizeof(struct sockaddr_in); + s_opt = sizeof (struct sockaddr_in); - if (bind(fd, (struct sockaddr *) &server->address, s_opt)==0) - { - if (listen(fd, SOMAXCONN) == 0) - { - server->fd = fd; - return AISL_SUCCESS; - } - } + if (bind(fd, (struct sockaddr *) &server->address, s_opt) == 0) { + if (listen(fd, SOMAXCONN) == 0) { + server->fd = fd; + return AISL_SUCCESS; + } + } + close(fd); + } - close(fd); - } - - return AISL_SYSCALL_ERROR; + return AISL_SYSCALL_ERROR; } /** * @brief Tries to accept a new client. - * @param server a pointer to #aisl_server_t instance. - * @param p_client a pointer to store #aisl_client_t instance pointer. - * @return #aisl_status_t code. + * @param server a pointer to #AislServer instance. + * @param p_client a pointer to store #AislClient instance pointer. + * @return #AislStatus code. */ -static aisl_status_t -aisl_server_accept( aisl_server_t server, - aisl_client_t * p_client ) +static AislStatus +aisl_server_accept(AislServer server, AislClient *p_client ) { - int fd; - struct sockaddr_in addr; - socklen_t len = sizeof(struct sockaddr_in); + int fd; + struct sockaddr_in addr; + socklen_t len = sizeof (struct sockaddr_in); - fd = accept(server->fd, (struct sockaddr *) &addr, &len); + fd = accept(server->fd, (struct sockaddr *)&addr, &len); - if (fd != -1) - { - int flags; + if (fd != -1) { + int flags; - DPRINTF("accepted fd=%d", fd); + DPRINTF("accepted fd=%d", fd); - if ((flags = fcntl(fd, F_GETFL, 0)) != -1) - { - flags |= O_NONBLOCK; + if ((flags = fcntl(fd, F_GETFL, 0)) != -1) { + flags |= O_NONBLOCK; - if (fcntl(fd, F_SETFL, flags) == 0) - { - return (!(*p_client = aisl_client_new(server, fd, &addr))) ? - AISL_MALLOC_ERROR : AISL_SUCCESS; - } - } - close(fd); - } - else if (errno == EWOULDBLOCK) - return AISL_IDLE; - - return AISL_SYSCALL_ERROR; + if (fcntl(fd, F_SETFL, flags) == 0) { + return (!(*p_client = aisl_client_new(server, fd, &addr))) ? + AISL_MALLOC_ERROR : AISL_SUCCESS; + } + } + close(fd); + } else if (errno == EWOULDBLOCK) { + return AISL_IDLE; + } + return AISL_SYSCALL_ERROR; } /* Library Level ------------------------------------------------------------ */ -aisl_status_t -aisl_server_touch( aisl_server_t server, - aisl_client_t * p_client ) +AislStatus +aisl_server_touch(AislServer server, AislClient *p_client) { - aisl_status_t result; + AislStatus result; - if (server->fd == -1) - { - - if ((result = aisl_server_open(server)) != AISL_IDLE) - { - aisl_raise( - server->instance, - server, - ((result == AISL_SUCCESS) ? AISL_EVENT_SERVER_OPEN - : AISL_EVENT_SERVER_ERROR), - result - ); - } - } - else - result = aisl_server_accept(server, p_client); - - return result; + if (server->fd == -1) { + if ((result = aisl_server_open(server)) != AISL_IDLE) { + aisl_raise(server->instance, server, ((result == AISL_SUCCESS) ? + AISL_EVENT_SERVER_READY : AISL_EVENT_SERVER_ERROR), result); + } + } else { + result = aisl_server_accept(server, p_client); + } + return result; } int -aisl_server_get_socket( aisl_server_t server ) +aisl_server_get_socket(AislServer server) { - return server->fd; + return server->fd; } -aisl_server_t -aisl_server_new(aisl_cfg_srv_t const cfg_srv, aisl_t instance) +AislServer +aisl_server_new(const struct aisl_cfg_srv *cfg_srv, AislInstance instance) { - aisl_server_t server; + AislServer server; - if ( (server = calloc(1, sizeof(struct aisl_server))) != NULL ) - { - server->instance = instance; - server->fd = -1; - server->address.sin_family = AF_INET; - server->address.sin_addr.s_addr = inet_addr(cfg_srv->host); - server->address.sin_port = htons(cfg_srv->port); - server->ssl = cfg_srv->secure; - } - - return server; + if ((server = calloc(1, sizeof (struct aisl_server))) != NULL) { + server->instance = instance; + server->fd = -1; + server->address.sin_family = AF_INET; + server->address.sin_addr.s_addr = inet_addr(cfg_srv->host); + server->address.sin_port = htons(cfg_srv->port); + server->ssl = cfg_srv->secure; + } + return server; } void -aisl_server_free(aisl_server_t server) +aisl_server_free(AislServer server) { - if (server) - { - if ( server->fd != -1) - { - close(server->fd); - server->fd=-1; - } - - free(server); - } + if (server) { + if ( server->fd != -1) { + close(server->fd); + server->fd=-1; + } + free(server); + } } @@ -177,9 +151,9 @@ aisl_server_free(aisl_server_t server) __attribute__ ((visibility ("default") )) void -aisl_server_get_address( aisl_server_t server, struct sockaddr_in * address) +aisl_server_get_address(AislServer server, struct sockaddr_in *address) { - memcpy(address, &server->address, sizeof(struct sockaddr_in)); + memcpy(address, &server->address, sizeof (struct sockaddr_in)); } @@ -187,9 +161,9 @@ aisl_server_get_address( aisl_server_t server, struct sockaddr_in * address) __attribute__ ((visibility ("default") )) bool -aisl_server_get_ssl( aisl_server_t server ) +aisl_server_get_ssl(AislServer server) { - return server->ssl; + return server->ssl; } #endif diff --git a/src/server.h b/src/server.h index 70ac2b2..86d7945 100644 --- a/src/server.h +++ b/src/server.h @@ -1,4 +1,17 @@ -/* +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file dummy.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + *//* * @file src/server.h * * Copyright (c) 2017-2019 by Löwenware Ltd. @@ -13,60 +26,58 @@ #include #include -#define AISL_SERVER(x) ((aisl_server_t) x) +#define AISL_SERVER(x) ((AislServer) x) /** - * @brief HTTP(s) server data structure represented by #aisl_server_t pointer. + * @brief HTTP(s) server data structure represented by #AislServer pointer. */ -struct aisl_server -{ - struct sockaddr_in address; /**< TCP server address to listen to. */ - aisl_t instance; /**< Associated AISL instance pointer. */ - int fd; /**< System socket descriptor. */ - bool ssl; /**< SSL enabled/disabled flag. */ +struct aisl_server { + struct sockaddr_in address; /**< TCP server address to listen to. */ + AislInstance instance; /**< Associated AISL instance pointer. */ + int fd; /**< System socket descriptor. */ + bool ssl; /**< SSL enabled/disabled flag. */ }; /** - * @brief Allocates and instance of #aisl_server_t. + * @brief Allocates and instance of #AislServer. * @param cfg_srv a pointer to server configuration structure. - * @param instance a pointer to #aisl_t instance. - * @return a pointer to #aisl_server_t instance. + * @param instance a pointer to #AislInstance instance. + * @return a pointer to #AislServer instance. */ -aisl_server_t -aisl_server_new(aisl_cfg_srv_t const cfg_srv, aisl_t instance); +AislServer +aisl_server_new(const struct aisl_cfg_srv *cfg_srv, AislInstance instance); /** - * @brief Frees memory allocated for #aisl_server_t instance. - * @param server a pointer to #aisl_server_t instance. + * @brief Frees memory allocated for #AislServer instance. + * @param server a pointer to #AislServer instance. */ void -aisl_server_free(aisl_server_t server); +aisl_server_free(AislServer server); /** * @brief Does server routines. * Tries to open server if it was not opened yet, otherwise tries to accept a * new client connecting to the server. - * @param server a pointer to #aisl_server_t instance. - * @param p_client a pointer to store #aisl_client_t instance pointer. - * @return #aisl_status_t code: + * @param server a pointer to #AislServer instance. + * @param p_client a pointer to store #AislClient instance pointer. + * @return #AislStatus code: * - AISL_SUCCESS if client connected, * - AISL_IDLE if there is no client to connect, * - AISL_SYSCALL_ERROR if error occured. */ -aisl_status_t -aisl_server_touch( aisl_server_t server, - aisl_client_t * p_client ); +AislStatus +aisl_server_touch(AislServer server, AislClient *p_client); /** * @brief Gets a socket descriptor associated with HTTP client. - * @param server a pointer to #aisl_server_t instance. + * @param server a pointer to #AislServer instance. * @return a client socket descriptor. */ int -aisl_server_get_socket(aisl_server_t server); +aisl_server_get_socket(AislServer server); #endif /* !AISL_SERVER_H */ diff --git a/src/ssl.c b/src/ssl.c index d981e4c..7a03948 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -15,103 +15,88 @@ static int -aisl_ssl_on_get_ctx( SSL * ssl, int * ptr, void * instance ) +aisl_ssl_on_get_ctx(SSL *ssl, int *ptr, void *instance ) { - const char * server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + const char *server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + SSL_CTX *ctx = aisl_get_ssl_ctx((AislInstance) instance, server_name); - SSL_CTX * ctx = aisl_get_ssl_ctx( (aisl_t) instance, server_name ); + if (ctx) + SSL_set_SSL_CTX(ssl, ctx); - if (ctx) - { - SSL_set_SSL_CTX(ssl, ctx); - } + (void)ptr; - (void)ptr; - - return SSL_TLSEXT_ERR_OK; + return SSL_TLSEXT_ERR_OK; } SSL_CTX * -aisl_ssl_get_ctx(aisl_ssl_t ssl, void * p_instance) +aisl_ssl_get_ctx(struct aisl_ssl *ssl, void *p_instance) { - SSL_CTX * ctx; + SSL_CTX * ctx; - if ( (ctx = SSL_CTX_new(SSLv23_server_method())) != NULL ) - { - SSL_CTX_set_ecdh_auto(ctx, 1); + if ((ctx = SSL_CTX_new(SSLv23_server_method())) != NULL) { + SSL_CTX_set_ecdh_auto(ctx, 1); + SSL_CTX_set_tlsext_servername_callback( ctx, aisl_ssl_on_get_ctx ); + SSL_CTX_set_tlsext_servername_arg( ctx, p_instance ); - SSL_CTX_set_tlsext_servername_callback( ctx, aisl_ssl_on_get_ctx ); - SSL_CTX_set_tlsext_servername_arg( ctx, p_instance ); + if (!(SSL_CTX_use_certificate_file(ctx, ssl->crt_file, SSL_FILETYPE_PEM)>0)) + goto except; - if (!(SSL_CTX_use_certificate_file(ctx, ssl->crt_file, SSL_FILETYPE_PEM)>0)) - goto except; + if (!(SSL_CTX_use_PrivateKey_file(ctx, ssl->key_file, SSL_FILETYPE_PEM)>0)) + goto except; - if (!(SSL_CTX_use_PrivateKey_file(ctx, ssl->key_file, SSL_FILETYPE_PEM)>0)) - goto except; + ssl->ctx = ctx; - ssl->ctx = ctx; - - return ctx; - } + return ctx; + } except: - SSL_CTX_free(ctx); - return NULL; + SSL_CTX_free(ctx); + return NULL; } -aisl_ssl_t -aisl_ssl_new( const char * key_file, - const char * crt_file, - const char * host, - SSL_CTX * ctx ) +struct aisl_ssl * +aisl_ssl_new(const char *key_file, + const char *crt_file, + const char *host, + SSL_CTX *ctx) { - aisl_ssl_t ssl; + struct aisl_ssl *ssl; - if ((ssl = calloc(1, sizeof(struct aisl_ssl))) != NULL) - { - if ((ssl->host = str_copy( host ? host : "*" )) != NULL) - { - if (ctx) - { - ssl->ctx = ctx; - return ssl; - } - else - { - if ((ssl->key_file = str_copy(key_file)) != NULL) - { - if ((ssl->crt_file = str_copy(crt_file)) != NULL) - { - return ssl; - } - } - } - } - aisl_ssl_free(ssl); - } - - return NULL; + if ((ssl = calloc(1, sizeof (struct aisl_ssl))) != NULL) { + if ((ssl->host = str_copy( host ? host : "*" )) != NULL) { + if (ctx) { + ssl->ctx = ctx; + return ssl; + } else { + if ((ssl->key_file = str_copy(key_file)) != NULL) { + if ((ssl->crt_file = str_copy(crt_file)) != NULL) { + return ssl; + } + } + } + } + aisl_ssl_free(ssl); + } + return NULL; } void -aisl_ssl_free( aisl_ssl_t ssl ) +aisl_ssl_free( struct aisl_ssl *ssl ) { - if (ssl->host) - free(ssl->host); + if (ssl->host) + free(ssl->host); - if (ssl->key_file) - { - free(ssl->key_file); - SSL_CTX_free(ssl->ctx); - } + if (ssl->key_file) { + free(ssl->key_file); + SSL_CTX_free(ssl->ctx); + } - if (ssl->crt_file) - free(ssl->crt_file); + if (ssl->crt_file) + free(ssl->crt_file); - free(ssl); + free(ssl); } - #endif diff --git a/src/ssl.h b/src/ssl.h index 349fd0c..d381fff 100644 --- a/src/ssl.h +++ b/src/ssl.h @@ -1,4 +1,17 @@ -/* +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file dummy.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + *//* * src/ssl.h * * Copyright (C) 2019 Ilja Kartašov @@ -15,30 +28,27 @@ #include -struct aisl_ssl -{ - char * key_file; - char * crt_file; - char * host; - SSL_CTX * ctx; +struct aisl_ssl { + char *key_file; + char *crt_file; + char *host; + SSL_CTX *ctx; }; -typedef struct aisl_ssl * aisl_ssl_t; - -aisl_ssl_t -aisl_ssl_new( const char * key_file, - const char * crt_file, - const char * host, - SSL_CTX * ctx ); +struct aisl_ssl * +aisl_ssl_new( const char *key_file, + const char *crt_file, + const char *host, + SSL_CTX *ctx ); SSL_CTX * -aisl_ssl_get_ctx(aisl_ssl_t ssl, void * p_instance); +aisl_ssl_get_ctx(struct aisl_ssl *ssl, void *p_instance); void -aisl_ssl_free( aisl_ssl_t ssl ); +aisl_ssl_free(struct aisl_ssl *ssl); #endif /* !AISL_SSL_H */ diff --git a/src/str-utils.c b/src/str-utils.c index c9dc6bd..c602678 100644 --- a/src/str-utils.c +++ b/src/str-utils.c @@ -20,34 +20,33 @@ char * -str_copy(const char * source) +str_copy(const char *source) { - int l = strlen(source); + int l = strlen(source); - char * result = malloc(l+1); + char *result = malloc(l+1); - if (result) - strcpy(result, source); + if (result) + strcpy(result, source); - return result; + return result; } int -str_cmpi(const char * s1, const char * s2) +str_cmpi(const char *s1, const char *s2) { - char c1, c2, r = 0; + char c1, c2, r = 0; - do - { - c1 = tolower(*(s1++)); - c2 = tolower(*(s2++)); + do { + c1 = tolower(*(s1++)); + c2 = tolower(*(s2++)); - if ((r = c1-c2) != 0) - break; + if ((r = c1-c2) != 0) + break; - } while (c1 != 0); + } while (c1 != 0); - return r; + return r; } diff --git a/src/str-utils.h b/src/str-utils.h index 24fcbeb..e160b22 100644 --- a/src/str-utils.h +++ b/src/str-utils.h @@ -18,9 +18,9 @@ char * -str_copy(const char * source); +str_copy(const char *source); int -str_cmpi(const char * anycase, const char * lowcase); +str_cmpi(const char *anycase, const char *lowcase); #endif /* !STR_UTILS_H */ diff --git a/src/stream.c b/src/stream.c index d82595b..56c4058 100644 --- a/src/stream.c +++ b/src/stream.c @@ -21,657 +21,580 @@ /* Library level */ static void -aisl_stream_reset(aisl_stream_t stream, bool initial) +aisl_stream_reset(AislStream stream, bool initial) { - if (!initial) - { - aisl_raise( - aisl_stream_get_instance(stream) - , (void*) stream - , AISL_EVENT_STREAM_CLOSE - , AISL_SUCCESS - ); - } + if (!initial) { + aisl_raise(aisl_stream_get_instance(stream), (void*) stream, + AISL_EVENT_STREAM_CLOSE, AISL_SUCCESS); + } - buffer_release(&stream->buffer); + buffer_release(&stream->buffer); - stream->u_ptr = NULL; - stream->content_length = AISL_AUTO_LENGTH; - stream->head_offset = 0; - stream->flags = 0; - stream->state = AISL_STREAM_STATE_IDLE; - stream->http_response = AISL_HTTP_OK; + stream->u_ptr = NULL; + stream->content_length = AISL_AUTO_LENGTH; + stream->head_offset = 0; + stream->flags = 0; + stream->state = AISL_STREAM_STATE_IDLE; + stream->http_response = AISL_HTTP_OK; } -aisl_stream_t -aisl_stream_new(aisl_client_t client, int id) +AislStream +aisl_stream_new(AislClient client, int id) { - aisl_stream_t stream = calloc(1, sizeof(struct aisl_stream)); + AislStream stream = calloc(1, sizeof (struct aisl_stream)); - if (stream) - { - stream->id = id; - stream->client = client; - aisl_stream_reset(stream, true); - } - - return stream; + if (stream) { + stream->id = id; + stream->client = client; + aisl_stream_reset(stream, true); + } + return stream; } void -aisl_stream_free(aisl_stream_t stream) +aisl_stream_free(AislStream stream) { - aisl_stream_reset(stream, false); - free(stream); + aisl_stream_reset(stream, false); + free(stream); } int32_t -aisl_stream_get_buffer_space(aisl_stream_t stream) +aisl_stream_get_buffer_space(AislStream stream) { - return stream->buffer.size - stream->buffer.used; + return stream->buffer.size - stream->buffer.used; } int32_t -aisl_stream_get_buffer_size(aisl_stream_t stream) +aisl_stream_get_buffer_size(AislStream stream) { - return stream->buffer.size; + return stream->buffer.size; } char * -aisl_stream_get_data(aisl_stream_t stream, int32_t * p_length) +aisl_stream_get_data(AislStream stream, int32_t *p_length) { - *p_length = stream->buffer.used; + *p_length = stream->buffer.used; - return stream->buffer.data; + return stream->buffer.data; } void -aisl_stream_shift(aisl_stream_t stream, int32_t offset) +aisl_stream_shift(AislStream stream, int32_t offset) { - buffer_shift(&stream->buffer, offset); + buffer_shift(&stream->buffer, offset); } bool -aisl_stream_is_done(aisl_stream_t stream) +aisl_stream_is_done(AislStream stream) { - return (!stream->buffer.used && stream->state == AISL_STREAM_STATE_DONE); + return (!stream->buffer.used && stream->state == AISL_STREAM_STATE_DONE); } -aisl_stream_state_t -aisl_stream_get_state(aisl_stream_t stream) +AislStreamState +aisl_stream_get_state(AislStream stream) { - return stream->state; + return stream->state; } void -aisl_stream_set_request( aisl_stream_t stream, - aisl_http_method_t http_method, - const char * path, - const char * query ) +aisl_stream_set_request(AislStream stream, + AislHttpMethod http_method, + const char *path, + const char *query) { - struct aisl_evt_stream_open on_open; + struct aisl_evt_open on_open; - stream->state = AISL_STREAM_STATE_WAIT_HEADER; + stream->state = AISL_STREAM_STATE_WAIT_HEADER; - DPRINTF( - "%s -> path: %s, query: %s" - , aisl_http_method_to_string(http_method) - , path - , query - ); + DPRINTF("%s -> path: %s, query: %s", aisl_http_method_to_string(http_method), + path, query); - on_open.evt.code = AISL_EVENT_STREAM_OPEN; - on_open.evt.source = (void *) stream; - on_open.evt.status = AISL_SUCCESS; - on_open.http_method = http_method; - on_open.path = path; - on_open.query = query; + on_open.evt.code = AISL_EVENT_STREAM_OPEN; + on_open.evt.source = (void *) stream; + on_open.evt.status = AISL_SUCCESS; + on_open.http_method = http_method; + on_open.path = path; + on_open.query = query; - aisl_raise_evt(aisl_stream_get_instance(stream), (aisl_evt_t)&on_open); + aisl_raise_evt(aisl_stream_get_instance(stream), (struct aisl_evt *)&on_open); } void -aisl_stream_set_header( aisl_stream_t stream, - const char * key, - const char * value ) +aisl_stream_set_header(AislStream stream, const char *key, const char *value) { - struct aisl_evt_stream_header on_header; + struct aisl_evt_header on_header; - if (stream->state != AISL_STREAM_STATE_WAIT_HEADER) - return; + if (stream->state != AISL_STREAM_STATE_WAIT_HEADER) + return; - if (strcmp(key, "content-length")==0) - stream->content_length = strtoll(value, NULL, 10); - else if (strcmp(key, "connection")==0) - aisl_client_set_keepalive( - stream->client - , (str_cmpi(value, "close")==0) ? false : true - ); + if (strcmp(key, "content-length") == 0) { + stream->content_length = strtoll(value, NULL, 10); + } else if (strcmp(key, "connection") == 0) { + aisl_client_set_keepalive(stream->client, + (str_cmpi(value, "close")==0) ? false : true); + } - DPRINTF("%s: %s", key, value); + DPRINTF("%s: %s", key, value); - on_header.evt.code = AISL_EVENT_STREAM_HEADER; - on_header.evt.source = (void *) stream; - on_header.evt.status = AISL_SUCCESS; - on_header.key = key; - on_header.value = value; + on_header.evt.code = AISL_EVENT_STREAM_HEADER; + on_header.evt.source = (void *) stream; + on_header.evt.status = AISL_SUCCESS; + on_header.key = key; + on_header.value = value; - aisl_raise_evt(aisl_stream_get_instance(stream), (aisl_evt_t)&on_header); + aisl_raise_evt(aisl_stream_get_instance(stream), + (struct aisl_evt *) &on_header); } int -aisl_stream_set_end_of_headers( aisl_stream_t stream ) +aisl_stream_set_end_of_headers(AislStream stream) { - int result; + int result; - if (stream->state == AISL_STREAM_STATE_WAIT_HEADER) - { - stream->state = AISL_STREAM_STATE_WAIT_BODY; - result = (stream->content_length == 0); - } - else - result = 2; - - return result; + if (stream->state == AISL_STREAM_STATE_WAIT_HEADER) { + stream->state = AISL_STREAM_STATE_WAIT_BODY; + result = (stream->content_length == 0); + } else { + result = 2; + } + return result; } int -aisl_stream_set_body( aisl_stream_t stream, const char * data, int32_t size ) +aisl_stream_set_body(AislStream stream, const char *data, int32_t size) { - int result; - if (stream->state == AISL_STREAM_STATE_WAIT_BODY) - { - if ( !(stream->content_length < size) ) - { - struct aisl_evt_stream_input on_input; + int result; + if (stream->state == AISL_STREAM_STATE_WAIT_BODY) { + if (!(stream->content_length < size)) { + struct aisl_evt_input on_input; - if (stream->content_length == 0) - { - stream->state = AISL_STREAM_STATE_READY; - result = 0; - } - else - result = 1; + if (stream->content_length == 0) { + stream->state = AISL_STREAM_STATE_READY; + result = 0; + } else { + result = 1; + } - on_input.evt.code = AISL_EVENT_STREAM_INPUT; - on_input.evt.source = (void *) stream; - on_input.evt.status = AISL_SUCCESS; - on_input.data = data; - on_input.size = size; + on_input.evt.code = AISL_EVENT_STREAM_INPUT; + on_input.evt.source = (void *) stream; + on_input.evt.status = AISL_SUCCESS; + on_input.data = data; + on_input.size = size; - aisl_raise_evt(stream->client->server->instance, (aisl_evt_t)&on_input); - } - else - result = -1; - } - else - result = 2; - - return result; + aisl_raise_evt(stream->client->server->instance, + (struct aisl_evt *) &on_input); + } else { + result = -1; + } + } else { + result = 2; + } + return result; } /* API Level */ /* Why it was here? static int -aisl_stream_write(aisl_stream_t stream, const char * data, uint32_t d_len) +aisl_stream_write(AislStream stream, const char * data, uint32_t d_len) { - return buffer_add( &stream->buffer, data, d_len); + return buffer_add( &stream->buffer, data, d_len); } __attribute__ ((visibility ("default") )) void -aisl_cancel(aisl_stream_t stream) +aisl_cancel(AislStream stream) { - aisl_client_close( stream->client ); + aisl_client_close( stream->client ); } */ __attribute__ ((visibility ("default") )) void * -aisl_get_context(aisl_stream_t s) +aisl_get_context(AislStream s) { - return s->u_ptr; + return s->u_ptr; } __attribute__ ((visibility ("default") )) void -aisl_set_context(aisl_stream_t s, void * u_ptr) +aisl_set_context(AislStream s, void *u_ptr) { - s->u_ptr = u_ptr; + s->u_ptr = u_ptr; } __attribute__ ((visibility ("default") )) -aisl_client_t -aisl_get_client(aisl_stream_t s) +AislClient +aisl_get_client(AislStream s) { - return s->client; + return s->client; } __attribute__ ((visibility ("default") )) -aisl_server_t -aisl_get_server(aisl_stream_t s) +AislServer +aisl_get_server(AislStream s) { - return aisl_client_get_server(s->client); + return aisl_client_get_server(s->client); } __attribute__ ((visibility ("default") )) -aisl_http_version_t -aisl_get_http_version(aisl_stream_t s) +AislHttpVersion +aisl_get_http_version(AislStream s) { - return aisl_client_get_http_version(s->client); + return aisl_client_get_http_version(s->client); } __attribute__ ((visibility ("default") )) void -aisl_reject(aisl_stream_t s) +aisl_reject(AislStream s) { - aisl_client_disconnect( s->client ); + aisl_client_disconnect( s->client ); } -static aisl_status_t -aisl_start_response(aisl_stream_t stream) +static AislStatus +aisl_start_response(AislStream stream) { - return aisl_response( stream - , AISL_HTTP_OK - , AISL_AUTO_LENGTH ); + return aisl_response(stream, AISL_HTTP_OK, AISL_AUTO_LENGTH); } -static aisl_status_t -aisl_stream_close_headers(aisl_stream_t stream) +static AislStatus +aisl_stream_close_headers(AislStream stream) { - int32_t l; + int32_t l; - if (aisl_start_response(stream) == AISL_MALLOC_ERROR) - return AISL_MALLOC_ERROR; + if (aisl_start_response(stream) == AISL_MALLOC_ERROR) + return AISL_MALLOC_ERROR; - if (!(stream->flags & FLAG_SERVER_HEADER_SENT)) - { - l = buffer_append( &stream->buffer, "Server: AISL\r\n", 14); - if (l == -1) - return AISL_MALLOC_ERROR; + if (!(stream->flags & FLAG_SERVER_HEADER_SENT)) { + l = buffer_append( &stream->buffer, "Server: AISL\r\n", 14); + if (l == -1) + return AISL_MALLOC_ERROR; - stream->flags |= FLAG_SERVER_HEADER_SENT; - } + stream->flags |= FLAG_SERVER_HEADER_SENT; + } - if (!(stream->flags & FLAG_CONTENT_TYPE_HEADER_SENT)) - { - l = buffer_append( &stream->buffer - , "Content-type: text/html; encoding=utf-8\r\n" - , 41); - if (l == -1) - return AISL_MALLOC_ERROR; + if (!(stream->flags & FLAG_CONTENT_TYPE_HEADER_SENT)) { + l = buffer_append(&stream->buffer, + "Content-type: text/html; encoding=utf-8\r\n", 41); - stream->flags |= FLAG_CONTENT_TYPE_HEADER_SENT; - } + if (l == -1) + return AISL_MALLOC_ERROR; - if (!(stream->flags & FLAG_CONTENT_LENGTH_HEADER_SENT)) - { - if (stream->content_length == AISL_AUTO_LENGTH) - { - l = buffer_append_printf( &stream->buffer - , "Content-length: %"PRIu64"\r\n" - , stream->content_length ); - if (l == -1) - return AISL_MALLOC_ERROR; + stream->flags |= FLAG_CONTENT_TYPE_HEADER_SENT; + } - stream->flags |= FLAG_CONTENT_LENGTH_HEADER_SENT; - } - } + if (!(stream->flags & FLAG_CONTENT_LENGTH_HEADER_SENT)) { + if (stream->content_length == AISL_AUTO_LENGTH) { + l = buffer_append_printf(&stream->buffer, "Content-length: %"PRIu64"\r\n", + stream->content_length); - if (!(stream->flags & FLAG_CONNECTION_HEADER_SENT)) - { - l = buffer_append_printf( &stream->buffer - , "Connection: %s\r\n" - , (aisl_client_get_keepalive(stream->client) ? - "keepalive" : "close")); - if (l == -1) - return AISL_MALLOC_ERROR; + if (l == -1) + return AISL_MALLOC_ERROR; - stream->flags |= FLAG_CONNECTION_HEADER_SENT; - } + stream->flags |= FLAG_CONTENT_LENGTH_HEADER_SENT; + } + } - if (buffer_append( &stream->buffer, "\r\n", 2 ) == -1) - return AISL_MALLOC_ERROR; + if (!(stream->flags & FLAG_CONNECTION_HEADER_SENT)) { + l = buffer_append_printf(&stream->buffer, "Connection: %s\r\n", + (aisl_client_get_keepalive(stream->client) ? "keepalive" : "close")); - stream->body_offset = stream->buffer.used; + if (l == -1) + return AISL_MALLOC_ERROR; - stream->state = AISL_STREAM_STATE_SEND_BODY; + stream->flags |= FLAG_CONNECTION_HEADER_SENT; + } - return AISL_SUCCESS; + if (buffer_append( &stream->buffer, "\r\n", 2 ) == -1) + return AISL_MALLOC_ERROR; + + stream->body_offset = stream->buffer.used; + stream->state = AISL_STREAM_STATE_SEND_BODY; + + return AISL_SUCCESS; } __attribute__ ((visibility ("default") )) -aisl_status_t -aisl_response( aisl_stream_t stream - , aisl_http_response_t status_code - , uint64_t content_length ) +AislStatus +aisl_response(AislStream stream, AislHttpResponse rs_code, uint64_t c_len) { - int32_t l; + int32_t l; - /* check if those headers were already sent */ - if (stream->state > AISL_STREAM_STATE_READY) return AISL_IDLE; + /* check if those headers were already sent */ + if (stream->state > AISL_STREAM_STATE_READY) + return AISL_IDLE; - stream->http_response = status_code; - stream->content_length = content_length; + stream->http_response = rs_code; + stream->content_length = c_len; - buffer_init( &stream->buffer - , (content_length != AISL_AUTO_LENGTH) ? content_length : 0); + buffer_init(&stream->buffer, (c_len != AISL_AUTO_LENGTH) ? c_len : 0); - l = buffer_append_printf( - &stream->buffer - , "%s %d %s\r\n" - , aisl_http_version_to_string(stream->client->http_version) - , status_code - , aisl_http_response_to_string(status_code) - ); + l = buffer_append_printf(&stream->buffer, "%s %d %s\r\n", + aisl_http_version_to_string(stream->client->http_version), rs_code, + aisl_http_response_to_string(rs_code)); - if ( l == -1 ) - return AISL_MALLOC_ERROR; + if (l == -1) + return AISL_MALLOC_ERROR; - stream->head_offset = l; + stream->head_offset = l; + stream->state = AISL_STREAM_STATE_SEND_HEADER; - stream->state = AISL_STREAM_STATE_SEND_HEADER; - - return AISL_SUCCESS; + return AISL_SUCCESS; } __attribute__ ((visibility ("default") )) -aisl_status_t -aisl_flush(aisl_stream_t s) +AislStatus +aisl_flush(AislStream s) { - if (!(s->flags & FLAG_CONTENT_LENGTH_HEADER_SENT)) - { - char hdr[ 40 ]; + if (!(s->flags & FLAG_CONTENT_LENGTH_HEADER_SENT)) { + char hdr[ 40 ]; + uint64_t c_len = s->buffer.used - s->body_offset; + int32_t l; - uint64_t c_len = s->buffer.used - s->body_offset; - int32_t l; + l = snprintf(hdr, sizeof (hdr), "Content-length: %"PRIu64"\r\n", c_len); + l = buffer_insert(&s->buffer, s->body_offset - 2, hdr, l); - l = snprintf(hdr, sizeof(hdr), "Content-length: %"PRIu64"\r\n", c_len); + if (l == -1) + return AISL_MALLOC_ERROR; - l = buffer_insert( &s->buffer - , s->body_offset - 2 - , hdr - , l ); + s->flags |= FLAG_CONTENT_LENGTH_HEADER_SENT; + } - if (l == -1) - return AISL_MALLOC_ERROR; + s->state = AISL_STREAM_STATE_DONE; + s->flags |= FLAG_FLUSHED; - s->flags |= FLAG_CONTENT_LENGTH_HEADER_SENT; - } - - s->state = AISL_STREAM_STATE_DONE; - s->flags |= FLAG_FLUSHED; - - return AISL_SUCCESS; + return AISL_SUCCESS; } static int32_t -aisl_stream_verify_header( aisl_stream_t stream, - const char * key, - const char * value ) +aisl_stream_verify_header(AislStream stream, const char *key, const char *value) { - if (stream->state < AISL_STREAM_STATE_SEND_HEADER) - { - if (aisl_start_response(stream) != AISL_SUCCESS) - return -1; - } - else if (stream->state > AISL_STREAM_STATE_SEND_HEADER) - return 0; + if (stream->state < AISL_STREAM_STATE_SEND_HEADER) { + if (aisl_start_response(stream) != AISL_SUCCESS) + return -1; + } else if (stream->state > AISL_STREAM_STATE_SEND_HEADER) { + return 0; + } - if (!(stream->flags & FLAG_CONNECTION_HEADER_SENT)) - { - if (str_cmpi(key, "connection")==0) - { - stream->flags |= FLAG_CONNECTION_HEADER_SENT; - if (value) - { - aisl_client_set_keepalive( stream->client - , (str_cmpi(value, "keepalive")==0) ); - } - return 1; - } - } + if (!(stream->flags & FLAG_CONNECTION_HEADER_SENT)) { + if (str_cmpi(key, "connection")==0) { + stream->flags |= FLAG_CONNECTION_HEADER_SENT; + if (value) { + aisl_client_set_keepalive(stream->client, + (str_cmpi(value, "keepalive") == 0)); + } + return 1; + } + } - if (!(stream->flags & FLAG_CONTENT_TYPE_HEADER_SENT)) - { - if (str_cmpi(key, "content-type")==0) - { - stream->flags |= FLAG_CONTENT_TYPE_HEADER_SENT; - return 1; - } - } + if (!(stream->flags & FLAG_CONTENT_TYPE_HEADER_SENT)) { + if (str_cmpi(key, "content-type") == 0) { + stream->flags |= FLAG_CONTENT_TYPE_HEADER_SENT; + return 1; + } + } - if (!(stream->flags & FLAG_CONTENT_LENGTH_HEADER_SENT)) - { - if (str_cmpi(key, "content-length")==0) - { - stream->flags |= FLAG_CONTENT_LENGTH_HEADER_SENT; - return 1; - } - } + if (!(stream->flags & FLAG_CONTENT_LENGTH_HEADER_SENT)) { + if (str_cmpi(key, "content-length") == 0) { + stream->flags |= FLAG_CONTENT_LENGTH_HEADER_SENT; + return 1; + } + } - if (!(stream->flags & FLAG_CONTENT_LENGTH_HEADER_SENT)) - { - if (str_cmpi(key, "content-length")==0) - { - stream->flags |= FLAG_CONTENT_LENGTH_HEADER_SENT; - return 1; - } - } + if (!(stream->flags & FLAG_CONTENT_LENGTH_HEADER_SENT)) { + if (str_cmpi(key, "content-length")==0) { + stream->flags |= FLAG_CONTENT_LENGTH_HEADER_SENT; + return 1; + } + } - return 1; + return 1; } __attribute__ ((visibility ("default") )) int32_t -aisl_header(aisl_stream_t stream, const char *key, const char *value) +aisl_header(AislStream stream, const char *key, const char *value) { - int32_t result; + int32_t result; - if ( (result = aisl_stream_verify_header( stream, key, value )) != 1) - return result; + if ( (result = aisl_stream_verify_header( stream, key, value )) != 1) + return result; - result = buffer_append_printf( &stream->buffer - , "%s: %s\r\n" - , key - , value ); + result = buffer_append_printf(&stream->buffer, "%s: %s\r\n", key, value); + return result; - return result; + /* For debug purposes + if ( (pch = str_printf("%s: %s\r\n", key, value)) != NULL ) + { + ret = strlen(pch); + if ( buffer_insert( + &stream->buffer, + stream->end_of_headers, + pch, + ret + ) == -1 ) + { + ret = -1; + } + else + stream->end_of_headers += ret; - /* For debug purposes - if ( (pch = str_printf("%s: %s\r\n", key, value)) != NULL ) - { - ret = strlen(pch); - if ( buffer_insert( - &stream->buffer, - stream->end_of_headers, - pch, - ret - ) == -1 ) - { - ret = -1; - } - else - stream->end_of_headers += ret; + free(pch); + } + else + ret = -1; - free(pch); - } - else - ret = -1; - - return ret; - */ + return ret; + */ } __attribute__ ((visibility ("default") )) int32_t -aisl_header_printf(aisl_stream_t stream, const char *key, - const char *format, ...) +aisl_header_printf(AislStream stream, const char *key, const char *format, ...) { - int32_t result; + int32_t result; + va_list args; - va_list args; - va_start(args, format); + va_start(args, format); + result = aisl_header_vprintf( stream, key, format, args ); + va_end(args); - result = aisl_header_vprintf( stream, key, format, args ); - - va_end(args); - - return result; + return result; } __attribute__ ((visibility ("default") )) int32_t -aisl_header_vprintf(aisl_stream_t stream, const char *key, - const char *format, - va_list args) +aisl_header_vprintf(AislStream stream, + const char *key, + const char *format, + va_list args) { - int32_t result, - l; + int32_t result, l; - if ( (result = aisl_stream_verify_header( stream, key, NULL )) != 1) - return result; + if ( (result = aisl_stream_verify_header( stream, key, NULL )) != 1) + return result; - result = buffer_append_printf( &stream->buffer, "%s: ", key ); + result = buffer_append_printf( &stream->buffer, "%s: ", key ); - if (result != -1) - { - l = buffer_append_vprintf( &stream->buffer, format, args ); + if (result != -1) { + l = buffer_append_vprintf( &stream->buffer, format, args ); - if (l != -1) - { - result += l; - if ((l = buffer_append(&stream->buffer, "\r\n", 2)) != -1) - { - result += l; - - return result; - } - } - } - - - return -1; + if (l != -1) { + result += l; + if ((l = buffer_append(&stream->buffer, "\r\n", 2)) != -1) { + result += l; + return result; + } + } + } + return -1; } __attribute__ ((visibility ("default") )) int -aisl_printf(aisl_stream_t stream, const char *format, ...) +aisl_printf(AislStream stream, const char *format, ...) { - va_list arg; - va_start(arg, format); + int result; + va_list arg; - int result = aisl_vprintf(stream, format, arg); - - va_end(arg); - - /* No need to update length there, because vprintf do that - * - * if (stream->c_length_unknown) - stream->c_length += result; - */ - - - return result; + va_start(arg, format); + result = aisl_vprintf(stream, format, arg); + va_end(arg); + return result; } __attribute__ ((visibility ("default") )) int32_t -aisl_vprintf(aisl_stream_t stream, const char *format, va_list args) +aisl_vprintf(AislStream stream, const char *format, va_list args) { - if (stream->state < AISL_STREAM_STATE_SEND_BODY) - { - if (aisl_stream_close_headers(stream) != AISL_SUCCESS) - return -1; - } - return buffer_append_vprintf(&stream->buffer, format, args); + if (stream->state < AISL_STREAM_STATE_SEND_BODY) { + if (aisl_stream_close_headers(stream) != AISL_SUCCESS) + return -1; + } + return buffer_append_vprintf(&stream->buffer, format, args); } __attribute__ ((visibility ("default") )) int32_t -aisl_write(aisl_stream_t stream, const char *data, int32_t d_len) +aisl_write(AislStream stream, const char *data, int32_t d_len) { - if (stream->state < AISL_STREAM_STATE_SEND_BODY) - { - if (aisl_stream_close_headers(stream) != AISL_SUCCESS) - return -1; - } - if (d_len == -1) - d_len = strlen(data); + if (stream->state < AISL_STREAM_STATE_SEND_BODY) { + if (aisl_stream_close_headers(stream) != AISL_SUCCESS) + return -1; + } - return buffer_append(&stream->buffer, data, d_len); + if (d_len == -1) + d_len = strlen(data); + + return buffer_append(&stream->buffer, data, d_len); } __attribute__ ((visibility ("default") )) int -aisl_puts(const char *str, aisl_stream_t stream) +aisl_puts(const char *str, AislStream stream) { - if (stream->state < AISL_STREAM_STATE_SEND_BODY) - { - if (aisl_stream_close_headers(stream) != AISL_SUCCESS) - return -1; - } - return aisl_write( stream, str, -1); + if (stream->state < AISL_STREAM_STATE_SEND_BODY) { + if (aisl_stream_close_headers(stream) != AISL_SUCCESS) + return -1; + } + return aisl_write( stream, str, -1); } __attribute__ ((visibility ("default") )) -aisl_t -aisl_stream_get_instance(aisl_stream_t stream) +AislInstance +aisl_stream_get_instance(AislStream stream) { - return stream->client->server->instance; + return stream->client->server->instance; } __attribute__ ((visibility ("default") )) void -aisl_set_output_event(aisl_stream_t stream, bool value) +aisl_set_output_event(AislStream stream, bool value) { - if (value) - stream->flags |= FLAG_OUTPUT_CHUNKED; - else if (stream->flags & FLAG_OUTPUT_CHUNKED) - stream->flags &= ~FLAG_OUTPUT_CHUNKED; + if (value) + stream->flags |= FLAG_OUTPUT_CHUNKED; + else if (stream->flags & FLAG_OUTPUT_CHUNKED) + stream->flags &= ~FLAG_OUTPUT_CHUNKED; } __attribute__ ((visibility ("default") )) bool -aisl_get_output_event(aisl_stream_t stream) +aisl_get_output_event(AislStream stream) { - return (stream->flags & FLAG_OUTPUT_CHUNKED); + return (stream->flags & FLAG_OUTPUT_CHUNKED); } - - diff --git a/src/stream.h b/src/stream.h index 6dbad30..a787505 100644 --- a/src/stream.h +++ b/src/stream.h @@ -1,96 +1,106 @@ -#ifndef AISL_STREAM_H_A9EC6601_34B2_4F3E_B631_EEDA8B6EF0D3 +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file dummy.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */#ifndef AISL_STREAM_H_A9EC6601_34B2_4F3E_B631_EEDA8B6EF0D3 #define AISL_STREAM_H_A9EC6601_34B2_4F3E_B631_EEDA8B6EF0D3 #include #include #include "buffer.h" -#define AISL_STREAM(x) ((aisl_stream_t) x) +#define AISL_STREAM(x) ((AislStream) x) typedef enum { - AISL_STREAM_STATE_IDLE + AISL_STREAM_STATE_IDLE - , AISL_STREAM_STATE_WAIT_HEADER - , AISL_STREAM_STATE_WAIT_BODY + , AISL_STREAM_STATE_WAIT_HEADER + , AISL_STREAM_STATE_WAIT_BODY - , AISL_STREAM_STATE_READY + , AISL_STREAM_STATE_READY - , AISL_STREAM_STATE_SEND_HEADER - , AISL_STREAM_STATE_SEND_BODY + , AISL_STREAM_STATE_SEND_HEADER + , AISL_STREAM_STATE_SEND_BODY - , AISL_STREAM_STATE_DONE + , AISL_STREAM_STATE_DONE -} aisl_stream_state_t; +} AislStreamState; -struct aisl_stream -{ - struct buffer buffer; - aisl_client_t client; +struct aisl_stream { + struct buffer buffer; + AislClient client; - void * u_ptr; + void *u_ptr; - uint64_t content_length; - int32_t head_offset; - int32_t body_offset; - int id; - int flags; + uint64_t content_length; + int32_t head_offset; + int32_t body_offset; + int id; + int flags; - aisl_http_response_t http_response; - aisl_stream_state_t state; + AislHttpResponse http_response; + AislStreamState state; }; -aisl_stream_t -aisl_stream_new(aisl_client_t client, int id ); +AislStream +aisl_stream_new(AislClient client, int id); void -aisl_stream_free(aisl_stream_t stream); +aisl_stream_free(AislStream stream); int32_t -aisl_stream_get_buffer_space(aisl_stream_t stream); +aisl_stream_get_buffer_space(AislStream stream); int32_t -aisl_stream_get_buffer_size(aisl_stream_t stream); +aisl_stream_get_buffer_size(AislStream stream); char * -aisl_stream_get_data(aisl_stream_t stream, int32_t * p_length); +aisl_stream_get_data(AislStream stream, int32_t *p_length); void -aisl_stream_shift(aisl_stream_t stream, int32_t offset); +aisl_stream_shift(AislStream stream, int32_t offset); bool -aisl_stream_is_done(aisl_stream_t stream); +aisl_stream_is_done(AislStream stream); -aisl_stream_state_t -aisl_stream_get_state(aisl_stream_t stream); +AislStreamState +aisl_stream_get_state(AislStream stream); void -aisl_stream_set_request( aisl_stream_t stream, - aisl_http_method_t http_method, - const char * path, - const char * query ); +aisl_stream_set_request(AislStream stream, + AislHttpMethod http_method, + const char *path, + const char *query ); void -aisl_stream_set_header( aisl_stream_t stream, - const char * key, - const char * value ); +aisl_stream_set_header(AislStream stream, const char *key, const char *value); int -aisl_stream_set_end_of_headers( aisl_stream_t stream ); +aisl_stream_set_end_of_headers(AislStream stream); int -aisl_stream_set_body( aisl_stream_t stream, const char * data, int32_t size ); +aisl_stream_set_body(AislStream stream, const char *data, int32_t size); #endif /* !AISL_STREAM_H */ diff --git a/src/types.c b/src/types.c index d502bd0..74c3a47 100644 --- a/src/types.c +++ b/src/types.c @@ -20,41 +20,39 @@ __attribute__ ((visibility ("default") )) const char * -aisl_status_to_string(aisl_status_t status) +aisl_status_to_string(AislStatus status) { - switch(status) - { - case AISL_INPUT_ERROR: return "AISL_INPUT_ERROR"; - case AISL_EXTCALL_ERROR: return "AISL_EXTCALL_ERROR"; - case AISL_SYSCALL_ERROR: return "AISL_SYSCALL_ERROR"; - case AISL_MALLOC_ERROR: return "AISL_MALLOC_ERROR"; - case AISL_SUCCESS: return "AISL_SUCCESS"; - case AISL_IDLE: return "AISL_IDLE"; - } - return "UNKNOWN"; + switch(status) { + case AISL_INPUT_ERROR: return "AISL_INPUT_ERROR"; + case AISL_EXTCALL_ERROR: return "AISL_EXTCALL_ERROR"; + case AISL_SYSCALL_ERROR: return "AISL_SYSCALL_ERROR"; + case AISL_MALLOC_ERROR: return "AISL_MALLOC_ERROR"; + case AISL_SUCCESS: return "AISL_SUCCESS"; + case AISL_IDLE: return "AISL_IDLE"; + } + return "UNKNOWN"; } __attribute__ ((visibility ("default") )) const char * -aisl_evt_code_to_string( aisl_evt_code_t evt_code ) +aisl_event_to_string(AislEvent evt_code) { - switch(evt_code) - { - case AISL_EVENT_SERVER_OPEN: return "SERVER OPEN"; - case AISL_EVENT_SERVER_ERROR: return "SERVER ERROR"; - case AISL_EVENT_CLIENT_CONNECT: return "CLIENT CONNECT"; - case AISL_EVENT_CLIENT_DISCONNECT: return "CLIENT DISCONNECT"; - case AISL_EVENT_STREAM_OPEN: return "STREAM OPEN"; - case AISL_EVENT_STREAM_HEADER: return "STREAM HEADER"; - case AISL_EVENT_STREAM_INPUT: return "STREAM INPUT"; - case AISL_EVENT_STREAM_REQUEST: return "STREAM REQUEST"; - case AISL_EVENT_STREAM_OUTPUT: return "STREAM OUTPUT"; - case AISL_EVENT_STREAM_CLOSE: return "STREAM CLOSE"; - case AISL_EVENT_STREAM_ERROR: return "STREAM ERROR"; - } + switch(evt_code) { + case AISL_EVENT_SERVER_READY: return "SERVER READY"; + case AISL_EVENT_SERVER_ERROR: return "SERVER ERROR"; + case AISL_EVENT_CLIENT_CONNECT: return "CLIENT CONNECT"; + case AISL_EVENT_CLIENT_DISCONNECT: return "CLIENT DISCONNECT"; + case AISL_EVENT_STREAM_OPEN: return "STREAM OPEN"; + case AISL_EVENT_STREAM_HEADER: return "STREAM HEADER"; + case AISL_EVENT_STREAM_INPUT: return "STREAM INPUT"; + case AISL_EVENT_STREAM_REQUEST: return "STREAM REQUEST"; + case AISL_EVENT_STREAM_OUTPUT: return "STREAM OUTPUT"; + case AISL_EVENT_STREAM_CLOSE: return "STREAM CLOSE"; + case AISL_EVENT_STREAM_ERROR: return "STREAM ERROR"; + } - return "UNKNOWN"; + return "UNKNOWN"; } #endif