Switch to initialization by config and new event model
This commit is contained in:
parent
d28f942cf7
commit
345450b35b
|
@ -17,6 +17,7 @@ tmp/*
|
|||
*.bz2
|
||||
pkg/*
|
||||
doc/html
|
||||
vgcore.*
|
||||
|
||||
include/webstuff_bak
|
||||
|
||||
|
|
|
@ -23,11 +23,16 @@
|
|||
#define DEFAULT_HTTP_PORT 8080 /**< Default HTTP server port */
|
||||
|
||||
|
||||
static bool
|
||||
hello_world(aisl_stream_t s)
|
||||
static void
|
||||
hello_world(aisl_evt_t const evt, void * p_ctx)
|
||||
{
|
||||
if (evt->code != AISL_EVENT_STREAM_REQUEST)
|
||||
return;
|
||||
|
||||
aisl_status_t status;
|
||||
|
||||
aisl_stream_t s = evt->source;
|
||||
|
||||
const char html[] =
|
||||
"<html>"
|
||||
"<head>"
|
||||
|
@ -51,58 +56,44 @@ hello_world(aisl_stream_t s)
|
|||
aisl_reject(s);
|
||||
}
|
||||
|
||||
return true; /**< do not propagate event anymore */
|
||||
(void) p_ctx;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char ** argv)
|
||||
{
|
||||
aisl_t aisl; /**< AISL instance pointer */
|
||||
aisl_status_t status; /**< AISL status code */
|
||||
struct aisl_config config = AISL_CONFIG_DEFAULT;
|
||||
uint16_t port = 0;
|
||||
aisl_t aisl; /**< AISL instance pointer */
|
||||
aisl_status_t status; /**< AISL status code */
|
||||
struct aisl_cfg cfg = AISL_CFG_DEFAULT;
|
||||
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 */
|
||||
if (argc > 1)
|
||||
port = strtoll(argv[1], NULL, 10);
|
||||
|
||||
/* Fallback to default if not set or failed */
|
||||
if (port == 0)
|
||||
port = DEFAULT_HTTP_PORT;
|
||||
cfg.srv = &srv;
|
||||
cfg.srv_cnt = 1;
|
||||
cfg.callback = hello_world;
|
||||
|
||||
/* 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 */
|
||||
aisl_set_callback( aisl
|
||||
, AISL_EVENT_STREAM_REQUEST
|
||||
, AISL_CALLBACK(hello_world) );
|
||||
status = aisl_run_cycle(aisl);
|
||||
|
||||
/* launch application loop */
|
||||
fprintf(stdout, "Entering main loop" );
|
||||
for(;;)
|
||||
{
|
||||
status = aisl_run_cycle(aisl);
|
||||
|
||||
if ( status != AISL_SUCCESS )
|
||||
aisl_sleep(aisl, 500);
|
||||
}
|
||||
|
||||
aisl_free(aisl);
|
||||
if ( status != AISL_SUCCESS )
|
||||
aisl_sleep(aisl, 500);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Failed to initialize HTTP server" );
|
||||
|
||||
aisl_free(aisl);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Failed to initialize AISL");
|
||||
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ aisl_client_is_online(aisl_client_t client);
|
|||
* @param client an #aisl_client_t instance pointer.
|
||||
*/
|
||||
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
|
||||
#define AISL_CONFIG_H_DB67A89B_5CAF_4A5F_AEB1_6DB9F84827D6
|
||||
|
||||
#include <stdint.h>
|
||||
#include <aisl/types.h>
|
||||
|
||||
#define AISL_CONFIG_DEFAULT \
|
||||
{ \
|
||||
.server_spool_size = 1 \
|
||||
#define AISL_CFG_DEFAULT \
|
||||
{ \
|
||||
.callback = NULL \
|
||||
, .p_ctx = NULL \
|
||||
, .srv = NULL \
|
||||
, .ssl = NULL \
|
||||
, .srv_cnt = 0 \
|
||||
, .ssl_cnt = 0 \
|
||||
, .client_spool_size = 32 \
|
||||
, .ssl_spool_size = 1 \
|
||||
, .initial_buffer_size = 16536 \
|
||||
, .client_accept_limit = 1024 \
|
||||
, .client_silence_timeout = 30 \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
struct aisl_config
|
||||
struct aisl_cfg_srv
|
||||
{
|
||||
uint32_t server_spool_size;
|
||||
uint32_t client_spool_size;
|
||||
uint32_t ssl_spool_size;
|
||||
uint32_t initial_buffer_size;
|
||||
uint32_t client_accept_limit;
|
||||
uint32_t client_silence_timeout;
|
||||
const char * host;
|
||||
uint16_t port;
|
||||
bool secure;
|
||||
};
|
||||
|
||||
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 */
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
/**
|
||||
* @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.
|
||||
*/
|
||||
aisl_t
|
||||
aisl_new( aisl_config_t config );
|
||||
aisl_new( aisl_cfg_t cfg );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -35,56 +35,6 @@ void
|
|||
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.
|
||||
* Designed to be called inside application main loop
|
||||
|
@ -106,12 +56,4 @@ aisl_status_t
|
|||
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 */
|
||||
|
|
|
@ -31,17 +31,6 @@ void
|
|||
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.
|
||||
* @param server an #aisl_server_t pointer.
|
||||
|
@ -50,6 +39,4 @@ aisl_server_set_ssl( aisl_server_t server, bool value );
|
|||
bool
|
||||
aisl_server_get_ssl( aisl_server_t server );
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !AISL_SERVER_H */
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
/* AISL Instance */
|
||||
typedef struct aisl * aisl_t;
|
||||
|
||||
/* Event Identifier */
|
||||
typedef uint32_t aisl_event_t;
|
||||
|
||||
/* HTTP(s) Server */
|
||||
typedef struct aisl_server * aisl_server_t;
|
||||
|
||||
|
@ -39,10 +36,6 @@ typedef struct aisl_client * aisl_client_t;
|
|||
/* Server<->Client Stream */
|
||||
typedef struct aisl_stream * aisl_stream_t;
|
||||
|
||||
/* void type event callback */
|
||||
typedef void
|
||||
(* aisl_callback_t) (void);
|
||||
|
||||
|
||||
/* status return codes */
|
||||
typedef enum
|
||||
|
@ -64,6 +57,7 @@ aisl_status_to_string(aisl_status_t status);
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
/* Generic HTTP Enumerations */
|
||||
|
||||
typedef enum
|
||||
|
@ -156,16 +150,15 @@ const char *
|
|||
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_ERROR = 190
|
||||
|
||||
, AISL_EVENT_CLIENT_CONNECT = 200
|
||||
, AISL_EVENT_CLIENT_DISCONNECT = 210
|
||||
, AISL_EVENT_CLIENT_TIMEOUT = 220
|
||||
|
||||
, AISL_EVENT_STREAM_OPEN = 300
|
||||
, AISL_EVENT_STREAM_HEADER = 310
|
||||
|
@ -175,62 +168,59 @@ enum
|
|||
, AISL_EVENT_STREAM_CLOSE = 350
|
||||
, 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
|
||||
|
||||
const char *
|
||||
aisl_event_to_string( aisl_event_t event );
|
||||
aisl_evt_code_to_string( aisl_evt_code_t evt_code );
|
||||
|
||||
#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 */
|
||||
|
|
|
@ -51,8 +51,8 @@ PROJECT_LIBRARIES = \
|
|||
|
||||
# flags
|
||||
PROJECT_CFLAGS = -D_POSIX_C_SOURCE=200809L
|
||||
#PROJECT_CFLAGS += -DDEBUG
|
||||
#PROJECT_CFLAGS += -DAISL_WITHOUT_SSL
|
||||
PROJECT_CFLAGS += -DDEBUG
|
||||
PROJECT_CFLAGS += -DAISL_WITHOUT_SSL
|
||||
#PROJECT_CFLAGS += -DAISL_WITHOUT_STRINGIFIERS
|
||||
|
||||
|
||||
|
|
139
src/client.c
139
src/client.c
|
@ -26,13 +26,33 @@
|
|||
#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
|
||||
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;
|
||||
|
||||
|
||||
int32_t bytes_left = size;
|
||||
|
||||
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_1:
|
||||
|
||||
s = client->stream;
|
||||
/* s = client->stream; */
|
||||
|
||||
while ( p == HTTP_PARSER_SUCCESS )
|
||||
{
|
||||
|
@ -70,17 +90,7 @@ aisl_client_parse(aisl_client_t client, char * data, int32_t size)
|
|||
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;
|
||||
|
||||
|
@ -89,27 +99,43 @@ aisl_client_parse(aisl_client_t client, char * data, int32_t size)
|
|||
break;
|
||||
}
|
||||
|
||||
if (p == HTTP_PARSER_ERROR)
|
||||
switch(p)
|
||||
{
|
||||
/* reply Bad Request here */
|
||||
client->stream->http_response = AISL_HTTP_BAD_REQUEST;
|
||||
case HTTP_PARSER_READY:
|
||||
client->flags &= ~FLAG_CAN_READ;
|
||||
client->flags |= FLAG_CAN_WRITE;
|
||||
|
||||
aisl_raise(
|
||||
client->server->instance,
|
||||
client->stream,
|
||||
AISL_EVENT_STREAM_ERROR
|
||||
);
|
||||
aisl_raise(
|
||||
client->server->instance
|
||||
, (void *) s
|
||||
, 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)
|
||||
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) );
|
||||
|
||||
aisl_client_close(client);
|
||||
return AISL_SYSCALL_ERROR;
|
||||
aisl_client_close(client, AISL_EXTCALL_ERROR);
|
||||
return AISL_EXTCALL_ERROR;
|
||||
}
|
||||
|
||||
client->flags &= ~FLAG_HANDSHAKE;
|
||||
|
@ -186,7 +212,7 @@ aisl_client_input(aisl_client_t client)
|
|||
|
||||
/* both: client disconnect + on read error */
|
||||
/* todo: raise client error here */
|
||||
aisl_client_close(client);
|
||||
aisl_client_close(client, 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) )
|
||||
{
|
||||
aisl_raise(
|
||||
aisl_server_get_instance(client->server),
|
||||
s,
|
||||
AISL_EVENT_STREAM_OUTPUT,
|
||||
l
|
||||
client->server->instance
|
||||
, (void*)s
|
||||
, AISL_EVENT_STREAM_OUTPUT
|
||||
, AISL_SUCCESS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -289,7 +317,7 @@ aisl_client_output(aisl_client_t client)
|
|||
return AISL_IDLE;
|
||||
}
|
||||
|
||||
aisl_client_close(client);
|
||||
aisl_client_close(client, AISL_SYSCALL_ERROR);
|
||||
|
||||
return AISL_SYSCALL_ERROR;
|
||||
}
|
||||
|
@ -360,7 +388,7 @@ aisl_client_new( aisl_server_t server,
|
|||
void
|
||||
aisl_client_free(aisl_client_t client)
|
||||
{
|
||||
aisl_client_close(client);
|
||||
aisl_client_close(client, AISL_SUCCESS);
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
if (client->ssl)
|
||||
|
@ -380,7 +408,7 @@ aisl_client_free(aisl_client_t client)
|
|||
|
||||
|
||||
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,
|
||||
status = AISL_IDLE;
|
||||
|
@ -418,29 +446,22 @@ aisl_client_touch(aisl_client_t client)
|
|||
|
||||
if (result == AISL_SUCCESS)
|
||||
client->timestamp = time(NULL);
|
||||
else
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
if ( !(now - client->timestamp < timeout) )
|
||||
{
|
||||
aisl_client_close(client, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
aisl_client_get_socket(aisl_client_t client)
|
||||
{
|
||||
|
@ -494,19 +515,11 @@ aisl_client_is_online(aisl_client_t client)
|
|||
|
||||
|
||||
void
|
||||
aisl_client_close(aisl_client_t client)
|
||||
aisl_client_disconnect(aisl_client_t client)
|
||||
{
|
||||
if (client->fd != -1)
|
||||
{
|
||||
aisl_raise(client->server->instance, client, AISL_EVENT_CLIENT_DISCONNECT);
|
||||
|
||||
close(client->fd);
|
||||
shutdown(client->fd, SHUT_RDWR);
|
||||
client->fd = -1;
|
||||
}
|
||||
aisl_client_close(client, AISL_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
aisl_http_version_t
|
||||
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.
|
||||
* Reads and parses requests, writes responses.
|
||||
* @param client an #aisl_client_t instance pointer.
|
||||
* @param timeout an allowed client silence time in seconds.
|
||||
* @return #aisl_status_t code.
|
||||
*/
|
||||
aisl_status_t
|
||||
aisl_client_touch(aisl_client_t client);
|
||||
|
||||
|
||||
/**
|
||||
* @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);
|
||||
aisl_client_touch(aisl_client_t client, int32_t timeout);
|
||||
|
||||
|
||||
/**
|
||||
|
|
519
src/instance.c
519
src/instance.c
|
@ -25,14 +25,53 @@
|
|||
|
||||
#include "client.h"
|
||||
#include "server.h"
|
||||
#include "ssl.h"
|
||||
//#include "globals.h"
|
||||
#include "stream.h"
|
||||
#include "instance.h"
|
||||
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -40,34 +79,50 @@ static uint32_t m_instances = 0;
|
|||
|
||||
__attribute__ ((visibility ("default") ))
|
||||
aisl_t
|
||||
aisl_new( aisl_config_t config )
|
||||
aisl_new( aisl_cfg_t cfg )
|
||||
{
|
||||
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
|
||||
if ((m_instances++) == 0)
|
||||
{
|
||||
SSL_load_error_strings();
|
||||
OpenSSL_add_ssl_algorithms();
|
||||
}
|
||||
|
||||
if ( !(instance->ssl = calloc(cfg->ssl_cnt+1, sizeof(aisl_ssl_t))) )
|
||||
goto release;
|
||||
|
||||
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
|
||||
|
||||
if ( !(instance = calloc(1, sizeof(struct aisl))) )
|
||||
goto finally;
|
||||
|
||||
if ( list_init(&instance->server_spool, config->server_spool_size) == -1 )
|
||||
if ( list_init(&instance->client_spool, cfg->client_spool_size) == -1 )
|
||||
goto release;
|
||||
|
||||
if ( list_init(&instance->client_spool, config->client_spool_size) == -1 )
|
||||
goto release;
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
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;
|
||||
instance->accept_limit = cfg->client_accept_limit;
|
||||
instance->silence_timeout = cfg->client_silence_timeout;
|
||||
instance->callback = cfg->callback;
|
||||
instance->p_ctx = cfg->p_ctx;
|
||||
|
||||
goto finally;
|
||||
|
||||
|
@ -84,304 +139,100 @@ __attribute__ ((visibility ("default") ))
|
|||
void
|
||||
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->server_spool, (list_destructor_t) aisl_server_free );
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
list_release(&instance->ssl_spool, (list_destructor_t) aisl_ssl_free );
|
||||
#endif
|
||||
if (instance->ssl)
|
||||
{
|
||||
aisl_ssl_t * ssl = instance->ssl;
|
||||
|
||||
if (instance->last_error)
|
||||
free(instance->last_error);
|
||||
while (*ssl)
|
||||
{
|
||||
aisl_ssl_free(*ssl);
|
||||
ssl++;
|
||||
}
|
||||
|
||||
free(instance);
|
||||
free(instance->ssl);
|
||||
}
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
if ((--m_instances) == 0)
|
||||
{
|
||||
EVP_cleanup();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
__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;
|
||||
free(instance);
|
||||
}
|
||||
|
||||
|
||||
#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 *
|
||||
aisl_get_ssl_ctx( aisl_t instance, const char * host )
|
||||
{
|
||||
size_t i;
|
||||
aisl_ssl_t ssl;
|
||||
aisl_ssl_t * list = instance->ssl,
|
||||
ssl;
|
||||
|
||||
if (host)
|
||||
{
|
||||
for (i=0; i<instance->ssl_spool.count; i++)
|
||||
while ( (ssl = *list) )
|
||||
{
|
||||
ssl = LIST_INDEX(instance->ssl_spool, i);
|
||||
if (strcmp(ssl->host, host) != 0)
|
||||
continue;
|
||||
if (str_cmpi(ssl->host, host) == 0)
|
||||
{
|
||||
return ssl->ctx;
|
||||
}
|
||||
|
||||
return ssl->ctx;
|
||||
list++;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
__attribute__ ((visibility ("default") ))
|
||||
|
||||
void
|
||||
aisl_set_callback( aisl_t instance,
|
||||
aisl_event_t event,
|
||||
aisl_callback_t callback )
|
||||
aisl_raise_evt( aisl_t instance, aisl_evt_t const evt )
|
||||
{
|
||||
switch( event )
|
||||
{
|
||||
case AISL_EVENT_SERVER_OPEN:
|
||||
instance->on_server_open = (aisl_on_server_open_t) callback;
|
||||
break;
|
||||
#ifdef AISL_WITHOUT_STRINGIFIERS
|
||||
DPRINTF("! %d", evt->code);
|
||||
#else
|
||||
DPRINTF("! %s", aisl_evt_code_to_string(evt->code));
|
||||
#endif
|
||||
|
||||
case AISL_EVENT_SERVER_ERROR:
|
||||
instance->on_server_error = (aisl_on_server_error_t) callback;
|
||||
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;
|
||||
}
|
||||
if (instance->callback)
|
||||
instance->callback(evt, instance->p_ctx);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
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);
|
||||
aisl_raise_evt(instance, &evt);
|
||||
}
|
||||
|
||||
|
||||
|
@ -391,103 +242,49 @@ aisl_run_cycle( aisl_t instance )
|
|||
{
|
||||
aisl_status_t result = AISL_IDLE;
|
||||
|
||||
int32_t i = instance->iterator,
|
||||
max = instance->server_spool.count + instance->client_spool.count;
|
||||
aisl_server_t * list = instance->srv,
|
||||
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)
|
||||
{
|
||||
aisl_server_t srv;
|
||||
/* 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;
|
||||
}
|
||||
DPRINTF("Accepted %p", (void*)cli);
|
||||
if ( list_append(&instance->client_spool, cli) == -1 )
|
||||
aisl_client_free(cli);
|
||||
}
|
||||
|
||||
max--;
|
||||
i++;
|
||||
list++;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
__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") ))
|
||||
aisl_status_t
|
||||
aisl_sleep( aisl_t instance, uint32_t usec )
|
||||
|
@ -503,19 +300,21 @@ aisl_sleep( aisl_t instance, uint32_t usec )
|
|||
fd_set fs;
|
||||
FD_ZERO (&fs);
|
||||
|
||||
for (i=0; i<instance->server_spool.count; i++)
|
||||
{
|
||||
aisl_server_t s = LIST_INDEX(instance->server_spool, i);
|
||||
aisl_server_t * list = instance->srv,
|
||||
srv;
|
||||
|
||||
sd = aisl_server_get_socket(s);
|
||||
while ( (srv = *list) )
|
||||
{
|
||||
sd = aisl_server_get_socket(srv);
|
||||
|
||||
if (sd != -1)
|
||||
{
|
||||
FD_SET(sd, &fs);
|
||||
if (sd > maxfd) maxfd = sd;
|
||||
}
|
||||
}
|
||||
|
||||
list++;
|
||||
}
|
||||
|
||||
for (i=0; i<instance->client_spool.count; i++)
|
||||
{
|
||||
|
|
|
@ -15,37 +15,23 @@
|
|||
#endif
|
||||
|
||||
#include <aisl/instance.h>
|
||||
#include "ssl.h"
|
||||
#include "list.h"
|
||||
|
||||
|
||||
struct aisl
|
||||
{
|
||||
struct list server_spool;
|
||||
struct list client_spool;
|
||||
aisl_server_t * srv;
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
struct list ssl_spool;
|
||||
aisl_ssl_t * ssl;
|
||||
#endif
|
||||
struct list client_spool;
|
||||
aisl_callback_t callback;
|
||||
void * p_ctx;
|
||||
|
||||
char * last_error;
|
||||
|
||||
int32_t iterator;
|
||||
|
||||
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;
|
||||
uint32_t accept_limit;
|
||||
uint32_t silence_timeout;
|
||||
uint32_t buffer_size;
|
||||
};
|
||||
|
||||
|
||||
|
@ -61,24 +47,19 @@ aisl_get_ssl_ctx( aisl_t instance, const char * server_name );
|
|||
#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.
|
||||
* @param instance a pointer to #aisl_t instance.
|
||||
* @param source a pointer to an event source.
|
||||
* @param event a code of event.
|
||||
* @param ... a list of arguments specific for event.
|
||||
* @param evt a pointer to event structure.
|
||||
*/
|
||||
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 */
|
||||
|
|
42
src/server.c
42
src/server.c
|
@ -22,9 +22,6 @@
|
|||
#include "server.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates TCP server socket, binds to address and starts to listen.
|
||||
* @param server a pointer to #aisl_server_t instance.
|
||||
|
@ -101,8 +98,6 @@ aisl_server_accept( aisl_server_t server,
|
|||
else if (errno == EWOULDBLOCK)
|
||||
return AISL_IDLE;
|
||||
|
||||
aisl_raise( server->instance, server, AISL_EVENT_SERVER_ERROR );
|
||||
|
||||
return AISL_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -116,13 +111,17 @@ aisl_server_touch( aisl_server_t server,
|
|||
|
||||
if (server->fd == -1)
|
||||
{
|
||||
aisl_event_t event;
|
||||
|
||||
result = aisl_server_open(server);
|
||||
event = (result == AISL_SUCCESS) ? AISL_EVENT_SERVER_OPEN
|
||||
: AISL_EVENT_SERVER_ERROR;
|
||||
|
||||
aisl_raise(server->instance, server, event);
|
||||
if ((result = aisl_server_open(server)) != AISL_IDLE)
|
||||
{
|
||||
aisl_raise(
|
||||
server->instance,
|
||||
server,
|
||||
((result == AISL_SUCCESS) ? AISL_EVENT_SERVER_OPEN
|
||||
: AISL_EVENT_SERVER_ERROR),
|
||||
result
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
result = aisl_server_accept(server, p_client);
|
||||
|
@ -141,7 +140,7 @@ aisl_server_get_socket( aisl_server_t server )
|
|||
/* API Level ---------------------------------------------------------------- */
|
||||
|
||||
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;
|
||||
|
||||
|
@ -150,8 +149,9 @@ aisl_server_new(aisl_t instance, const char * host, uint16_t port)
|
|||
server->instance = instance;
|
||||
server->fd = -1;
|
||||
server->address.sin_family = AF_INET;
|
||||
server->address.sin_addr.s_addr = inet_addr(host);
|
||||
server->address.sin_port = htons(port);
|
||||
server->address.sin_addr.s_addr = inet_addr(cfg_srv->host);
|
||||
server->address.sin_port = htons(cfg_srv->port);
|
||||
server->ssl = cfg_srv->secure;
|
||||
}
|
||||
|
||||
return server;
|
||||
|
@ -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
|
||||
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
|
||||
|
||||
void
|
||||
aisl_server_set_ssl( aisl_server_t server, bool value )
|
||||
{
|
||||
server->ssl = value;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
aisl_server_get_ssl( aisl_server_t server )
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef 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>
|
||||
|
||||
#define AISL_SERVER(x) ((aisl_server_t) x)
|
||||
|
@ -27,13 +28,12 @@ struct aisl_server
|
|||
|
||||
/**
|
||||
* @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 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.
|
||||
*/
|
||||
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 "ssl.h"
|
||||
#include "str-utils.h"
|
||||
#include "instance.h"
|
||||
#include "ssl.h"
|
||||
|
||||
|
||||
#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_new( const char * key_file,
|
||||
const char * crt_file,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef 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 <openssl/ssl.h>
|
||||
|
||||
|
@ -32,6 +33,10 @@ aisl_ssl_new( const char * key_file,
|
|||
SSL_CTX * ctx );
|
||||
|
||||
|
||||
SSL_CTX *
|
||||
aisl_ssl_get_ctx(aisl_ssl_t ssl, void * p_instance);
|
||||
|
||||
|
||||
void
|
||||
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)
|
||||
{
|
||||
aisl_t instance;
|
||||
|
||||
instance = aisl_stream_get_instance(stream);
|
||||
|
||||
aisl_raise(instance, stream, AISL_EVENT_STREAM_CLOSE);
|
||||
aisl_raise(
|
||||
aisl_stream_get_instance(stream)
|
||||
, (void*) stream
|
||||
, AISL_EVENT_STREAM_CLOSE
|
||||
, AISL_SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
buffer_release(&stream->buffer);
|
||||
|
@ -134,6 +135,7 @@ aisl_stream_set_request( aisl_stream_t stream,
|
|||
const char * path,
|
||||
const char * query )
|
||||
{
|
||||
struct aisl_evt_stream_open on_open;
|
||||
|
||||
stream->state = AISL_STREAM_STATE_WAIT_HEADER;
|
||||
|
||||
|
@ -144,22 +146,24 @@ aisl_stream_set_request( aisl_stream_t stream,
|
|||
, query
|
||||
);
|
||||
|
||||
aisl_raise(
|
||||
aisl_stream_get_instance(stream),
|
||||
stream,
|
||||
AISL_EVENT_STREAM_OPEN,
|
||||
http_method,
|
||||
path,
|
||||
query
|
||||
);
|
||||
on_open.evt.code = AISL_EVENT_STREAM_OPEN;
|
||||
on_open.evt.source = (void *) stream;
|
||||
on_open.evt.status = AISL_SUCCESS;
|
||||
on_open.http_method = http_method;
|
||||
on_open.path = path;
|
||||
on_open.query = query;
|
||||
|
||||
aisl_raise_evt(aisl_stream_get_instance(stream), (aisl_evt_t)&on_open);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
aisl_stream_set_header( aisl_stream_t stream,
|
||||
const char * key,
|
||||
const char * value )
|
||||
aisl_stream_set_header( aisl_stream_t stream,
|
||||
const char * key,
|
||||
const char * value )
|
||||
{
|
||||
struct aisl_evt_stream_header on_header;
|
||||
|
||||
if (stream->state != AISL_STREAM_STATE_WAIT_HEADER)
|
||||
return;
|
||||
|
||||
|
@ -173,13 +177,13 @@ aisl_stream_set_header( aisl_stream_t stream,
|
|||
|
||||
DPRINTF("%s: %s", key, value);
|
||||
|
||||
aisl_raise(
|
||||
aisl_stream_get_instance(stream),
|
||||
stream,
|
||||
AISL_EVENT_STREAM_HEADER,
|
||||
key,
|
||||
value
|
||||
);
|
||||
on_header.evt.code = AISL_EVENT_STREAM_HEADER;
|
||||
on_header.evt.source = (void *) stream;
|
||||
on_header.evt.status = AISL_SUCCESS;
|
||||
on_header.key = key;
|
||||
on_header.value = value;
|
||||
|
||||
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) )
|
||||
{
|
||||
struct aisl_evt_stream_input on_input;
|
||||
|
||||
if (stream->content_length == 0)
|
||||
{
|
||||
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
|
||||
result = 1;
|
||||
|
||||
aisl_raise(
|
||||
aisl_stream_get_instance(stream),
|
||||
stream,
|
||||
AISL_EVENT_STREAM_OUTPUT,
|
||||
data,
|
||||
size
|
||||
);
|
||||
on_input.evt.code = AISL_EVENT_STREAM_INPUT;
|
||||
on_input.evt.source = (void *) stream;
|
||||
on_input.evt.status = AISL_SUCCESS;
|
||||
on_input.data = data;
|
||||
on_input.size = size;
|
||||
|
||||
aisl_raise_evt(stream->client->server->instance, (aisl_evt_t)&on_input);
|
||||
}
|
||||
else
|
||||
result = -1;
|
||||
|
@ -295,7 +301,7 @@ __attribute__ ((visibility ("default") ))
|
|||
void
|
||||
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_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") ))
|
||||
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_ERROR: return "SERVER_ERROR";
|
||||
case AISL_EVENT_CLIENT_CONNECT: return "CLIENT_CONNECT";
|
||||
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_HEADER: return "STREAM_HEADER";
|
||||
case AISL_EVENT_STREAM_INPUT: return "STREAM_INPUT";
|
||||
case AISL_EVENT_STREAM_REQUEST: return "STREAM_REQUEST";
|
||||
case AISL_EVENT_STREAM_OUTPUT: return "STREAM_OUTPUT";
|
||||
case AISL_EVENT_STREAM_CLOSE: return "STREAM_CLOSE";
|
||||
case AISL_EVENT_STREAM_ERROR: return "STREAM_ERROR";
|
||||
case AISL_EVENT_SERVER_OPEN: return "SERVER OPEN";
|
||||
case AISL_EVENT_SERVER_ERROR: return "SERVER ERROR";
|
||||
case AISL_EVENT_CLIENT_CONNECT: return "CLIENT CONNECT";
|
||||
case AISL_EVENT_CLIENT_DISCONNECT: return "CLIENT DISCONNECT";
|
||||
case AISL_EVENT_STREAM_OPEN: return "STREAM OPEN";
|
||||
case AISL_EVENT_STREAM_HEADER: return "STREAM HEADER";
|
||||
case AISL_EVENT_STREAM_INPUT: return "STREAM INPUT";
|
||||
case AISL_EVENT_STREAM_REQUEST: return "STREAM REQUEST";
|
||||
case AISL_EVENT_STREAM_OUTPUT: return "STREAM OUTPUT";
|
||||
case AISL_EVENT_STREAM_CLOSE: return "STREAM CLOSE";
|
||||
case AISL_EVENT_STREAM_ERROR: return "STREAM ERROR";
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
|
|
Loading…
Reference in New Issue