From 8ed43da0be2ecb23e66a2354086763223080be13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilja=20Karta=C5=A1ov?= Date: Sun, 16 Jun 2019 22:34:10 +0200 Subject: [PATCH] Add 50% of AISL handbook --- aisl/handbook.html | 933 +++++++++++++++++++++++++++++++++++ aisl/hello-world.jpg | Bin 0 -> 57464 bytes aisl/index.html | 12 +- blog/coding_style_for_c.html | 3 +- static/style.css | 14 +- 5 files changed, 958 insertions(+), 4 deletions(-) create mode 100644 aisl/handbook.html create mode 100644 aisl/hello-world.jpg diff --git a/aisl/handbook.html b/aisl/handbook.html new file mode 100644 index 0000000..6fef746 --- /dev/null +++ b/aisl/handbook.html @@ -0,0 +1,933 @@ + + + + + + + + + + + + + + AISL Handbook + + + + + + + +
+
+ + + + + + + + + +
Löwenware
+
+ + + + +
+

AISL Handbook

+ +

This document describes main concepts and API of AISL library + v.1.0.x.

+

Last update: 2019-06-16

+ +

Table of Contents

+ + +
+ +

AISL Overview

+ +

If you are reading this, either you are somehow already familiar with web + applications and web servers and you probably used to count them as an + independent entities. Indeed, most of the existing web technologies are + based on standalone web server and HTTP parser that together provide some + programming interface to work with cached in memory and on a hard disk HTTP + request. It is not that efficient and sometimes even vulnerable in sence of + DDoS attacks.

+

AISL works differently. Using AISL you can create web application + that is a web server. It means that developer can keep under control all the + workflow of an HTTP stream, by appropriate reactoin on triggered by AISL + programmable events, which is a great performance and security advantage. + For example, application may want to already start some routines to prepare + response, when just first line of the HTTP request like + GET /index.html HTTP/1.1 was received. Or + it may also want to ignore some of the HTTP headers or even full body + content to preserve resources and CPU time, if they are unnecessary + or even unwelcome.

+ +

Features

+
    +
  • Asynchronous event-based engine
  • +
  • Lightweight solution: size of the shared C library is just about 38 + Kbytes.
  • +
  • HTTP 1.x support (support of HTTP 2.0 is planned).
  • +
  • HTTPS support (using openssl).
  • +
  • Free software with open source code.
  • +
  • CC BY-ND 4.0 License.

    +
+ +

Installation

+

One can get AISL sources from GitHub at any time. Master branch is always + stable. To get the Library follow these steps:

+
    +
  1. Clone GIT repositroy$ git clone https://github.com/lowenware/aisl.git
  2. +
  3. Navigate to cloned folder$ cd aisl
  4. +
  5. Compile the library$ make PREFIX=/usr/local LIB_DIR=lib + Set PREFIX to preffered installation path + and LIB_DIR to your system related name of + library directory (lib, lib32 or lib64).
  6. +
  7. Install the library$ sudo make install
  8. +
  9. Optionaly advanced users may want to build library with one or more + options: + AISL_WITH_SSL=0 - disable + HTTPS support, AISL_WITH_STRINGIFIERS=0 - + disable several optional *_to_string functions to preserve library sizea, + AISL_WITH_DEBUG=1 - enable library debug + output.
  10. +
  11. You may also want to edit (if you have changed + PREFIX or LIB_DIR) + and copy libaisl.pc.example file to /usr/lib/pkgconfig, so + pkgconfig could be used to simplify future linking.
  12. +
+ +

Getting started - Hello World

+

If you have AISL installed, it is time to try it out with simple + `Hello World!` application. Full source code could be found on a + GitHub + and the most important steps are highlighted bellow.

+

Include AISL meta-header file to add necessary declarations to you + code file. You should never include other AISL header files in to your + projects.

+ #include + +

In this example we create one HTTP server without encryption, that will + listen to port 8080 on all available network interfaces.

+ struct aisl_cfg_srv[] srv = {{ + .host = "0.0.0.0", + .port = 8080, + .secure = false +}}; + +

To initialize configuration structure we use default values.

+ struct aisl_cfg cfg = AISL_CFG_DEFAULT; + +

An address of the defined servers configuration and their number must be + also stored in the structure.

+ cfg.srv = srv; +cfg.srv_cnt = sizeof (srv) / sizeof (srv[0]); + +

Event handler is a core function of the web application. It should match + AislCallback prototype and its address also + must be stored in the configuration structure before library + initialization.

+ cfg.callback = hello_world; + +

When configuration is ready, it is time to allocate and initialize our + AislInstance and start application loop.

