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