Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06c99b1e4b | ||
|
|
f7a9f255df |
+1
-2
@@ -7,6 +7,7 @@ demo/*
|
||||
bin/*
|
||||
obj/*
|
||||
webstuff-*
|
||||
Makefile
|
||||
tmp
|
||||
tmp/*
|
||||
*.tar.gz
|
||||
@@ -15,8 +16,6 @@ tmp/*
|
||||
*.gz
|
||||
*.bz2
|
||||
pkg/*
|
||||
doc/html
|
||||
vgcore.*
|
||||
|
||||
include/webstuff_bak
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[submodule "cStuff"]
|
||||
path = cStuff
|
||||
url = git@lowenware.com:lowenware/cStuff.git
|
||||
[submodule "aisl-sdk"]
|
||||
path = aisl-sdk
|
||||
url = git@lowenware.com:lowenware/aisl-sdk.git
|
||||
@@ -0,0 +1,8 @@
|
||||
# Release 1.0.0
|
||||
|
||||
By Ilja Kartašov <ik@lowenware.com>, 2019-06-02
|
||||
|
||||
1. Library release with new and final API and documented code.
|
||||
2. Previous version is being called `aisl-legacy` and will be maintained in
|
||||
security aspects in branch called `legacy` until all applications using it will
|
||||
be updated.
|
||||
@@ -1,90 +0,0 @@
|
||||
#
|
||||
# Makefile
|
||||
# Ilja Kartašov, 2019-03-02 17:32
|
||||
#
|
||||
.POSIX:
|
||||
|
||||
# Project directories
|
||||
SRC_DIR ?= src
|
||||
SDK_DIR ?= sdk
|
||||
OUT_DIR ?= build
|
||||
LIB_DIR ?= lib
|
||||
DESTDIR ?=
|
||||
|
||||
# Project definition
|
||||
include project.mk
|
||||
|
||||
# Examples submodule
|
||||
include examples.mk
|
||||
|
||||
# CFLAGS
|
||||
|
||||
CFLAGS := \
|
||||
$(PROJECT_INCLUDES) \
|
||||
-std=c99 \
|
||||
-pedantic \
|
||||
-Wall \
|
||||
-Wmissing-prototypes \
|
||||
-Wstrict-prototypes \
|
||||
-Wold-style-definition \
|
||||
-O2 \
|
||||
-s \
|
||||
-fvisibility=hidden \
|
||||
-DVERSION_MAJOR=$(PROJECT_VERSION_MAJOR) \
|
||||
-DVERSION_MINOR=$(PROJECT_VERSION_MINOR) \
|
||||
-DVERSION_TWEAK=$(PROJECT_VERSION_TWEAK) \
|
||||
-DVERSION_LABEL=$(PROJECT_VERSION_LABEL) \
|
||||
$(CPPFLAGS) \
|
||||
$(CFLAGS) \
|
||||
$(PROJECT_CFLAGS) \
|
||||
|
||||
|
||||
LDFLAGS := \
|
||||
$(PROJECT_LIBRARIES) \
|
||||
$(LDFLAGS) \
|
||||
$(PROJECT_LDFLAGS) \
|
||||
|
||||
|
||||
SOURCE_LIST := $(wildcard $(PROJECT_SOURCES))
|
||||
OBJECT_FILES := $(addprefix $(OUT_DIR)/o_, ${SOURCE_LIST:.c=.o})
|
||||
|
||||
|
||||
library: dirs $(OBJECT_FILES)
|
||||
$(info linking target: $@)
|
||||
@$(CC) -shared -o $(OUT_DIR)/lib$(PROJECT_NAME).so $(OBJECT_FILES) $(LDFLAGS)
|
||||
$(info done: $@)
|
||||
|
||||
|
||||
build/o_%.o: %.c
|
||||
$(info compiling file: $<)
|
||||
@$(CC) $(CFLAGS) -fpic -c $< -o $@
|
||||
|
||||
dirs:
|
||||
$(info preparing: build folders)
|
||||
@mkdir -p $(OUT_DIR)/o_$(SRC_DIR)
|
||||
@mkdir -p $(OUT_DIR)/o_$(SDK_DIR)
|
||||
|
||||
|
||||
clean:
|
||||
$(info cleaning: build files)
|
||||
@rm -Rf $(OUT_DIR)
|
||||
@rm -Rf ./vgcore.*
|
||||
|
||||
doc:
|
||||
doxygen doc/api-reference.conf
|
||||
|
||||
all: library examples doc
|
||||
|
||||
default: library
|
||||
.PHONY: all dirs clean doc install
|
||||
|
||||
install: library
|
||||
$(info installing files)
|
||||
@mkdir -p $(DESTDIR)$(PREFIX)/$(LIB_DIR)
|
||||
@mkdir -p $(DESTDIR)$(PREFIX)/include
|
||||
|
||||
@cp $(OUT_DIR)/lib$(PROJECT_NAME).so $(DESTDIR)$(PREFIX)/$(LIB_DIR)
|
||||
@cp -R include/aisl $(DESTDIR)$(PREFIX)/include
|
||||
|
||||
# vim:ft=make
|
||||
#
|
||||
@@ -1,36 +1,32 @@
|
||||
# AISL
|
||||
Asynchronous Internet Server Library
|
||||
|
||||
## Installation on CentOS 7 / RedHat 7
|
||||
Asynchronous Internet Server Library provides innovative way of web development.
|
||||
AISL based applications have built-in web server giving full control of client
|
||||
serving. All you need to know is a request string? - Start prepare the response
|
||||
without waiting for headers and body! Don't need some headers? - Don't save them
|
||||
in memory! Unwanted content-body? - simply ignore it!
|
||||
|
||||
## Documentation
|
||||
|
||||
[Hello World](https://lowenware.com/aisl/handbook.html#getting-started) example
|
||||
and full [API reference](https://lowenware.com/aisl/handbook.html#api-reference)
|
||||
can be found in an oficial [AISL HandBook](https://lowenware.com/aisl/handbook.html).
|
||||
|
||||
## Installation
|
||||
|
||||
1. Add repository
|
||||
```
|
||||
sudo curl -o /etc/yum.repos.d/lowenware.repo https://lowenware.com/rpm/redhat-7/lowenware.repo
|
||||
$ make PREFIX=/usr/local
|
||||
$ sudo make PREFIX=/usr/local install
|
||||
$ sudo cp libaisl.pc.example /usr/lib/pkgconfig/libaisl.pc
|
||||
```
|
||||
|
||||
2. Import GPG key
|
||||
ArchLinux users can install from [AUR](https://aur.archlinux.org/packages/aisl-git/) :
|
||||
|
||||
```
|
||||
sudo rpm --import https://lowenware.com/rpm/RPM-GPG-KEY-Lowenware
|
||||
$ yaourt -S aisl-git
|
||||
```
|
||||
|
||||
3. Install
|
||||
```
|
||||
sudo yum install aisl aisl-devel
|
||||
```
|
||||
## License
|
||||
|
||||
## Installation from sources on any distro
|
||||
|
||||
1. Configuration
|
||||
```
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr/local
|
||||
```
|
||||
|
||||
2. Compilation
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
3. Installation
|
||||
```
|
||||
sudo make install
|
||||
```
|
||||
AISL is free for both commercial and non-commercial use, being distributed under
|
||||
terms of [CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0/).
|
||||
|
||||
Submodule
+1
Submodule aisl-sdk added at b9e247b88f
Submodule
+1
Submodule cStuff added at 4ba00ca17a
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
<!-- HTML footer for doxygen 1.8.14-->
|
||||
<!-- start footer part -->
|
||||
<!--BEGIN GENERATE_TREEVIEW-->
|
||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||||
<ul>
|
||||
$navpath
|
||||
<li class="footer">$generatedby
|
||||
<a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--END GENERATE_TREEVIEW-->
|
||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
$generatedby  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
|
||||
</a> $doxygenversion
|
||||
</small></address>
|
||||
<!--END !GENERATE_TREEVIEW-->
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,56 +0,0 @@
|
||||
<!-- HTML header for doxygen 1.8.14-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
<body>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
||||
<!--BEGIN TITLEAREA-->
|
||||
<div id="titlearea">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr style="height: 56px;">
|
||||
<!--BEGIN PROJECT_LOGO-->
|
||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
||||
<!--END PROJECT_LOGO-->
|
||||
<!--BEGIN PROJECT_NAME-->
|
||||
<td id="projectalign" style="padding-left: 0.5em;">
|
||||
<div id="projectname">$projectname
|
||||
<!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
|
||||
</div>
|
||||
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
|
||||
</td>
|
||||
<!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME-->
|
||||
<!--BEGIN PROJECT_BRIEF-->
|
||||
<td style="padding-left: 0.5em;">
|
||||
<div id="projectbrief">$projectbrief</div>
|
||||
</td>
|
||||
<!--END PROJECT_BRIEF-->
|
||||
<!--END !PROJECT_NAME-->
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
<td>$searchbox</td>
|
||||
<!--END SEARCHENGINE-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--END TITLEAREA-->
|
||||
<!-- end header part -->
|
||||
-1596
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -24,7 +24,7 @@ examples: library hello_world
|
||||
|
||||
hello_world:
|
||||
$(info compiling: hello world)
|
||||
$(CC) $(EXAMPLES_CFLAGS) \
|
||||
@$(CC) $(EXAMPLES_CFLAGS) \
|
||||
-o $(OUT_DIR)/hello-world $(EXAMPLES_DIR)/hello-world.c $(EXAMPLES_LDFLAGS)
|
||||
|
||||
# vim:ft=make
|
||||
|
||||
+61
-56
@@ -20,80 +20,85 @@
|
||||
#include <aisl/aisl.h>
|
||||
|
||||
|
||||
#define DEFAULT_HTTP_PORT 8080 /**< Default HTTP server port */
|
||||
static void
|
||||
hello_world(const struct aisl_evt *evt, void *p_ctx);
|
||||
|
||||
|
||||
static const struct aisl_cfg_srv m_srv[] = {{
|
||||
.host = "0.0.0.0",
|
||||
.port = 8080,
|
||||
.secure = false
|
||||
}};
|
||||
|
||||
|
||||
static const struct aisl_cfg m_cfg = {
|
||||
AISL_CFG_DEFAULTS
|
||||
, .srv = m_srv
|
||||
, .srv_cnt = sizeof (m_srv) / sizeof (m_srv[0])
|
||||
, .ssl = NULL
|
||||
, .ssl_cnt = 0
|
||||
, .callback = hello_world
|
||||
, .p_ctx = NULL
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
hello_world(const struct aisl_evt *evt, void *p_ctx)
|
||||
{
|
||||
if (evt->code != AISL_EVENT_STREAM_REQUEST)
|
||||
return;
|
||||
AislStream s;
|
||||
|
||||
AislStatus status;
|
||||
const char html[] =
|
||||
"<html>"
|
||||
"<head>"
|
||||
"<title>Hello World</title>"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<h1>Hello World</h1>"
|
||||
"<p>Powered by AISL</p>"
|
||||
"</body>"
|
||||
"</html>";
|
||||
|
||||
fprintf(stdout, "Event: %s\n", aisl_event_to_string(evt->code) );
|
||||
|
||||
AislStream s = evt->source;
|
||||
if (evt->code != AISL_EVENT_STREAM_REQUEST)
|
||||
return;
|
||||
|
||||
const char html[] =
|
||||
"<html>"
|
||||
"<head>"
|
||||
"<title>Hello World</title>"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<h1>Hello World</h1>"
|
||||
"<p>Powered by AISL</p>"
|
||||
"</body>"
|
||||
"</html>";
|
||||
s = evt->source;
|
||||
|
||||
status = aisl_response(s, AISL_HTTP_OK, sizeof (html)-1);
|
||||
if (aisl_response(s, AISL_HTTP_OK, sizeof (html)-1) == AISL_SUCCESS) {
|
||||
if (aisl_write(s, html, sizeof (html)-1) != -1) {
|
||||
aisl_flush(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == AISL_SUCCESS)
|
||||
{
|
||||
if (aisl_write(s, html, sizeof (html)-1) != -1)
|
||||
{
|
||||
aisl_flush(s);
|
||||
}
|
||||
else
|
||||
aisl_reject(s);
|
||||
}
|
||||
|
||||
(void) p_ctx;
|
||||
aisl_reject(s);
|
||||
(void) p_ctx;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char ** argv)
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
AislInstance aisl; /**< AISL instance pointer */
|
||||
AislStatus status; /**< AISL status code */
|
||||
struct aisl_cfg cfg = AISL_CFG_DEFAULT;
|
||||
struct aisl_cfg_srv srv = {
|
||||
.host = "0.0.0.0",
|
||||
.port = DEFAULT_HTTP_PORT,
|
||||
.secure = false
|
||||
};
|
||||
AislInstance aisl; /**< AISL instance pointer */
|
||||
AislStatus status; /**< AISL status code */
|
||||
|
||||
cfg.srv = &srv;
|
||||
cfg.srv_cnt = 1;
|
||||
cfg.callback = hello_world;
|
||||
/* Initialize instance */
|
||||
if ( (aisl = aisl_new(&m_cfg)) != NULL ) {
|
||||
/* launch application loop */
|
||||
fprintf(stdout, "Entering main loop\n" );
|
||||
for(;;) {
|
||||
status = aisl_run_cycle(aisl);
|
||||
|
||||
/* Initialize instance */
|
||||
if ( (aisl = aisl_new(&cfg)) != NULL )
|
||||
{
|
||||
/* launch application loop */
|
||||
fprintf(stdout, "Entering main loop" );
|
||||
for(;;)
|
||||
{
|
||||
status = aisl_run_cycle(aisl);
|
||||
if ( status != AISL_SUCCESS )
|
||||
aisl_sleep(aisl, 500);
|
||||
}
|
||||
|
||||
if ( status != AISL_SUCCESS )
|
||||
aisl_sleep(aisl, 500);
|
||||
}
|
||||
aisl_free(aisl);
|
||||
} else {
|
||||
fprintf(stderr, "Failed to initialize AISL\n");
|
||||
}
|
||||
|
||||
aisl_free(aisl);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Failed to initialize AISL");
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -63,6 +63,11 @@ AislHttpVersion
|
||||
aisl_client_get_http_version(AislClient client);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Copies #AislClient network address to provided sockaddr_in structure.
|
||||
* @param client an #AislClient instance pointer.
|
||||
* @param address a pointer to a sockaddr_in structure
|
||||
*/
|
||||
void
|
||||
aisl_client_get_address(AislClient client, struct sockaddr_in *address);
|
||||
|
||||
|
||||
+26
-28
@@ -18,49 +18,47 @@
|
||||
|
||||
#include <aisl/types.h>
|
||||
|
||||
#define AISL_CFG_DEFAULT { \
|
||||
.callback = NULL \
|
||||
, .p_ctx = NULL \
|
||||
, .srv = NULL \
|
||||
, .ssl = NULL \
|
||||
, .srv_cnt = 0 \
|
||||
, .ssl_cnt = 0 \
|
||||
, .client_spool_size = 32 \
|
||||
#define AISL_CFG_DEFAULTS \
|
||||
.client_spool_size = 32 \
|
||||
, .initial_buffer_size = 16536 \
|
||||
, .client_accept_limit = 1024 \
|
||||
, .client_silence_timeout = 30 \
|
||||
} \
|
||||
|
||||
|
||||
/** @brief Server configuration structure
|
||||
*/
|
||||
struct aisl_cfg_srv {
|
||||
const char * host;
|
||||
uint16_t port;
|
||||
bool secure;
|
||||
const char *host; /**< server IP to listen */
|
||||
uint16_t port; /**< server port to listen */
|
||||
bool secure; /**< shall server use TLS */
|
||||
};
|
||||
|
||||
|
||||
/** @brief SSL configuration structure
|
||||
*/
|
||||
struct aisl_cfg_ssl {
|
||||
const char * host;
|
||||
const char * key_file;
|
||||
const char * crt_file;
|
||||
const char *host; /**< secure server hostname */
|
||||
const char *key_file; /**< path to SSL key file */
|
||||
const char *crt_file; /**< path to SSL certificate file */
|
||||
};
|
||||
|
||||
|
||||
struct aisl_cfg
|
||||
{
|
||||
/* event handlers */
|
||||
AislCallback callback;
|
||||
void *p_ctx;
|
||||
/** @brief AISL initial configuration structure
|
||||
*/
|
||||
struct aisl_cfg {
|
||||
AislCallback callback; /**< A pointer to #AislCallback event handler */
|
||||
void *p_ctx; /**< User defined context for #AislCallback */
|
||||
|
||||
struct aisl_cfg_srv *srv;
|
||||
struct aisl_cfg_ssl *ssl;
|
||||
const struct aisl_cfg_srv *srv; /**< A pointer to array of #aisl_cfg_srv */
|
||||
const struct aisl_cfg_ssl *ssl; /**< A pointer to array of #aisl_cfg_ssl */
|
||||
|
||||
int srv_cnt;
|
||||
int ssl_cnt;
|
||||
int srv_cnt; /**< Size of #aisl_cfg_srv array */
|
||||
int ssl_cnt; /**< Size of #aisl_cfg_ssl array */
|
||||
|
||||
int client_spool_size;
|
||||
int initial_buffer_size;
|
||||
int client_accept_limit;
|
||||
int client_silence_timeout;
|
||||
int client_spool_size; /**< Initial size of client spool */
|
||||
int initial_buffer_size; /**< Initial size of communication buffer */
|
||||
int client_accept_limit; /**< Maximal number of concurent clients */
|
||||
int client_silence_timeout; /**< Client silence timeout */
|
||||
};
|
||||
|
||||
#endif /* !AISL_CONFIG_H */
|
||||
|
||||
+95
-2
@@ -19,53 +19,109 @@
|
||||
#include <stdarg.h>
|
||||
#include <aisl/types.h>
|
||||
|
||||
#define aisl_stream_get_instance aisl_get_instance
|
||||
|
||||
/** @brief Gets a value of #AislStream security flag
|
||||
* @param stream an #AislStream instance
|
||||
* @return is true if stream is encrypted and false otherwise
|
||||
*/
|
||||
bool
|
||||
aisl_is_secure(AislStream stream);
|
||||
|
||||
|
||||
/** @brief Gets an #AislClient instance associated with the stream
|
||||
* @param stream an #AislStream instance
|
||||
* @return an #AislClient instance pointer
|
||||
*/
|
||||
AislClient
|
||||
aisl_get_client(AislStream stream);
|
||||
|
||||
|
||||
/** @brief Gets an #AislServer instance associated with the stream
|
||||
* @param stream an #AislStream instance
|
||||
* @return an #AislServer instance pointer
|
||||
*/
|
||||
AislServer
|
||||
aisl_get_server(AislStream stream);
|
||||
|
||||
|
||||
/** @brief Gets an #AislHttpVersion of the stream
|
||||
* @param stream an #AislStream instance
|
||||
* @return an #AislHttpVersion value
|
||||
*/
|
||||
AislHttpVersion
|
||||
aisl_get_http_version(AislStream stream);
|
||||
|
||||
|
||||
/** @brief Gets an #AislInstance pointer associated with the stream
|
||||
* @param stream an #AislStream instance
|
||||
* @return an #AislInstance pointer
|
||||
*/
|
||||
AislInstance
|
||||
aisl_stream_get_instance(AislStream s);
|
||||
aisl_get_instance(AislStream s);
|
||||
|
||||
|
||||
/** @brief Gets the stream context previously set with #aisl_set_context
|
||||
* @param stream an #AislStream instance
|
||||
* @return a pointer to the stream context
|
||||
*/
|
||||
void *
|
||||
aisl_get_context(AislStream stream);
|
||||
|
||||
|
||||
/** @brief Associate a context pointer with the stream until its lifetime.
|
||||
* Previously allocated data should be free'd on #AISL_EVENT_STREAM_CLOSE if
|
||||
* not needed anymore.
|
||||
* @param stream an #AislStream instance
|
||||
* @param context a pointer to any user-defined data
|
||||
*/
|
||||
void
|
||||
aisl_set_context(AislStream stream, void *context);
|
||||
|
||||
|
||||
/** @brief A call to start stream data transmission to a client
|
||||
* @param stream an #AislStream instance
|
||||
* @return a #AislStatus displaying if stream is ready to be proceed by teh engine
|
||||
*/
|
||||
AislStatus
|
||||
aisl_flush(AislStream stream);
|
||||
|
||||
|
||||
/** @brief A call to reject the stream. In HTTP 1.X it also closes client's connection
|
||||
* @param stream an #AislStream instance
|
||||
*/
|
||||
void
|
||||
aisl_reject(AislStream stream);
|
||||
|
||||
|
||||
/** @brief A call to begin the HTTP response
|
||||
* @param stream an #AislStream instance
|
||||
* @param status_code of the HTTP response
|
||||
* @param content_length in bytes or #AISL_AUTO_LENGTH if length is not knonw yet
|
||||
* @return #AislStatus code
|
||||
*/
|
||||
AislStatus
|
||||
aisl_response(AislStream stream,
|
||||
AislHttpResponse status_code,
|
||||
uint64_t content_length);
|
||||
|
||||
|
||||
/** @brief Adds HTTP header to the stream buffer
|
||||
* @param stream an #AislStream instance
|
||||
* @param key of HTTP header
|
||||
* @param value of HTTP header
|
||||
* @return a length of data added to the stream buffer
|
||||
*/
|
||||
int
|
||||
aisl_header(AislStream stream, const char *key, const char *value );
|
||||
aisl_header(AislStream stream, const char *key, const char *value);
|
||||
|
||||
|
||||
/** @brief Adds printf-like formatted HTTP header to the stream buffer
|
||||
* @param stream an #AislStream instance
|
||||
* @param key of HTTP header
|
||||
* @param format of HTTP header value
|
||||
* @return a length of data added to the stream buffer
|
||||
*/
|
||||
int
|
||||
aisl_header_printf(AislStream stream,
|
||||
const char *key,
|
||||
@@ -73,6 +129,13 @@ aisl_header_printf(AislStream stream,
|
||||
... );
|
||||
|
||||
|
||||
/** @brief Adds vprintf-like formatted HTTP header to the stream buffer
|
||||
* @param stream an #AislStream instance
|
||||
* @param key of HTTP header
|
||||
* @param format of HTTP header value
|
||||
* @param args list for HTTP header value construction
|
||||
* @return a length of data added to the stream buffer
|
||||
*/
|
||||
int
|
||||
aisl_header_vprintf(AislStream stream,
|
||||
const char *key,
|
||||
@@ -80,26 +143,56 @@ aisl_header_vprintf(AislStream stream,
|
||||
va_list args );
|
||||
|
||||
|
||||
/** @brief Adds printf-like formatted HTTP response to the stream buffer
|
||||
* @param stream an #AislStream instance
|
||||
* @param format of the HTTP response
|
||||
* @return a length of data added to the stream buffer
|
||||
*/
|
||||
int
|
||||
aisl_printf(AislStream stream, const char *format, ...);
|
||||
|
||||
|
||||
/** @brief Adds vprintf-like formatted HTTP response to the stream buffer
|
||||
* @param stream an #AislStream instance
|
||||
* @param format of the HTTP response
|
||||
* @param args list for HTTP response construction
|
||||
* @return a length of data added to the stream buffer
|
||||
*/
|
||||
int
|
||||
aisl_vprintf(AislStream stream, const char *format, va_list args);
|
||||
|
||||
|
||||
/** @brief Adds data of the HTTP response to the stream buffer
|
||||
* @param stream an #AislStream instance
|
||||
* @param data a pointer to HTTP response data array
|
||||
* @param d_len size of the HTTP response data array
|
||||
* @return a length of data added to the stream buffer
|
||||
*/
|
||||
int
|
||||
aisl_write(AislStream stream, const char *data, int d_len);
|
||||
|
||||
|
||||
/** @brief Adds a null-terminated string to the stream buffer
|
||||
* @param str_data the HTTP response string
|
||||
* @param stream an #AislStream instance
|
||||
* @return a length of data added to the stream buffer
|
||||
*/
|
||||
int
|
||||
aisl_puts(const char *str_data, AislStream stream);
|
||||
|
||||
|
||||
/** @brief Switches triggering of #AISL_EVENT_STREAM_OUTPUT
|
||||
* @param stream an #AislStream instance
|
||||
* @param value a true to enable or false to disable (default) triggering
|
||||
*/
|
||||
void
|
||||
aisl_set_output_event(AislStream stream, bool value);
|
||||
|
||||
|
||||
/** @brief Gets state of the #AISL_EVENT_STREAM_OUTPUT triggering
|
||||
* @param stream an #AislStream instance
|
||||
* @return true if triggering is enabled and flase otherwise
|
||||
*/
|
||||
bool
|
||||
aisl_get_output_event(AislStream stream);
|
||||
|
||||
|
||||
+51
-33
@@ -20,26 +20,22 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
#define AISL_AUTO_LENGTH (~0)
|
||||
|
||||
/** type casts */
|
||||
#define AISL_CALLBACK(x) ((AislCallback) x)
|
||||
|
||||
|
||||
/** AISL Instance */
|
||||
/** @brief AISL Instance */
|
||||
typedef struct aisl_instance * AislInstance;
|
||||
|
||||
/** HTTP(s) Server */
|
||||
/** @brief HTTP(s) Server */
|
||||
typedef struct aisl_server * AislServer;
|
||||
|
||||
/** HTTP(s) Client */
|
||||
/** @brief HTTP(s) Client */
|
||||
typedef struct aisl_client * AislClient;
|
||||
|
||||
/** Server<->Client Stream */
|
||||
/** @brief Server<->Client Stream */
|
||||
typedef struct aisl_stream * AislStream;
|
||||
|
||||
|
||||
@@ -54,15 +50,16 @@ typedef enum {
|
||||
, AISL_IDLE = 1
|
||||
} AislStatus;
|
||||
|
||||
#ifndef WITHOUT_STRINGIFIERS
|
||||
|
||||
/** @brief Converts #AislStatus code to a null terminated string
|
||||
* @param status an #AislStatus code
|
||||
* @return pointer to the string representing #AislStatus
|
||||
*/
|
||||
const char *
|
||||
aisl_status_to_string(AislStatus status);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/** Generic HTTP Enumerations */
|
||||
/** @brief HTTP version enumeration */
|
||||
typedef enum {
|
||||
AISL_HTTP_0_9 = 0x0009
|
||||
, AISL_HTTP_1_0 = 0x0100
|
||||
@@ -71,10 +68,15 @@ typedef enum {
|
||||
} AislHttpVersion;
|
||||
|
||||
|
||||
/** @brief Converts #AislHttpVersion code to a null terminated string
|
||||
* @param version an #AislHttpVersion code
|
||||
* @return pointer to the string representing #AislHttpVersion
|
||||
*/
|
||||
const char *
|
||||
aisl_http_version_to_string(AislHttpVersion version);
|
||||
|
||||
|
||||
/** HTTP method enumeration */
|
||||
typedef enum {
|
||||
AISL_HTTP_METHOD_UNKNOWN
|
||||
, AISL_HTTP_GET
|
||||
@@ -89,10 +91,15 @@ typedef enum {
|
||||
} AislHttpMethod;
|
||||
|
||||
|
||||
/** @brief Converts #AislHttpMethod code to a null terminated string
|
||||
* @param method an #AislHttpMethod code
|
||||
* @return pointer to the string representing #AislHttpMethod
|
||||
*/
|
||||
const char *
|
||||
aisl_http_method_to_string( AislHttpMethod method );
|
||||
aisl_http_method_to_string(AislHttpMethod method);
|
||||
|
||||
|
||||
/** @brief HTTP response status enumeration */
|
||||
typedef enum {
|
||||
AISL_HTTP_CONTINUE = 100
|
||||
, AISL_HTTP_SWITCHING_PROTOCOLS
|
||||
@@ -142,11 +149,15 @@ typedef enum {
|
||||
} AislHttpResponse;
|
||||
|
||||
|
||||
/** @brief Converts #AislHttpResponse code to a null terminated string
|
||||
* @param code an #AislHttpResponse code
|
||||
* @return pointer to the string representing #AislHttpResponse
|
||||
*/
|
||||
const char *
|
||||
aisl_http_response_to_string( AislHttpResponse code );
|
||||
aisl_http_response_to_string(AislHttpResponse code);
|
||||
|
||||
|
||||
/** Codes of AISL events */
|
||||
/** @brief AISL events enumeration */
|
||||
typedef enum {
|
||||
AISL_EVENT_SERVER_READY = 100
|
||||
, AISL_EVENT_SERVER_ERROR = 190
|
||||
@@ -164,45 +175,52 @@ typedef enum {
|
||||
} AislEvent;
|
||||
|
||||
|
||||
/** @brief generic AISL event structure */
|
||||
struct aisl_evt {
|
||||
void *source;
|
||||
AislEvent code;
|
||||
AislStatus status;
|
||||
void *source; /**< Pointer to an event source: #AislServer, #AislClient, #AislStream */
|
||||
AislEvent code; /**< Event code */
|
||||
AislStatus status; /**< Event status */
|
||||
};
|
||||
|
||||
|
||||
/* void type event callback */
|
||||
/** @brief event handler callback definition
|
||||
* @param evt a pointer to an #aisl_evt structure
|
||||
* @param ctx a pointer to a context defined by user (see #aisl_cfg)
|
||||
*/
|
||||
typedef void
|
||||
(* AislCallback) (const struct aisl_evt *evt, void *ctx);
|
||||
|
||||
|
||||
/** @brief AISL event structue passed on stream opening */
|
||||
struct aisl_evt_open {
|
||||
struct aisl_evt evt;
|
||||
const char *path;
|
||||
const char *query;
|
||||
AislHttpMethod http_method;
|
||||
struct aisl_evt evt; /**< generic #aisl_evt structure */
|
||||
const char *path; /**< HTTP request path */
|
||||
const char *query; /**< HTTP request query (GET params) */
|
||||
AislHttpMethod http_method; /**< HTTP request method */
|
||||
};
|
||||
|
||||
|
||||
/** @brief AISL event structue passed on HTTP header reception */
|
||||
struct aisl_evt_header {
|
||||
struct aisl_evt evt;
|
||||
const char *key;
|
||||
const char *value;
|
||||
struct aisl_evt evt; /**< generic #aisl_evt structure */
|
||||
const char *key; /**< low case HTTP header name */
|
||||
const char *value; /**< HTTP header string */
|
||||
};
|
||||
|
||||
|
||||
/** @brief AISL event structue passed on HTTP request data part received */
|
||||
struct aisl_evt_input {
|
||||
struct aisl_evt evt;
|
||||
const char *data;
|
||||
int32_t size;
|
||||
struct aisl_evt evt; /**< generic #aisl_evt structure */
|
||||
const char *data; /**< a pointer to received data array */
|
||||
int32_t size; /**< data array size */
|
||||
};
|
||||
|
||||
|
||||
#ifndef WITHOUT_STRINGIFIERS
|
||||
|
||||
/** @brief Converts #AislEvent code to a null terminated string
|
||||
* @param evt an #AislEvent code
|
||||
* @return pointer to the string representing #AislEvent
|
||||
*/
|
||||
const char *
|
||||
aisl_event_to_string(AislEvent evt);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !AISL_TYPES_H */
|
||||
|
||||
@@ -12,7 +12,7 @@ PROJECT_NAME = aisl
|
||||
|
||||
PROJECT_VERSION_MAJOR = 1
|
||||
PROJECT_VERSION_MINOR = 0
|
||||
PROJECT_VERSION_TWEAK = 0
|
||||
PROJECT_VERSION_TWEAK = 5
|
||||
PROJECT_VERSION_LABEL = 0
|
||||
|
||||
#SRC_DIR = src
|
||||
@@ -46,15 +46,17 @@ PROJECT_LIBRARIES = \
|
||||
|
||||
|
||||
# compilation macro options:
|
||||
# AISL_WITHOUT_SSL - exclude HTTPS support
|
||||
# AISL_WITHOUT_STRINGIFIERS - exclude several *_to_string functions not
|
||||
|
||||
AISL_WITH_DEBUG ?= 0 # disable debug output
|
||||
AISL_WITH_SSL ?= 1 # enable SSL support
|
||||
AISL_WITH_STRINGIFIERS ?= 1 # enable *_to_string functions
|
||||
|
||||
|
||||
# flags
|
||||
PROJECT_CFLAGS = -D_POSIX_C_SOURCE=200809L
|
||||
#PROJECT_CFLAGS += -DDEBUG
|
||||
#PROJECT_CFLAGS += -DAISL_WITHOUT_SSL
|
||||
#PROJECT_CFLAGS += -DAISL_WITHOUT_STRINGIFIERS
|
||||
|
||||
PROJECT_CFLAGS += -DAISL_WITH_DEBUG=$(AISL_WITH_DEBUG)
|
||||
PROJECT_CFLAGS += -DAISL_WITH_SSL=$(AISL_WITH_SSL)
|
||||
PROJECT_CFLAGS += -DAISL_WITH_STRINGIFIERS=$(AISL_WITH_STRINGIFIERS)
|
||||
|
||||
# PROJECT_LDFLAGS = -L
|
||||
|
||||
@@ -15,20 +15,19 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
#include "buffer.h"
|
||||
|
||||
|
||||
static int32_t
|
||||
buffer_set_size(struct buffer *buffer, int32_t new_size)
|
||||
{
|
||||
if (new_size != buffer->size) {
|
||||
if (!buffer->size || new_size != buffer->size) {
|
||||
char *data;
|
||||
|
||||
if (new_size) {
|
||||
int32_t s = new_size / 1024;
|
||||
|
||||
if ( new_size % 1024 ) {
|
||||
new_size = (s+1) * 1024;
|
||||
if (new_size % 4096) {
|
||||
new_size = (new_size / 4096 + 1) * 4096;
|
||||
}
|
||||
} else {
|
||||
new_size = 16*1024;
|
||||
@@ -49,7 +48,7 @@ buffer_set_size(struct buffer *buffer, int32_t new_size)
|
||||
int32_t
|
||||
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;
|
||||
|
||||
return size;
|
||||
@@ -84,14 +83,14 @@ buffer_move_offset(struct buffer *buffer, int32_t offset, int32_t size)
|
||||
}
|
||||
|
||||
int32_t
|
||||
buffer_insert(struct buffer *buffer,
|
||||
int32_t offset,
|
||||
const char *data,
|
||||
int32_t size)
|
||||
buffer_insert(struct buffer *buffer, int32_t offset, const char *data,
|
||||
int32_t size)
|
||||
{
|
||||
int32_t result;
|
||||
|
||||
if ( (result = buffer_set_size(buffer, size)) != -1) {
|
||||
DPRINTF("Buffer: %d of %d", buffer->used, buffer->size);
|
||||
|
||||
if ( (result = buffer_set_size(buffer, buffer->size + size)) != -1) {
|
||||
if ((result = buffer_move_offset(buffer, offset, size)) != -1) {
|
||||
memcpy(&buffer->data[offset], data, size);
|
||||
buffer->used += result;
|
||||
@@ -118,17 +117,18 @@ buffer_append_printf(struct buffer *buffer, const char *format, ...)
|
||||
int32_t
|
||||
buffer_append_vprintf(struct buffer *buffer, const char *format, va_list args)
|
||||
{
|
||||
DPRINTF("Buffer: %d of %d", buffer->used, buffer->size);
|
||||
int32_t space, result;
|
||||
va_list cp_args;
|
||||
|
||||
va_copy(cp_args, args);
|
||||
space = buffer->size - buffer->used,
|
||||
space = buffer->size - buffer->used;
|
||||
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);
|
||||
result = buffer_set_size(buffer, buffer->size + result - space + 1);
|
||||
if (result != -1)
|
||||
result = buffer_append_vprintf(buffer, format, cp_args);
|
||||
}
|
||||
@@ -140,6 +140,7 @@ buffer_append_vprintf(struct buffer *buffer, const char *format, va_list args)
|
||||
int32_t
|
||||
buffer_append(struct buffer *buffer, const char *data, int32_t size)
|
||||
{
|
||||
DPRINTF("Buffer: %d of %d", buffer->used, buffer->size);
|
||||
int32_t used, space;
|
||||
|
||||
used = buffer->used,
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
@@ -47,13 +47,15 @@ aisl_client_parse(AislClient client, char *data, int32_t size)
|
||||
AislStream s = client->stream;
|
||||
ParserStatus p = HTTP_PARSER_SUCCESS;
|
||||
|
||||
int32_t bytes_left = size;
|
||||
int32_t data_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) {
|
||||
data_size = size;
|
||||
|
||||
switch (aisl_stream_get_state(s)) {
|
||||
case AISL_STREAM_STATE_IDLE:
|
||||
p = http_10_parse_request(data, &size, client->stream);
|
||||
@@ -68,13 +70,13 @@ aisl_client_parse(AislClient client, char *data, int32_t size)
|
||||
break;
|
||||
|
||||
default: /* has input data, but request was already parsed */
|
||||
DPRINTF("misleading request length");
|
||||
p = HTTP_PARSER_ERROR;
|
||||
continue;
|
||||
}
|
||||
// size now has number of parsed bytes
|
||||
data += size;
|
||||
bytes_left -= size;
|
||||
size = bytes_left;
|
||||
DPRINTF("%d bytes parsed, %d bytes left", (data_size - size), size);
|
||||
data += (data_size - size);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -104,8 +106,7 @@ aisl_client_parse(AislClient client, char *data, int32_t size)
|
||||
break;
|
||||
}
|
||||
|
||||
if (size)
|
||||
buffer_shift(&client->in, client->in.used - size); /* reset buffer */
|
||||
buffer_shift(&client->in, client->in.used - size); /* reset buffer */
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -122,7 +123,7 @@ aisl_client_input(AislClient client)
|
||||
char *data = &client->in.data[ client->in.used ];
|
||||
int32_t size = client->in.size - client->in.used;
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
if (client->ssl) {
|
||||
DPRINTF("SSL_read");
|
||||
if (!(client->flags & FLAG_HANDSHAKE)) {
|
||||
@@ -155,7 +156,7 @@ aisl_client_input(AislClient client)
|
||||
return aisl_client_parse(client, data, size);
|
||||
} else if (l<0) {
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
if (client->ssl) {
|
||||
if (SSL_get_error(client->ssl, l) == SSL_ERROR_WANT_READ)
|
||||
return AISL_IDLE;
|
||||
@@ -215,17 +216,16 @@ aisl_client_output(AislClient client)
|
||||
if ( !l )
|
||||
return AISL_IDLE;
|
||||
|
||||
#ifdef AISL_WITHOUT_SSL
|
||||
l = send( client->fd, data, l, 0);
|
||||
#if AISL_WITH_SSL == 1
|
||||
l = (client->ssl) ? SSL_write(client->ssl, data, l) :
|
||||
send(client->fd, data, l, 0);
|
||||
#else
|
||||
l = (client->ssl) ?
|
||||
SSL_write(client->ssl, data, l) :
|
||||
send( client->fd, data, l, 0);
|
||||
l = send(client->fd, data, l, 0);
|
||||
#endif
|
||||
|
||||
if (l > 0) {
|
||||
aisl_stream_shift(s, l);
|
||||
if ( aisl_stream_is_done(s) ) {
|
||||
if (aisl_stream_is_done(s)) {
|
||||
/* data has been sent */
|
||||
if (client->flags & FLAG_KEEPALIVE) {
|
||||
aisl_stream_free(s);
|
||||
@@ -234,8 +234,8 @@ aisl_client_output(AislClient client)
|
||||
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.
|
||||
/* in case of malloc error it will not be an error as long as the
|
||||
* request was handled and we just close the connection.
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ aisl_client_output(AislClient client)
|
||||
}
|
||||
|
||||
/* l < 0 */
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
if (client->ssl) {
|
||||
if (SSL_get_error(client->ssl, l) == SSL_ERROR_WANT_WRITE)
|
||||
return AISL_IDLE;
|
||||
@@ -288,7 +288,7 @@ aisl_client_new(AislServer server, int fd, struct sockaddr_in *addr)
|
||||
client->stream = stream;
|
||||
DPRINTF("client stream alocated");
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
if (server->ssl) {
|
||||
SSL_CTX * ssl_ctx = aisl_get_ssl_ctx(server->instance, NULL);
|
||||
|
||||
@@ -315,7 +315,7 @@ aisl_client_free(AislClient client)
|
||||
{
|
||||
aisl_client_close(client, AISL_SUCCESS);
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
if (client->ssl)
|
||||
SSL_free(client->ssl);
|
||||
#endif
|
||||
@@ -406,10 +406,10 @@ __attribute__ ((visibility ("default") ))
|
||||
bool
|
||||
aisl_client_is_secure(AislClient client)
|
||||
{
|
||||
#ifdef AISL_WITHOUT_SSL
|
||||
return false;
|
||||
#else
|
||||
#if AISL_WITH_SSL == 1
|
||||
return (client->ssl == NULL) ? false : true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#if AISL_WITH_SSL == 1
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
#include <aisl/client.h>
|
||||
#include "buffer.h"
|
||||
|
||||
@@ -29,7 +33,7 @@ struct aisl_client {
|
||||
struct buffer out; /**< Client's output buffer. */
|
||||
AislServer server; /**< Server instance. */
|
||||
AislStream stream; /**< Pending client's stream. */
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
SSL *ssl; /**< SSL pointer for HTTPS. */
|
||||
#endif
|
||||
time_t timestamp; /**< Last communication timestamp. */
|
||||
@@ -16,7 +16,7 @@
|
||||
#ifndef AISL_DEBUG_H_703E22F9_4A6E_426F_B708_81BCA019049B
|
||||
#define AISL_DEBUG_H_703E22F9_4A6E_426F_B708_81BCA019049B
|
||||
|
||||
#ifdef DEBUG
|
||||
#if AISL_WITH_DEBUG == 1
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
+52
-21
@@ -124,12 +124,14 @@ http_10_parse_request(char *data, int32_t *p_size, AislStream stream)
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if (uri && !host)
|
||||
if (uri && !host) {
|
||||
host = data+3;
|
||||
else if (host && !port)
|
||||
} else if (host && !port) {
|
||||
port = data+1;
|
||||
else if (version)
|
||||
} else if (version) {
|
||||
DPRINTF("bad character in HTTP version (%c)", *data);
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case '/':
|
||||
@@ -138,15 +140,18 @@ http_10_parse_request(char *data, int32_t *p_size, AislStream stream)
|
||||
if (!uri)
|
||||
uri = path;
|
||||
} else if (version && data-version != 4) {
|
||||
DPRINTF("wrong HTTP version length");
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
if (!query)
|
||||
if (!query) {
|
||||
query = data+1;
|
||||
else if (version)
|
||||
} else if (version) {
|
||||
DPRINTF("bad character in HTTP version (%c)", *data);
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
@@ -154,54 +159,68 @@ http_10_parse_request(char *data, int32_t *p_size, AislStream stream)
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
if (!version)
|
||||
if (!version) {
|
||||
DPRINTF("unexpected end of HTTP request");
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!uri && method_end)
|
||||
if (!uri && method_end) {
|
||||
uri = data;
|
||||
else if (!version && uri_end)
|
||||
} else if (!version && uri_end) {
|
||||
version = data;
|
||||
else if (version && data-version > 7)
|
||||
} else if (version && data-version > 7) {
|
||||
DPRINTF("bad HTTP version length");
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
/* STEP 2. Verifly splitting was completed */
|
||||
/* STEP 2. Verify splitting was completed */
|
||||
|
||||
/* Was request sent? */
|
||||
if (!newline)
|
||||
return HTTP_PARSER_HUNGRY;
|
||||
|
||||
/* Check mandatory parts presence */
|
||||
if (!method_end || !path || !uri_end || !version)
|
||||
if (!method_end || !path || !uri_end || !version) {
|
||||
DPRINTF("parser error: method=%d, path=%d, uri_end=%d, version=%d",
|
||||
(method_end ? 1 : 0), (path ? 1 : 0), (uri_end ? 1 : 0),
|
||||
(version ? 1: 0));
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
|
||||
*method_end = 0;
|
||||
*newline = 0;
|
||||
*uri_end = 0;
|
||||
|
||||
http_method = http_method_from_string(method, method_end - method);
|
||||
if (http_method == AISL_HTTP_METHOD_UNKNOWN)
|
||||
if (http_method == AISL_HTTP_METHOD_UNKNOWN) {
|
||||
DPRINTF("invalid HTTP method");
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
|
||||
if ((http_version = http_version_from_string(version))==0)
|
||||
if ((http_version = http_version_from_string(version))==0) {
|
||||
DPRINTF("invalid HTTP version");
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
|
||||
if (query) {
|
||||
*(query-1)=0;
|
||||
*(query - 1) = 0;
|
||||
} else {
|
||||
query = uri_end;
|
||||
}
|
||||
|
||||
if (host) {
|
||||
if (strncmp(uri, "http://", 7) || strncmp(uri, "https://", 8))
|
||||
if (strncmp(uri, "http://", 7) || strncmp(uri, "https://", 8)) {
|
||||
DPRINTF("invalid HTTP uri");
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
|
||||
if (port)
|
||||
*(port-1)=0;
|
||||
*(port - 1) = 0;
|
||||
}
|
||||
|
||||
stream->client->http_version = http_version;
|
||||
@@ -210,7 +229,7 @@ http_10_parse_request(char *data, int32_t *p_size, AislStream stream)
|
||||
if (host)
|
||||
aisl_stream_set_header(stream, "host", host);
|
||||
/* how many characters has been read */
|
||||
*(p_size)-=size;
|
||||
*(p_size) = size;
|
||||
return HTTP_PARSER_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -225,6 +244,9 @@ http_10_parse_header(char *data, int32_t *p_size, AislStream stream)
|
||||
*val_end = NULL,
|
||||
*newline = NULL;
|
||||
|
||||
|
||||
DPRINTF("parse header: %p, %d, %02X %02X", data, *p_size, *data & 0xFF, *(data+1) & 0xFF);
|
||||
|
||||
while(!newline && size-- ) {
|
||||
switch(*data) {
|
||||
case ' ':
|
||||
@@ -234,8 +256,10 @@ http_10_parse_header(char *data, int32_t *p_size, AislStream stream)
|
||||
|
||||
case ':':
|
||||
if (!colon) {
|
||||
if (colon == key)
|
||||
if (colon == key) {
|
||||
DPRINTF("parser error: nameless HTTP header");
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
|
||||
colon = data;
|
||||
}
|
||||
@@ -266,17 +290,21 @@ http_10_parse_header(char *data, int32_t *p_size, AislStream stream)
|
||||
if (!newline)
|
||||
return HTTP_PARSER_HUNGRY;
|
||||
|
||||
/* DPRINTF("(%p == %p); *key == 0x%02x", newline, key, *key & 0xFF); */
|
||||
|
||||
if (colon && val && val_end) {
|
||||
*colon = 0;
|
||||
*val_end = 0;
|
||||
aisl_stream_set_header(stream, key, val);
|
||||
*p_size -= size;
|
||||
*p_size = size;
|
||||
return HTTP_PARSER_SUCCESS;
|
||||
} else if (newline == key || (newline == key+1 && *key == '\r')) {
|
||||
*p_size -= size;
|
||||
*p_size = size;
|
||||
DPRINTF("end of headers received");
|
||||
return (aisl_stream_set_end_of_headers(stream) == 0) ?
|
||||
HTTP_PARSER_SUCCESS : HTTP_PARSER_READY;
|
||||
HTTP_PARSER_READY : HTTP_PARSER_SUCCESS;
|
||||
}
|
||||
DPRINTF("parser error: invalid HTTP header");
|
||||
return HTTP_PARSER_ERROR;
|
||||
}
|
||||
|
||||
@@ -289,10 +317,13 @@ http_10_parse_body(char *data, int32_t *p_size, AislStream stream)
|
||||
if (!size)
|
||||
return HTTP_PARSER_HUNGRY;
|
||||
|
||||
*p_size = 0;
|
||||
|
||||
switch (aisl_stream_set_body(stream, data, size)) {
|
||||
case 0:
|
||||
return HTTP_PARSER_READY;
|
||||
case -1:
|
||||
DPRINTF("parser error: invalid HTTP body length");
|
||||
return HTTP_PARSER_ERROR;
|
||||
default:
|
||||
return HTTP_PARSER_SUCCESS;
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "instance.h"
|
||||
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
|
||||
static uint32_t m_instances = 0;
|
||||
|
||||
@@ -89,7 +89,7 @@ aisl_new(const struct aisl_cfg *cfg)
|
||||
goto release;
|
||||
}
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
if ((m_instances++) == 0) {
|
||||
SSL_load_error_strings();
|
||||
OpenSSL_add_ssl_algorithms();
|
||||
@@ -140,7 +140,7 @@ aisl_free(AislInstance instance)
|
||||
|
||||
list_release(&instance->client_spool, (list_destructor_t)aisl_client_free);
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
if (instance->ssl) {
|
||||
struct aisl_ssl **ssl = instance->ssl;
|
||||
|
||||
@@ -159,7 +159,7 @@ aisl_free(AislInstance instance)
|
||||
}
|
||||
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
|
||||
SSL_CTX *
|
||||
aisl_get_ssl_ctx(AislInstance instance, const char * host)
|
||||
@@ -185,10 +185,10 @@ aisl_get_ssl_ctx(AislInstance instance, const char * host)
|
||||
void
|
||||
aisl_raise_evt(AislInstance instance, const struct aisl_evt *evt)
|
||||
{
|
||||
#ifdef AISL_WITHOUT_STRINGIFIERS
|
||||
DPRINTF("! %d", evt->code);
|
||||
#else
|
||||
#if AISL_WITH_STRINGIFIERS == 1
|
||||
DPRINTF("! %s", aisl_event_to_string(evt->code));
|
||||
#else
|
||||
DPRINTF("! %d", evt->code);
|
||||
#endif
|
||||
|
||||
if (instance->callback)
|
||||
@@ -16,7 +16,7 @@
|
||||
#ifndef AISL_INSTANCE_H_814CF474_A646_45B7_B6B2_3F4C7BEFA484
|
||||
#define AISL_INSTANCE_H_814CF474_A646_45B7_B6B2_3F4C7BEFA484
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
struct aisl_instance {
|
||||
AislServer *srv;
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
struct aisl_ssl * *ssl;
|
||||
#endif
|
||||
struct list client_spool;
|
||||
@@ -40,7 +40,7 @@ struct aisl_instance {
|
||||
};
|
||||
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
/**
|
||||
* @brief Gets SSL context for appropriate server name.
|
||||
* @param instance a pointer to #AislInstance instance.
|
||||
@@ -157,7 +157,7 @@ aisl_server_get_address(AislServer server, struct sockaddr_in *address)
|
||||
}
|
||||
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
|
||||
__attribute__ ((visibility ("default") ))
|
||||
bool
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "ssl.h"
|
||||
|
||||
|
||||
#ifndef AISL_WITHOUT_SSL
|
||||
#if AISL_WITH_SSL == 1
|
||||
|
||||
|
||||
static int
|
||||
@@ -24,14 +24,14 @@ static void
|
||||
aisl_stream_reset(AislStream stream, bool initial)
|
||||
{
|
||||
if (!initial) {
|
||||
aisl_raise(aisl_stream_get_instance(stream), (void*) stream,
|
||||
aisl_raise(aisl_get_instance(stream), (void*) stream,
|
||||
AISL_EVENT_STREAM_CLOSE, AISL_SUCCESS);
|
||||
}
|
||||
|
||||
buffer_release(&stream->buffer);
|
||||
|
||||
stream->u_ptr = NULL;
|
||||
stream->content_length = AISL_AUTO_LENGTH;
|
||||
stream->content_length = 0; //AISL_AUTO_LENGTH;
|
||||
stream->head_offset = 0;
|
||||
stream->flags = 0;
|
||||
stream->state = AISL_STREAM_STATE_IDLE;
|
||||
@@ -125,7 +125,7 @@ aisl_stream_set_request(AislStream stream,
|
||||
on_open.path = path;
|
||||
on_open.query = query;
|
||||
|
||||
aisl_raise_evt(aisl_stream_get_instance(stream), (struct aisl_evt *)&on_open);
|
||||
aisl_raise_evt(aisl_get_instance(stream), (struct aisl_evt *)&on_open);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ aisl_stream_set_header(AislStream stream, const char *key, const char *value)
|
||||
on_header.key = key;
|
||||
on_header.value = value;
|
||||
|
||||
aisl_raise_evt(aisl_stream_get_instance(stream),
|
||||
aisl_raise_evt(aisl_get_instance(stream),
|
||||
(struct aisl_evt *) &on_header);
|
||||
}
|
||||
|
||||
@@ -162,9 +162,12 @@ aisl_stream_set_end_of_headers(AislStream stream)
|
||||
{
|
||||
int result;
|
||||
|
||||
DPRINTF("stream->content_length == %"PRIu64"", stream->content_length);
|
||||
|
||||
if (stream->state == AISL_STREAM_STATE_WAIT_HEADER) {
|
||||
stream->state = AISL_STREAM_STATE_WAIT_BODY;
|
||||
result = (stream->content_length == 0);
|
||||
result = (stream->content_length != 0);
|
||||
stream->state = (result) ? AISL_STREAM_STATE_WAIT_BODY :
|
||||
AISL_STREAM_STATE_READY;
|
||||
} else {
|
||||
result = 2;
|
||||
}
|
||||
@@ -241,6 +244,14 @@ aisl_set_context(AislStream s, void *u_ptr)
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((visibility ("default") ))
|
||||
bool
|
||||
aisl_is_secure(AislStream stream)
|
||||
{
|
||||
return aisl_client_is_secure(stream->client);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((visibility ("default") ))
|
||||
AislClient
|
||||
aisl_get_client(AislStream s)
|
||||
@@ -579,7 +590,7 @@ aisl_puts(const char *str, AislStream stream)
|
||||
|
||||
__attribute__ ((visibility ("default") ))
|
||||
AislInstance
|
||||
aisl_stream_get_instance(AislStream stream)
|
||||
aisl_get_instance(AislStream stream)
|
||||
{
|
||||
return stream->client->server->instance;
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <aisl/types.h>
|
||||
|
||||
|
||||
#ifndef WITHOUT_STRINGIFIERS
|
||||
#if AISL_WITH_STRINGIFIERS == 1
|
||||
|
||||
__attribute__ ((visibility ("default") ))
|
||||
const char *
|
||||
Reference in New Issue
Block a user