+ AislInstance aisl; +AislStatus status; +... +if ( (aisl = aisl_new(&cfg)) != NULL ) { + /* launch application loop */ + fprintf(stdout, "Entering main loop\n" ); + for(;;) { + status = aisl_run_cycle(aisl); + + if ( status != AISL_SUCCESS ) + aisl_sleep(aisl, 500); + } + aisl_free(aisl); +} else { + fprintf(stderr, "Failed to initialize AISL\n"); +} +

Function aisl_run_cycle being called within + a loop does all the core routines of our HTTP server and triggers event callback + defined in configuration structure. To avoid unnecessary CPU loading we + also execute aisl_sleep on idle cycles. To + release allocated by AISL resources on a runtime we are using + aisl_sleep.

+ +

And finally it is time to define the event handler matching + AislCallback prototype.

+ static void +hello_world(const struct aisl_evt *evt, void *p_ctx) +{ + AislStream s; + + const char html[] = + "<html>" + "<head>" + "<title>Hello World</title>" + "</head>" + "<body>" + "<h1>Hello World</h1>" + "<p>Powered by AISL</p>" + "</body>" + "</html>"; + + if (evt->code != AISL_EVENT_STREAM_REQUEST) + return; + + s = evt->source; + + 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; + } + } + + aisl_reject(s); + (void) p_ctx; +} +

The function is being called by AISL engine on every event, but proceeds + only if AISL_EVENT_STREAM_REQUEST + is received. It starts an HTML response stored in html + constant. Make sure you use sizeof (htmk)-1 for + content length, to avoid unwanted write of last NULL terminating character + of html string constant.

+ +

To compile the example using GCC and pkgconfig run:

+ $ gcc `pkgconf --libs --cflags libaisl` hello-world.c -o hello-world +

Or specify paths to installed header files and library manualy:

+ $ -I/usr/local/include -L/usr/local/lib -laisl hello-world.c -o hello-world + +

Now execute compiled hello_world binary and open http://localhost:8080 in + your browser. If you get any symbol lookup error on execution attempt, + try to specify the path to the library in the environment variable:

+ $ LD_LIBRARY_PATH="/usr/local/lib" ./hello-world +

The result should look like this:

+ + +

Getting advanced

+

Right after this chapter you will find full AISL + API Reference that guides through all the types + and functions. The most significant of them you may already know from the + Hello World example. To become an advanced + AISL developer, you will need to understand events model + and stream concept. The rest of library + components carry more auxiliary function.

+ +

API Reference

+

AISL library API has object oriented model. Although C has no objects, + it still allows to use transparent data structures to represent classes and + functions as methods.

+

Each AISL component has a library specific prefix:

+
    +
  • Aisl* - for data types (typedefs)
  • +
  • aisl_* - for functions and structures names
  • +
  • AISL_* - for constants and macro definitions
  • +
+

Functions, related to some data type (methods), include name of the type in + their names, i.e. AislServer - aisl_server_get_address(). + There are two exceptions from this rule though introduced for simplicity and + shorter names for the functions being used most often: AislInstance + and AislStream.

+ +

Class AislInstance

+

This class represents library engine, that could be dynamically allocated + in memory. It means that you can have several library instances in one application, + though you may never meet a real use case for this.

+

Every instance may handle several independent HTTP servers running on + different network sockets and manages SSL certificates and communication with + clients.

+

Each instance must be configured with proper parameters stored in + aisl_cfg data structure with at least one HTTP + server and event handler matching AislCallback + prototype. + +

Methods

+
aisl_new
+ AislInstance +aisl_new(const struct aisl_cfg *cfg); + +

DESCRIPTION

+

A constructor of AislInstance class.

+

PARAMETERS

+
    +
  • cfg — a pointer to an aisl_cfg configuration + structure
  • +
+

RETURN VALUE

+

Pointer to an AislInstance or NULL if + out of memory.

+ +
aisl_free
+ void +aisl_free(AislInstance instance); +

DESCRIPTION

+

Frees previously allocated pointer of AISL instance.

+

PARAMETERS

+ +

RETURN VALUE

+

Returns no value.

+ +
aisl_run_cycle
+ AislStatus +aisl_run_cycle(AislInstance instance); +

DESCRIPTION

+

+

PARAMETERS

+ +

RETURN VALUE

+ +

Return value handling should be soft. It is completely safe to continue + program execution even if error value was returned.

+

To preserve CPU time it is recommended to add a delay between + aisl_run_cycle calls, at least if anything but + AISL_SUCCESS has been returned. You may want to + use aisl_sleep for this.

+ +
aisl_sleep
+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

Class AislServer

+

Class AislClient

+

Class AislStream

+

Enumeration AislStatus

+

Enumeration AislEvent

+

Enumeration AislHttpVersion

+

Enumeration AislHttpMethod

+

Enumeration AislHttpResponse

