Refactoring pending
This commit is contained in:
parent
86b69c89b8
commit
d87c7454b5
|
@ -13,14 +13,8 @@
|
||||||
/* AISL configuration structure */
|
/* AISL configuration structure */
|
||||||
#include <aisl/config.h>
|
#include <aisl/config.h>
|
||||||
|
|
||||||
/* AISL status codes and utilities */
|
/* AISL types and stringifiers */
|
||||||
#include <aisl/status.h>
|
#include <aisl/types.h>
|
||||||
|
|
||||||
/* AISL callbacks definitions */
|
|
||||||
#include <aisl/callback.h>
|
|
||||||
|
|
||||||
/* AISL events enumeration and utilities*/
|
|
||||||
#include <aisl/event.h>
|
|
||||||
|
|
||||||
/* AISL instancing, initialization and processing */
|
/* AISL instancing, initialization and processing */
|
||||||
#include <aisl/instance.h>
|
#include <aisl/instance.h>
|
||||||
|
@ -34,7 +28,4 @@
|
||||||
/* HTTP(s) streaming */
|
/* HTTP(s) streaming */
|
||||||
#include <aisl/stream.h>
|
#include <aisl/stream.h>
|
||||||
|
|
||||||
/* HTTP constants and utilities */
|
|
||||||
#include <aisl/http.h>
|
|
||||||
|
|
||||||
#endif /* !AISL_H */
|
#endif /* !AISL_H */
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* <aisl/callback.h>
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017 by Löwenware Ltd.
|
|
||||||
*
|
|
||||||
* Project homepage: https://lowenware.com/aisl/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AISL_CALLBACK_H_E99458C9_CCAA_4CAC_97F8_41E8869EE26F
|
|
||||||
#define AISL_CALLBACK_H_E99458C9_CCAA_4CAC_97F8_41E8869EE26F
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include <aisl/server.h>
|
|
||||||
#include <aisl/client.h>
|
|
||||||
#include <aisl/stream.h>
|
|
||||||
#include <aisl/http.h>
|
|
||||||
|
|
||||||
#define AISL_CALLBACK(x) ((aisl_callback_t) x)
|
|
||||||
|
|
||||||
|
|
||||||
/* void-type callback */
|
|
||||||
typedef void
|
|
||||||
(* aisl_callback_t) (void);
|
|
||||||
|
|
||||||
|
|
||||||
/* real type callbacks */
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_server_open_t)( aisl_server_t server, int flags );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_server_error_t)( aisl_server_t server, int flags, const char * details );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_client_connect_t)( aisl_server_t server, aisl_client_t client );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_client_disconnect_t)( aisl_server_t server, aisl_client_t client );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_client_timeout_t)( aisl_server_t server, aisl_client_t client );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_stream_open_t)( aisl_stream_t stream,
|
|
||||||
aisl_http_method_t method,
|
|
||||||
const char * path,
|
|
||||||
const char * query );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_stream_header_t)( aisl_stream_t stream,
|
|
||||||
const char * key,
|
|
||||||
const char * val );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_stream_input_t)( aisl_stream_t stream, char * data, int len );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_stream_request_t)( aisl_stream_t stream );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_stream_output_t)( aisl_stream_t stream, uint32_t buffer_space );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_stream_close_t)( aisl_stream_t stream );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_stream_error_t)( aisl_stream_t stream, const char * details );
|
|
||||||
|
|
||||||
typedef bool
|
|
||||||
(*aisl_custom_event_t)( void * source, va_list vl );
|
|
||||||
|
|
||||||
#endif /* !AISL_CALLBACK_H */
|
|
|
@ -10,6 +10,6 @@
|
||||||
#ifndef AISL_CLIENT_H_A6C37DCF_2183_4F22_A5A0_668311757A08
|
#ifndef AISL_CLIENT_H_A6C37DCF_2183_4F22_A5A0_668311757A08
|
||||||
#define AISL_CLIENT_H_A6C37DCF_2183_4F22_A5A0_668311757A08
|
#define AISL_CLIENT_H_A6C37DCF_2183_4F22_A5A0_668311757A08
|
||||||
|
|
||||||
typedef struct aisl_client * aisl_client_t;
|
#include <aisl/types.h>
|
||||||
|
|
||||||
#endif /* !AISL_CLIENT_H */
|
#endif /* !AISL_CLIENT_H */
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* <aisl/event.h>
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017 by Löwenware Ltd.
|
|
||||||
*
|
|
||||||
* Project homepage: https://lowenware.com/aisl/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AISL_EVENT_H_E99458C9_CCAA_4CAC_97F8_41E8869EE26F
|
|
||||||
#define AISL_EVENT_H_E99458C9_CCAA_4CAC_97F8_41E8869EE26F
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
AISL_SERVER_OPEN = 100
|
|
||||||
, AISL_SERVER_ERROR = 190
|
|
||||||
|
|
||||||
, AISL_CLIENT_CONNECT = 200
|
|
||||||
, AISL_CLIENT_DISCONNECT = 210
|
|
||||||
, AISL_CLIENT_TIMEOUT = 220
|
|
||||||
|
|
||||||
, AISL_STREAM_OPEN = 300
|
|
||||||
, AISL_STREAM_HEADER = 310
|
|
||||||
, AISL_STREAM_INPUT = 320
|
|
||||||
, AISL_STREAM_REQUEST = 330
|
|
||||||
, AISL_STREAM_OUTPUT = 340
|
|
||||||
, AISL_STREAM_CLOSE = 350
|
|
||||||
, AISL_STREAM_ERROR = 390
|
|
||||||
|
|
||||||
, AISL_EVENTS_CUSTOM = 1000
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef uint32_t aisl_event_t;
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
|
||||||
aisl_event_get_text( aisl_event_t event );
|
|
||||||
|
|
||||||
#endif /* !AISL_EVENT_H */
|
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
* aisl/http.h
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017 by Löwenware Ltd.
|
|
||||||
*
|
|
||||||
* Project homepage: https://lowenware.com/aisl/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AISL_HTTP_H_2BB40A17_5EB3_438B_8A98_EB3C68BA3A45
|
|
||||||
#define AISL_HTTP_H_2BB40A17_5EB3_438B_8A98_EB3C68BA3A45
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
AISL_HTTP_1_0
|
|
||||||
, AISL_HTTP_1_1
|
|
||||||
, AISL_HTTP_2_0
|
|
||||||
|
|
||||||
} aisl_http_version_t;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
AISL_HTTP_GET
|
|
||||||
, AISL_HTTP_PUT
|
|
||||||
, AISL_HTTP_POST
|
|
||||||
, AISL_HTTP_HEAD
|
|
||||||
, AISL_HTTP_TRACE
|
|
||||||
, AISL_HTTP_DELETE
|
|
||||||
, AISL_HTTP_OPTIONS
|
|
||||||
, AISL_HTTP_CONNECT
|
|
||||||
|
|
||||||
, AISL_HTTP_PRI
|
|
||||||
|
|
||||||
} aisl_http_method_t;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
AISL_HTTP_CONTINUE = 100
|
|
||||||
, AISL_HTTP_SWITCHING_PROTOCOLS
|
|
||||||
|
|
||||||
, AISL_HTTP_OK = 200
|
|
||||||
, AISL_HTTP_CREATED
|
|
||||||
, AISL_HTTP_ACCEPTED
|
|
||||||
, AISL_HTTP_NON_AUTHORITATIVE_INFORMATION
|
|
||||||
, AISL_HTTP_NO_CONTENT
|
|
||||||
, AISL_HTTP_RESET_CONTENT
|
|
||||||
, AISL_HTTP_PARTIAL_CONTENT
|
|
||||||
|
|
||||||
, AISL_HTTP_MULTIPLE_CHOICES = 300
|
|
||||||
, AISL_HTTP_MOVED_PERMANENTLY
|
|
||||||
, AISL_HTTP_FOUND
|
|
||||||
, AISL_HTTP_SEE_OTHER
|
|
||||||
, AISL_HTTP_NOT_MODIFIED
|
|
||||||
, AISL_HTTP_USE_PROXY
|
|
||||||
, AISL_HTTP_UNUSED
|
|
||||||
, AISL_HTTP_TEMPORARY_REDIRECT
|
|
||||||
|
|
||||||
, AISL_HTTP_BAD_REQUEST = 400
|
|
||||||
, AISL_HTTP_UNAUTHORIZED
|
|
||||||
, AISL_HTTP_PAYMENT_REQUIRED
|
|
||||||
, AISL_HTTP_FORBIDDEN
|
|
||||||
, AISL_HTTP_NOT_FOUND
|
|
||||||
, AISL_HTTP_METHOD_NOT_ALLOWED
|
|
||||||
, AISL_HTTP_NOT_ACCEPTABLE
|
|
||||||
, AISL_HTTP_PROXY_AUTHENTICATION_REQUIRED
|
|
||||||
, AISL_HTTP_REQUEST_TIMEOUT
|
|
||||||
, AISL_HTTP_CONFLICT
|
|
||||||
, AISL_HTTP_GONE
|
|
||||||
, AISL_HTTP_LENGTH_REQUIRED
|
|
||||||
, AISL_HTTP_PRECONDITION_FAILED
|
|
||||||
, AISL_HTTP_REQUEST_ENTITY_TOO_LARGE
|
|
||||||
, AISL_HTTP_REQUEST_URI_TOO_LONG
|
|
||||||
, AISL_HTTP_UNSUPPORTED_MEDIA_TYPE
|
|
||||||
, AISL_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE
|
|
||||||
, AISL_HTTP_EXPECTATION_FAILED
|
|
||||||
|
|
||||||
, AISL_HTTP_INTERNAL_SERVER_ERROR = 500
|
|
||||||
, AISL_HTTP_NOT_IMPLEMENTED
|
|
||||||
, AISL_HTTP_BAD_GATEWAY
|
|
||||||
, AISL_HTTP_SERVICE_UNAVAILABLE
|
|
||||||
, AISL_HTTP_GATEWAY_TIMEOUT
|
|
||||||
, AISL_HTTP_VERSION_NOT_SUPPORTED
|
|
||||||
|
|
||||||
} aisl_http_response_t;
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
|
||||||
aisl_http_version_to_string( aisl_http_version_t version );
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
|
||||||
aisl_http_response_to_string( aisl_http_response_t code );
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
|
||||||
aisl_http_secure_to_string( int is_secure );
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
|
||||||
aisl_http_method_to_string( aisl_http_method_t method );
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* !AISL_HTTP_H */
|
|
|
@ -7,69 +7,76 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef INSTANCE_H_60576F41_454C_4189_B91A_F40501132230
|
#ifndef AISL_INSTANCE_H_60576F41_454C_4189_B91A_F40501132230
|
||||||
#define INSTANCE_H_60576F41_454C_4189_B91A_F40501132230
|
#define AISL_INSTANCE_H_60576F41_454C_4189_B91A_F40501132230
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <aisl/types.h>
|
||||||
|
#include <aisl/config.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct aisl_instance * aisl_instance_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialization functions */
|
/* Initialization functions */
|
||||||
|
|
||||||
aisl_instance_t
|
aisl_t
|
||||||
aisl_new( aisl_config_t * config );
|
aisl_new( aisl_config_t config );
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
aisl_free( aisl_instance_t instance );
|
aisl_free( aisl_t instance );
|
||||||
|
|
||||||
|
|
||||||
aisl_server_t
|
aisl_server_t
|
||||||
aisl_listen( aisl_instance_t instance,
|
aisl_listen( aisl_t instance, const char * address, uint16_t port );
|
||||||
const char * address,
|
|
||||||
uint16_t port );
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef AISL_WITH_SSL
|
#ifdef AISL_WITH_SSL
|
||||||
|
|
||||||
aisl_status_t
|
aisl_status_t
|
||||||
aisl_set_ssl( aisl_instance_t instance,
|
aisl_set_ssl( aisl_t instance,
|
||||||
const char * hostname,
|
const char * hostname,
|
||||||
const char * key_file,
|
const char * key_file,
|
||||||
const char * crt_file );
|
const char * crt_file );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Callbacks and Events functions */
|
||||||
|
|
||||||
aisl_status_t
|
aisl_status_t
|
||||||
aisl_set_callback( aisl_instance_t instance,
|
aisl_set_callback( aisl_t instance,
|
||||||
void * source,
|
void * source,
|
||||||
aisl_event_t e_id,
|
aisl_event_t event,
|
||||||
aisl_callback_t cb );
|
aisl_callback_t callback );
|
||||||
|
|
||||||
|
|
||||||
|
aisl_status_t
|
||||||
|
aisl_raise( aisl_t instance, void * source, aisl_event_t event, ... );
|
||||||
|
|
||||||
|
|
||||||
|
aisl_status_t
|
||||||
|
aisl_raise_vl( aisl_t instance,
|
||||||
|
void * source,
|
||||||
|
aisl_event_t event,
|
||||||
|
va_list args );
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
aisl_unset_callback_for( aisl_t instance, void * source );
|
||||||
|
|
||||||
|
|
||||||
/* Control functions */
|
/* Control functions */
|
||||||
|
|
||||||
aisl_status_t
|
aisl_status_t
|
||||||
aisl_run_cycle( aisl_instance_t instance );
|
aisl_run_cycle( aisl_t instance );
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
aisl_get_error( aisl_instance_t instance );
|
aisl_get_error( aisl_t instance );
|
||||||
|
|
||||||
|
|
||||||
aisl_status_t
|
aisl_status_t
|
||||||
aisl_sleep( aisl_instance_t instance, uint32_t usec );
|
aisl_sleep( aisl_t instance, uint32_t usec );
|
||||||
|
|
||||||
|
|
||||||
aisl_status_t
|
#endif /* !AISL_INSTANCE_H */
|
||||||
aisl_raise( aisl_instance_t instance, aisl_event_t event, ...);
|
|
||||||
|
|
||||||
|
|
||||||
aisl_status_t
|
|
||||||
aisl_raisev( aisl_instance_t instance, aisl_event_t event, va_list args);
|
|
||||||
|
|
||||||
#endif /* !INSTANCE_H */
|
|
||||||
|
|
|
@ -10,9 +10,8 @@
|
||||||
#ifndef AISL_SERVER_H_CC564608_7A05_4B31_9E7E_32750BC60768
|
#ifndef AISL_SERVER_H_CC564608_7A05_4B31_9E7E_32750BC60768
|
||||||
#define AISL_SERVER_H_CC564608_7A05_4B31_9E7E_32750BC60768
|
#define AISL_SERVER_H_CC564608_7A05_4B31_9E7E_32750BC60768
|
||||||
|
|
||||||
typedef struct aisl_server * aisl_server_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <aisl/types.h>
|
||||||
#ifdef AISL_WITH_SSL
|
#ifdef AISL_WITH_SSL
|
||||||
|
|
||||||
aisl_status_t
|
aisl_status_t
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* <aisl/status.h>
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017 by Löwenware Ltd.
|
|
||||||
*
|
|
||||||
* Project homepage: https://lowenware.com/aisl/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AISL_STATUS_H_BF7E4434_A711_4D7C_B3AE_1BA2E1A020EF
|
|
||||||
#define AISL_STATUS_H_BF7E4434_A711_4D7C_B3AE_1BA2E1A020EF
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
AISL_EXTCALL_ERROR = -3
|
|
||||||
, AISL_SYSCALL_ERROR = -2
|
|
||||||
, AISL_MALLOC_ERROR = -1
|
|
||||||
|
|
||||||
, AISL_SUCCESS = 0
|
|
||||||
, AISL_IDLE = 1
|
|
||||||
|
|
||||||
} aisl_status_t;
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
|
||||||
aisl_status_to_string(aisl_status_t status);
|
|
||||||
|
|
||||||
#endif /* !AISL_STATUS_H */
|
|
|
@ -7,10 +7,13 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STREAM_H_4D8EB622_3CE0_4F1B_AC1F_B27CCB5C2EDC
|
#ifndef AISL_STREAM_H_4D8EB622_3CE0_4F1B_AC1F_B27CCB5C2EDC
|
||||||
#define STREAM_H_4D8EB622_3CE0_4F1B_AC1F_B27CCB5C2EDC
|
#define AISL_STREAM_H_4D8EB622_3CE0_4F1B_AC1F_B27CCB5C2EDC
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <aisl/types.h>
|
||||||
|
|
||||||
typedef struct aisl_stream * aisl_stream_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* Stream helpers */
|
/* Stream helpers */
|
||||||
|
@ -31,7 +34,7 @@ aisl_http_version_t
|
||||||
aisl_get_http_version( aisl_stream_t stream );
|
aisl_get_http_version( aisl_stream_t stream );
|
||||||
|
|
||||||
|
|
||||||
aisl_instance_t
|
aisl_t
|
||||||
aisl_stream_get_instance( aisl_stream_t s );
|
aisl_stream_get_instance( aisl_stream_t s );
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,243 @@
|
||||||
|
/*
|
||||||
|
* <aisl/types.h>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2019 by Löwenware Ltd.
|
||||||
|
*
|
||||||
|
* Project homepage: https://lowenware.com/aisl/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AISL_TYPES_H_86A9DBA7_C0E6_4CF4_8A64_DAAD4A81031B
|
||||||
|
#define AISL_TYPES_H_86A9DBA7_C0E6_4CF4_8A64_DAAD4A81031B
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/* type casts */
|
||||||
|
#define AISL_CALLBACK(x) ((aisl_callback_t) x)
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* HTTP(s) Client */
|
||||||
|
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
|
||||||
|
{
|
||||||
|
AISL_EXTCALL_ERROR = -3
|
||||||
|
, AISL_SYSCALL_ERROR = -2
|
||||||
|
, AISL_MALLOC_ERROR = -1
|
||||||
|
|
||||||
|
, AISL_SUCCESS = 0
|
||||||
|
, AISL_IDLE = 1
|
||||||
|
|
||||||
|
} aisl_status_t;
|
||||||
|
|
||||||
|
#ifdef WITH_STRINGIFIERS
|
||||||
|
|
||||||
|
const char *
|
||||||
|
aisl_status_to_string(aisl_status_t status);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Generic HTTP Enumerations */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
AISL_HTTP_1_0
|
||||||
|
, AISL_HTTP_1_1
|
||||||
|
, AISL_HTTP_2_0
|
||||||
|
|
||||||
|
} aisl_http_version_t;
|
||||||
|
|
||||||
|
#ifdef WITH_STRINGIFIERS
|
||||||
|
|
||||||
|
const char *
|
||||||
|
aisl_http_version_to_string( aisl_http_version_t version );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
AISL_HTTP_GET
|
||||||
|
, AISL_HTTP_PUT
|
||||||
|
, AISL_HTTP_POST
|
||||||
|
, AISL_HTTP_HEAD
|
||||||
|
, AISL_HTTP_TRACE
|
||||||
|
, AISL_HTTP_DELETE
|
||||||
|
, AISL_HTTP_OPTIONS
|
||||||
|
, AISL_HTTP_CONNECT
|
||||||
|
|
||||||
|
, AISL_HTTP_PRI
|
||||||
|
|
||||||
|
} aisl_http_method_t;
|
||||||
|
|
||||||
|
#ifdef WITH_STRINGIFIERS
|
||||||
|
|
||||||
|
const char *
|
||||||
|
aisl_http_method_to_string( aisl_http_method_t method );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
AISL_HTTP_CONTINUE = 100
|
||||||
|
, AISL_HTTP_SWITCHING_PROTOCOLS
|
||||||
|
|
||||||
|
, AISL_HTTP_OK = 200
|
||||||
|
, AISL_HTTP_CREATED
|
||||||
|
, AISL_HTTP_ACCEPTED
|
||||||
|
, AISL_HTTP_NON_AUTHORITATIVE_INFORMATION
|
||||||
|
, AISL_HTTP_NO_CONTENT
|
||||||
|
, AISL_HTTP_RESET_CONTENT
|
||||||
|
, AISL_HTTP_PARTIAL_CONTENT
|
||||||
|
|
||||||
|
, AISL_HTTP_MULTIPLE_CHOICES = 300
|
||||||
|
, AISL_HTTP_MOVED_PERMANENTLY
|
||||||
|
, AISL_HTTP_FOUND
|
||||||
|
, AISL_HTTP_SEE_OTHER
|
||||||
|
, AISL_HTTP_NOT_MODIFIED
|
||||||
|
, AISL_HTTP_USE_PROXY
|
||||||
|
, AISL_HTTP_UNUSED
|
||||||
|
, AISL_HTTP_TEMPORARY_REDIRECT
|
||||||
|
|
||||||
|
, AISL_HTTP_BAD_REQUEST = 400
|
||||||
|
, AISL_HTTP_UNAUTHORIZED
|
||||||
|
, AISL_HTTP_PAYMENT_REQUIRED
|
||||||
|
, AISL_HTTP_FORBIDDEN
|
||||||
|
, AISL_HTTP_NOT_FOUND
|
||||||
|
, AISL_HTTP_METHOD_NOT_ALLOWED
|
||||||
|
, AISL_HTTP_NOT_ACCEPTABLE
|
||||||
|
, AISL_HTTP_PROXY_AUTHENTICATION_REQUIRED
|
||||||
|
, AISL_HTTP_REQUEST_TIMEOUT
|
||||||
|
, AISL_HTTP_CONFLICT
|
||||||
|
, AISL_HTTP_GONE
|
||||||
|
, AISL_HTTP_LENGTH_REQUIRED
|
||||||
|
, AISL_HTTP_PRECONDITION_FAILED
|
||||||
|
, AISL_HTTP_REQUEST_ENTITY_TOO_LARGE
|
||||||
|
, AISL_HTTP_REQUEST_URI_TOO_LONG
|
||||||
|
, AISL_HTTP_UNSUPPORTED_MEDIA_TYPE
|
||||||
|
, AISL_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE
|
||||||
|
, AISL_HTTP_EXPECTATION_FAILED
|
||||||
|
|
||||||
|
, AISL_HTTP_INTERNAL_SERVER_ERROR = 500
|
||||||
|
, AISL_HTTP_NOT_IMPLEMENTED
|
||||||
|
, AISL_HTTP_BAD_GATEWAY
|
||||||
|
, AISL_HTTP_SERVICE_UNAVAILABLE
|
||||||
|
, AISL_HTTP_GATEWAY_TIMEOUT
|
||||||
|
, AISL_HTTP_VERSION_NOT_SUPPORTED
|
||||||
|
|
||||||
|
} aisl_http_response_t;
|
||||||
|
|
||||||
|
#ifdef WITH_STRINGIFIERS
|
||||||
|
|
||||||
|
const char *
|
||||||
|
aisl_http_response_to_string( aisl_http_response_t code );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WITH_STRINGIFIERS
|
||||||
|
|
||||||
|
const char *
|
||||||
|
aisl_http_secure_to_string( bool is_secure );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Built-in Events IDs */
|
||||||
|
|
||||||
|
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
|
||||||
|
, AISL_EVENT_STREAM_INPUT = 320
|
||||||
|
, AISL_EVENT_STREAM_REQUEST = 330
|
||||||
|
, AISL_EVENT_STREAM_OUTPUT = 340
|
||||||
|
, AISL_EVENT_STREAM_CLOSE = 350
|
||||||
|
, AISL_EVENT_STREAM_ERROR = 390
|
||||||
|
|
||||||
|
, AISL_EVENTS_CUSTOM = 1000
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef WITH_STRINGIFIERS
|
||||||
|
|
||||||
|
const char *
|
||||||
|
aisl_event_to_string( aisl_event_t event );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* real type event callbacks */
|
||||||
|
|
||||||
|
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, char * data, size_t len );
|
||||||
|
|
||||||
|
typedef bool
|
||||||
|
(*aisl_on_stream_request_t)( aisl_stream_t stream );
|
||||||
|
|
||||||
|
typedef bool
|
||||||
|
(*aisl_on_stream_output_t)( aisl_stream_t stream, size_t buffer_space );
|
||||||
|
|
||||||
|
typedef bool
|
||||||
|
(*aisl_on_stream_close_t)( aisl_stream_t stream );
|
||||||
|
|
||||||
|
typedef bool
|
||||||
|
(*aisl_on_stream_error_t)( aisl_stream_t stream );
|
||||||
|
|
||||||
|
typedef bool
|
||||||
|
(*aisl_on_custom_event_t)( void * source, va_list vl );
|
||||||
|
|
||||||
|
#endif /* !AISL_TYPES_H */
|
376
src/aisl.c
376
src/aisl.c
|
@ -1,376 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#include <aisl/aisl.h>
|
|
||||||
|
|
||||||
#include "aisl.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "str-utils.h"
|
|
||||||
#include "handle.h"
|
|
||||||
#include "client.h"
|
|
||||||
#include "server.h"
|
|
||||||
#include "globals.h"
|
|
||||||
#include "stream.h"
|
|
||||||
#include "buffer.h"
|
|
||||||
|
|
||||||
|
|
||||||
struct aisl_instance
|
|
||||||
{
|
|
||||||
list_t * servers;
|
|
||||||
#ifdef AISL_WITH_SSL
|
|
||||||
list_t * ssl;
|
|
||||||
#endif
|
|
||||||
list_t servers;
|
|
||||||
list_t clients;
|
|
||||||
list_t callbacks;
|
|
||||||
buffer_t buffer;
|
|
||||||
char * last_error;
|
|
||||||
int iterator;
|
|
||||||
int stage;
|
|
||||||
int flags;
|
|
||||||
uint32_t accept_limit;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef AISL_WITH_SSL
|
|
||||||
static uint32_t m_instances = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Initialization functions */
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
aisl_t
|
|
||||||
aisl_new( aisl_config_t * config )
|
|
||||||
{
|
|
||||||
aisl_t self;
|
|
||||||
|
|
||||||
#ifdef AISL_WITH_SSL
|
|
||||||
if ((m_instances++) == 0)
|
|
||||||
{
|
|
||||||
SSL_load_error_strings();
|
|
||||||
OpenSSL_add_ssl_algorithms();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( !(self = calloc(1, sizeof(struct aisl_instance))) )
|
|
||||||
goto finally;
|
|
||||||
|
|
||||||
if ( !(self->servers = list_new(config->servers_spool_size)) )
|
|
||||||
goto release;
|
|
||||||
|
|
||||||
if ( !(self->clients = list_new(config->clients_spool_size)) )
|
|
||||||
goto release;
|
|
||||||
|
|
||||||
if ( !(self->callbacks = list_new(config->callbacks_spool_size)) )
|
|
||||||
goto release;
|
|
||||||
|
|
||||||
if ( !(self->buffer = buffer_new(config->initial_buffer_size)) )
|
|
||||||
goto release;
|
|
||||||
|
|
||||||
#ifdef AISL_WITH_SSL
|
|
||||||
if ( !(self->ssl = list_new(config->ssl_spool_size)) )
|
|
||||||
goto release;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
self->accept_limit = config->clients_accept_limit;
|
|
||||||
|
|
||||||
goto finally;
|
|
||||||
|
|
||||||
release:
|
|
||||||
aisl_free(self);
|
|
||||||
self = NULL;
|
|
||||||
|
|
||||||
finally:
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
void
|
|
||||||
aisl_free( aisl_t self )
|
|
||||||
{
|
|
||||||
if (self->clients)
|
|
||||||
list_free(self->clients, (list_destructor_t) client_free );
|
|
||||||
|
|
||||||
if (self->servers)
|
|
||||||
list_free(self->servers, (list_destructor_t) server_free );
|
|
||||||
|
|
||||||
if (self->callbacks)
|
|
||||||
list_free(self->callbacks, free);
|
|
||||||
|
|
||||||
if (self->buffer)
|
|
||||||
buffer_free(self->buffer);
|
|
||||||
|
|
||||||
if (self->ssl)
|
|
||||||
list_free(self->ssl, (list_destructor_t) crypter_free );
|
|
||||||
|
|
||||||
if (self->last_error)
|
|
||||||
free(self->last_error);
|
|
||||||
|
|
||||||
free(self);
|
|
||||||
|
|
||||||
#ifdef AISL_WITH_SSL
|
|
||||||
if ((--m_instances) == 0)
|
|
||||||
{
|
|
||||||
EVP_cleanup();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
aisl_server_t
|
|
||||||
aisl_listen( aisl_instance_t instance,
|
|
||||||
const char * address,
|
|
||||||
uint16_t port )
|
|
||||||
{
|
|
||||||
aisl_server_t result;
|
|
||||||
|
|
||||||
if ( (result = aisl_server_new(address, port)) != NULL )
|
|
||||||
{
|
|
||||||
result->instance = instance;
|
|
||||||
|
|
||||||
if (list_append(instance->servers, result) == LIST_NAN)
|
|
||||||
{
|
|
||||||
server_free(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static char *
|
|
||||||
get_response_begin(stream_t stream)
|
|
||||||
{
|
|
||||||
char * r;
|
|
||||||
client_t cli = CLIENT(ASTREAM(stream)->client);
|
|
||||||
|
|
||||||
r = str_printf(
|
|
||||||
"%s %d %s\r\n"
|
|
||||||
"Server: AISL\r\n"
|
|
||||||
"Connection: %s\r\n\r\n",
|
|
||||||
aisl_http_version_to_string(cli->protocol),
|
|
||||||
stream->response,
|
|
||||||
aisl_http_response_to_string(stream->response),
|
|
||||||
((cli->flags & CLIENT_FLAG_KEEPALIVE) ? "keep-alive" : "close")
|
|
||||||
);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
aisl_status_t
|
|
||||||
aisl_response(aisl_stream_t stream, aisl_http_response_t status_code,
|
|
||||||
const char *content_type,
|
|
||||||
uint32_t content_length)
|
|
||||||
{
|
|
||||||
char * pch;
|
|
||||||
int l;
|
|
||||||
|
|
||||||
|
|
||||||
/* check if those headers were already sent */
|
|
||||||
if (STREAM(stream)->state > STREAM_REQUEST_READY) return AISL_IDLE;
|
|
||||||
|
|
||||||
STREAM(stream)->response = status_code;
|
|
||||||
STREAM(stream)->c_type = content_type;
|
|
||||||
STREAM(stream)->c_length = content_length;
|
|
||||||
|
|
||||||
if ( !(pch = get_response_begin(STREAM(stream))) )
|
|
||||||
return AISL_MALLOC_ERROR;
|
|
||||||
|
|
||||||
l = strlen(pch);
|
|
||||||
STREAM(stream)->c_offset = l-2;
|
|
||||||
|
|
||||||
buffer_clear(STREAM(stream)->buffer, content_length);
|
|
||||||
|
|
||||||
l = buffer_add( STREAM(stream)->buffer, pch, l );
|
|
||||||
free(pch);
|
|
||||||
|
|
||||||
if (l == BUFFER_EOB) return AISL_MALLOC_ERROR;
|
|
||||||
|
|
||||||
if (content_length)
|
|
||||||
{
|
|
||||||
if (!aisl_header_printf( stream, "Content-Length", "%u", content_length ))
|
|
||||||
return AISL_MALLOC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content_type)
|
|
||||||
{
|
|
||||||
if (!aisl_header( stream, "Content-Type", content_type ))
|
|
||||||
return AISL_MALLOC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
STREAM(stream)->state = STREAM_RESPONSE_HEADER;
|
|
||||||
|
|
||||||
return AISL_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
aisl_status_t
|
|
||||||
aisl_flush(aisl_stream_t stream)
|
|
||||||
{
|
|
||||||
stream_t s = STREAM(stream);
|
|
||||||
if ( ! s->c_length )
|
|
||||||
{
|
|
||||||
s->c_length = s->buffer->size - s->c_offset - 2;
|
|
||||||
if (!aisl_header_printf(stream, "Content-Length", "%u", s->c_length))
|
|
||||||
return AISL_MALLOC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
fprintf(stdout, "(%lu bytes)------->\n", STREAM(stream)->buffer->size);
|
|
||||||
fwrite(STREAM(stream)->buffer->data, 1, STREAM(stream)->buffer->size, stdout);
|
|
||||||
fprintf(stdout, "<------\n");
|
|
||||||
*/
|
|
||||||
s->state = STREAM_RESPONSE_READY;
|
|
||||||
|
|
||||||
s->flags |= STREAM_FLAG_OUTPUT_READY;
|
|
||||||
|
|
||||||
return AISL_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
int
|
|
||||||
aisl_header(aisl_stream_t stream, const char *key, const char *value)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
char * pch;
|
|
||||||
|
|
||||||
if ( (pch = str_printf("%s: %s\r\n", key, value)) != NULL )
|
|
||||||
{
|
|
||||||
ret = strlen(pch);
|
|
||||||
if ( buffer_insert(
|
|
||||||
STREAM(stream)->buffer,
|
|
||||||
STREAM(stream)->c_offset,
|
|
||||||
pch,
|
|
||||||
ret
|
|
||||||
) == BUFFER_EOB )
|
|
||||||
{
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
STREAM(stream)->c_offset += ret;
|
|
||||||
|
|
||||||
free(pch);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
int
|
|
||||||
aisl_header_printf(aisl_stream_t stream, const char *key,
|
|
||||||
const char *f_value, ...)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
va_list arg;
|
|
||||||
va_start(arg, f_value);
|
|
||||||
|
|
||||||
ret = aisl_header_vprintf(stream, key, f_value, arg);
|
|
||||||
|
|
||||||
va_end(arg);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
int
|
|
||||||
aisl_header_vprintf(aisl_stream_t stream, const char *key,
|
|
||||||
const char *format,
|
|
||||||
va_list args)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
char * value;
|
|
||||||
|
|
||||||
if ( (value = str_vprintf(format, args)) != NULL )
|
|
||||||
{
|
|
||||||
ret = aisl_header( stream, key, value );
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
int
|
|
||||||
aisl_printf(aisl_stream_t stream, const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list arg;
|
|
||||||
va_start(arg, format);
|
|
||||||
|
|
||||||
int result = aisl_vprintf(stream, format, arg);
|
|
||||||
|
|
||||||
va_end(arg);
|
|
||||||
|
|
||||||
/* No need to update length there, because vprintf do that
|
|
||||||
*
|
|
||||||
* if (STREAM(stream)->c_length_unknown)
|
|
||||||
STREAM(stream)->c_length += result;
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
int
|
|
||||||
aisl_vprintf(aisl_stream_t stream, const char *format, va_list args)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
char * r;
|
|
||||||
|
|
||||||
if ( (r = str_vprintf(format, args)) != NULL)
|
|
||||||
{
|
|
||||||
result = strlen(r);
|
|
||||||
if (buffer_add(STREAM(stream)->buffer, r, result) == BUFFER_EOB)
|
|
||||||
result = -1;
|
|
||||||
|
|
||||||
free(r);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result = -1;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
int
|
|
||||||
aisl_write(aisl_stream_t stream, const char *data, int d_len)
|
|
||||||
{
|
|
||||||
if (d_len < 0)
|
|
||||||
d_len = strlen(data);
|
|
||||||
|
|
||||||
if (buffer_add(STREAM(stream)->buffer, data, d_len) == BUFFER_EOB)
|
|
||||||
d_len = -1;
|
|
||||||
|
|
||||||
return d_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((visibility ("default") ))
|
|
||||||
int
|
|
||||||
aisl_puts(const char *str, aisl_stream_t stream)
|
|
||||||
{
|
|
||||||
return aisl_write( stream, str, strlen(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
19
src/aisl.h
19
src/aisl.h
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* src/aisl.h
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017 by Löwenware Ltd.
|
|
||||||
*
|
|
||||||
* Project homepage: https://lowenware.com/aisl/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AISL_H_F49DC34C_7EF3_44EF_8E4B_22F4CC1A665C
|
|
||||||
#define AISL_H_F49DC34C_7EF3_44EF_8E4B_22F4CC1A665C
|
|
||||||
|
|
||||||
bool
|
|
||||||
aisl_raise_event( aisl_instance_t instance,
|
|
||||||
void * source,
|
|
||||||
aisl_event_t e_id,
|
|
||||||
... );
|
|
||||||
|
|
||||||
#endif /* !AISL_H */
|
|
15
src/client.c
15
src/client.c
|
@ -15,7 +15,22 @@
|
||||||
#ifndef OUTPUT_BUFFER_SIZE
|
#ifndef OUTPUT_BUFFER_SIZE
|
||||||
#define OUTPUT_BUFFER_SIZE 4096
|
#define OUTPUT_BUFFER_SIZE 4096
|
||||||
#endif
|
#endif
|
||||||
|
struct client
|
||||||
|
{
|
||||||
|
struct sockaddr_in address;
|
||||||
|
server_t server;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
int next_id; /* server id generator (even, starts from 2) */
|
||||||
|
int istream; /* input stream id */
|
||||||
|
int ostream; /* output stream id */
|
||||||
|
list_t streams;
|
||||||
|
SSL * ssl;
|
||||||
|
|
||||||
|
time_t timestamp;
|
||||||
|
aisl_http_version_t protocol;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
44
src/client.h
44
src/client.h
|
@ -1,67 +1,47 @@
|
||||||
#ifndef _AISL_CLIENT_H_
|
#ifndef AISL_CLIENT_H_164FE6B2_E5D4_4968_B50F_823E30E8F777
|
||||||
#define _AISL_CLIENT_H_
|
#define AISL_CLIENT_H_164FE6B2_E5D4_4968_B50F_823E30E8F777
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include <aisl/aisl.h>
|
|
||||||
#include <aisl/http.h>
|
|
||||||
#include "list.h"
|
|
||||||
|
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
#include <aisl/client.h>
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
#define CLIENT_FLAG_KEEPALIVE (1<<0)
|
#define CLIENT_FLAG_KEEPALIVE (1<<0)
|
||||||
#define CLIENT_FLAG_HANDSHAKE (1<<1)
|
#define CLIENT_FLAG_HANDSHAKE (1<<1)
|
||||||
|
|
||||||
|
#define CLIENT(x) ((aisl_client_t)x)
|
||||||
struct client
|
|
||||||
{
|
|
||||||
struct sockaddr_in address;
|
|
||||||
server_t server;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
int next_id; /* server id generator (even, starts from 2) */
|
|
||||||
int istream; /* input stream id */
|
|
||||||
int ostream; /* output stream id */
|
|
||||||
list_t streams;
|
|
||||||
SSL * ssl;
|
|
||||||
|
|
||||||
time_t timestamp;
|
|
||||||
aisl_http_version_t protocol;
|
|
||||||
int flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct client * client_t;
|
|
||||||
|
|
||||||
#define CLIENT(x) ((client_t)x)
|
|
||||||
|
|
||||||
/* constructor -------------------------------------------------------------- */
|
/* constructor -------------------------------------------------------------- */
|
||||||
|
|
||||||
aisl_status_t
|
aisl_status_t
|
||||||
client_accept(client_t * self, server_t server);
|
aisl_client_accept(aisl_client_t * self, aisl_server_t server);
|
||||||
|
|
||||||
/* destructor --------------------------------------------------------------- */
|
/* destructor --------------------------------------------------------------- */
|
||||||
|
|
||||||
void
|
void
|
||||||
client_free(client_t self);
|
aisl_client_free(aisl_client_t self);
|
||||||
|
|
||||||
/* all regular client routines. return true if something happened ----------- */
|
/* all regular client routines. return true if something happened ----------- */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
client_touch(client_t self);
|
aisl_client_touch(aisl_client_t self);
|
||||||
|
|
||||||
/* check if communication time with client is expired ----------------------- */
|
/* check if communication time with client is expired ----------------------- */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
client_is_timeout(client_t self);
|
aisl_client_is_timeout(aisl_client_t self);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void
|
void
|
||||||
client_close(client_t self);
|
aisl_client_close(aisl_client_t self);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
#endif
|
|
||||||
|
#endif /* !AISL_CLIENT_H */
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef _AISL_GLOBALS_H_
|
#ifndef _AISL_GLOBALS_H_
|
||||||
#define _AISL_GLOBALS_H_
|
#define _AISL_GLOBALS_H_
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wuninitialized"
|
//#pragma GCC diagnostic ignored "-Wuninitialized"
|
||||||
|
|
||||||
#include <aisl/handle.h>
|
|
||||||
|
|
||||||
/* MACOS FIX AND OTHER OS */
|
/* MACOS FIX AND OTHER OS */
|
||||||
#ifndef SOCK_NONBLOCK
|
#ifndef SOCK_NONBLOCK
|
||||||
|
@ -42,7 +40,4 @@
|
||||||
#define AISL_MAX_CLIENT_SILENCE 10
|
#define AISL_MAX_CLIENT_SILENCE 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern aisl_handle_t gHandle;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
572
src/instance.c
572
src/instance.c
|
@ -7,7 +7,579 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
#include "str-utils.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
#include "server.h"
|
||||||
|
//#include "globals.h"
|
||||||
|
//#include "stream.h"
|
||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AISL_CYCLE_SERVER = 0
|
||||||
|
, AISL_CYCLE_CLIENT = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct aisl
|
||||||
|
{
|
||||||
|
list_t servers;
|
||||||
|
list_t clients;
|
||||||
|
list_t callbacks;
|
||||||
|
#ifdef AISL_WITH_SSL
|
||||||
|
list_t ssl;
|
||||||
|
#endif
|
||||||
|
buffer_t buffer;
|
||||||
|
char * last_error;
|
||||||
|
int iterator;
|
||||||
|
int stage;
|
||||||
|
int flags;
|
||||||
|
uint32_t accept_limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef AISL_WITH_SSL
|
||||||
|
static uint32_t m_instances = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialization functions */
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
aisl_t
|
||||||
|
aisl_new( aisl_config_t config )
|
||||||
|
{
|
||||||
|
aisl_t instance;
|
||||||
|
|
||||||
|
#ifdef AISL_WITH_SSL
|
||||||
|
if ((m_instances++) == 0)
|
||||||
|
{
|
||||||
|
SSL_load_error_strings();
|
||||||
|
OpenSSL_add_ssl_algorithms();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( !(instance = calloc(1, sizeof(struct aisl))) )
|
||||||
|
goto finally;
|
||||||
|
|
||||||
|
if ( !(instance->servers = list_new(config->servers_spool_size)) )
|
||||||
|
goto release;
|
||||||
|
|
||||||
|
if ( !(instance->clients = list_new(config->clients_spool_size)) )
|
||||||
|
goto release;
|
||||||
|
|
||||||
|
if ( !(instance->callbacks = list_new(config->callbacks_spool_size)) )
|
||||||
|
goto release;
|
||||||
|
|
||||||
|
if ( !(instance->buffer = buffer_new(config->initial_buffer_size)) )
|
||||||
|
goto release;
|
||||||
|
|
||||||
|
#ifdef AISL_WITH_SSL
|
||||||
|
if ( !(instance->ssl = list_new(config->ssl_spool_size)) )
|
||||||
|
goto release;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
instance->accept_limit = config->clients_accept_limit;
|
||||||
|
|
||||||
|
goto finally;
|
||||||
|
|
||||||
|
release:
|
||||||
|
aisl_free(instance);
|
||||||
|
instance = NULL;
|
||||||
|
|
||||||
|
finally:
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
void
|
||||||
|
aisl_free( aisl_t instance )
|
||||||
|
{
|
||||||
|
if (instance->clients)
|
||||||
|
list_free(instance->clients, (list_destructor_t) aisl_client_free );
|
||||||
|
|
||||||
|
if (instance->servers)
|
||||||
|
list_free(instance->servers, (list_destructor_t) aisl_server_free );
|
||||||
|
|
||||||
|
if (instance->callbacks)
|
||||||
|
list_free(instance->callbacks, free);
|
||||||
|
|
||||||
|
if (instance->buffer)
|
||||||
|
buffer_free(instance->buffer);
|
||||||
|
|
||||||
|
if (instance->ssl)
|
||||||
|
list_free(instance->ssl, (list_destructor_t) ssl_free );
|
||||||
|
|
||||||
|
if (instance->last_error)
|
||||||
|
free(instance->last_error);
|
||||||
|
|
||||||
|
free(instance);
|
||||||
|
|
||||||
|
#ifdef AISL_WITH_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(address, port)) != NULL )
|
||||||
|
{
|
||||||
|
result->instance = instance;
|
||||||
|
|
||||||
|
if (list_append(instance->servers, result) == LIST_NAN)
|
||||||
|
{
|
||||||
|
aisl_server_free(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef AISL_WITH_SSL
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_ssl_context( SSL * ssl, int * ptr, void * handle )
|
||||||
|
{
|
||||||
|
const char * server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||||
|
|
||||||
|
SSL_CTX * ctx = aisl_get_ssl_ctx( (aisl_t) handle, server_name );
|
||||||
|
|
||||||
|
if (ctx)
|
||||||
|
{
|
||||||
|
SSL_set_SSL_CTX(ssl, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static SSL_CTX *
|
||||||
|
create_ssl_context( aisl_t instance,
|
||||||
|
const char * key_file,
|
||||||
|
const char * crt_file )
|
||||||
|
{
|
||||||
|
const SSL_METHOD * method;
|
||||||
|
SSL_CTX * ctx;
|
||||||
|
|
||||||
|
method = SSLv23_server_method();
|
||||||
|
|
||||||
|
if ( !(ctx = SSL_CTX_new(method)) )
|
||||||
|
goto except;
|
||||||
|
|
||||||
|
SSL_CTX_set_ecdh_auto(ctx, 1);
|
||||||
|
|
||||||
|
SSL_CTX_set_tlsext_servername_callback( ctx, get_ssl_context );
|
||||||
|
SSL_CTX_set_tlsext_servername_arg( ctx, (void *) instance );
|
||||||
|
|
||||||
|
if (!(SSL_CTX_use_certificate_file(ctx, crt_file, SSL_FILETYPE_PEM) > 0))
|
||||||
|
goto release;
|
||||||
|
|
||||||
|
if (!(SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) > 0))
|
||||||
|
goto release;
|
||||||
|
|
||||||
|
goto finally;
|
||||||
|
|
||||||
|
release:
|
||||||
|
SSL_CTX_free(ctx);
|
||||||
|
ctx = NULL;
|
||||||
|
|
||||||
|
except:
|
||||||
|
aisl_set_error( instance, ERR_error_string(ERR_get_error(),NULL) );
|
||||||
|
|
||||||
|
finally:
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
aisl_status_t
|
||||||
|
aisl_set_ssl( aisl_t instance, const char * server_name,
|
||||||
|
const char * key_file,
|
||||||
|
const char * crt_file )
|
||||||
|
{
|
||||||
|
SSL_CTX * ssl_ctx = NULL;
|
||||||
|
int i;
|
||||||
|
crypter_t crypter;
|
||||||
|
|
||||||
|
/* lookup for existing contexts */
|
||||||
|
for (i=0; i<instance->crypters->count; i++)
|
||||||
|
{
|
||||||
|
crypter = list_index(instance->crypters, i);
|
||||||
|
if (crypter->keyFile && strcmp(crypter->keyFile, key_file)==0 &&
|
||||||
|
crypter->crtFile && strcmp(crypter->crtFile, crt_file)==0 )
|
||||||
|
{
|
||||||
|
ssl_ctx = crypter->sslCtx;
|
||||||
|
key_file = NULL;
|
||||||
|
crt_file = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! (crypter = crypter_new(server_name, key_file, crt_file)) )
|
||||||
|
{
|
||||||
|
return AISL_MALLOC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! ssl_ctx)
|
||||||
|
{
|
||||||
|
if (!(ssl_ctx = create_ssl_context(instance, key_file, crt_file)))
|
||||||
|
{
|
||||||
|
crypter_free(crypter);
|
||||||
|
return AISL_EXTCALL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crypter->sslCtx = ssl_ctx;
|
||||||
|
|
||||||
|
if (list_append(instance->crypters, crypter)==-1)
|
||||||
|
{
|
||||||
|
crypter_free(crypter);
|
||||||
|
return AISL_MALLOC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AISL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_CTX *
|
||||||
|
aisl_get_ssl_ctx( aisl_t instance, const char * server_name )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
crypter_t crypter;
|
||||||
|
|
||||||
|
for (i=0; i<instance->crypters->count; i++)
|
||||||
|
{
|
||||||
|
crypter = list_index(instance->crypters, i);
|
||||||
|
if (server_name)
|
||||||
|
{
|
||||||
|
if (strcmp(crypter->srvName, server_name)!=0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crypter->sslCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
aisl_status_t
|
||||||
|
aisl_set_callback( aisl_t instance,
|
||||||
|
void * source,
|
||||||
|
aisl_event_t e_id,
|
||||||
|
aisl_callback_t cb )
|
||||||
|
{
|
||||||
|
listener_t listener;
|
||||||
|
|
||||||
|
if (! (listener = listener_new(source, e_id, cb)) )
|
||||||
|
return AISL_MALLOC_ERROR;
|
||||||
|
|
||||||
|
if (list_append(instance->callbacks, listener) == -1)
|
||||||
|
{
|
||||||
|
free(listener);
|
||||||
|
return AISL_MALLOC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e_id == AISL_STREAM_OUTPUT) /* subscribtion for chunked output */
|
||||||
|
{
|
||||||
|
if (source)
|
||||||
|
{
|
||||||
|
( (stream_t) source )->flags |= STREAM_FLAG_OUTPUT_CHUNKED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (e_id == AISL_STREAM_OPEN)
|
||||||
|
{
|
||||||
|
instance->flags |= AISL_HANDLE_HAS_STREAM_LISTENERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AISL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
void
|
||||||
|
aisl_unset_callback_for( aisl_t instance, void * source )
|
||||||
|
{
|
||||||
|
int i=instance->callbacks->count-1;
|
||||||
|
while ( !(i < 0) )
|
||||||
|
{
|
||||||
|
listener_t listener = list_index(instance->callbacks, i);
|
||||||
|
if ( listener->source == source )
|
||||||
|
{
|
||||||
|
free(listener);
|
||||||
|
list_remove_index(instance->callbacks, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
bool
|
||||||
|
aisl_raise( aisl_t instance,
|
||||||
|
void * source,
|
||||||
|
aisl_event_t e_id,
|
||||||
|
... )
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
va_start(vl, e_id);
|
||||||
|
result = aisl_raise_vl(instance, source, e_id, vl);
|
||||||
|
va_end(vl);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
bool
|
||||||
|
aisl_raise_vl( aisl_t instance,
|
||||||
|
void * source,
|
||||||
|
aisl_event_t e_id,
|
||||||
|
va_list vl )
|
||||||
|
{
|
||||||
|
int i,
|
||||||
|
i_val;
|
||||||
|
listener_t lst;
|
||||||
|
bool res = false;
|
||||||
|
|
||||||
|
char * c_ptr,
|
||||||
|
* c_ptr2;
|
||||||
|
|
||||||
|
for(i=instance->callbacks->count-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
lst = list_index(instance->callbacks, i);
|
||||||
|
|
||||||
|
/*printf("AISL> raise %s:%s, %p:%p\n", _event_text(e_id), _event_text(lst->e_id), source, lst->source);*/
|
||||||
|
if (lst->e_id == e_id && (source == lst->source || lst->source == NULL))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if (e_id == AISL_STREAM_HEADER)
|
||||||
|
fprintf(stderr,"FOUND HANDLER %d\n", i);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*printf(" catch\n");*/
|
||||||
|
switch(e_id)
|
||||||
|
{
|
||||||
|
/* server events */
|
||||||
|
case AISL_EVENT_SERVER_OPEN:
|
||||||
|
i_val = va_arg(vl, aisl_status_t);
|
||||||
|
res = ((aisl_on_server_open_t) lst->cb)( source, i_val );
|
||||||
|
break;
|
||||||
|
case AISL_EVENT_SERVER_ERROR:
|
||||||
|
i_val = va_arg(vl, aisl_status_t);
|
||||||
|
c_ptr = va_arg(vl, char *);
|
||||||
|
res = ((aisl_on_server_error_t) lst->cb)( source, i_val, c_ptr );
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* client events */
|
||||||
|
case AISL_EVENT_CLIENT_CONNECT:
|
||||||
|
res = ((aisl_on_client_connect_t) lst->cb)(source, va_arg(vl, void *));
|
||||||
|
break;
|
||||||
|
case AISL_EVENT_CLIENT_DISCONNECT:
|
||||||
|
res = ((aisl_on_client_disconnect_t) lst->cb)(source, va_arg(vl, void*));
|
||||||
|
aisl_unset_callback_for( instance, source );
|
||||||
|
break;
|
||||||
|
case AISL_EVENT_CLIENT_TIMEOUT:
|
||||||
|
res = ((aisl_client_timeout_t) lst->cb)(source, va_arg(vl, void *));
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* request events */
|
||||||
|
case AISL_EVENT_STREAM_OPEN:
|
||||||
|
i_val = va_arg(vl, int);
|
||||||
|
c_ptr = va_arg(vl, char *);
|
||||||
|
c_ptr2 = va_arg(vl, char *);
|
||||||
|
res = ((aisl_on_stream_open_t) lst->cb)(source, i_val, c_ptr, c_ptr2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AISL_EVENT_STREAM_HEADER:
|
||||||
|
c_ptr = va_arg(vl, char *);
|
||||||
|
c_ptr2 = va_arg(vl, char *);
|
||||||
|
res = ((aisl_on_stream_header_t) lst->cb)(source, c_ptr, c_ptr2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case AISL_EVENT_STREAM_INPUT:
|
||||||
|
/*printf("AISL> raise AISL_STREAM_INPUT\n");*/
|
||||||
|
c_ptr = va_arg(vl, char *);
|
||||||
|
i_val = va_arg(vl, int );
|
||||||
|
res = ((aisl_on_stream_input_t) lst->cb)(source, c_ptr, i_val);
|
||||||
|
break;
|
||||||
|
case AISL_EVENT_STREAM_REQUEST:
|
||||||
|
/*printf("AISL> raise AISL_STREAM_REQUEST\n");*/
|
||||||
|
buffer_clear( STREAM(source)->buffer, 0);
|
||||||
|
res = ((aisl_on_stream_request_t) lst->cb)(source);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case AISL_EVENT_STREAM_ERROR:
|
||||||
|
res = ((aisl_on_stream_error_t) lst->cb)( source, va_arg(vl, char *));
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* response events */
|
||||||
|
case AISL_EVENT_STREAM_OUTPUT:
|
||||||
|
res = ((aisl_on_stream_output_t)lst->cb)(
|
||||||
|
source,
|
||||||
|
va_arg(vl, uint32_t)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case AISL_EVENT_STREAM_CLOSE:
|
||||||
|
res = ((aisl_on_stream_close_t)lst->cb)( source );
|
||||||
|
aisl_unset_callback_for( instance, source );
|
||||||
|
((aisl_stream_t) source)->u_ptr=NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
res = ((aisl_on_custom_event_t) lst->cb)(source, vl);
|
||||||
|
}
|
||||||
|
if (res) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
aisl_status_t
|
||||||
|
aisl_run_cycle( aisl_t instance )
|
||||||
|
{
|
||||||
|
int max = instance->servers->count+instance->clients->count+instance->delays->count,
|
||||||
|
cnt = 0;
|
||||||
|
|
||||||
|
|
||||||
|
switch (instance->stage)
|
||||||
|
{
|
||||||
|
case STAGE_SERVER:
|
||||||
|
while (instance->iterator < instance->servers->count )
|
||||||
|
{
|
||||||
|
aisl_server_t srv = (server_t)list_index(instance->servers, instance->iterator++);
|
||||||
|
if ( aisl_server_touch(srv) != AISL_IDLE )
|
||||||
|
return AISL_SUCCESS;
|
||||||
|
|
||||||
|
if ( ! (++cnt < max) ) return AISL_IDLE;
|
||||||
|
}
|
||||||
|
if ( ! (instance->flags & AISL_HANDLE_HAS_STREAM_LISTENERS) )
|
||||||
|
return AISL_IDLE;
|
||||||
|
|
||||||
|
instance->iterator = 0;
|
||||||
|
instance->stage++;
|
||||||
|
|
||||||
|
|
||||||
|
case STAGE_CLIENT:
|
||||||
|
while (instance->iterator < instance->clients->count )
|
||||||
|
{
|
||||||
|
int i = instance->iterator++;
|
||||||
|
aisl_client_t cli = list_index(instance->clients, i);
|
||||||
|
bool r = aisl_client_touch( cli );
|
||||||
|
|
||||||
|
if (aisl_client_is_timeout( cli ) )
|
||||||
|
aisl_raise( instance, cli->server, AISL_CLIENT_TIMEOUT, cli );
|
||||||
|
|
||||||
|
if ( cli->fd == -1 )
|
||||||
|
{
|
||||||
|
aisl_client_free( cli );
|
||||||
|
list_remove_index(instance->clients, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r) return AISL_SUCCESS;
|
||||||
|
|
||||||
|
if ( ! (++cnt < max) ) return AISL_IDLE;
|
||||||
|
}
|
||||||
|
instance->iterator = 0;
|
||||||
|
instance->stage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AISL_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__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") ))
|
||||||
|
int
|
||||||
|
aisl_sleep( aisl_t instance, unsigned long usec )
|
||||||
|
{
|
||||||
|
int maxfd=0,
|
||||||
|
sd;
|
||||||
|
size_t i;
|
||||||
|
struct timeval timeout = {0,usec};
|
||||||
|
|
||||||
|
memset(&timeout, 0, sizeof(struct timeval));
|
||||||
|
timeout.tv_usec = usec;
|
||||||
|
|
||||||
|
fd_set fs;
|
||||||
|
FD_ZERO (&fs);
|
||||||
|
|
||||||
|
for (i=0; i<instance->servers->count; i++)
|
||||||
|
{
|
||||||
|
aisl_server_t s = list_index(instance->servers, i);
|
||||||
|
|
||||||
|
sd = aisl_server_get_socket(s);
|
||||||
|
|
||||||
|
if (sd != -1)
|
||||||
|
{
|
||||||
|
FD_SET(sd, &fs);
|
||||||
|
if (sd > maxfd) maxfd = sd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (i=0; i<instance->clients->count; i++)
|
||||||
|
{
|
||||||
|
aisl_client_t c = list_index(instance->clients, i);
|
||||||
|
sd = aisl_client_get_socket(s);
|
||||||
|
if (sd != -1)
|
||||||
|
{
|
||||||
|
FD_SET(sd, &fs);
|
||||||
|
if (sd > maxfd) maxfd = sd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return select(maxfd+1, &fs, NULL, NULL, &timeout);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,12 @@
|
||||||
#ifndef INSTANCE_H_814CF474_A646_45B7_B6B2_3F4C7BEFA484
|
#ifndef INSTANCE_H_814CF474_A646_45B7_B6B2_3F4C7BEFA484
|
||||||
#define INSTANCE_H_814CF474_A646_45B7_B6B2_3F4C7BEFA484
|
#define INSTANCE_H_814CF474_A646_45B7_B6B2_3F4C7BEFA484
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
#include <aisl/instance.h>
|
#include <aisl/instance.h>
|
||||||
|
|
||||||
|
SSL_CTX *
|
||||||
|
aisl_get_ssl_ctx( aisl_t instance, const char * server_name );
|
||||||
|
|
||||||
|
void
|
||||||
|
aisl_set_error( aisl_t instance, const char * err_msg );
|
||||||
#endif /* !INSTANCE_H */
|
#endif /* !INSTANCE_H */
|
||||||
|
|
18
src/server.c
18
src/server.c
|
@ -8,11 +8,27 @@
|
||||||
|
|
||||||
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "handle.h"
|
#include "instance.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "str-utils.h"
|
#include "str-utils.h"
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct aisl_server
|
||||||
|
{
|
||||||
|
struct sockaddr_in address;
|
||||||
|
aisl_t instance;
|
||||||
|
char * host;
|
||||||
|
int fd;
|
||||||
|
int port;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
44
src/server.h
44
src/server.h
|
@ -1,47 +1,25 @@
|
||||||
#ifndef _AISL_SERVER_H_
|
#ifndef AISL_SERVER_H_FACD3B4D_0D72_4345_9A30_811103DA9AE2
|
||||||
#define _AISL_SERVER_H_
|
#define AISL_SERVER_H_FACD3B4D_0D72_4345_9A30_811103DA9AE2
|
||||||
|
|
||||||
#include <aisl/status.h>
|
|
||||||
#include <aisl/handle.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <aisl/types.h>
|
||||||
|
#include <aisl/instance.h>
|
||||||
|
#include <aisl/server.h>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
#define SERVER(x) ((aisl_server_t) x)
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* types -------------------------------------------------------------------- */
|
aisl_server_t
|
||||||
struct server
|
aisl_server_new(const char * address, int port);
|
||||||
{
|
|
||||||
struct sockaddr_in address;
|
|
||||||
aisl_handle_t owner;
|
|
||||||
char * host;
|
|
||||||
int fd;
|
|
||||||
int port;
|
|
||||||
int flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct server * server_t;
|
|
||||||
|
|
||||||
#define SERVER(x) ((server_t) x)
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
server_t
|
|
||||||
server_new(const char * address, int port);
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
server_free(server_t self);
|
aisl_server_free(aisl_server_t self);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
server_touch(server_t self);
|
aisl_server_touch(aisl_server_t self);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#endif
|
#endif /* !AISL_SERVER_H */
|
||||||
|
|
252
src/stream.c
252
src/stream.c
|
@ -1,13 +1,31 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <aisl/status.h>
|
|
||||||
|
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "handle.h"
|
#include "handle.h"
|
||||||
|
struct stream
|
||||||
|
{
|
||||||
|
struct aisl_stream _public;
|
||||||
|
|
||||||
|
/* private data */
|
||||||
|
list_t headers; /* request headers */
|
||||||
|
buffer_t buffer;
|
||||||
|
|
||||||
|
const char *c_type;
|
||||||
|
|
||||||
|
aisl_http_response_t response;
|
||||||
|
stream_state_t state;
|
||||||
|
uint32_t c_length;
|
||||||
|
uint32_t c_offset;
|
||||||
|
int id;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
bool c_length_unknown;
|
||||||
|
|
||||||
|
};
|
||||||
static void
|
static void
|
||||||
pair_free( pair_t self )
|
pair_free( pair_t self )
|
||||||
{
|
{
|
||||||
|
@ -194,3 +212,235 @@ aisl_reject(aisl_stream_t s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_response_begin(stream_t stream)
|
||||||
|
{
|
||||||
|
char * r;
|
||||||
|
client_t cli = CLIENT(ASTREAM(stream)->client);
|
||||||
|
|
||||||
|
r = str_printf(
|
||||||
|
"%s %d %s\r\n"
|
||||||
|
"Server: AISL\r\n"
|
||||||
|
"Connection: %s\r\n\r\n",
|
||||||
|
aisl_http_version_to_string(cli->protocol),
|
||||||
|
stream->response,
|
||||||
|
aisl_http_response_to_string(stream->response),
|
||||||
|
((cli->flags & CLIENT_FLAG_KEEPALIVE) ? "keep-alive" : "close")
|
||||||
|
);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
aisl_status_t
|
||||||
|
aisl_response(aisl_stream_t stream, aisl_http_response_t status_code,
|
||||||
|
const char *content_type,
|
||||||
|
uint32_t content_length)
|
||||||
|
{
|
||||||
|
char * pch;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
|
||||||
|
/* check if those headers were already sent */
|
||||||
|
if (STREAM(stream)->state > STREAM_REQUEST_READY) return AISL_IDLE;
|
||||||
|
|
||||||
|
STREAM(stream)->response = status_code;
|
||||||
|
STREAM(stream)->c_type = content_type;
|
||||||
|
STREAM(stream)->c_length = content_length;
|
||||||
|
|
||||||
|
if ( !(pch = get_response_begin(STREAM(stream))) )
|
||||||
|
return AISL_MALLOC_ERROR;
|
||||||
|
|
||||||
|
l = strlen(pch);
|
||||||
|
STREAM(stream)->c_offset = l-2;
|
||||||
|
|
||||||
|
buffer_clear(STREAM(stream)->buffer, content_length);
|
||||||
|
|
||||||
|
l = buffer_add( STREAM(stream)->buffer, pch, l );
|
||||||
|
free(pch);
|
||||||
|
|
||||||
|
if (l == BUFFER_EOB) return AISL_MALLOC_ERROR;
|
||||||
|
|
||||||
|
if (content_length)
|
||||||
|
{
|
||||||
|
if (!aisl_header_printf( stream, "Content-Length", "%u", content_length ))
|
||||||
|
return AISL_MALLOC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content_type)
|
||||||
|
{
|
||||||
|
if (!aisl_header( stream, "Content-Type", content_type ))
|
||||||
|
return AISL_MALLOC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
STREAM(stream)->state = STREAM_RESPONSE_HEADER;
|
||||||
|
|
||||||
|
return AISL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
aisl_status_t
|
||||||
|
aisl_flush(aisl_stream_t stream)
|
||||||
|
{
|
||||||
|
stream_t s = STREAM(stream);
|
||||||
|
if ( ! s->c_length )
|
||||||
|
{
|
||||||
|
s->c_length = s->buffer->size - s->c_offset - 2;
|
||||||
|
if (!aisl_header_printf(stream, "Content-Length", "%u", s->c_length))
|
||||||
|
return AISL_MALLOC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fprintf(stdout, "(%lu bytes)------->\n", STREAM(stream)->buffer->size);
|
||||||
|
fwrite(STREAM(stream)->buffer->data, 1, STREAM(stream)->buffer->size, stdout);
|
||||||
|
fprintf(stdout, "<------\n");
|
||||||
|
*/
|
||||||
|
s->state = STREAM_RESPONSE_READY;
|
||||||
|
|
||||||
|
s->flags |= STREAM_FLAG_OUTPUT_READY;
|
||||||
|
|
||||||
|
return AISL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
int
|
||||||
|
aisl_header(aisl_stream_t stream, const char *key, const char *value)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char * pch;
|
||||||
|
|
||||||
|
if ( (pch = str_printf("%s: %s\r\n", key, value)) != NULL )
|
||||||
|
{
|
||||||
|
ret = strlen(pch);
|
||||||
|
if ( buffer_insert(
|
||||||
|
STREAM(stream)->buffer,
|
||||||
|
STREAM(stream)->c_offset,
|
||||||
|
pch,
|
||||||
|
ret
|
||||||
|
) == BUFFER_EOB )
|
||||||
|
{
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
STREAM(stream)->c_offset += ret;
|
||||||
|
|
||||||
|
free(pch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
int
|
||||||
|
aisl_header_printf(aisl_stream_t stream, const char *key,
|
||||||
|
const char *f_value, ...)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, f_value);
|
||||||
|
|
||||||
|
ret = aisl_header_vprintf(stream, key, f_value, arg);
|
||||||
|
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
int
|
||||||
|
aisl_header_vprintf(aisl_stream_t stream, const char *key,
|
||||||
|
const char *format,
|
||||||
|
va_list args)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char * value;
|
||||||
|
|
||||||
|
if ( (value = str_vprintf(format, args)) != NULL )
|
||||||
|
{
|
||||||
|
ret = aisl_header( stream, key, value );
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
int
|
||||||
|
aisl_printf(aisl_stream_t stream, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, format);
|
||||||
|
|
||||||
|
int result = aisl_vprintf(stream, format, arg);
|
||||||
|
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
/* No need to update length there, because vprintf do that
|
||||||
|
*
|
||||||
|
* if (STREAM(stream)->c_length_unknown)
|
||||||
|
STREAM(stream)->c_length += result;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
int
|
||||||
|
aisl_vprintf(aisl_stream_t stream, const char *format, va_list args)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
char * r;
|
||||||
|
|
||||||
|
if ( (r = str_vprintf(format, args)) != NULL)
|
||||||
|
{
|
||||||
|
result = strlen(r);
|
||||||
|
if (buffer_add(STREAM(stream)->buffer, r, result) == BUFFER_EOB)
|
||||||
|
result = -1;
|
||||||
|
|
||||||
|
free(r);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = -1;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
int
|
||||||
|
aisl_write(aisl_stream_t stream, const char *data, int d_len)
|
||||||
|
{
|
||||||
|
if (d_len < 0)
|
||||||
|
d_len = strlen(data);
|
||||||
|
|
||||||
|
if (buffer_add(STREAM(stream)->buffer, data, d_len) == BUFFER_EOB)
|
||||||
|
d_len = -1;
|
||||||
|
|
||||||
|
return d_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("default") ))
|
||||||
|
int
|
||||||
|
aisl_puts(const char *str, aisl_stream_t stream)
|
||||||
|
{
|
||||||
|
return aisl_write( stream, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
39
src/stream.h
39
src/stream.h
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _AISL_STREAM_H__
|
#ifndef AISL_STREAM_H_A9EC6601_34B2_4F3E_B631_EEDA8B6EF0D3
|
||||||
#define _AISL_STREAM_H__
|
#define AISL_STREAM_H_A9EC6601_34B2_4F3E_B631_EEDA8B6EF0D3
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <aisl/stream.h>
|
#include <aisl/stream.h>
|
||||||
|
@ -43,51 +43,32 @@ typedef enum {
|
||||||
STREAM_RESPONSE_CONTENT,
|
STREAM_RESPONSE_CONTENT,
|
||||||
STREAM_RESPONSE_READY
|
STREAM_RESPONSE_READY
|
||||||
|
|
||||||
} stream_state_t;
|
} aisl_stream_state_t;
|
||||||
|
|
||||||
|
|
||||||
/* real wrapper for aisl_stream_t */
|
/* real wrapper for aisl_stream_t */
|
||||||
struct stream
|
|
||||||
{
|
|
||||||
struct aisl_stream _public;
|
|
||||||
|
|
||||||
/* private data */
|
|
||||||
list_t headers; /* request headers */
|
|
||||||
buffer_t buffer;
|
|
||||||
|
|
||||||
const char *c_type;
|
typedef struct aisl_stream * aisl_stream_t;
|
||||||
|
|
||||||
aisl_http_response_t response;
|
|
||||||
stream_state_t state;
|
|
||||||
uint32_t c_length;
|
|
||||||
uint32_t c_offset;
|
|
||||||
int id;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
bool c_length_unknown;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct stream * stream_t;
|
|
||||||
|
|
||||||
#define STREAM(x) ((stream_t) x)
|
#define STREAM(x) ((stream_t) x)
|
||||||
#define ASTREAM(x) ((aisl_stream_t) x)
|
#define ASTREAM(x) ((aisl_stream_t) x)
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
stream_t
|
aisl_stream_t
|
||||||
stream_new(struct sockaddr_in *client, int id, stream_state_t state);
|
aisl_stream_new(struct sockaddr_in *client, int id, stream_state_t state);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void
|
void
|
||||||
stream_free(stream_t self);
|
aisl_stream_free(aisl_stream_t self);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
stream_t
|
aisl_stream_t
|
||||||
stream_reset(stream_t self);
|
aisl_stream_reset(aisl_stream_t self);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#endif
|
#endif /* !AISL_STREAM_H */
|
||||||
|
|
Loading…
Reference in New Issue