Switch to initialization by config and new event model

This commit is contained in:
Ilja Kartašov 2019-03-24 21:00:25 +01:00
parent d28f942cf7
commit 345450b35b
18 changed files with 505 additions and 735 deletions

1
.gitignore vendored
View File

@ -17,6 +17,7 @@ tmp/*
*.bz2 *.bz2
pkg/* pkg/*
doc/html doc/html
vgcore.*
include/webstuff_bak include/webstuff_bak

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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