Giter Site home page Giter Site logo

boazsegev / facil.io Goto Github PK

View Code? Open in Web Editor NEW
2.0K 68.0 134.0 12.16 MB

Your high performance web application C framework

Home Page: http://facil.io

License: MIT License

C 97.41% Makefile 2.34% Shell 0.18% CMake 0.07%
websocket-server http-protocol http-parser c concurrency framework webserver networking websockets pubsub

facil.io's Introduction

GitHub Build Status Codacy Badge codecov

facil.io is a C micro-framework for web applications. facil.io includes:

  • A fast HTTP/1.1 and Websocket static file + application server.
  • Support for custom network protocols for both server and client connections.
  • Dynamic types designed with web applications in mind (Strings, Hashes, Arrays etc').
  • Performant JSON parsing and formatting for easy network communication.
  • A pub/sub process cluster engine for local and Websocket pub/sub.
  • Optional connectivity with Redis.

facil.io provides high performance TCP/IP network services to Linux / BSD (and macOS) by using an evented design (as well as thread pool and forking support) and provides an easy solution to the C10K problem.

You can read more about facil.io on the facil.io website.

Important to Note

The master branch on the git repo is the development branch and is likely to be broken at any given time (especially when working on major revisions, as I am at the moment).

Please select a release version for any production needs.

Who's running on facil.io

An HTTP example

#include "http.h" /* the HTTP facil.io extension */

// We'll use this callback in `http_listen`, to handles HTTP requests
void on_request(http_s *request);

// These will contain pre-allocated values that we will use often
FIOBJ HTTP_X_DATA;

// Listen to HTTP requests and start facil.io
int main(int argc, char const **argv) {
  // allocating values we use often
  HTTP_X_DATA = fiobj_str_new("X-Data", 6);
  // listen on port 3000 and any available network binding (NULL == 0.0.0.0)
  http_listen("3000", NULL, .on_request = on_request, .log = 1);
  // start the server
  facil_start(.threads = 1);
  // deallocating the common values
  fiobj_free(HTTP_X_DATA);
}

// Easy HTTP handling
void on_request(http_s *request) {
  http_set_cookie(request, .name = "my_cookie", .name_len = 9, .value = "data",
                  .value_len = 4);
  http_set_header(request, HTTP_HEADER_CONTENT_TYPE,
                  http_mimetype_find("txt", 3));
  http_set_header(request, HTTP_X_DATA, fiobj_str_new("my data", 7));
  http_send_body(request, "Hello World!\r\n", 14);
}

Using facil.io in your project

It's possible to either start a new project with facil.io or simply add it to an existing one. GNU make is the default build system and CMake is also supported.

facil.io should be C99 compatible.

Starting a new project with facil.io

To start a new project using the facil.io framework, run the following command in the terminal (change appname to whatever you want):

 $ bash <(curl -s https://raw.githubusercontent.com/boazsegev/facil.io/master/scripts/new/app) appname

You can review the script here. In short, it will create a new folder, download a copy of the stable branch, add some demo boiler plate code and run make clean (which is required to build the tmp folder structure).

Next, edit the makefile to remove any generic features you don't need, such as the DUMP_LIB feature, the DEBUG flag or the DISAMS disassembler and start development.

Credit to @benjcal for suggesting the script.

Notice: The master branch is the development branch. Please select the latest release tag for the latest stable release version.

Adding facil.io to an existing project

facil.io is a source code library, so it's easy to copy the source code into an existing project and start using the library right away.

The make libdump command will dump all the relevant files in a single folder called libdump, and you can copy them all or divide them into header ands source files.

It's also possible to compile the facil.io library separately using the make lib command.

Using facil.io as a CMake submodule

facil.io also supports both git and CMake submodules. Credit to @OwenDelahoy (PR#8).

First, add the repository as a submodule using git:

git submodule add https://github.com/boazsegev/facil.io.git

Then add the following line the project's CMakeLists.txt

add_subdirectory(facil.io)

Using facil.io with Meson

facil.io is available at Meson Wrap DB.

First, install the wrap file:

meson wrap install facil

Then add the following line to your project's meson.build:

facil_dep = subproject('facil').get_variable('facil_dep')

More Examples

The examples folder includes code examples for a telnet echo protocol, a Simple Hello World server, an example for Websocket pub/sub with (optional) Redis, etc'.

You can find more information on the facil.io website


Forking, Contributing and all that Jazz

The contribution guide can be found here.

Sure, why not. If you can add Solaris or Windows support to evio and sock, that could mean facil would become available for use on these platforms as well.

If you encounter any issues, open an issue (or, even better, a pull request with a fix) - that would be great :-)

Hit me up if you want to:

  • Write tests... I always need more tests...

  • Help me write HPACK / HTTP2 protocol support.

  • Help me design / write a generic HTTP routing helper library for the http_s struct.

  • If you want to help me write a new SSL/TLS library or have an SSL/TLS solution we can fit into facil (as source code)... Note: SSL/TLS solutions should fit both client and server modes.

  • If you want to help promote the library, that would be great as well. Perhaps publish benchmarks or share your story.

  • Writing documentation into the facil.io website would be great. I keep the source code documentation fairly updated, but the documentation should be copied to the docs folder to get the documentation website up and running.

facil.io's People

Contributors

0xflotus avatar 64 avatar area55git avatar benjcal avatar boazsegev avatar fbrausse avatar gnaneshkunal avatar joeyhoek avatar kradih avatar low-power avatar neshkeev avatar owendelahoy avatar raminfp avatar svenefftinge avatar timgates42 avatar wishdev avatar zweimach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

facil.io's Issues

Support CoAP

CoAP is a protocol used in resource-constrained environments like IoT (see http://coap.technology.) libcoap is a popular C implementation of the protocol and includes a trivial server example. Could libcoap be used with facli.io?

Timers still running after main()

Hi,

I'm having trouble with object lifetimes. My (dumbed down) application looks something like this:

#include <fio.h>

struct my_context { /* ... */ };
void on_timer(void *) { /* ... */ }
void on_finish(void *udata)
{
  struct my_context *ctx = udata;
  do_some_last_thing_with(ctx);
}

int main()
{
  struct my_context ctx;
  init(&ctx);
  fio_run_every(5000, 1, on_timer, &ctx, on_finish);
  fio_start(.threads=1);
  fini(&my_context);
}

I should add, that I link it dynamically to libfacil.so.

When the application is interrupted by e.g. SIGINT, my understanding is that facil.io's custom signal handler will cause fio_start() to return to main. After main the atexit(3) handlers run, including those that call _dl_fini which calls:

static void __attribute__((destructor)) fio_lib_destroy(void) {

Now, there is still the on_timer active and will be shutdown by calling on_finish here:
fio_timer_clear_all();
after main already called fini() on ctx, leading to an access violation in on_finish.

Is this the intended behaviour and, if so, how am I using facil.io in the wrong way? My expectation was that on_finish (and actually the entire shutdown procedures from fio_lib_destroy) would be called before fio_start() returns and not when unloading libfacil.so.

I realize this is relatively easy to fix either by dynamic allocation of ctx and something like reference-counting, or by manually dlopen/dlclose, but I am wondering whether there was a way to avoid both of these. Maybe by exposing some kind of fio_init() and fio_fini(), which I could call around fio_start()?

Please forgive me if this issue is already covered by the documentation, I couldn't find any hint regarding timers or interaction of the .on_unsubscribe callbacks with fio_start() or the shutdown procedure of facil.io.

How to send data image base64 in socket in http?

Hi,

Thanks for repo,

I have a question, How to you convert a image (.png) that is a large character to base64 from clinet side and send data in the socket to server and convert base64 image (.png) of server side in C in facil ? how to handle to buffer large character?

Thanks,

Some strange libs dependencies.

Brief about me. Newbie lnx usr. trying to write C server with blackjack and... saw you lib and it is quite lite.
But i have fail from the start due to dependencies... and i ask you for advise.

from the start, i tried download with script + newapp and typical way.
e.g.

$ wget https://github.com/boazsegev/facil.io/archive/master.zip
$ unzip master.zip
$ cd facil.io-master/
$ ls
CHANGELOG.md    CONTRIBUTING.md  docs      examples  LICENSE   NOTICE     scripts
CMakeLists.txt  dev              Doxyfile  lib       makefile  README.md  tests
# for case
$ make clean
rm: cannot remove 'tmp/demo': No such file or directory
makefile:167: recipe for target 'clean' failed
make: [clean] Error 1 (ignored)
rm: cannot remove 'tmp': No such file or directory
makefile:167: recipe for target 'clean' failed
make: [clean] Error 1 (ignored)

# lets make it from the box. ...i said...
$ make
lib/facil/core/defer.c:56:3: error: unknown type name ‘uint8_t’
   uint8_t state;
   ^
makefile:158: recipe for target 'tmp/./lib/facil/core/defer.o' failed
make: *** [tmp/./lib/facil/core/defer.o] Error 1

#nope said compiler... ver is
$ gcc -v
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.5)

# i assumed fail of #include <sys/types.h>
$ echo "#include <sys/types.h>" | gcc -E -x c - | grep /types.h
1 "/usr/include/x86_64-linux-gnu/sys/types.h" 1 3 4

root@ubuntu-512mb-ams2-01: / vim /usr/include/x86_64-linux-gnu/sys/types.h

# hm... they are without needed types... i guess... strange

$ vim lib/facil/core/defer.c
include <inttypes.h> //add //for test
include <sys/types.h>

$ make

# this should not have happened...
lib/facil/core/types/fiobj/fiobj_str.c: In function ‘fiobj_str_readfile’:
lib/facil/core/types/fiobj/fiobj_str.c:222:45: error: ‘PATH_MAX’ undeclared (first use in this function)
   if (file_path_len == 0 || file_path_len > PATH_MAX)
                                             ^
lib/facil/core/types/fiobj/fiobj_str.c:222:45: note: each undeclared identifier is reported only once for each function it appears in
lib/facil/core/types/fiobj/fiobj_str.c:249:7: warning: implicit declaration of function ‘pread’ [-Wimplicit-function-declaration]
   if (pread(file, obj2str(str)->str, limit, start_at) != (ssize_t)limit) {
       ^
lib/facil/core/types/fiobj/fiobj_str.c:225:8: warning: unused variable ‘real_public_path’ [-Wunused-variable]
   char real_public_path[PATH_MAX + 1];
        ^
makefile:158: recipe for target 'tmp/./lib/facil/core/types/fiobj/fiobj_str.o' failed
make: *** [tmp/./lib/facil/core/types/fiobj/fiobj_str.o] Error 1

# first guess it could be limits...
$ echo "#include <limits.h>" | gcc -E -x c - | grep /limits.h
1 "/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed/limits.h" 1 3 4
1 "/usr/include/limits.h" 1 3 4
1 "/usr/include/linux/limits.h" 1 3 4

# but they present... what is happening... something going wrong...

I don't know why something is wrong with libs and dependencies... or they are different... so i ask you for advise how should i solve this? Do i need do download some extra libs files? Is this something wrong with distro?

I can use facil lib in http protocol response?

Hi @boazsegev ,

I have question! how to i use facil lib in http protocol response for get status response ex: (OK) 200,(forbidden) 404,...,
i saw your http lib but sill i'm not sure, please help,

my means : this is a an example of CURLlib, CURLE_OK == 200 if it's status == 200 in response, you will see printf("OK\n"),

#include <stdio.h>
#include <curl/curl.h>
 
int main(void)
{
  CURL *curl;
  CURLcode res;
 
  curl = curl_easy_init();
  if(curl) {
  
    curl_easy_setopt(curl, CURLOPT_URL, "http://google.com");
    res = curl_easy_perform(curl);
    if(res == CURLE_OK) {
        printf("OK!\n ");
        long response_code;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
    }
    curl_easy_cleanup(curl);
  }
  return 0;
}

Thanks,

What Features do you want to see in fail.io?

I'm in the processes of rewriting many part of the library, including major updates to the HTTP and Pub/Sub design and API, with the intention of making everything as easy to use as can be.

You can have a look at the reHTTP branch to see the work so far.

But now is your chance to vote or suggest any new features you want to see in facil.io.

What features would you prefer (HTTP client? how big should the total HTTP headers length size should be? etc')

What default behaviors would you prefer? (Do you want forked processes to re spawn automatically after a crash or do you prefer a cild process crashing to bring down the while process cluster node?)

Leave comments below.

Attempting to free stack allocated channel_s object

Version 0.7.0.beta8

When building a release with gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 I see the following:

In function ‘fio_channel_free.part.26’,
    inlined from ‘fio_ch_set__insert_or_overwrite_.constprop’,
    inlined from ‘fio_filter_dup_lock_internal’ at lib/facil/fio.h:6127:10,
    inlined from ‘fio_filter_dup_lock’ at lib/facil/fio.c:5383:10,
    inlined from ‘fio_subscribe’ at lib/facil/fio.c:5455:8:
lib/facil/fio.c:5151:3: warning: attempt to free a non-heap object ‘ch’ [-Wfree-nonheap-object]
   free(ch);
   ^~~~~~~~
In function ‘fio_channel_free.part.26’,
    inlined from ‘fio_ch_set__insert_or_overwrite_.constprop’,
    inlined from ‘fio_filter_dup_lock_internal’ at lib/facil/fio.h:6127:10,
    inlined from ‘fio_channel_match_dup_lock.isra.67’ at lib/facil/fio.c:5416:14,
    inlined from ‘fio_subscribe’ at lib/facil/fio.c:5457:8:
lib/facil/fio.c:5151:3: warning: attempt to free a non-heap object ‘ch’ [-Wfree-nonheap-object]
   free(ch);
   ^~~~~~~~
In function ‘fio_channel_free.part.26’,
    inlined from ‘fio_ch_set__insert_or_overwrite_.constprop’,
    inlined from ‘fio_filter_dup_lock_internal’ at lib/facil/fio.h:6127:10,
    inlined from ‘fio_channel_dup_lock.isra.68’ at lib/facil/fio.c:5396:14,
    inlined from ‘fio_subscribe’ at lib/facil/fio.c:5459:8:
lib/facil/fio.c:5151:3: warning: attempt to free a non-heap object ‘ch’ [-Wfree-nonheap-object]
   free(ch);

Build issue

I can't build via make /usr/bin/ld: cannot find /usr/lib64/libasan.so.0.0.0

bash issues under Linux

it works like this under Ubuntu:

bash <(curl -s https://raw.githubusercontent.com/boazsegev/facil.io/master/scripts/new/app) testapp
* Creating testapp
https://api.github.com/repos/boazsegev/facil.io/tarball/v.0.6.0.beta
rm: cannot remove 'src': No such file or directory

next

~/testapp$ make
/bin/sh: 1: Syntax error: Bad fd number
/bin/sh: 1: Syntax error: Bad fd number
/bin/sh: 1: Syntax error: Bad fd number
/bin/sh: 1: Syntax error: Bad fd number

maybe because of >& instead of &> ? Not sure. Just tried once and the output looks a bit weird

High-level description of how this framework works

Hi there!

I found this framework interesting and promising due to its handy API syntax. However, the documentation somewhat confuses me. Well, this is unsurprising because I'm not an expert in Web development anyway. Actually, I have received little formal education in CS, but I know the very basics of TCP thanks to Beej's Guide to Network Programming. In addition, I have previously worked with kcgi, Flask, and Django.

Anyway, from my perspective, both the comments in the header files and the HTML document are enumerating functions without sufficiently stating how they interact with each other as a whole. For example, the HTML document begins with introducing fio_protocol_s which has a lot of on_* callbacks. This part inevitably contains several forward references to stuff like FIO_PR_LOCK_TASK. When working through it I'm totally lost for a while, because I have no idea how the connections and locks are handled by the framework (without reading the rest of the document, which is kinda long and dry).

Personally, I would like to see a high-level description at the very beginning of this documentation, preferably presented with a diagram like the following one. Plain text descriptions like "On startup, we allocate a fio_protocol_s object with malloc and set its callback functions by writing a compound literal. Next, we get a UUID from somewhere. Then we can conveniently attach it to a connection with fio_attach and set up some kind of lock. ..." are also nice to have.

diagram

Function prefixes

First, congratulations for the work!

I was seeing the example usage:

// Listen to HTTP requests and start facil.io
int main(int argc, char const **argv) {
  // allocating values we use often
  HTTP_X_DATA = fiobj_str_new("X-Data", 6);
  // listen on port 3000 and any available network binding (NULL == 0.0.0.0)
  http_listen("3000", NULL, .on_request = on_request, .log = 1);
  // start the server
  facil_run(.threads = 1);
  // deallocating the common values
  fiobj_free(HTTP_X_DATA);
}

And, at least for me, using 3 different prefixes (http, fiobj, facil) appear a bit unintuitive.

What about all prefixes being just http_?

In this way we don't need to remember each functions should use this or that prefix. The learning curve is smaller, and hence the adoption can be bigger.

Just an idea.

Another thing is this line:

FIOBJ HTTP_X_DATA;

Generally in C we use uppercase letters for constants, but this is a variable.

The typedef is also in uppercase. A bit unusual for me.

But this can be less important.

Cheers,

Question about facil.listen() argument

Hi there,
I'm writing a simple websocket server based on a sample from the site.
I needed to change some rows of code to compile, 'cause they have a different prototipes.
In particular
facil_listen(
.port = "7681",
.on_open = create_protocol,
Now create_protocol() is
static inline void create_protocol(intptr_t uuid, void * arg) {
returns nothing and then I'm wondering how to return the pointer to protocol_s structure.
In this way the connection is not possible.
Thanks!

Outdated demo on website

Just wanted to tell you, that you have a bug in demo on your website.

It is under "Simple API (Echo example)" section on "Getting started" page.

This is the compilation log:

a.c: In function ‘create_echo_protocol’:
a.c:45:19: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
.on_close = destroy_echo_protocol,
^~~~~~~~~~~~~~~~~~~~~
a.c:45:19: note: (near initialization for ‘(anonymous).on_close’)

And it really crashes when one tries to close connection to the server.

Consistent Coding Style

I realize this may seem like grasping at straws but spending tons of time programing these things become quite an annoyance. Both Google and Github searches show clearly that ARR instead of ARY is the preferred abbreviation for array. While this would not be a big concern in a vacuum, in combining several libraries remembering that Facil says ARY while all other libs say ARR is frustrating. For these reasons I'm suggesting that for the next major version we should standardize this abbreviation for everyone and grep all ARY/ary replacing with ARR/arr. I am willing to take on this task if we decide to do it...

The biggest concern is that this will impact backwards compatibility. So it needs to be planned instead of just sending a pull request in a vacuum.

Logo Proposal for Facil.io

Hi @boazsegev, I'm a graphic designer and I like to collaborate with open source projects. Do you know that the graphic image of a project is very important? thinking about it I would like to design a logo for your Project Facil.io.

I will be pleased to collaborate with you.
Att
Francisco

Memory leak in example code?

I'm on macOS 10.14 so I cannot use Valgrind to verify my concern, but please take a look here.

// A callback called for new connections
static void echo_on_open(intptr_t uuid, void *udata) {
// Protocol objects MUST be dynamically allocated when multi-threading.
fio_protocol_s *echo_proto = malloc(sizeof(*echo_proto));
*echo_proto = (fio_protocol_s){.on_data = echo_on_data,
.on_shutdown = echo_on_shutdown,
.on_close = echo_on_close,
.ping = echo_ping};
fprintf(stderr, "New Connection %p received from %s\n", (void *)echo_proto,
fio_peer_addr(uuid).data);
fio_attach(uuid, echo_proto);
fio_write2(uuid, .data.buffer = "Echo Service: Welcome\n", .length = 22,
.after.dealloc = FIO_DEALLOC_NOOP);
fio_timeout_set(uuid, 5);
(void)udata; // ignore this
}

On L77, you allocated a chunk of memory for echo_proto, but on the very next line, you point it to a compound literal with automatic storage duration, discarding its previous value. I think this might cause a memory leak because you never called free.

To make thing even more confusing, there appears to be a related compiler bug.

Read content from file descriptor

When request body more then 1024 - it stored data in some tmp file?
May you please explain where i may find this file and how to read data from it
Thank you

Processing of big test frames.

Hi,
i am just testing your websocket library and noticed that when sending big text Frames like this here, the parsing Fails with "ERROR Websockets: unmasked frame, disconnecting."

Is it just for me, or can you also reproduce this on your side?

Thanks for any hints.

bad output in sha1

Hi @boazsegev ,

#18 i use example of README and compiled but i get bad output of program:

[root@raminfp ramin]# make
gcc -Iinclude  src/sha1.c src/sha2.c src/hex.c src/jalali.c src/misc.c src/random.c src/siphash.c src/main.c -o main
[root@raminfp ramin]# 
[root@raminfp ramin]# ./main 
sha1 : /���z-(�턞��v�9����

How to compile facil.io

Hi,

i'm not sure, how to compile facil.io,because on your docs any point about this,

[root@raminfp facil.io]# ls
CHANGELOG.md  CMakeLists.txt  dev  docs  Doxyfile  examples  lib  LICENSE  makefile  NOTICE  README.md  scripts  tests
[root@raminfp facil.io]# 
[root@raminfp facil.io]# make
Assembler messages:
Fatal error: can't create tmp/./lib/core/defer.o: No such file or directory
makefile:114: recipe for target 'tmp/./lib/core/defer.o' failed
make: *** [tmp/./lib/core/defer.o] Error 1

please help for it,

Thanks,
Ramin

Is building on Windows supported?

Hi,

I am currently looking into using this framework on an upcoming project I am trying to finish. I thought that this was a good lighter alternative for a TCP implementation than LibUV.

I am curious about building on Windows. I was able to use cmake with no erroneous output however I also dont see any binaries or headers.

The makefile doesnt seem to support Windows. Am I just way off the beaten path here?

Can we get a more complete explanation for the C11 requirement?

This library is pretty sweet. Thanks for making it!

I'm evaluating the portability of this library. The README made it sound like there are only a few C11 features being used. If it's not too much work it would be great to have support for C99. There are way more compliant compilers for that standard. If that's not going to be an easy task, can the reasons behind that be elaborated more in the README or some other relevant part of the repo?

Thanks :)

Websocket: heavy `on_open` could cause a client's first message to drop

As discovered by @madsheep and @nilclass, detailed in issue iodine#10 here, a client's first message might be lost due to a long on_open.

The issue seems to have been caused by the previous locking scheme, probably by the HTTP layer collecting the data instead of the Websocket.

At this point, the root of the cause is only guesswork. The issue prompted me to fragment the upgrade process (so now the on_open action is deferred), something that was on my internal TODO list for a while.

Along the way, the issue disappeared. I wish I know what was wrong with the previous upgrade locking scheme, so I would be sure the issue is solved and not masked... but it is what it is.

Credit to @madsheep and @nilclass, who did amazing work exposing the issue and tracking it down to the on_open callback.

SSL / TLS library

I know one of the main concerns for SSL/TLS is that it doesn't gonk the license. Most SSL/TLS is sadly CPL cancer which is a problem for keeping facil.io MIT. After a bit of Googling I came upon BearSSL which is MIT and appears to meat the needs of simple, client and server side implementations. Without much overhead in its own right.

https://bearssl.org/index.html

You could either pull it in as a compiled dependency or pull in the bits and pieces of code that you want to salvage without causing license problems. Seems like it might work...

how to use http_connect with keep-alive

I sent http request body with the first time on_response, and process the returned second time on_response body.

so, how can I keep a http client connection alive to reuse the http socket connection to some server? Can I do that? @boazsegev

Thanks

From Project 3: MIT -> ISC

https://github.com/boazsegev/facil.io/projects/3

These are equivalent licenses but ISC has more modern language. For most commercial projects BSD, MIT and ISC licenses are thought of as identical since they each can be included in commercial products ad nauseum.

  • MIT probably has more "brand recognition" than ISC. It is the current favorite of most web frameworks and technologies - so better understood by your target audience.
  • ISC is considered easier to read with more modern legalese.

I'm not sure if you gain anything by switching and may scare off some people in the web world less familiar with the ISC (since it's newer). I try to keep things simple in my projects with either, MIT, LGPL or GPL. These are the household names. BSD gets confusing because they can't decided whether it's 2, 3 or 4 clauses.

Bottomline: I won't waste time on this.

You'll lose more people than you gain on the switch and it doesn't change anything legally other than MIT having more case law because it's an older license...

`strtod` might be unsafe on some systems

facil.io protects the JSON parser and Strings from overflowing during a call to strtod... however, it still appears that strtod calls strlen internally on some systems.

One might have assumed the issue was fixed... however, using my profiler showed distinct calls make from strtod to strlen on some systems (and I hope it was some sort of mistake).

This isn't really safe if the string isn't NUL terminated.

It also wastes CPU cycles when the floating point number is in the middle (rather than the end) of a string.

Rolling an strtod alternative (or copying the buffer to a NUL terminated buffer before parsing the data), should be considered.

It is currently recommended that developers test the strtod implementations and consider overriding the function using safe implementations (when discovering an issue).

Possible bug in start/stop routines

Played with "echo" demo, as found on "Getting started" page (using stable branch with debug symbols).

All runs smoothly, however when I run this demo under valgrind and ^C it, the following errors are reported:

==7444== Memcheck, a memory error detector
==7444== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==7444== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==7444== Command: ./a.out
==7444==
* Listening on port 3000
Server is running 1 worker X 1 thread, press ^C to stop
* 7444 is running.
^C==7444== Invalid read of size 4
==7444==    at 0x12115D: defer_perform_in_fork (defer.c:394)
==7444==    by 0x112DD6: facil_run (facil.c:1069)
==7444==    by 0x1105A8: main (e2.c:53)
==7444==  Address 0x5404cc0 is 0 bytes after a block of size 0 alloc'd
==7444==    at 0x4C2DBC5: calloc (vg_replace_malloc.c:711)
==7444==    by 0x121022: defer_perform_in_fork (defer.c:363)
==7444==    by 0x112DD6: facil_run (facil.c:1069)
==7444==    by 0x1105A8: main (e2.c:53)
==7444==
==7444== Invalid read of size 4
==7444==    at 0x121196: defer_perform_in_fork (defer.c:397)
==7444==    by 0x112DD6: facil_run (facil.c:1069)
==7444==    by 0x1105A8: main (e2.c:53)
==7444==  Address 0x5404cc0 is 0 bytes after a block of size 0 alloc'd
==7444==    at 0x4C2DBC5: calloc (vg_replace_malloc.c:711)
==7444==    by 0x121022: defer_perform_in_fork (defer.c:363)
==7444==    by 0x112DD6: facil_run (facil.c:1069)
==7444==    by 0x1105A8: main (e2.c:53)
==7444==
* 7444 cleanning up.
* (7444) Stopped listening on port 3000

   ---  Completed Shutdown  ---

Probably there is an error there and you should have a look.

unclear how to add openssl support

Hi, i was able to use facil.io as websocket client, now i need tls support and tried to add openssl...

I cloned openssl, compiled it and added the headers to the include search path - but if i include <fio_tls.h> and call fio_tls_s * tls = fio_tls_new("www.example.com", NULL, NULL, NULL); then i get the output:
FATAL: No supported SSL/TLS library available.

i also tried setting some defines i found in the source:

#define HAVE_OPENSSL
#define FIO_TLS_FOUND

#include <http.h>
#include <fio.h>
#include <fio_tls.h>

this did not change anything, unfortunately

Adding a void *udata field to fio_protocol_s

I think it would be nice to have some data private to each connection, just like Flask's request context. The most obvious way to do this is by adding a void *udata field to fio_protocol_s.

A typical use case is attaching a database instance db to each connection, so that during a request, references to db will always refer to the same object. Also, this db instance will be closed automatically at the end of the request with the help of on_close.

Option to not set signal handlers

Since facil is a library, it is unfortunate for it to unconditionally overwrite signal handlers with it's own. The functionality implemented through them seems non-essential and could just as well be triggered through the integrating program (e.g. fio_stop).

It should in any case chain signals to the signal handlers it overwrote, which isn't currently done.

document 0.7 version fio_connect function description is error

/* *****************************************************************************
The connection protocol (use the facil.io API to make a socket and attach it)
***************************************************************************** */

typedef struct {
fio_protocol_s pr;
intptr_t uuid;
void *udata;
void *tls;
void (*on_connect)(intptr_t uuid, void *udata);
void (*on_fail)(intptr_t uuid, void *udata);
} fio_connect_protocol_s;
document description is
image

on_fail callback not found on this web page doc

Strange with keep-alive

Hi, Boaz!
It's again i)
At first off all, i create database prototype based on your library: https://github.com/recoilme/okdb

But some strange things found with flag keep alive(
Then i test with keep-alive - all looks good:
ab -n 1000 -c 200 -k http://127.0.0.1:8888/
Requests per second: 86452

But if i disable keep-alive:
ab -n 1000 -c 200 http://127.0.0.1:8888/
Requests per second: 33.85

I test in on mac and debian with same results.

May be i do something wrong with headers? https://github.com/recoilme/okdb/blob/master/okdb.c (sophia not used for this request)

And i dont may reproduce right now - but i see one time, then i send long value (around 1024 bytes) without keep-alive from curl it dont work

Example request:

curl -v -H "Connection: keep-alive" -X PUT -d "01234567890123456789012345678901234567890123456789012345678901234567890123456901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456701234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" http://127.0.0.1:8888/hello
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8888 (#0)
> PUT /hello HTTP/1.1
> User-Agent: curl/7.38.0
> Host: 127.0.0.1:8888
> Accept: */*
> Connection: keep-alive
> Content-Length: 1021
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 1021 out of 1021 bytes
< HTTP/1.1 200 OK
< Content-Length: 2
< Connection: keep-alive
< Keep-Alive: 1;timeout=5
<
* Connection #0 to host 127.0.0.1 left intact

And last - then i try to reproduce - looks like server down:

./tmp/okdb

Initialized libsock for 512000 sockets, each one requires 32 bytes.
overall ovearhead: 16384000 bytes.
Initialized packet pool for 1024 elements, each one 16424 bytes.
overall buffer ovearhead: 16818176 bytes.
=== Total: 33202176 bytes ===

* Listenning on port 8888
* Running 19 processes X 1 threads.
* [23163] Running.
* [23164] Running.
* [23161] Running.
* [23162] Running.
* [23165] Running.
* [23166] Running.
* [23167] Running.
* [23168] Running.
* [23169] Running.
* [23175] Running.
* [23177] Running.
* [23179] Running.
* [23181] Running.
* [23183] Running.
* [23185] Running.
* [23187] Running.
* [23154] Running.
* [23189] Running.
* [23191] Running.
Segmentation fault

But then i grep - i see some running procces and server proccesed request.

ps aux|grep okdb
vkuliba+ 23161  0.1  0.0 3591948 33572 pts/0   Sl   14:08   0:15 ./tmp/okdb
vkuliba+ 23164  0.1  0.0 3591948 33572 pts/0   Sl   14:08   0:16 ./tmp/okdb
vkuliba+ 23165  0.1  0.0 3591948 33572 pts/0   Sl   14:08   0:17 ./tmp/okdb
vkuliba+ 23167  0.1  0.0 3591948 33572 pts/0   Sl   14:08   0:15 ./tmp/okdb
vkuliba+ 23168  0.1  0.0 3591948 33572 pts/0   Sl   14:08   0:16 ./tmp/okdb
vkuliba+ 23175  0.1  0.0 3591948 33572 pts/0   Sl   14:08   0:16 ./tmp/okdb
vkuliba+ 24072  0.0  0.0  14644  1612 pts/0    S+   16:43   0:00 grep okdb

there are some proplems with fio_str_tmp function

this is my source code

typedef struct table_data{
    char **fields;
    char **value;
}table_data;
char *fields[] = {"id","name","age"};
    char *value[] = {"1","jack","100"};
    insert("users",(table_data){.fields=fields,.value=value}); 
int insert(char *table,table_data data)
{
    int i=0;
    FIOBJ fields = fiobj_str_tmp();
    FIOBJ val = fiobj_str_tmp();
    if (table){
        while (data.fields[i]){
            fiobj_str_write(fields,"`",1);
            fiobj_str_write(fields,data.fields[i],strlen(data.fields[i]));
            fiobj_str_write(fields,"`",1);
            fiobj_str_write(fields,",",1);

            fiobj_str_write(val,"'",1);
            fiobj_str_write(val,data.value[i],strlen(data.value[i]));
            fiobj_str_write(val,"'",1);
            fiobj_str_write(val,",",1);
            i++;
        }
        printf("fields=%s\n",fiobj_obj2cstr(fields).data);
        printf("value=%s\n",fiobj_obj2cstr(val).data);

    }
}

run it shows

fields=`id`,'1',`name`,'jack',`age`,'100',
value=`id`,'1',`name`,'jack',`age`,'100',

Unexpected Numeral and String representation issue when parsing a query

int main(int argc, char const *argv[]) {

    http_listen("80", NULL,
                .on_request = on_http_request,
                .on_upgrade = on_http_upgrade,
                .max_clients=10240,
                .log = 1,
                .public_folder="../web"
    );
    fio_start(.threads = 1, .workers = 1);
    return 0;
} 
static void on_http_request(http_s *h) {
   if (fiobj_type_is(h->params,FIOBJ_T_HASH)){
        if (fiobj_hash_haskey(h->params,fiobj_str_new("name",4))){
            printf("ok=%s\n",fiobj_obj2cstr(fiobj_hash_get(h->params,fiobj_str_new("name",4))).data);
            printf("ok1=%s\n",fiobj_obj2cstr(h->query).data);
        }
    }
}

use postman send a request:
http://ip:port/?name=xbbb&age=100
图片

print result :
图片

图片
图片

1、when name=b or name=x will display 0
2、when name value is 'b' and 'x' will display number value
3、when name value=0b001,value=0100 value=0x11 will display number value

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.