From a49e32dff8a5080e08f019dc50f1bdf5430c9f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilja=20Karta=C5=A1ov?= Date: Tue, 12 Mar 2019 09:26:44 +0100 Subject: [PATCH] Refactored client module --- include/aisl/types.h | 8 +- src/buffer.h | 7 +- src/client.c | 263 ++++++++++++++++++++++++------------------- src/client.h | 16 ++- src/http.h | 42 +++++++ src/stream.c | 183 +++++++++++++++--------------- src/stream.h | 91 +++++++-------- 7 files changed, 352 insertions(+), 258 deletions(-) create mode 100644 src/http.h diff --git a/include/aisl/types.h b/include/aisl/types.h index d69f635..6dd70a7 100644 --- a/include/aisl/types.h +++ b/include/aisl/types.h @@ -14,6 +14,10 @@ #include #include +#ifndef AISL_WITHOUT_SSL +#include +#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 diff --git a/src/buffer.h b/src/buffer.h index 9e1fc94..9c2cfec 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -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 diff --git a/src/client.c b/src/client.c index 5f3a242..060ed28 100644 --- a/src/client.c +++ b/src/client.c @@ -6,9 +6,14 @@ #include #include +#ifndef AISL_WITHOUT_SSL +#include +#endif + #include -#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->statehttp_version==AISL_HTTP_2_0 || s->statetimestamp = 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); diff --git a/src/client.h b/src/client.h index b0deafd..9370182 100644 --- a/src/client.h +++ b/src/client.h @@ -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 /** diff --git a/src/http.h b/src/http.h new file mode 100644 index 0000000..044a16d --- /dev/null +++ b/src/http.h @@ -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 + * @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 + +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 */ diff --git a/src/stream.c b/src/stream.c index d18e09c..38c0434 100644 --- a/src/stream.c +++ b/src/stream.c @@ -2,141 +2,142 @@ #include #include +#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)); } diff --git a/src/stream.h b/src/stream.h index 21c7d5f..38c5b24 100644 --- a/src/stream.h +++ b/src/stream.h @@ -3,74 +3,69 @@ #include #include -#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 */