Refactored client module

This commit is contained in:
Ilja Kartašov 2019-03-12 09:26:44 +01:00
parent 0b05984f85
commit a49e32dff8
7 changed files with 352 additions and 258 deletions

View File

@ -14,6 +14,10 @@
#include <stdarg.h>
#include <stdbool.h>
#ifndef AISL_WITHOUT_SSL
#include <openssl/ssl.h>
#endif
/* type casts */
#define AISL_CALLBACK(x) ((aisl_callback_t) x)
@ -37,10 +41,12 @@ typedef struct aisl_stream * aisl_stream_t;
typedef void
(* aisl_callback_t) (void);
/* status return codes */
typedef enum
{
AISL_EXTCALL_ERROR = -3
AISL_INPUT_ERROR = -4
, AISL_EXTCALL_ERROR = -3
, AISL_SYSCALL_ERROR = -2
, AISL_MALLOC_ERROR = -1

View File

@ -8,13 +8,18 @@
struct buffer
{
char * data;
size_t size;
int32_t size;
int32_t length;
};
typedef struct buffer * buffer_t;
#define BUFFER_EOB ( ~0L )
int
buffer_init( buffer_t buffer, int32_t size );
/* -------------------------------------------------------------------------- */
buffer_t

View File

@ -6,9 +6,14 @@
#include <unistd.h>
#include <fcntl.h>
#ifndef AISL_WITHOUT_SSL
#include <openssl/err.h>
#endif
#include <aisl/aisl.h>
#include "list.h"
#include "stream.h"
#include "http.h"
#include "buffer.h"
#include "client.h"
#define FLAG_KEEPALIVE (1<<0)
@ -16,32 +21,30 @@
#define FLAG_CAN_READ (1<<2)
#define FLAG_CAN_WRITE (1<<3)
#define BUFFER_SIZE (16*1024)
struct aisl_client
{
struct sockaddr_in address; /**< Client's address structure */
aisl_server_t server; /**< Server instance associated with client */
list_t streams; /**< list of client streams */
struct buffer in; /**< Client's input buffer */
struct buffer out; /**< Client's output buffer */
struct sockaddr_in address; /**< Client's address structure. */
aisl_server_t server; /**< Server instance. */
struct buffer in; /**< Client's input buffer. */
struct buffer out; /**< Client's output buffer. */
#ifndef AISL_WITHOUT_SSL
SSL * ssl; /**< SSL pointer for encrypted connections */
SSL * ssl; /**< SSL pointer for HTTPS. */
#endif
time_t timestamp; /**< Last communication timestamp */
time_t timestamp; /**< Last communication timestamp. */
aisl_stream_t stream; /**< Pending client's stream */
/* int next_id; / **< stream id generator (even)*/
/* int istream; / **< input stream id */
/* int ostream; / **< output stream id */
int flags; /**< Client's flag bitmask */
int fd; /**< Client's socket descriptor */
aisl_stream_t stream; /**< Pending client's stream. */
int next_id; /**< Stream id generator (even). */
int flags; /**< Client's flag bitmask. */
int fd; /**< Client's socket descriptor. */
aisl_http_version_t protocol; /**< Client's protocol version */
aisl_http_version_t http_version; /**< Client's http_version version. */
};
static bool
aisl_client_raise_event(aisl_client_t client, aisl_event_t event, ...)
aisl_client_raise(aisl_client_t client, aisl_event_t event, ...)
{
bool result;
va_list vl_args;
@ -57,52 +60,73 @@ aisl_client_raise_event(aisl_client_t client, aisl_event_t event, ...)
static aisl_status_t
aisl_client_parse(aisl_client_t client, char * data, size_t size)
aisl_client_parse(aisl_client_t client, char * data, int32_t size)
{
/* parse next data chunk */
while ( p_status == PARSER_PENDING )
{
switch(s->state)
aisl_stream_t s;
http_parser_t p = HTTP_PARSER_PENDING;
int32_t bytes_left = size;
switch (client->http_version)
{
case AISL_HTTP_1_0:
case AISL_HTTP_1_1:
s = client->stream;
while ( p == HTTP_PARSER_PENDING )
{
case STREAM_REQUEST_METHOD:
p_status = parse_request_method(client, &ptr, &l);
break;
case STREAM_REQUEST_PATH:
p_status = parse_request_path(client, &ptr, &l);
break;
case STREAM_REQUEST_PROTOCOL:
p_status = parse_request_protocol(client, &ptr, &l);
break;
case STREAM_REQUEST_HEADER_KEY:
p_status = parse_request_header_key(client, &ptr, &l);
break;
case STREAM_REQUEST_HEADER_VALUE:
p_status = parse_request_header_value(client, &ptr, &l);
break;
switch ( aisl_stream_get_state(s) )
{
case AISL_STREAM_STATE_IDLE:
p = http_10_parse_request(data, &size, client);
break;
case STREAM_REQUEST_CONTENT:
p_status = parse_request_content(client, &ptr, &l);
break;
case AISL_STREAM_STATE_WAIT_HEADER:
p = http_10_parse_header(data, &size, client);
break;
default:
p_status = PARSER_FINISHED;
/* this is error actually */
case AISL_STREAM_STATE_WAIT_BODY:
p = http_10_parse_body(data, &size, client);
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;
}
}
if (p_status == PARSER_FAILED)
{
/* reply Bad Request here */
client_close(client);
}
else if (l)
{
buffer_shift(s->buffer, s->buffer->size-l); /* reset buffer */
}
if (p == HTTP_PARSER_FINISHED)
{
client->flags &= ~FLAG_CAN_READ;
client->flags |= FLAG_CAN_WRITE;
}
break;
case AISL_HTTP_2_0:
break;
}
if (p == HTTP_PARSER_ERROR)
{
/* reply Bad Request here */
aisl_client_close(client);
return AISL_INPUT_ERROR;
}
if (size)
buffer_shift(&client->in, client->in.length - size); /* reset buffer */
return AISL_SUCCESS;
}
@ -114,11 +138,9 @@ static aisl_status_t
aisl_client_input(aisl_client_t client)
{
int l;
parser_status_t p_status = PARSER_PENDING;
aisl_stream_t s = client->stream;
char * data = &client->in.data[ client->in.length ];
size_t size = client->in.size - client.in.length;
int32_t size = client->in.size - client->in.length;
#ifndef AISL_WITHOUT_SSL
if (client->ssl)
@ -174,40 +196,30 @@ aisl_client_input(aisl_client_t client)
/* both: client disconnect + on read error */
/* todo: raise client error here */
client_close(client);
aisl_client_close(client);
return AISL_SYSCALL_ERROR;
}
static bool
static aisl_status_t
aisl_client_output(aisl_client_t client)
{
if (client->fd < 0)
{
fprintf(stderr, "[aisl] assertion !(client->fd<0) failed\n");
return true;
}
int l;
char * data;
stream_t s;
int l;
s = list_index(client->streams, client->ostream);
/*
if (!s->c_length_unknown && s->buffer && s->buffer->len)
buffer_move(gBuffer, s->buffer);
*/
aisl_stream_t s = client->stream;
/* while stream is not flushed, we should raise event */
if(s->flags & STREAM_FLAG_OUTPUT_CHUNKED)
if( aisl_stream_get_chunked_output(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
* */
size_t bsz = s->buffer->size;
l = aisl_stream_get_buffer_space(s);
/*
if (bsz < OUTPUT_BUFFER_SIZE)
{
if (buffer_clear(s->buffer, OUTPUT_BUFFER_SIZE) == 0)
@ -216,90 +228,108 @@ aisl_client_output(aisl_client_t client)
s->buffer->size = bsz;
bsz = OUTPUT_BUFFER_SIZE;
}
*/
if ( (l = bsz - s->buffer->size) > OUTPUT_BUFFER_SIZE / 2 )
aisl_raise_event( client->server->owner, s, AISL_STREAM_OUTPUT, l);
if ( !(l < aisl_stream_get_buffer_size(s) / 2) )
aisl_raise(
aisl_server_get_instance(client->server),
s,
AISL_EVENT_STREAM_OUTPUT,
l
);
}
if (s->buffer->size == 0)
return false;
aisl_stream_get_buffer(s, &data, &l);
if ( !l )
return AISL_IDLE;
l = (client->ssl) ?
SSL_write(client->ssl, s->buffer->data, s->buffer->size) :
send( client->fd, s->buffer->data, s->buffer->size, 0);
SSL_write(client->ssl, data, l) :
send( client->fd, data, l, 0);
if (l > 0)
{
buffer_shift(s->buffer, l);
if (s->state == STREAM_RESPONSE_READY && /* flushed */
s->buffer->size == 0) /* all sent */
aisl_stream_shift(s, l);
/*
if (s->state == STREAM_RESPONSE_READY && / * flushed * /
s->buffer->size == 0) / * all sent * /
*/
if ( ! aisl_stream_has_data(s) )
{
buffer_clear(s->buffer, 0);
/* buffer_clear(s->buffer, 0); */
/* data has been sent */
/*
if (client->protocol == AISL_HTTP_2_0)
{
}
else*/
if (client->flags & CLIENT_FLAG_KEEPALIVE)
if (client->flags & FLAG_KEEPALIVE)
{
list_remove(client->streams, s);
stream_free(s);
aisl_stream_free(s);
s = stream_new((struct sockaddr_in *) client, client->next_id++, STREAM_REQUEST_METHOD );
list_append(client->streams, s);
}
else
{
client_close(client);
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);
}
return true;
return AISL_SUCCESS;
}
/* l < 0 */
if (client->ssl)
{
if ( SSL_get_error(client->ssl, l) == SSL_ERROR_WANT_WRITE )
return false;
return AISL_IDLE;
}
else
{
if (errno == EWOULDBLOCK)
return false;
return AISL_IDLE;
}
client_close(client);
aisl_client_close(client);
return true;
return AISL_SYSCALL_ERROR;
}
#ifndef AISL_WITHOUT_SSL
aisl_client_t
aisl_client_new( aisl_server_t server,
int fd,
struct sockaddr_in * addr,
SSL_CTX * ssl_ctx )
#else
aisl_client_t
aisl_client_new( aisl_server_t server,
int fd,
struct sockaddr_in * addr )
#endif
{
aisl_client_t client;
aisl_stream_t stream;
if ( (client = calloc(1, sizeof(struct client))) != NULL )
if ( (client = calloc(1, sizeof(struct aisl_client))) != NULL )
{
memcpy(&client->address, addr, sizeof(struct sockaddr_in));
client->server = server;
client->fd = fd;
client->next_id = 2;
client->protocol = AISL_HTTP_1_0;
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) == 0)
if (buffer_init(&client->in, 2*BUFFER_SIZE) == 0)
{
memcpy(&client->out, client->in, sizeof(struct buffer));
memcpy(&client->out, &client->in, sizeof(struct buffer));
stream = aisl_stream_new(client, 0, STREAM_REQUEST_METHOD);
stream = aisl_stream_new(client, 0);
if (stream != NULL)
{
@ -346,7 +376,8 @@ aisl_client_free(aisl_client_t client)
/* out buffer is a shared part of input buffer, so no need to free it */
list_free(client->streams, (list_destructor_t)aisl_stream_free);
if (client->stream)
aisl_stream_free(client->stream);
free(client);
}
@ -355,26 +386,26 @@ aisl_client_free(aisl_client_t client)
aisl_status_t
aisl_client_touch(aisl_client_t client)
{
aisl_status_t result, status;
aisl_stream_t s = client->stream;
aisl_status_t result = AISL_IDLE,
status = AISL_IDLE;
/* input */
if (client->flags & FLAG_CAN_READ)
{
if ( (result = client_input(client)) < 0 )
if ( (result = aisl_client_input(client)) < 0 )
return result;
}
/* output */
if (client->flags & FLAG_CAN_WRITE)
{
if ( (status = client_output(client)) < 0 )
if ( (status = aisl_client_output(client)) < 0 )
return status;
}
/*
if ((client->protocol==AISL_HTTP_2_0 || s->state<STREAM_REQUEST_READY) &&
if ((client->http_version==AISL_HTTP_2_0 || s->state<STREAM_REQUEST_READY) &&
(client_input(client)) ) result = true;
*/
/* output */
@ -389,7 +420,7 @@ aisl_client_touch(aisl_client_t client)
if (result == AISL_IDLE)
result = status;
if (result = AISL_SUCCESS)
if (result == AISL_SUCCESS)
client->timestamp = time(NULL);
return result;
@ -405,7 +436,7 @@ aisl_client_is_timed_out(aisl_client_t client, uint32_t timeout)
if ( !(now - client->timestamp < timeout) )
{
aisl_client_raise_event( client, AISL_CLIENT_TIMEOUT );
aisl_client_raise(client, AISL_EVENT_CLIENT_TIMEOUT);
aisl_client_close(client);
return true;
}
@ -449,7 +480,7 @@ aisl_client_close(aisl_client_t client)
{
if (client->fd != -1)
{
aisl_client_raise_event( client, AISL_CLIENT_DISCONNECT );
aisl_client_raise( client, AISL_EVENT_CLIENT_DISCONNECT );
close(client->fd);
shutdown(client->fd, SHUT_RDWR);

View File

@ -7,7 +7,7 @@
#define AISL_CLIENT(x) ((aisl_client_t) x)
#ifndef AISL_WITHOUT_SSL
/**
* @brief Constructor for #aisl_client_t instance.
* @param server an #aisl_server_t instance pointer.
@ -20,6 +20,20 @@ aisl_client_new( aisl_server_t server,
int fd,
struct sockaddr_in * addr,
SSL_CTX * ssl_ctx);
#else
/**
* @brief Constructor for #aisl_client_t instance.
* @param server an #aisl_server_t instance pointer.
* @param fd a client socket descriptor.
* @param addr a pointer to client's address structure.
* @param ssl_ctx a pointer to SSL context or NULL if encryption is disabled
*/
aisl_client_t
aisl_client_new( aisl_server_t server,
int fd,
struct sockaddr_in * addr );
#endif
/**

42
src/http.h Normal file
View File

@ -0,0 +1,42 @@
/******************************************************************************
*
* Copyright (c) 2017-%YEAR% by Löwenware Ltd
* Please, refer LICENSE file for legal information
*
******************************************************************************/
/**
* @file http.h
* @author Ilja Kartašov <ik@lowenware.com>
* @brief Declarations of HTTP parser module
*
* @see https://lowenware.com/aisl/
*/
#ifndef AISL_HTTP_H_E2921FF1_6BD3_4E60_B599_ACA1A494CD01
#define AISL_HTTP_H_E2921FF1_6BD3_4E60_B599_ACA1A494CD01
#include <aisl/types.h>
typedef enum
{
HTTP_PARSER_PENDING
, HTTP_PARSER_ERROR
, HTTP_PARSER_FINISHED
} http_parser_t;
http_parser_t
http_10_parse_request(char * data, int32_t * size, aisl_client_t client);
http_parser_t
http_10_parse_header(char * data, int32_t * size, aisl_client_t client);
http_parser_t
http_10_parse_body(char * data, int32_t * size, aisl_client_t client);
#endif /* !AISL_HTTP_H */

View File

@ -2,141 +2,142 @@
#include <stdarg.h>
#include <string.h>
#include "buffer.h"
#include "stream.h"
#include "globals.h"
#include "client.h"
#include "handle.h"
struct stream
#define FLAG_OUTPUT_READY (1<<0)
#define FLAG_OUTPUT_CHUNKED (1<<1)
struct aisl_stream
{
struct aisl_stream _public;
aisl_client_t client;
/* private data */
list_t headers; /* request headers */
buffer_t buffer;
struct buffer buffer;
const char *c_type;
const char *content_type;
aisl_http_response_t response;
stream_state_t state;
uint32_t c_length;
uint32_t c_offset;
size_t content_length;
int32_t content_offset;
int id;
int flags;
aisl_http_response_t response;
aisl_stream_state_t state;
bool c_length_unknown;
};
static void
pair_free( pair_t self )
pair_free( pair_t stream )
{
if (!self) return;
if (!stream) return;
if(self->key) free(self->key);
if(self->value) free(self->value);
free(self);
if(stream->key) free(stream->key);
if(stream->value) free(stream->value);
free(stream);
}
/* -------------------------------------------------------------------------- */
stream_t
aisl_stream_t
stream_new(struct sockaddr_in *client, int id, stream_state_t state)
{
stream_t self = malloc(sizeof(struct stream));
aisl_stream_t stream = malloc(sizeof(struct aisl_stream));
if (self)
if (stream)
{
/* public data */
ASTREAM(self)->client = client;
ASTREAM(self)->host = NULL;
ASTREAM(self)->path = NULL;
ASTREAM(self)->query = NULL;
ASTREAM(self)->scheme = NULL;
ASTREAM(self)->u_ptr = NULL;
ASTREAM(self)->request_method = AISL_HTTP_GET;
ASTREAM(stream)->client = client;
ASTREAM(stream)->host = NULL;
ASTREAM(stream)->path = NULL;
ASTREAM(stream)->query = NULL;
ASTREAM(stream)->scheme = NULL;
ASTREAM(stream)->u_ptr = NULL;
ASTREAM(stream)->request_method = AISL_HTTP_GET;
/* private data */
self->headers = NULL; /* request headers */
self->buffer = buffer_new(0);
stream->headers = NULL; /* request headers */
stream->buffer = buffer_new(0);
self->c_type = NULL;
stream->c_type = NULL;
self->response = AISL_HTTP_OK;
self->state = STREAM_REQUEST_METHOD;
self->c_length = 0;
self->c_offset = 0; /* headers length */
self->id = id;
self->c_length_unknown = true;
self->flags = 0;
stream->response = AISL_HTTP_OK;
stream->state = STREAM_REQUEST_METHOD;
stream->c_length = 0;
stream->c_offset = 0; /* headers length */
stream->id = id;
stream->c_length_unknown = true;
stream->flags = 0;
}
return self;
return stream;
}
/*
stream_t
stream_reset(stream_t self)
aisl_stream_t
stream_reset(aisl_stream_t stream)
{
if (ASTREAM(self)->path)
if (ASTREAM(stream)->path)
{
free( (char*) ASTREAM(self)->path);
ASTREAM(self)->path = NULL;
free( (char*) ASTREAM(stream)->path);
ASTREAM(stream)->path = NULL;
}
if (ASTREAM(self)->query)
if (ASTREAM(stream)->query)
{
free( (char*) ASTREAM(self)->query);
ASTREAM(self)->query = NULL;
free( (char*) ASTREAM(stream)->query);
ASTREAM(stream)->query = NULL;
}
ASTREAM(self)->u_ptr = NULL;
ASTREAM(self)->request_method = AISL_HTTP_GET;
ASTREAM(stream)->u_ptr = NULL;
ASTREAM(stream)->request_method = AISL_HTTP_GET;
if (self->headers)
if (stream->headers)
{
list_free(self->headers, (list_destructor_t) pair_free);
self->headers = NULL;
list_free(stream->headers, (list_destructor_t) pair_free);
stream->headers = NULL;
}
self->c_type = NULL;
self->response = AISL_HTTP_OK;
self->state = STREAM_REQUEST_METHOD;
self->c_length = 0;
self->c_offset = 0; / * headers length * /
self->c_length_unknown = true;
self->flags = 0;
stream->c_type = NULL;
stream->response = AISL_HTTP_OK;
stream->state = STREAM_REQUEST_METHOD;
stream->c_length = 0;
stream->c_offset = 0; / * headers length * /
stream->c_length_unknown = true;
stream->flags = 0;
return self;
return stream;
}
*/
/* -------------------------------------------------------------------------- */
void
stream_free(stream_t self)
stream_free(aisl_stream_t stream)
{
if (self->buffer) buffer_free(self->buffer);
if (self->headers) list_free(self->headers, (list_destructor_t) pair_free);
if (stream->buffer) buffer_free(stream->buffer);
if (stream->headers) list_free(stream->headers, (list_destructor_t) pair_free);
if (ASTREAM(self)->path) free( (char*) ASTREAM(self)->path);
if (ASTREAM(self)->query) free( (char*) ASTREAM(self)->query);
if (ASTREAM(stream)->path) free( (char*) ASTREAM(stream)->path);
if (ASTREAM(stream)->query) free( (char*) ASTREAM(stream)->query);
aisl_handle_t hd = ((client_t) ASTREAM(self)->client)->server->owner;
aisl_raise_event(hd, self, AISL_STREAM_CLOSE);
ASTREAM(self)->u_ptr = NULL;
aisl_remove_listeners_for(hd, self);
free(self);
aisl_handle_t hd = ((client_t) ASTREAM(stream)->client)->server->owner;
aisl_raise_event(hd, stream, AISL_STREAM_CLOSE);
ASTREAM(stream)->u_ptr = NULL;
aisl_remove_listeners_for(hd, stream);
free(stream);
}
/* -------------------------------------------------------------------------- */
int
stream_write(stream_t self, const char * data, uint32_t d_len)
stream_write(aisl_stream_t stream, const char * data, uint32_t d_len)
{
return buffer_add( self->buffer, data, d_len);
return buffer_add( stream->buffer, data, d_len);
}
/* -------------------------------------------------------------------------- */
__attribute__ ((visibility ("default") ))
void
aisl_cancel(aisl_stream_t s)
aisl_cancel(aisl_aisl_stream_t s)
{
client_close( (client_t) s->client );
}
@ -145,7 +146,7 @@ aisl_cancel(aisl_stream_t s)
__attribute__ ((visibility ("default") ))
bool
aisl_is_secure(aisl_stream_t s)
aisl_is_secure(aisl_aisl_stream_t s)
{
client_t cli = (client_t) s->client;
@ -156,7 +157,7 @@ aisl_is_secure(aisl_stream_t s)
__attribute__ ((visibility ("default") ))
void *
aisl_get_context(aisl_stream_t s)
aisl_get_context(aisl_aisl_stream_t s)
{
return s->u_ptr;
}
@ -165,7 +166,7 @@ aisl_get_context(aisl_stream_t s)
__attribute__ ((visibility ("default") ))
void
aisl_set_context(aisl_stream_t s, void * u_ptr)
aisl_set_context(aisl_aisl_stream_t s, void * u_ptr)
{
s->u_ptr = u_ptr;
}
@ -174,7 +175,7 @@ aisl_set_context(aisl_stream_t s, void * u_ptr)
__attribute__ ((visibility ("default") ))
aisl_client_t
aisl_get_client(aisl_stream_t s)
aisl_get_client(aisl_aisl_stream_t s)
{
return s->client;
}
@ -183,7 +184,7 @@ aisl_get_client(aisl_stream_t s)
__attribute__ ((visibility ("default") ))
aisl_server_t
aisl_get_server(aisl_stream_t s)
aisl_get_server(aisl_aisl_stream_t s)
{
return (aisl_server_t) (((client_t) s->client)->server);
}
@ -193,7 +194,7 @@ aisl_get_server(aisl_stream_t s)
__attribute__ ((visibility ("default") ))
aisl_http_version_t
aisl_get_http_version(aisl_stream_t s)
aisl_get_http_version(aisl_aisl_stream_t s)
{
client_t cli = (client_t) s->client;
@ -204,7 +205,7 @@ aisl_get_http_version(aisl_stream_t s)
__attribute__ ((visibility ("default") ))
void
aisl_reject(aisl_stream_t s)
aisl_reject(aisl_aisl_stream_t s)
{
client_t cli = (client_t) s->client;
@ -216,7 +217,7 @@ aisl_reject(aisl_stream_t s)
static char *
get_response_begin(stream_t stream)
get_response_begin(aisl_stream_t stream)
{
char * r;
client_t cli = CLIENT(ASTREAM(stream)->client);
@ -236,7 +237,7 @@ get_response_begin(stream_t stream)
__attribute__ ((visibility ("default") ))
aisl_status_t
aisl_response(aisl_stream_t stream, aisl_http_response_t status_code,
aisl_response(aisl_aisl_stream_t stream, aisl_http_response_t status_code,
const char *content_type,
uint32_t content_length)
{
@ -284,9 +285,9 @@ aisl_response(aisl_stream_t stream, aisl_http_response_t status_code,
__attribute__ ((visibility ("default") ))
aisl_status_t
aisl_flush(aisl_stream_t stream)
aisl_flush(aisl_aisl_stream_t stream)
{
stream_t s = STREAM(stream);
aisl_stream_t s = STREAM(stream);
if ( ! s->c_length )
{
s->c_length = s->buffer->size - s->c_offset - 2;
@ -309,7 +310,7 @@ aisl_flush(aisl_stream_t stream)
__attribute__ ((visibility ("default") ))
int
aisl_header(aisl_stream_t stream, const char *key, const char *value)
aisl_header(aisl_aisl_stream_t stream, const char *key, const char *value)
{
int ret;
char * pch;
@ -340,7 +341,7 @@ aisl_header(aisl_stream_t stream, const char *key, const char *value)
__attribute__ ((visibility ("default") ))
int
aisl_header_printf(aisl_stream_t stream, const char *key,
aisl_header_printf(aisl_aisl_stream_t stream, const char *key,
const char *f_value, ...)
{
int ret;
@ -358,7 +359,7 @@ aisl_header_printf(aisl_stream_t stream, const char *key,
__attribute__ ((visibility ("default") ))
int
aisl_header_vprintf(aisl_stream_t stream, const char *key,
aisl_header_vprintf(aisl_aisl_stream_t stream, const char *key,
const char *format,
va_list args)
{
@ -379,7 +380,7 @@ aisl_header_vprintf(aisl_stream_t stream, const char *key,
__attribute__ ((visibility ("default") ))
int
aisl_printf(aisl_stream_t stream, const char *format, ...)
aisl_printf(aisl_aisl_stream_t stream, const char *format, ...)
{
va_list arg;
va_start(arg, format);
@ -402,7 +403,7 @@ aisl_printf(aisl_stream_t stream, const char *format, ...)
__attribute__ ((visibility ("default") ))
int
aisl_vprintf(aisl_stream_t stream, const char *format, va_list args)
aisl_vprintf(aisl_aisl_stream_t stream, const char *format, va_list args)
{
int result;
char * r;
@ -424,7 +425,7 @@ aisl_vprintf(aisl_stream_t stream, const char *format, va_list args)
__attribute__ ((visibility ("default") ))
int
aisl_write(aisl_stream_t stream, const char *data, int d_len)
aisl_write(aisl_aisl_stream_t stream, const char *data, int d_len)
{
if (d_len < 0)
d_len = strlen(data);
@ -438,7 +439,7 @@ aisl_write(aisl_stream_t stream, const char *data, int d_len)
__attribute__ ((visibility ("default") ))
int
aisl_puts(const char *str, aisl_stream_t stream)
aisl_puts(const char *str, aisl_aisl_stream_t stream)
{
return aisl_write( stream, str, strlen(str));
}

View File

@ -3,74 +3,69 @@
#include <aisl/types.h>
#include <aisl/stream.h>
#include "list.h"
#include "buffer.h"
/* -------------------------------------------------------------------------- */
#define AISL_STREAM(x) ((aisl_stream_t) x)
#define STREAM_FLAG_OUTPUT_READY (1<<0)
#define STREAM_FLAG_OUTPUT_CHUNKED (1<<1)
/* -------------------------------------------------------------------------- */
struct pair
typedef enum
{
char *key;
char *value;
};
AISL_STREAM_STATE_IDLE
typedef struct pair * pair_t;
, AISL_STREAM_STATE_WAIT_HEADER
, AISL_STREAM_STATE_WAIT_BODY
/* -------------------------------------------------------------------------- */
, AISL_STREAM_STATE_READY
typedef enum {
, AISL_STREAM_STATE_SEND_HEADER
, AISL_STREAM_STATE_SEND_BODY
STREAM_REQUEST_METHOD,
STREAM_REQUEST_PATH,
STREAM_REQUEST_PROTOCOL,
STREAM_REQUEST_HEADER_KEY, /* HTTP1 header key */
STREAM_REQUEST_HEADER_VALUE, /* HTTP1 header value */
STREAM_REQUEST_CONTENT, /* HTTP1 data value */
/* states below show stream state
* and do not show what data was sent to client
* */
STREAM_REQUEST_READY,
STREAM_RESPONSE_HEADER,
STREAM_RESPONSE_CONTENT,
STREAM_RESPONSE_READY
, AISL_STREAM_STATE_DONE
} aisl_stream_state_t;
/* real wrapper for aisl_stream_t */
#define STREAM(x) ((aisl_stream_t) x)
/* -------------------------------------------------------------------------- */
aisl_stream_t
aisl_stream_new(struct sockaddr_in *client, int id, aisl_stream_state_t state);
aisl_stream_new(aisl_client_t client, int id );
/* -------------------------------------------------------------------------- */
void
aisl_stream_free(aisl_stream_t self);
aisl_stream_free(aisl_stream_t stream);
/* -------------------------------------------------------------------------- */
aisl_stream_t
aisl_stream_reset(aisl_stream_t self);
/* to be removed ??
* aisl_stream_t
* aisl_stream_reset(aisl_stream_t stream);
*/
/* -------------------------------------------------------------------------- */
void
aisl_stream_set_chunked_output(aisl_stream_t self, bool value);
aisl_stream_set_chunked_output(aisl_stream_t stream, bool value);
/* -------------------------------------------------------------------------- */
bool
aisl_stream_get_chunked_output(aisl_stream_t stream);
int32_t
aisl_stream_get_buffer_space(aisl_stream_t stream);
int32_t
aisl_stream_get_buffer_size(aisl_stream_t stream);
void
aisl_stream_get_buffer(aisl_stream_t stream, char ** data, int32_t * size);
void
aisl_stream_shift(aisl_stream_t stream, int32_t offset);
bool
aisl_stream_has_data(aisl_stream_t stream);
aisl_stream_state_t
aisl_stream_get_state(aisl_stream_t stream);
#endif /* !AISL_STREAM_H */