Switch to initialization by config and new event model
This commit is contained in:
parent
d28f942cf7
commit
345450b35b
|
@ -17,6 +17,7 @@ tmp/*
|
||||||
*.bz2
|
*.bz2
|
||||||
pkg/*
|
pkg/*
|
||||||
doc/html
|
doc/html
|
||||||
|
vgcore.*
|
||||||
|
|
||||||
include/webstuff_bak
|
include/webstuff_bak
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,16 @@
|
||||||
#define DEFAULT_HTTP_PORT 8080 /**< Default HTTP server port */
|
#define DEFAULT_HTTP_PORT 8080 /**< Default HTTP server port */
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
hello_world(aisl_stream_t s)
|
hello_world(aisl_evt_t const evt, void * p_ctx)
|
||||||
{
|
{
|
||||||
|
if (evt->code != AISL_EVENT_STREAM_REQUEST)
|
||||||
|
return;
|
||||||
|
|
||||||
aisl_status_t status;
|
aisl_status_t status;
|
||||||
|
|
||||||
|
aisl_stream_t s = evt->source;
|
||||||
|
|
||||||
const char html[] =
|
const char html[] =
|
||||||
"<html>"
|
"<html>"
|
||||||
"<head>"
|
"<head>"
|
||||||
|
@ -51,58 +56,44 @@ hello_world(aisl_stream_t s)
|
||||||
aisl_reject(s);
|
aisl_reject(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; /**< do not propagate event anymore */
|
(void) p_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char ** argv)
|
main(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
aisl_t aisl; /**< AISL instance pointer */
|
aisl_t aisl; /**< AISL instance pointer */
|
||||||
aisl_status_t status; /**< AISL status code */
|
aisl_status_t status; /**< AISL status code */
|
||||||
struct aisl_config config = AISL_CONFIG_DEFAULT;
|
struct aisl_cfg cfg = AISL_CFG_DEFAULT;
|
||||||
uint16_t port = 0;
|
struct aisl_cfg_srv srv = {
|
||||||
|
.host = "0.0.0.0",
|
||||||
|
.port = DEFAULT_HTTP_PORT,
|
||||||
|
.secure = false
|
||||||
|
};
|
||||||
|
|
||||||
/* Try to use first argument as a port number */
|
cfg.srv = &srv;
|
||||||
if (argc > 1)
|
cfg.srv_cnt = 1;
|
||||||
port = strtoll(argv[1], NULL, 10);
|
cfg.callback = hello_world;
|
||||||
|
|
||||||
/* Fallback to default if not set or failed */
|
|
||||||
if (port == 0)
|
|
||||||
port = DEFAULT_HTTP_PORT;
|
|
||||||
|
|
||||||
/* Initialize instance */
|
/* Initialize instance */
|
||||||
if ( (aisl = aisl_new(&config)) != NULL )
|
if ( (aisl = aisl_new(&cfg)) != NULL )
|
||||||
{
|
{
|
||||||
if (aisl_listen( aisl, "0.0.0.0", port ) != NULL)
|
/* launch application loop */
|
||||||
|
fprintf(stdout, "Entering main loop" );
|
||||||
|
for(;;)
|
||||||
{
|
{
|
||||||
/* Set up request callback */
|
status = aisl_run_cycle(aisl);
|
||||||
aisl_set_callback( aisl
|
|
||||||
, AISL_EVENT_STREAM_REQUEST
|
|
||||||
, AISL_CALLBACK(hello_world) );
|
|
||||||
|
|
||||||
/* launch application loop */
|
if ( status != AISL_SUCCESS )
|
||||||
fprintf(stdout, "Entering main loop" );
|
aisl_sleep(aisl, 500);
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
status = aisl_run_cycle(aisl);
|
|
||||||
|
|
||||||
if ( status != AISL_SUCCESS )
|
|
||||||
aisl_sleep(aisl, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
aisl_free(aisl);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
fprintf(stderr, "Failed to initialize HTTP server" );
|
aisl_free(aisl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Failed to initialize AISL");
|
fprintf(stderr, "Failed to initialize AISL");
|
||||||
|
|
||||||
|
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ aisl_client_is_online(aisl_client_t client);
|
||||||
* @param client an #aisl_client_t instance pointer.
|
* @param client an #aisl_client_t instance pointer.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
aisl_client_close(aisl_client_t client);
|
aisl_client_disconnect(aisl_client_t client);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -10,29 +10,61 @@
|
||||||
#ifndef AISL_CONFIG_H_DB67A89B_5CAF_4A5F_AEB1_6DB9F84827D6
|
#ifndef AISL_CONFIG_H_DB67A89B_5CAF_4A5F_AEB1_6DB9F84827D6
|
||||||
#define AISL_CONFIG_H_DB67A89B_5CAF_4A5F_AEB1_6DB9F84827D6
|
#define AISL_CONFIG_H_DB67A89B_5CAF_4A5F_AEB1_6DB9F84827D6
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <aisl/types.h>
|
||||||
|
|
||||||
#define AISL_CONFIG_DEFAULT \
|
#define AISL_CFG_DEFAULT \
|
||||||
{ \
|
{ \
|
||||||
.server_spool_size = 1 \
|
.callback = NULL \
|
||||||
|
, .p_ctx = NULL \
|
||||||
|
, .srv = NULL \
|
||||||
|
, .ssl = NULL \
|
||||||
|
, .srv_cnt = 0 \
|
||||||
|
, .ssl_cnt = 0 \
|
||||||
, .client_spool_size = 32 \
|
, .client_spool_size = 32 \
|
||||||
, .ssl_spool_size = 1 \
|
|
||||||
, .initial_buffer_size = 16536 \
|
, .initial_buffer_size = 16536 \
|
||||||
, .client_accept_limit = 1024 \
|
, .client_accept_limit = 1024 \
|
||||||
, .client_silence_timeout = 30 \
|
, .client_silence_timeout = 30 \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
||||||
struct aisl_config
|
struct aisl_cfg_srv
|
||||||
{
|
{
|
||||||
uint32_t server_spool_size;
|
const char * host;
|
||||||
uint32_t client_spool_size;
|
uint16_t port;
|
||||||
uint32_t ssl_spool_size;
|
bool secure;
|
||||||
uint32_t initial_buffer_size;
|
|
||||||
uint32_t client_accept_limit;
|
|
||||||
uint32_t client_silence_timeout;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct aisl_config * aisl_config_t;
|
typedef struct aisl_cfg_srv * aisl_cfg_srv_t;
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
aisl_cfg_srv_t srv;
|
||||||
|
aisl_cfg_ssl_t ssl;
|
||||||
|
|
||||||
|
int srv_cnt;
|
||||||
|
int ssl_cnt;
|
||||||
|
|
||||||
|
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 */
|
#endif /* !AISL_CONFIG_H */
|
||||||
|
|
|
@ -20,11 +20,11 @@
|
||||||
/**
|
/**
|
||||||
* @brief Allocates new AISL instance.
|
* @brief Allocates new AISL instance.
|
||||||
*
|
*
|
||||||
* @param config a pointer to #aisl_config structure.
|
* @param cfg a pointer to #aisl_cfg_t structure.
|
||||||
* @return an #aisl_t instance pointer.
|
* @return an #aisl_t instance pointer.
|
||||||
*/
|
*/
|
||||||
aisl_t
|
aisl_t
|
||||||
aisl_new( aisl_config_t config );
|
aisl_new( aisl_cfg_t cfg );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,56 +35,6 @@ void
|
||||||
aisl_free( aisl_t instance );
|
aisl_free( aisl_t instance );
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Allocates and registers HTTP server instance.
|
|
||||||
* @param instance a pointer to #aisl_t instance.
|
|
||||||
* @param address a null-terminated ip or hostname string.
|
|
||||||
* @param port a number of port to listen.
|
|
||||||
* @return a pointer representing HTTP server.
|
|
||||||
*/
|
|
||||||
aisl_server_t
|
|
||||||
aisl_listen( aisl_t instance, const char * address, uint16_t port );
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets pair of SSL certificate and key for domain name.
|
|
||||||
* @param instance a pointer to #aisl_t instance.
|
|
||||||
* @param domain a null-terminated string with domain name.
|
|
||||||
* @param key_file a null-terminated string with path to private SSL key file.
|
|
||||||
* @param crt_file a null-terminated string with path to SSL certificate file.
|
|
||||||
* @return #aisl_status_t code.
|
|
||||||
*/
|
|
||||||
aisl_status_t
|
|
||||||
aisl_set_ssl( aisl_t instance,
|
|
||||||
const char * domain,
|
|
||||||
const char * key_file,
|
|
||||||
const char * crt_file );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Registers a callback for event and its source.
|
|
||||||
* If source is NULL, then callback will be executed for all events of specified
|
|
||||||
* type.
|
|
||||||
*
|
|
||||||
* Typical sources are:
|
|
||||||
* - #aisl_server_t,
|
|
||||||
* - #aisl_client_t,
|
|
||||||
* - #aisl_stream_t;
|
|
||||||
*
|
|
||||||
* @param instance a pointer to #aisl_t instance.
|
|
||||||
* @param event a code of event.
|
|
||||||
* @param callback a pointer to function that will be triggered on event.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
aisl_set_callback( aisl_t instance,
|
|
||||||
aisl_event_t event,
|
|
||||||
aisl_callback_t callback );
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A core function doing all the library routines.
|
* @brief A core function doing all the library routines.
|
||||||
* Designed to be called inside application main loop
|
* Designed to be called inside application main loop
|
||||||
|
@ -106,12 +56,4 @@ aisl_status_t
|
||||||
aisl_sleep( aisl_t instance, uint32_t usec );
|
aisl_sleep( aisl_t instance, uint32_t usec );
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get last error message.
|
|
||||||
* @param instance a pointer to #aisl_t instance.
|
|
||||||
* @return a null-terminated string with error message.
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
aisl_get_error( aisl_t instance );
|
|
||||||
|
|
||||||
#endif /* !AISL_INSTANCE_H */
|
#endif /* !AISL_INSTANCE_H */
|
||||||
|
|
|
@ -31,17 +31,6 @@ void
|
||||||
aisl_server_get_address( aisl_server_t server, struct sockaddr_in * address);
|
aisl_server_get_address( aisl_server_t server, struct sockaddr_in * address);
|
||||||
|
|
||||||
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Function to switch on and off SSL for the #aisl_server_t.
|
|
||||||
* @param server an #aisl_server_t pointer.
|
|
||||||
* @param value a boolean value representing SSL enabled/disabled state.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
aisl_server_set_ssl( aisl_server_t server, bool value );
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Function to get on and off status of SSL for the #aisl_server_t.
|
* @brief Function to get on and off status of SSL for the #aisl_server_t.
|
||||||
* @param server an #aisl_server_t pointer.
|
* @param server an #aisl_server_t pointer.
|
||||||
|
@ -50,6 +39,4 @@ aisl_server_set_ssl( aisl_server_t server, bool value );
|
||||||
bool
|
bool
|
||||||
aisl_server_get_ssl( aisl_server_t server );
|
aisl_server_get_ssl( aisl_server_t server );
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !AISL_SERVER_H */
|
#endif /* !AISL_SERVER_H */
|
||||||
|
|
|
@ -27,9 +27,6 @@
|
||||||
/* AISL Instance */
|
/* AISL Instance */
|
||||||
typedef struct aisl * aisl_t;
|
typedef struct aisl * aisl_t;
|
||||||
|
|
||||||
/* Event Identifier */
|
|
||||||
typedef uint32_t aisl_event_t;
|
|
||||||
|
|
||||||
/* HTTP(s) Server */
|
/* HTTP(s) Server */
|
||||||
typedef struct aisl_server * aisl_server_t;
|
typedef struct aisl_server * aisl_server_t;
|
||||||
|
|
||||||
|
@ -39,10 +36,6 @@ typedef struct aisl_client * aisl_client_t;
|
||||||
/* Server<->Client Stream */
|
/* Server<->Client Stream */
|
||||||
typedef struct aisl_stream * aisl_stream_t;
|
typedef struct aisl_stream * aisl_stream_t;
|
||||||
|
|
||||||
/* void type event callback */
|
|
||||||
typedef void
|
|
||||||
(* aisl_callback_t) (void);
|
|
||||||
|
|
||||||
|
|
||||||
/* status return codes */
|
/* status return codes */
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -64,6 +57,7 @@ aisl_status_to_string(aisl_status_t status);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Generic HTTP Enumerations */
|
/* Generic HTTP Enumerations */
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -156,16 +150,15 @@ const char *
|
||||||
aisl_http_response_to_string( aisl_http_response_t code );
|
aisl_http_response_to_string( aisl_http_response_t code );
|
||||||
|
|
||||||
|
|
||||||
/* Built-in Events IDs */
|
/* Events */
|
||||||
|
|
||||||
enum
|
typedef enum
|
||||||
{
|
{
|
||||||
AISL_EVENT_SERVER_OPEN = 100
|
AISL_EVENT_SERVER_OPEN = 100
|
||||||
, AISL_EVENT_SERVER_ERROR = 190
|
, AISL_EVENT_SERVER_ERROR = 190
|
||||||
|
|
||||||
, AISL_EVENT_CLIENT_CONNECT = 200
|
, AISL_EVENT_CLIENT_CONNECT = 200
|
||||||
, AISL_EVENT_CLIENT_DISCONNECT = 210
|
, AISL_EVENT_CLIENT_DISCONNECT = 210
|
||||||
, AISL_EVENT_CLIENT_TIMEOUT = 220
|
|
||||||
|
|
||||||
, AISL_EVENT_STREAM_OPEN = 300
|
, AISL_EVENT_STREAM_OPEN = 300
|
||||||
, AISL_EVENT_STREAM_HEADER = 310
|
, AISL_EVENT_STREAM_HEADER = 310
|
||||||
|
@ -175,62 +168,59 @@ enum
|
||||||
, AISL_EVENT_STREAM_CLOSE = 350
|
, AISL_EVENT_STREAM_CLOSE = 350
|
||||||
, AISL_EVENT_STREAM_ERROR = 390
|
, AISL_EVENT_STREAM_ERROR = 390
|
||||||
|
|
||||||
|
} aisl_evt_code_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct aisl_evt
|
||||||
|
{
|
||||||
|
void * source;
|
||||||
|
aisl_evt_code_t code;
|
||||||
|
aisl_status_t 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);
|
||||||
|
|
||||||
|
|
||||||
|
struct aisl_evt_stream_open
|
||||||
|
{
|
||||||
|
struct aisl_evt evt;
|
||||||
|
const char * path;
|
||||||
|
const char * query;
|
||||||
|
aisl_http_method_t 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct aisl_evt_stream_input * aisl_evt_stream_input_t;
|
||||||
|
|
||||||
#ifndef WITHOUT_STRINGIFIERS
|
#ifndef WITHOUT_STRINGIFIERS
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
aisl_event_to_string( aisl_event_t event );
|
aisl_evt_code_to_string( aisl_evt_code_t evt_code );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* real type event callbacks */
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_source_event_t)( void * source );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_server_open_t)( aisl_server_t server );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_server_error_t)( aisl_server_t server );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_client_connect_t)( aisl_client_t client );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_client_disconnect_t)( aisl_client_t client );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_client_timeout_t)( aisl_client_t client );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_stream_open_t)( aisl_stream_t stream,
|
|
||||||
aisl_http_method_t method,
|
|
||||||
const char * path,
|
|
||||||
const char * query );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_stream_header_t)( aisl_stream_t stream,
|
|
||||||
const char * key,
|
|
||||||
const char * val );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_stream_input_t)( aisl_stream_t stream,
|
|
||||||
const char * data,
|
|
||||||
int32_t len );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_stream_request_t)( aisl_stream_t stream );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_stream_output_t)( aisl_stream_t stream );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_stream_close_t)( aisl_stream_t stream );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_on_stream_error_t)( aisl_stream_t stream );
|
|
||||||
|
|
||||||
#endif /* !AISL_TYPES_H */
|
#endif /* !AISL_TYPES_H */
|
||||||
|
|
|
@ -51,8 +51,8 @@ PROJECT_LIBRARIES = \
|
||||||
|
|
||||||
# flags
|
# flags
|
||||||
PROJECT_CFLAGS = -D_POSIX_C_SOURCE=200809L
|
PROJECT_CFLAGS = -D_POSIX_C_SOURCE=200809L
|
||||||
#PROJECT_CFLAGS += -DDEBUG
|
PROJECT_CFLAGS += -DDEBUG
|
||||||
#PROJECT_CFLAGS += -DAISL_WITHOUT_SSL
|
PROJECT_CFLAGS += -DAISL_WITHOUT_SSL
|
||||||
#PROJECT_CFLAGS += -DAISL_WITHOUT_STRINGIFIERS
|
#PROJECT_CFLAGS += -DAISL_WITHOUT_STRINGIFIERS
|
||||||
|
|
||||||
|
|
||||||
|
|
139
src/client.c
139
src/client.c
|
@ -26,13 +26,33 @@
|
||||||
#define BUFFER_SIZE (16*1024)
|
#define BUFFER_SIZE (16*1024)
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
aisl_client_close(aisl_client_t client, aisl_status_t 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 aisl_status_t
|
static aisl_status_t
|
||||||
aisl_client_parse(aisl_client_t client, char * data, int32_t size)
|
aisl_client_parse(aisl_client_t client, char * data, int32_t size)
|
||||||
{
|
{
|
||||||
aisl_stream_t s;
|
aisl_status_t result = AISL_SUCCESS;
|
||||||
|
aisl_stream_t s = client->stream;
|
||||||
http_parser_t p = HTTP_PARSER_SUCCESS;
|
http_parser_t p = HTTP_PARSER_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
int32_t bytes_left = size;
|
int32_t bytes_left = size;
|
||||||
|
|
||||||
switch (client->http_version)
|
switch (client->http_version)
|
||||||
|
@ -41,7 +61,7 @@ aisl_client_parse(aisl_client_t client, char * data, int32_t size)
|
||||||
case AISL_HTTP_1_0:
|
case AISL_HTTP_1_0:
|
||||||
case AISL_HTTP_1_1:
|
case AISL_HTTP_1_1:
|
||||||
|
|
||||||
s = client->stream;
|
/* s = client->stream; */
|
||||||
|
|
||||||
while ( p == HTTP_PARSER_SUCCESS )
|
while ( p == HTTP_PARSER_SUCCESS )
|
||||||
{
|
{
|
||||||
|
@ -70,17 +90,7 @@ aisl_client_parse(aisl_client_t client, char * data, int32_t size)
|
||||||
size = bytes_left;
|
size = bytes_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == HTTP_PARSER_READY)
|
|
||||||
{
|
|
||||||
client->flags &= ~FLAG_CAN_READ;
|
|
||||||
client->flags |= FLAG_CAN_WRITE;
|
|
||||||
|
|
||||||
aisl_raise(
|
|
||||||
client->server->instance,
|
|
||||||
client->stream,
|
|
||||||
AISL_EVENT_STREAM_REQUEST
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -89,27 +99,43 @@ aisl_client_parse(aisl_client_t client, char * data, int32_t size)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == HTTP_PARSER_ERROR)
|
switch(p)
|
||||||
{
|
{
|
||||||
/* reply Bad Request here */
|
case HTTP_PARSER_READY:
|
||||||
client->stream->http_response = AISL_HTTP_BAD_REQUEST;
|
client->flags &= ~FLAG_CAN_READ;
|
||||||
|
client->flags |= FLAG_CAN_WRITE;
|
||||||
|
|
||||||
aisl_raise(
|
aisl_raise(
|
||||||
client->server->instance,
|
client->server->instance
|
||||||
client->stream,
|
, (void *) s
|
||||||
AISL_EVENT_STREAM_ERROR
|
, AISL_EVENT_STREAM_REQUEST
|
||||||
);
|
, result
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
aisl_client_close(client);
|
case HTTP_PARSER_ERROR:
|
||||||
|
/* reply Bad Request here */
|
||||||
|
client->stream->http_response = AISL_HTTP_BAD_REQUEST;
|
||||||
|
|
||||||
return AISL_INPUT_ERROR;
|
aisl_raise(
|
||||||
|
client->server->instance
|
||||||
|
, (void *) s
|
||||||
|
, AISL_EVENT_STREAM_ERROR
|
||||||
|
, result
|
||||||
|
);
|
||||||
|
|
||||||
|
aisl_client_close(client, result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (size)
|
if (size)
|
||||||
buffer_shift(&client->in, client->in.used - size); /* reset buffer */
|
buffer_shift(&client->in, client->in.used - size); /* reset buffer */
|
||||||
|
|
||||||
return AISL_SUCCESS;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,8 +168,8 @@ aisl_client_input(aisl_client_t client)
|
||||||
|
|
||||||
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_client_close(client, AISL_EXTCALL_ERROR);
|
||||||
return AISL_SYSCALL_ERROR;
|
return AISL_EXTCALL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->flags &= ~FLAG_HANDSHAKE;
|
client->flags &= ~FLAG_HANDSHAKE;
|
||||||
|
@ -186,7 +212,7 @@ aisl_client_input(aisl_client_t client)
|
||||||
|
|
||||||
/* both: client disconnect + on read error */
|
/* both: client disconnect + on read error */
|
||||||
/* todo: raise client error here */
|
/* todo: raise client error here */
|
||||||
aisl_client_close(client);
|
aisl_client_close(client, AISL_SYSCALL_ERROR);
|
||||||
|
|
||||||
return AISL_SYSCALL_ERROR;
|
return AISL_SYSCALL_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -221,12 +247,14 @@ aisl_client_output(aisl_client_t client)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( !(l < aisl_stream_get_buffer_size(s) / 2) )
|
if ( !(l < aisl_stream_get_buffer_size(s) / 2) )
|
||||||
|
{
|
||||||
aisl_raise(
|
aisl_raise(
|
||||||
aisl_server_get_instance(client->server),
|
client->server->instance
|
||||||
s,
|
, (void*)s
|
||||||
AISL_EVENT_STREAM_OUTPUT,
|
, AISL_EVENT_STREAM_OUTPUT
|
||||||
l
|
, AISL_SUCCESS
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data = aisl_stream_get_data(s, &l);
|
data = aisl_stream_get_data(s, &l);
|
||||||
|
@ -269,7 +297,7 @@ aisl_client_output(aisl_client_t client)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
aisl_client_close(client);
|
aisl_client_close(client, AISL_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return AISL_SUCCESS;
|
return AISL_SUCCESS;
|
||||||
|
@ -289,7 +317,7 @@ aisl_client_output(aisl_client_t client)
|
||||||
return AISL_IDLE;
|
return AISL_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
aisl_client_close(client);
|
aisl_client_close(client, AISL_SYSCALL_ERROR);
|
||||||
|
|
||||||
return AISL_SYSCALL_ERROR;
|
return AISL_SYSCALL_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +388,7 @@ aisl_client_new( aisl_server_t server,
|
||||||
void
|
void
|
||||||
aisl_client_free(aisl_client_t client)
|
aisl_client_free(aisl_client_t client)
|
||||||
{
|
{
|
||||||
aisl_client_close(client);
|
aisl_client_close(client, AISL_SUCCESS);
|
||||||
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
#ifndef AISL_WITHOUT_SSL
|
||||||
if (client->ssl)
|
if (client->ssl)
|
||||||
|
@ -380,7 +408,7 @@ aisl_client_free(aisl_client_t client)
|
||||||
|
|
||||||
|
|
||||||
aisl_status_t
|
aisl_status_t
|
||||||
aisl_client_touch(aisl_client_t client)
|
aisl_client_touch(aisl_client_t client, int32_t timeout)
|
||||||
{
|
{
|
||||||
aisl_status_t result = AISL_IDLE,
|
aisl_status_t result = AISL_IDLE,
|
||||||
status = AISL_IDLE;
|
status = AISL_IDLE;
|
||||||
|
@ -418,29 +446,22 @@ aisl_client_touch(aisl_client_t client)
|
||||||
|
|
||||||
if (result == AISL_SUCCESS)
|
if (result == AISL_SUCCESS)
|
||||||
client->timestamp = time(NULL);
|
client->timestamp = time(NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
time_t now;
|
||||||
|
time(&now);
|
||||||
|
|
||||||
|
if ( !(now - client->timestamp < timeout) )
|
||||||
|
{
|
||||||
|
aisl_client_close(client, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
aisl_client_is_timed_out(aisl_client_t client, uint32_t timeout)
|
|
||||||
{
|
|
||||||
time_t now;
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
|
|
||||||
if ( !(now - client->timestamp < timeout) )
|
|
||||||
{
|
|
||||||
aisl_raise(client->server->instance, client, AISL_EVENT_CLIENT_TIMEOUT);
|
|
||||||
aisl_client_close(client);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
aisl_client_get_socket(aisl_client_t client)
|
aisl_client_get_socket(aisl_client_t client)
|
||||||
{
|
{
|
||||||
|
@ -494,19 +515,11 @@ aisl_client_is_online(aisl_client_t client)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
aisl_client_close(aisl_client_t client)
|
aisl_client_disconnect(aisl_client_t client)
|
||||||
{
|
{
|
||||||
if (client->fd != -1)
|
aisl_client_close(client, AISL_SUCCESS);
|
||||||
{
|
|
||||||
aisl_raise(client->server->instance, client, AISL_EVENT_CLIENT_DISCONNECT);
|
|
||||||
|
|
||||||
close(client->fd);
|
|
||||||
shutdown(client->fd, SHUT_RDWR);
|
|
||||||
client->fd = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
aisl_http_version_t
|
aisl_http_version_t
|
||||||
aisl_client_get_http_version(aisl_client_t client)
|
aisl_client_get_http_version(aisl_client_t client)
|
||||||
{
|
{
|
||||||
|
|
13
src/client.h
13
src/client.h
|
@ -54,20 +54,11 @@ aisl_client_free(aisl_client_t client);
|
||||||
* @brief Does all HTTP client routines.
|
* @brief Does all HTTP client routines.
|
||||||
* Reads and parses requests, writes responses.
|
* Reads and parses requests, writes responses.
|
||||||
* @param client an #aisl_client_t instance pointer.
|
* @param client an #aisl_client_t instance pointer.
|
||||||
|
* @param timeout an allowed client silence time in seconds.
|
||||||
* @return #aisl_status_t code.
|
* @return #aisl_status_t code.
|
||||||
*/
|
*/
|
||||||
aisl_status_t
|
aisl_status_t
|
||||||
aisl_client_touch(aisl_client_t client);
|
aisl_client_touch(aisl_client_t client, int32_t timeout);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Controls if communication time is not timed out.
|
|
||||||
* @param client an #aisl_client_t instance pointer.
|
|
||||||
* @param timeout an allowed client silence time in seconds.
|
|
||||||
* @return true if client communication is timed out, otherwise false.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
aisl_client_is_timed_out(aisl_client_t client, uint32_t timeout);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
519
src/instance.c
519
src/instance.c
|
@ -25,14 +25,53 @@
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "ssl.h"
|
|
||||||
//#include "globals.h"
|
//#include "globals.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
#ifndef AISL_WITHOUT_SSL
|
||||||
|
|
||||||
static uint32_t m_instances = 0;
|
static uint32_t m_instances = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static const aisl_ssl_t
|
||||||
|
aisl_new_ssl( aisl_t instance, const aisl_cfg_ssl_t cfg_ssl)
|
||||||
|
{
|
||||||
|
SSL_CTX * ssl_ctx = NULL;
|
||||||
|
aisl_ssl_t * list = instance->ssl,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
list++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,34 +79,50 @@ static uint32_t m_instances = 0;
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
__attribute__ ((visibility ("default") ))
|
||||||
aisl_t
|
aisl_t
|
||||||
aisl_new( aisl_config_t config )
|
aisl_new( aisl_cfg_t cfg )
|
||||||
{
|
{
|
||||||
aisl_t instance;
|
aisl_t instance;
|
||||||
|
|
||||||
|
/* allocate root structure */
|
||||||
|
if ( !(instance = calloc(1, sizeof(struct aisl))) )
|
||||||
|
goto finally;
|
||||||
|
|
||||||
|
/* allocate servers */
|
||||||
|
if ( !(instance->srv = calloc(cfg->srv_cnt+1, sizeof(aisl_server_t))) )
|
||||||
|
goto release;
|
||||||
|
|
||||||
|
for (int 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
|
#ifndef AISL_WITHOUT_SSL
|
||||||
if ((m_instances++) == 0)
|
if ((m_instances++) == 0)
|
||||||
{
|
{
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
OpenSSL_add_ssl_algorithms();
|
OpenSSL_add_ssl_algorithms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !(instance->ssl = calloc(cfg->ssl_cnt+1, sizeof(aisl_ssl_t))) )
|
||||||
|
goto release;
|
||||||
|
|
||||||
|
for (int i=0; i<cfg->ssl_cnt; i++)
|
||||||
|
{
|
||||||
|
DPRINTF("new ssl %d", i);
|
||||||
|
if (!(instance->ssl[i] = aisl_new_ssl(instance, &cfg->ssl[i])))
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( !(instance = calloc(1, sizeof(struct aisl))) )
|
if ( list_init(&instance->client_spool, cfg->client_spool_size) == -1 )
|
||||||
goto finally;
|
|
||||||
|
|
||||||
if ( list_init(&instance->server_spool, config->server_spool_size) == -1 )
|
|
||||||
goto release;
|
goto release;
|
||||||
|
|
||||||
if ( list_init(&instance->client_spool, config->client_spool_size) == -1 )
|
instance->accept_limit = cfg->client_accept_limit;
|
||||||
goto release;
|
instance->silence_timeout = cfg->client_silence_timeout;
|
||||||
|
instance->callback = cfg->callback;
|
||||||
#ifndef AISL_WITHOUT_SSL
|
instance->p_ctx = cfg->p_ctx;
|
||||||
if ( list_init(&instance->ssl_spool, config->ssl_spool_size) == -1 )
|
|
||||||
goto release;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
instance->accept_limit = config->client_accept_limit;
|
|
||||||
instance->silence_timeout = config->client_silence_timeout;
|
|
||||||
|
|
||||||
goto finally;
|
goto finally;
|
||||||
|
|
||||||
|
@ -84,304 +139,100 @@ __attribute__ ((visibility ("default") ))
|
||||||
void
|
void
|
||||||
aisl_free( aisl_t instance )
|
aisl_free( aisl_t instance )
|
||||||
{
|
{
|
||||||
|
if (instance->srv)
|
||||||
|
{
|
||||||
|
aisl_server_t * srv = instance->srv;
|
||||||
|
|
||||||
|
while (*srv)
|
||||||
|
{
|
||||||
|
aisl_server_free(*srv);
|
||||||
|
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 );
|
||||||
|
|
||||||
list_release(&instance->server_spool, (list_destructor_t) aisl_server_free );
|
|
||||||
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
#ifndef AISL_WITHOUT_SSL
|
||||||
list_release(&instance->ssl_spool, (list_destructor_t) aisl_ssl_free );
|
if (instance->ssl)
|
||||||
#endif
|
{
|
||||||
|
aisl_ssl_t * ssl = instance->ssl;
|
||||||
|
|
||||||
if (instance->last_error)
|
while (*ssl)
|
||||||
free(instance->last_error);
|
{
|
||||||
|
aisl_ssl_free(*ssl);
|
||||||
|
ssl++;
|
||||||
|
}
|
||||||
|
|
||||||
free(instance);
|
free(instance->ssl);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
|
||||||
if ((--m_instances) == 0)
|
if ((--m_instances) == 0)
|
||||||
{
|
{
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
|
free(instance);
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
aisl_server_t
|
|
||||||
aisl_listen( aisl_t instance, const char * address, uint16_t port )
|
|
||||||
{
|
|
||||||
aisl_server_t result;
|
|
||||||
|
|
||||||
if ( (result = aisl_server_new(instance, address, port)) != NULL )
|
|
||||||
{
|
|
||||||
if (list_append(&instance->server_spool, result) == -1)
|
|
||||||
{
|
|
||||||
aisl_server_free(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
#ifndef AISL_WITHOUT_SSL
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
aisl_on_get_ssl( SSL * ssl, int * ptr, void * instance )
|
|
||||||
{
|
|
||||||
const char * server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
|
||||||
|
|
||||||
SSL_CTX * ctx = aisl_get_ssl_ctx( (aisl_t) instance, server_name );
|
|
||||||
|
|
||||||
if (ctx)
|
|
||||||
{
|
|
||||||
SSL_set_SSL_CTX(ssl, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)ptr;
|
|
||||||
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static aisl_status_t
|
|
||||||
aisl_set_ssl_ctx(aisl_t instance, aisl_ssl_t ssl)
|
|
||||||
{
|
|
||||||
const SSL_METHOD * method;
|
|
||||||
SSL_CTX * ctx;
|
|
||||||
|
|
||||||
method = SSLv23_server_method();
|
|
||||||
|
|
||||||
if ( (ctx = SSL_CTX_new(method)) != NULL )
|
|
||||||
{
|
|
||||||
SSL_CTX_set_ecdh_auto(ctx, 1);
|
|
||||||
|
|
||||||
SSL_CTX_set_tlsext_servername_callback( ctx, aisl_on_get_ssl );
|
|
||||||
SSL_CTX_set_tlsext_servername_arg( ctx, (void *) instance );
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
ssl->ctx = ctx;
|
|
||||||
|
|
||||||
return AISL_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
except:
|
|
||||||
SSL_CTX_free(ctx);
|
|
||||||
aisl_set_error( instance, ERR_error_string(ERR_get_error(),NULL) );
|
|
||||||
return AISL_SYSCALL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
aisl_status_t
|
|
||||||
aisl_set_ssl( aisl_t instance, const char * host,
|
|
||||||
const char * key_file,
|
|
||||||
const char * crt_file )
|
|
||||||
{
|
|
||||||
SSL_CTX * ssl_ctx = NULL;
|
|
||||||
aisl_ssl_t ssl;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
/* lookup for existing contexts */
|
|
||||||
for (i=0; i<instance->ssl_spool.count; i++)
|
|
||||||
{
|
|
||||||
ssl = LIST_INDEX(instance->ssl_spool, i);
|
|
||||||
if (ssl->key_file && strcmp(ssl->key_file, key_file)==0 &&
|
|
||||||
ssl->crt_file && strcmp(ssl->crt_file, crt_file)==0 )
|
|
||||||
{
|
|
||||||
ssl_ctx = ssl->ctx;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ssl = aisl_ssl_new(host, key_file, crt_file, ssl_ctx)) != NULL)
|
|
||||||
{
|
|
||||||
if (!ssl_ctx || (aisl_set_ssl_ctx(instance, ssl) == AISL_SUCCESS))
|
|
||||||
{
|
|
||||||
if (list_append(&instance->ssl_spool, ssl) != -1)
|
|
||||||
return AISL_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
aisl_ssl_free(ssl);
|
|
||||||
}
|
|
||||||
|
|
||||||
return AISL_MALLOC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SSL_CTX *
|
SSL_CTX *
|
||||||
aisl_get_ssl_ctx( aisl_t instance, const char * host )
|
aisl_get_ssl_ctx( aisl_t instance, const char * host )
|
||||||
{
|
{
|
||||||
size_t i;
|
aisl_ssl_t * list = instance->ssl,
|
||||||
aisl_ssl_t ssl;
|
ssl;
|
||||||
|
|
||||||
if (host)
|
if (host)
|
||||||
{
|
{
|
||||||
for (i=0; i<instance->ssl_spool.count; i++)
|
while ( (ssl = *list) )
|
||||||
{
|
{
|
||||||
ssl = LIST_INDEX(instance->ssl_spool, i);
|
if (str_cmpi(ssl->host, host) == 0)
|
||||||
if (strcmp(ssl->host, host) != 0)
|
{
|
||||||
continue;
|
return ssl->ctx;
|
||||||
|
}
|
||||||
|
|
||||||
return ssl->ctx;
|
list++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
void
|
void
|
||||||
aisl_set_callback( aisl_t instance,
|
aisl_raise_evt( aisl_t instance, aisl_evt_t const evt )
|
||||||
aisl_event_t event,
|
|
||||||
aisl_callback_t callback )
|
|
||||||
{
|
{
|
||||||
switch( event )
|
#ifdef AISL_WITHOUT_STRINGIFIERS
|
||||||
{
|
DPRINTF("! %d", evt->code);
|
||||||
case AISL_EVENT_SERVER_OPEN:
|
#else
|
||||||
instance->on_server_open = (aisl_on_server_open_t) callback;
|
DPRINTF("! %s", aisl_evt_code_to_string(evt->code));
|
||||||
break;
|
#endif
|
||||||
|
|
||||||
case AISL_EVENT_SERVER_ERROR:
|
if (instance->callback)
|
||||||
instance->on_server_error = (aisl_on_server_error_t) callback;
|
instance->callback(evt, instance->p_ctx);
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_CLIENT_CONNECT:
|
|
||||||
instance->on_client_connect = (aisl_on_client_connect_t) callback;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_CLIENT_DISCONNECT:
|
|
||||||
instance->on_client_disconnect = (aisl_on_client_disconnect_t) callback;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_CLIENT_TIMEOUT:
|
|
||||||
instance->on_client_timeout = (aisl_on_client_timeout_t) callback;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_OPEN:
|
|
||||||
instance->on_stream_open = (aisl_on_stream_open_t) callback;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_HEADER:
|
|
||||||
instance->on_stream_header = (aisl_on_stream_header_t) callback;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_INPUT:
|
|
||||||
instance->on_stream_input = (aisl_on_stream_input_t) callback;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_REQUEST:
|
|
||||||
instance->on_stream_request = (aisl_on_stream_request_t) callback;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_OUTPUT:
|
|
||||||
instance->on_stream_output = (aisl_on_stream_output_t) callback;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_CLOSE:
|
|
||||||
instance->on_stream_close = (aisl_on_stream_close_t) callback;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_ERROR:
|
|
||||||
instance->on_stream_error = (aisl_on_stream_error_t) callback;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
aisl_raise( aisl_t instance, void * source, aisl_event_t event, ... )
|
aisl_raise( aisl_t instance,
|
||||||
|
void * source,
|
||||||
|
aisl_evt_code_t code,
|
||||||
|
aisl_status_t status )
|
||||||
{
|
{
|
||||||
DPRINTF("event %s", aisl_event_to_string(event));
|
struct aisl_evt evt;
|
||||||
|
|
||||||
va_list vl;
|
evt.source = source;
|
||||||
|
evt.code = code;
|
||||||
|
evt.status = status;
|
||||||
|
|
||||||
va_start(vl, event);
|
aisl_raise_evt(instance, &evt);
|
||||||
switch( event )
|
|
||||||
{
|
|
||||||
case AISL_EVENT_SERVER_OPEN:
|
|
||||||
if (instance->on_server_open)
|
|
||||||
instance->on_server_open((aisl_server_t)source);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_SERVER_ERROR:
|
|
||||||
if (instance->on_server_error)
|
|
||||||
instance->on_server_error((aisl_server_t)source);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_CLIENT_CONNECT:
|
|
||||||
if (instance->on_client_connect)
|
|
||||||
instance->on_client_connect((aisl_client_t)source);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_CLIENT_DISCONNECT:
|
|
||||||
if (instance->on_client_disconnect)
|
|
||||||
instance->on_client_disconnect((aisl_client_t)source);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_CLIENT_TIMEOUT:
|
|
||||||
if (instance->on_client_timeout)
|
|
||||||
instance->on_client_timeout((aisl_client_t)source);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_OPEN:
|
|
||||||
if (instance->on_stream_open)
|
|
||||||
{
|
|
||||||
aisl_http_method_t method = va_arg(vl, aisl_http_method_t);
|
|
||||||
const char * path = va_arg(vl, const char *);
|
|
||||||
const char * query = va_arg(vl, const char *);
|
|
||||||
instance->on_stream_open((aisl_stream_t)source, method, path, query);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_HEADER:
|
|
||||||
if (instance->on_stream_header)
|
|
||||||
{
|
|
||||||
const char * key = va_arg(vl, const char *);
|
|
||||||
const char * val = va_arg(vl, const char *);
|
|
||||||
instance->on_stream_header((aisl_stream_t)source, key, val);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_INPUT:
|
|
||||||
if (instance->on_stream_input)
|
|
||||||
{
|
|
||||||
const char * data = va_arg(vl, const char *);
|
|
||||||
int32_t size = va_arg(vl, int32_t);
|
|
||||||
instance->on_stream_input((aisl_stream_t)source, data, size);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_REQUEST:
|
|
||||||
if (instance->on_stream_request)
|
|
||||||
instance->on_stream_request((aisl_stream_t)source);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_OUTPUT:
|
|
||||||
if (instance->on_stream_output)
|
|
||||||
instance->on_stream_output((aisl_stream_t)source);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_CLOSE:
|
|
||||||
if (instance->on_stream_close)
|
|
||||||
instance->on_stream_close((aisl_stream_t)source);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AISL_EVENT_STREAM_ERROR:
|
|
||||||
if (instance->on_stream_error)
|
|
||||||
instance->on_stream_error((aisl_stream_t)source);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
va_end(vl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -391,103 +242,49 @@ aisl_run_cycle( aisl_t instance )
|
||||||
{
|
{
|
||||||
aisl_status_t result = AISL_IDLE;
|
aisl_status_t result = AISL_IDLE;
|
||||||
|
|
||||||
int32_t i = instance->iterator,
|
aisl_server_t * list = instance->srv,
|
||||||
max = instance->server_spool.count + instance->client_spool.count;
|
srv;
|
||||||
|
aisl_client_t cli;
|
||||||
|
|
||||||
while ( result == AISL_IDLE && max != 0)
|
while ( (srv = *list) )
|
||||||
{
|
{
|
||||||
aisl_client_t cli = NULL;
|
cli = NULL;
|
||||||
|
|
||||||
if (i < instance->server_spool.count)
|
if (aisl_server_touch(srv, &cli) != AISL_IDLE)
|
||||||
|
result = AISL_SUCCESS;
|
||||||
|
|
||||||
|
if (cli)
|
||||||
{
|
{
|
||||||
if (instance->client_spool.count < instance->accept_limit)
|
DPRINTF("Accepted %p", (void*)cli);
|
||||||
{
|
if ( list_append(&instance->client_spool, cli) == -1 )
|
||||||
aisl_server_t srv;
|
aisl_client_free(cli);
|
||||||
/* SSL_CTX * ssl_ctx; */
|
|
||||||
|
|
||||||
srv = (aisl_server_t) LIST_INDEX(instance->server_spool, i);
|
|
||||||
|
|
||||||
/*
|
|
||||||
ssl_ctx = (aisl_server_get_ssl(srv)) ?
|
|
||||||
aisl_get_ssl_ctx(instance, NULL) :
|
|
||||||
NULL;
|
|
||||||
*/
|
|
||||||
result = aisl_server_touch(srv, &cli);
|
|
||||||
|
|
||||||
if (cli)
|
|
||||||
{
|
|
||||||
DPRINTF("Accepted %p", (void*)cli);
|
|
||||||
if ( list_append(&instance->client_spool, cli) != -1 )
|
|
||||||
{
|
|
||||||
aisl_raise(instance, cli, AISL_EVENT_CLIENT_CONNECT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aisl_client_free(cli);
|
|
||||||
/* todo: save error message here */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = instance->server_spool.count;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int32_t j = i - instance->server_spool.count;
|
|
||||||
|
|
||||||
if (j < instance->client_spool.count)
|
|
||||||
{
|
|
||||||
aisl_client_t c = LIST_INDEX(instance->client_spool, j);
|
|
||||||
|
|
||||||
result = aisl_client_touch(c);
|
|
||||||
|
|
||||||
if (aisl_client_is_timed_out( c, instance->silence_timeout ) )
|
|
||||||
aisl_raise( instance, c, AISL_EVENT_CLIENT_TIMEOUT );
|
|
||||||
|
|
||||||
if ( !aisl_client_is_online(c) )
|
|
||||||
{
|
|
||||||
aisl_client_free( c );
|
|
||||||
list_remove_index(&instance->client_spool, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
max--;
|
list++;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->iterator = 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_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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
const char *
|
|
||||||
aisl_get_error( aisl_t instance )
|
|
||||||
{
|
|
||||||
return instance->last_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
aisl_set_error( aisl_t instance, const char * err_msg )
|
|
||||||
{
|
|
||||||
if (instance->last_error)
|
|
||||||
free(instance->last_error);
|
|
||||||
|
|
||||||
instance->last_error = str_copy(err_msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
__attribute__ ((visibility ("default") ))
|
||||||
aisl_status_t
|
aisl_status_t
|
||||||
aisl_sleep( aisl_t instance, uint32_t usec )
|
aisl_sleep( aisl_t instance, uint32_t usec )
|
||||||
|
@ -503,19 +300,21 @@ aisl_sleep( aisl_t instance, uint32_t usec )
|
||||||
fd_set fs;
|
fd_set fs;
|
||||||
FD_ZERO (&fs);
|
FD_ZERO (&fs);
|
||||||
|
|
||||||
for (i=0; i<instance->server_spool.count; i++)
|
aisl_server_t * list = instance->srv,
|
||||||
{
|
srv;
|
||||||
aisl_server_t s = LIST_INDEX(instance->server_spool, i);
|
|
||||||
|
|
||||||
sd = aisl_server_get_socket(s);
|
while ( (srv = *list) )
|
||||||
|
{
|
||||||
|
sd = aisl_server_get_socket(srv);
|
||||||
|
|
||||||
if (sd != -1)
|
if (sd != -1)
|
||||||
{
|
{
|
||||||
FD_SET(sd, &fs);
|
FD_SET(sd, &fs);
|
||||||
if (sd > maxfd) maxfd = sd;
|
if (sd > maxfd) maxfd = sd;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
list++;
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0; i<instance->client_spool.count; i++)
|
for (i=0; i<instance->client_spool.count; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,37 +15,23 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <aisl/instance.h>
|
#include <aisl/instance.h>
|
||||||
|
#include "ssl.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
|
|
||||||
struct aisl
|
struct aisl
|
||||||
{
|
{
|
||||||
struct list server_spool;
|
aisl_server_t * srv;
|
||||||
struct list client_spool;
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
#ifndef AISL_WITHOUT_SSL
|
||||||
struct list ssl_spool;
|
aisl_ssl_t * ssl;
|
||||||
#endif
|
#endif
|
||||||
|
struct list client_spool;
|
||||||
|
aisl_callback_t callback;
|
||||||
|
void * p_ctx;
|
||||||
|
|
||||||
char * last_error;
|
uint32_t accept_limit;
|
||||||
|
uint32_t silence_timeout;
|
||||||
int32_t iterator;
|
uint32_t buffer_size;
|
||||||
|
|
||||||
uint32_t accept_limit;
|
|
||||||
uint32_t silence_timeout;
|
|
||||||
|
|
||||||
/* callbacks */
|
|
||||||
aisl_on_server_open_t on_server_open;
|
|
||||||
aisl_on_server_error_t on_server_error;
|
|
||||||
aisl_on_client_connect_t on_client_connect;
|
|
||||||
aisl_on_client_disconnect_t on_client_disconnect;
|
|
||||||
aisl_on_client_timeout_t on_client_timeout;
|
|
||||||
aisl_on_stream_open_t on_stream_open;
|
|
||||||
aisl_on_stream_header_t on_stream_header;
|
|
||||||
aisl_on_stream_input_t on_stream_input;
|
|
||||||
aisl_on_stream_request_t on_stream_request;
|
|
||||||
aisl_on_stream_output_t on_stream_output;
|
|
||||||
aisl_on_stream_close_t on_stream_close;
|
|
||||||
aisl_on_stream_error_t on_stream_error;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,24 +47,19 @@ aisl_get_ssl_ctx( aisl_t instance, const char * server_name );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets error message for AISL instace.
|
|
||||||
* @param instance a pointer to #aisl_t instance.
|
|
||||||
* @param err_msge a null-terminated string with error message.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
aisl_set_error( aisl_t instance, const char * err_msg );
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Raises event from source.
|
* @brief Raises event from source.
|
||||||
* @param instance a pointer to #aisl_t instance.
|
* @param instance a pointer to #aisl_t instance.
|
||||||
* @param source a pointer to an event source.
|
* @param evt a pointer to event structure.
|
||||||
* @param event a code of event.
|
|
||||||
* @param ... a list of arguments specific for event.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
aisl_raise( aisl_t instance, void * source, aisl_event_t event, ... );
|
aisl_raise_evt( aisl_t instance, aisl_evt_t const evt );
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
aisl_raise( aisl_t instance,
|
||||||
|
void * source,
|
||||||
|
aisl_evt_code_t code,
|
||||||
|
aisl_status_t status );
|
||||||
|
|
||||||
#endif /* !AISL_INSTANCE_H */
|
#endif /* !AISL_INSTANCE_H */
|
||||||
|
|
42
src/server.c
42
src/server.c
|
@ -22,9 +22,6 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates TCP server socket, binds to address and starts to listen.
|
* @brief Creates TCP server socket, binds to address and starts to listen.
|
||||||
* @param server a pointer to #aisl_server_t instance.
|
* @param server a pointer to #aisl_server_t instance.
|
||||||
|
@ -101,8 +98,6 @@ aisl_server_accept( aisl_server_t server,
|
||||||
else if (errno == EWOULDBLOCK)
|
else if (errno == EWOULDBLOCK)
|
||||||
return AISL_IDLE;
|
return AISL_IDLE;
|
||||||
|
|
||||||
aisl_raise( server->instance, server, AISL_EVENT_SERVER_ERROR );
|
|
||||||
|
|
||||||
return AISL_SYSCALL_ERROR;
|
return AISL_SYSCALL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,13 +111,17 @@ aisl_server_touch( aisl_server_t server,
|
||||||
|
|
||||||
if (server->fd == -1)
|
if (server->fd == -1)
|
||||||
{
|
{
|
||||||
aisl_event_t event;
|
|
||||||
|
|
||||||
result = aisl_server_open(server);
|
if ((result = aisl_server_open(server)) != AISL_IDLE)
|
||||||
event = (result == AISL_SUCCESS) ? AISL_EVENT_SERVER_OPEN
|
{
|
||||||
: AISL_EVENT_SERVER_ERROR;
|
aisl_raise(
|
||||||
|
server->instance,
|
||||||
aisl_raise(server->instance, server, event);
|
server,
|
||||||
|
((result == AISL_SUCCESS) ? AISL_EVENT_SERVER_OPEN
|
||||||
|
: AISL_EVENT_SERVER_ERROR),
|
||||||
|
result
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = aisl_server_accept(server, p_client);
|
result = aisl_server_accept(server, p_client);
|
||||||
|
@ -141,7 +140,7 @@ aisl_server_get_socket( aisl_server_t server )
|
||||||
/* API Level ---------------------------------------------------------------- */
|
/* API Level ---------------------------------------------------------------- */
|
||||||
|
|
||||||
aisl_server_t
|
aisl_server_t
|
||||||
aisl_server_new(aisl_t instance, const char * host, uint16_t port)
|
aisl_server_new(aisl_cfg_srv_t const cfg_srv, aisl_t instance)
|
||||||
{
|
{
|
||||||
aisl_server_t server;
|
aisl_server_t server;
|
||||||
|
|
||||||
|
@ -150,8 +149,9 @@ aisl_server_new(aisl_t instance, const char * host, uint16_t port)
|
||||||
server->instance = instance;
|
server->instance = instance;
|
||||||
server->fd = -1;
|
server->fd = -1;
|
||||||
server->address.sin_family = AF_INET;
|
server->address.sin_family = AF_INET;
|
||||||
server->address.sin_addr.s_addr = inet_addr(host);
|
server->address.sin_addr.s_addr = inet_addr(cfg_srv->host);
|
||||||
server->address.sin_port = htons(port);
|
server->address.sin_port = htons(cfg_srv->port);
|
||||||
|
server->ssl = cfg_srv->secure;
|
||||||
}
|
}
|
||||||
|
|
||||||
return server;
|
return server;
|
||||||
|
@ -174,13 +174,6 @@ aisl_server_free(aisl_server_t server)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
aisl_t
|
|
||||||
aisl_server_get_instance( aisl_server_t server )
|
|
||||||
{
|
|
||||||
return server->instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
aisl_server_get_address( aisl_server_t server, struct sockaddr_in * address)
|
aisl_server_get_address( aisl_server_t server, struct sockaddr_in * address)
|
||||||
{
|
{
|
||||||
|
@ -190,13 +183,6 @@ aisl_server_get_address( aisl_server_t server, struct sockaddr_in * address)
|
||||||
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
#ifndef AISL_WITHOUT_SSL
|
||||||
|
|
||||||
void
|
|
||||||
aisl_server_set_ssl( aisl_server_t server, bool value )
|
|
||||||
{
|
|
||||||
server->ssl = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
aisl_server_get_ssl( aisl_server_t server )
|
aisl_server_get_ssl( aisl_server_t server )
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#ifndef AISL_SERVER_H_FACD3B4D_0D72_4345_9A30_811103DA9AE2
|
#ifndef AISL_SERVER_H_FACD3B4D_0D72_4345_9A30_811103DA9AE2
|
||||||
#define AISL_SERVER_H_FACD3B4D_0D72_4345_9A30_811103DA9AE2
|
#define AISL_SERVER_H_FACD3B4D_0D72_4345_9A30_811103DA9AE2
|
||||||
|
|
||||||
|
#include <aisl/config.h>
|
||||||
#include <aisl/server.h>
|
#include <aisl/server.h>
|
||||||
|
|
||||||
#define AISL_SERVER(x) ((aisl_server_t) x)
|
#define AISL_SERVER(x) ((aisl_server_t) x)
|
||||||
|
@ -27,13 +28,12 @@ struct aisl_server
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocates and instance of #aisl_server_t.
|
* @brief Allocates and instance of #aisl_server_t.
|
||||||
|
* @param cfg_srv a pointer to server configuration structure.
|
||||||
* @param instance a pointer to #aisl_t instance.
|
* @param instance a pointer to #aisl_t instance.
|
||||||
* @param host a null-terminated string with address to listen to.
|
|
||||||
* @param port a TCP server port number to listen to.
|
|
||||||
* @return a pointer to #aisl_server_t instance.
|
* @return a pointer to #aisl_server_t instance.
|
||||||
*/
|
*/
|
||||||
aisl_server_t
|
aisl_server_t
|
||||||
aisl_server_new(aisl_t instance, const char * host, uint16_t port);
|
aisl_server_new(aisl_cfg_srv_t const cfg_srv, aisl_t instance);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
49
src/ssl.c
49
src/ssl.c
|
@ -6,13 +6,60 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include "ssl.h"
|
|
||||||
#include "str-utils.h"
|
#include "str-utils.h"
|
||||||
|
#include "instance.h"
|
||||||
|
#include "ssl.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef AISL_WITHOUT_SSL
|
#ifndef AISL_WITHOUT_SSL
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
aisl_ssl_on_get_ctx( SSL * ssl, int * ptr, void * instance )
|
||||||
|
{
|
||||||
|
const char * server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||||
|
|
||||||
|
SSL_CTX * ctx = aisl_get_ssl_ctx( (aisl_t) instance, server_name );
|
||||||
|
|
||||||
|
if (ctx)
|
||||||
|
{
|
||||||
|
SSL_set_SSL_CTX(ssl, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)ptr;
|
||||||
|
|
||||||
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SSL_CTX *
|
||||||
|
aisl_ssl_get_ctx(aisl_ssl_t ssl, void * p_instance)
|
||||||
|
{
|
||||||
|
SSL_CTX * ctx;
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
ssl->ctx = ctx;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
except:
|
||||||
|
SSL_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
aisl_ssl_t
|
aisl_ssl_t
|
||||||
aisl_ssl_new( const char * key_file,
|
aisl_ssl_new( const char * key_file,
|
||||||
const char * crt_file,
|
const char * crt_file,
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#ifndef AISL_SSL_H_6F82B0BA_7C59_45BA_AF3B_C82A67C8585E
|
#ifndef AISL_SSL_H_6F82B0BA_7C59_45BA_AF3B_C82A67C8585E
|
||||||
#define AISL_SSL_H_6F82B0BA_7C59_45BA_AF3B_C82A67C8585E
|
#define AISL_SSL_H_6F82B0BA_7C59_45BA_AF3B_C82A67C8585E
|
||||||
|
|
||||||
|
#include <aisl/config.h>
|
||||||
#include <aisl/types.h>
|
#include <aisl/types.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
@ -32,6 +33,10 @@ aisl_ssl_new( const char * key_file,
|
||||||
SSL_CTX * ctx );
|
SSL_CTX * ctx );
|
||||||
|
|
||||||
|
|
||||||
|
SSL_CTX *
|
||||||
|
aisl_ssl_get_ctx(aisl_ssl_t ssl, void * p_instance);
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
aisl_ssl_free( aisl_ssl_t ssl );
|
aisl_ssl_free( aisl_ssl_t ssl );
|
||||||
|
|
||||||
|
|
70
src/stream.c
70
src/stream.c
|
@ -25,11 +25,12 @@ aisl_stream_reset(aisl_stream_t stream, bool initial)
|
||||||
{
|
{
|
||||||
if (!initial)
|
if (!initial)
|
||||||
{
|
{
|
||||||
aisl_t instance;
|
aisl_raise(
|
||||||
|
aisl_stream_get_instance(stream)
|
||||||
instance = aisl_stream_get_instance(stream);
|
, (void*) stream
|
||||||
|
, AISL_EVENT_STREAM_CLOSE
|
||||||
aisl_raise(instance, stream, AISL_EVENT_STREAM_CLOSE);
|
, AISL_SUCCESS
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_release(&stream->buffer);
|
buffer_release(&stream->buffer);
|
||||||
|
@ -134,6 +135,7 @@ aisl_stream_set_request( aisl_stream_t stream,
|
||||||
const char * path,
|
const char * path,
|
||||||
const char * query )
|
const char * query )
|
||||||
{
|
{
|
||||||
|
struct aisl_evt_stream_open on_open;
|
||||||
|
|
||||||
stream->state = AISL_STREAM_STATE_WAIT_HEADER;
|
stream->state = AISL_STREAM_STATE_WAIT_HEADER;
|
||||||
|
|
||||||
|
@ -144,22 +146,24 @@ aisl_stream_set_request( aisl_stream_t stream,
|
||||||
, query
|
, query
|
||||||
);
|
);
|
||||||
|
|
||||||
aisl_raise(
|
on_open.evt.code = AISL_EVENT_STREAM_OPEN;
|
||||||
aisl_stream_get_instance(stream),
|
on_open.evt.source = (void *) stream;
|
||||||
stream,
|
on_open.evt.status = AISL_SUCCESS;
|
||||||
AISL_EVENT_STREAM_OPEN,
|
on_open.http_method = http_method;
|
||||||
http_method,
|
on_open.path = path;
|
||||||
path,
|
on_open.query = query;
|
||||||
query
|
|
||||||
);
|
aisl_raise_evt(aisl_stream_get_instance(stream), (aisl_evt_t)&on_open);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
aisl_stream_set_header( aisl_stream_t stream,
|
aisl_stream_set_header( aisl_stream_t stream,
|
||||||
const char * key,
|
const char * key,
|
||||||
const char * value )
|
const char * value )
|
||||||
{
|
{
|
||||||
|
struct aisl_evt_stream_header on_header;
|
||||||
|
|
||||||
if (stream->state != AISL_STREAM_STATE_WAIT_HEADER)
|
if (stream->state != AISL_STREAM_STATE_WAIT_HEADER)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -173,13 +177,13 @@ aisl_stream_set_header( aisl_stream_t stream,
|
||||||
|
|
||||||
DPRINTF("%s: %s", key, value);
|
DPRINTF("%s: %s", key, value);
|
||||||
|
|
||||||
aisl_raise(
|
on_header.evt.code = AISL_EVENT_STREAM_HEADER;
|
||||||
aisl_stream_get_instance(stream),
|
on_header.evt.source = (void *) stream;
|
||||||
stream,
|
on_header.evt.status = AISL_SUCCESS;
|
||||||
AISL_EVENT_STREAM_HEADER,
|
on_header.key = key;
|
||||||
key,
|
on_header.value = value;
|
||||||
value
|
|
||||||
);
|
aisl_raise_evt(aisl_stream_get_instance(stream), (aisl_evt_t)&on_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,6 +212,8 @@ aisl_stream_set_body( aisl_stream_t stream, const char * data, int32_t size )
|
||||||
{
|
{
|
||||||
if ( !(stream->content_length < size) )
|
if ( !(stream->content_length < size) )
|
||||||
{
|
{
|
||||||
|
struct aisl_evt_stream_input on_input;
|
||||||
|
|
||||||
if (stream->content_length == 0)
|
if (stream->content_length == 0)
|
||||||
{
|
{
|
||||||
stream->state = AISL_STREAM_STATE_READY;
|
stream->state = AISL_STREAM_STATE_READY;
|
||||||
|
@ -216,13 +222,13 @@ aisl_stream_set_body( aisl_stream_t stream, const char * data, int32_t size )
|
||||||
else
|
else
|
||||||
result = 1;
|
result = 1;
|
||||||
|
|
||||||
aisl_raise(
|
on_input.evt.code = AISL_EVENT_STREAM_INPUT;
|
||||||
aisl_stream_get_instance(stream),
|
on_input.evt.source = (void *) stream;
|
||||||
stream,
|
on_input.evt.status = AISL_SUCCESS;
|
||||||
AISL_EVENT_STREAM_OUTPUT,
|
on_input.data = data;
|
||||||
data,
|
on_input.size = size;
|
||||||
size
|
|
||||||
);
|
aisl_raise_evt(stream->client->server->instance, (aisl_evt_t)&on_input);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = -1;
|
result = -1;
|
||||||
|
@ -295,7 +301,7 @@ __attribute__ ((visibility ("default") ))
|
||||||
void
|
void
|
||||||
aisl_reject(aisl_stream_t s)
|
aisl_reject(aisl_stream_t s)
|
||||||
{
|
{
|
||||||
aisl_client_close( s->client );
|
aisl_client_disconnect( s->client );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -662,5 +668,5 @@ __attribute__ ((visibility ("default") ))
|
||||||
aisl_t
|
aisl_t
|
||||||
aisl_stream_get_instance(aisl_stream_t stream)
|
aisl_stream_get_instance(aisl_stream_t stream)
|
||||||
{
|
{
|
||||||
return aisl_server_get_instance(aisl_client_get_server(stream->client));
|
return stream->client->server->instance;
|
||||||
}
|
}
|
||||||
|
|
27
src/types.c
27
src/types.c
|
@ -37,22 +37,21 @@ aisl_status_to_string(aisl_status_t status)
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
__attribute__ ((visibility ("default") ))
|
||||||
const char *
|
const char *
|
||||||
aisl_event_to_string( aisl_event_t event )
|
aisl_evt_code_to_string( aisl_evt_code_t evt_code )
|
||||||
{
|
{
|
||||||
switch(event)
|
switch(evt_code)
|
||||||
{
|
{
|
||||||
case AISL_EVENT_SERVER_OPEN: return "SERVER_OPEN";
|
case AISL_EVENT_SERVER_OPEN: return "SERVER OPEN";
|
||||||
case AISL_EVENT_SERVER_ERROR: return "SERVER_ERROR";
|
case AISL_EVENT_SERVER_ERROR: return "SERVER ERROR";
|
||||||
case AISL_EVENT_CLIENT_CONNECT: return "CLIENT_CONNECT";
|
case AISL_EVENT_CLIENT_CONNECT: return "CLIENT CONNECT";
|
||||||
case AISL_EVENT_CLIENT_DISCONNECT: return "CLIENT_DISCONNECT";
|
case AISL_EVENT_CLIENT_DISCONNECT: return "CLIENT DISCONNECT";
|
||||||
case AISL_EVENT_CLIENT_TIMEOUT: return "CLIENT_TIMEOUT";
|
case AISL_EVENT_STREAM_OPEN: return "STREAM OPEN";
|
||||||
case AISL_EVENT_STREAM_OPEN: return "STREAM_OPEN";
|
case AISL_EVENT_STREAM_HEADER: return "STREAM HEADER";
|
||||||
case AISL_EVENT_STREAM_HEADER: return "STREAM_HEADER";
|
case AISL_EVENT_STREAM_INPUT: return "STREAM INPUT";
|
||||||
case AISL_EVENT_STREAM_INPUT: return "STREAM_INPUT";
|
case AISL_EVENT_STREAM_REQUEST: return "STREAM REQUEST";
|
||||||
case AISL_EVENT_STREAM_REQUEST: return "STREAM_REQUEST";
|
case AISL_EVENT_STREAM_OUTPUT: return "STREAM OUTPUT";
|
||||||
case AISL_EVENT_STREAM_OUTPUT: return "STREAM_OUTPUT";
|
case AISL_EVENT_STREAM_CLOSE: return "STREAM CLOSE";
|
||||||
case AISL_EVENT_STREAM_CLOSE: return "STREAM_CLOSE";
|
case AISL_EVENT_STREAM_ERROR: return "STREAM ERROR";
|
||||||
case AISL_EVENT_STREAM_ERROR: return "STREAM_ERROR";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
|
|
Loading…
Reference in New Issue