+ +

Data Structures

+ +

struct aisl_cfg

+

struct aisl_cfg_ssl

+

struct aisl_cfg_srv

+

struct aisl_evt

+

struct aisl_evt_open

+

struct aisl_evt_header

+

struct aisl_evt_input

+ + +

Events

+ +

AISL_EVENT_SERVER_READY

+

AISL_EVENT_SERVER_ERROR

+

AISL_EVENT_CLIENT_CONNECT

+

AISL_EVENT_CLIENT_DISCONNECT

+

AISL_EVENT_STREAM_OPEN

+

AISL_EVENT_STREAM_HEADER

+

AISL_EVENT_STREAM_INPUT

+

AISL_EVENT_STREAM_REQUEST

+

AISL_EVENT_STREAM_OUTPUT

+

AISL_EVENT_STREAM_CLOSE

+

AISL_EVENT_STREAM_ERROR

+ + +

Functions

+ + + +

aisl_get_server

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ + +

aisl_get_client

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_stream_get_instance

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_is_secure

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ + +

aisl_get_http_version

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_set_context

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_get_context

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_set_output_event

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_get_output_event

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ + +

aisl_response

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_header

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_header_printf

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_header_vprintf

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_printf

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_vprintf

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_write

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_puts

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_flush

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_reject

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ + +

aisl_server_get_instance

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_server_get_address

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_server_get_ssl

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ + +

aisl_client_get_server

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_client_get_address

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_client_get_http_version

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_client_disconnect

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_client_is_secure

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_client_is_online

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ + + +

aisl_status_to_string

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_event_to_string

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_http_version_to_string

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_http_method_to_string

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +

aisl_http_response_to_string

+ +

DESCRIPTION

+

+

PARAMETERS

+
    +
  • +
+

RETURN VALUE

+

+ +
+ +
+ + + + diff --git a/aisl/hello-world.jpg b/aisl/hello-world.jpg new file mode 100644 index 0000000000000000000000000000000000000000..252a9866305662b834b034ba47719ddd1dc66180 GIT binary patch literal 57464 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 literal 0 HcmV?d00001 diff --git a/aisl/index.html b/aisl/index.html index 609c42f..945442c 100644 --- a/aisl/index.html +++ b/aisl/index.html @@ -11,7 +11,7 @@ - AISL Technology + AISL - a lightweight C library for web development @@ -46,7 +46,7 @@
-

AISL Technology

+

AISL - a lightweight C library for web development

AISL is an acronym for Asynchronous Internet Server Library - a C library for web development with built-in lightweight asynchronous HTTP server. It @@ -58,6 +58,14 @@

AISL can power up wide range of applications from small web sites to complex IoT or mobile application backends.

+

Documentation

+

We've combined all necessary information for a quick start and advanced + usage of AISL in a single all-in-one Handbook. + If you are looking for an installation instructions, + Hello World example or full + API reference, it is exactly what + you need.

+

The Technology

AISL is our contribution to faster Internet. In addition to library diff --git a/blog/coding_style_for_c.html b/blog/coding_style_for_c.html index b06c6fc..4130713 100644 --- a/blog/coding_style_for_c.html +++ b/blog/coding_style_for_c.html @@ -50,7 +50,7 @@ (or lack of it) quite often. Programmers, communities, corporations and software foundations may define and follow own rules without (or almost without) any affect on a resulting application work process and efficiency. -Such freedom and flixibility that C language grants to developers is one of its +Such freedom and flexibility that C language grants to developers is one of its greatest adventages and a proof of genius of Dennis Ritchie and Kenneth Thompson.

But what is the right coding style for C?

@@ -72,6 +72,7 @@ this case is a somthing that could really affect the price. So it is worth to follow at least some rules than nothing. Needless to say that for commercial projects, importance of those things goes higher.

+

File Layout

This is one of the most natural language aspects. Almost all developers are following such or similar order:

diff --git a/static/style.css b/static/style.css index acc5c4c..5ad73ca 100644 --- a/static/style.css +++ b/static/style.css @@ -183,12 +183,15 @@ h3, .h3-like { height: auto; } - .double-picture { float: left; width: 50%; height: auto; } + +.shrink-picture { + max-width: 100%; +} /* -------------------------------------------------------------------------- */ .svg-menu-icon .svg-menu-lines , @@ -382,6 +385,11 @@ h3, .h3-like { list-style-type: disc; } +.text-content ul ul{ + padding: 1em 0; + list-style-type: circle; +} + .text-content li { padding: 0 0 0.5em; display: list-item; @@ -391,6 +399,10 @@ h3, .h3-like { font-style: italic; } +.table-of-contents a { + text-decoration: none; +} + /* -------------------------------------------------------------------------- */ .main-content {