Code Monkey home page Code Monkey logo

cio's Introduction

cio - An ANSI C Conformant I/O Library.

License

Copyright (c) 2024 Stephan Gatzka. See the LICENSE file for license rights and limitations (MIT).

FOSSA Status

Build Status

Github action Coverity GitHub license codecov Quality Gate FOSSA Status

Open Hub

Howto Build

Create a build directory and change into it:

mkdir /tmp/cio && cd /tmp/cio

Configure the project using cmake:

cmake -DCMAKE_TOOLCHAIN_FILE=$PWD/toolchains/x86-linux-clang-14.cmake <path/to/cio/src/dir>

Please not that the passage with -DCMAKE_TOOLCHAIN_FILE is optional, if you want to use the build hosts gcc. By default cio is build as a static library. If you want to build a shared library instead, add -DBUILD_SHARED_LIBS=ON to the configuration command line. If you want to speed up the build, choose the Ninja generator by adding -GNinja to the configuration command line.

Then build the project:

cmake --build .

Run the unit test by issueing the following command:

cmake --build . --target test

CI builds

Continuous Integration builds are done using ctest. You can also run them locally. For instance, to run the CI build that gives you the code coverage of the unit test,run:

ctest -S ~/workspace/git/cio/build.cmake -DCTEST_TOOLCHAIN_FILE=toolchains/x86-linux-gcc.cmake -DCTEST_CONFIGURATION_TYPE:STRING=Coverage

Documentation

The generated doxygen documentation can be found here.

cio's People

Contributors

ballenthin avatar fossabot avatar gatzka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

cio's Issues

Test http server

Write unit test with illegal header and where write call in write_header blocks (so effectively goes via the eventloop)

Remove function pointers in structs

It should be possible to write a struct without any function pointers. Then write the "methods" by just prefixing them, i.e. cio_buffered_stream_

In tests this should be also easy to mock.

Use event_fd for to cancel linux eventloop

Currently the Linux eventloop cancel relies on the fact that a signal is delivered in addition.
While this works perfectly when the eventloop cancel is called from a signal handler, it does not work when called from a timer callback, for instance.

cmake: don't use GLOBs

If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.

Remove object oriented stuff

Lot's of functions are called via function pointers sitting in structs. This effectively prevents compilers to perform link time optimization (LTO) and is in general no the most efficient way to do. It also make the structs smaller, so less memory (RAM) is consumed.

The original intention was to make unit testing easier. This is not true (the functions could be easily mocked by the fff).

Add shutdown function to cio_http_server

Implement a shutdown function which closes the server socket used.
The shutdown function should have a "closed" callback.
Use the server sockets close callback to call the "closed" callback.
Rework example http_server to shutdown the server in the signal handler and destroy the eventloop in the "closed" callback.

Unit tests

  • Websockets
    • Perform websocket close() directly in onconnect callback function

Use eventloop error callback on Linux

Currently the error callback int the epoll eventloop implementation is not used.
So if epoll_wait comes out with an event where an error is signaled, this error will not be processed.

  • Rename enum cio_error to cio_socket_error
  • Introduce enum cio_eventloop error
  • try to share CIO_SUCCESS between both enums
  • Rework all callback function hooked into the eventloop accordingly
  • Check socket timeout error with getsockopt in connect_callback, not in epoll_run

Rework close handling in buffered_stream

Closing a stream is currently a mess. The code needs to track the number of currently running reads and write to avoid accessing memory that was already freed.

Simplify check for no callback in http handler

Write function no_user_callback_in_handler in cio_http_location_handler.

Use this function in cio_http_server on_url to check and send responses. Eliminate User_handler flag in on_url.

Improve socket close

Web browser (namely Chrome and it's derivatives) do not perform a nice socket close. If you have a http connection with keepalive, cio closes the TCP connection after a certain timeout. cio correctly sends a FIN packet. The OS Chrome runs on ACKs the FIN, but Chrome does not send a FIN to close down it's own socket.
This leaves the socket quite long in FIN_WAIT_2 state on the cio side, which effectively prevents freeing resources associated with that socket.

A solution in cio might shutdown with SHUT_WR, keep reading until read() returns 0 (close from the other side). This read is monitored by a timeout. If the timeout occurs, a connection reset (TCP RST) is performed. This can be done by enabling the linger, setting the linger timeout to 0 and then closing the socket.

Unify test names.

Platform independent test are named:
cio_test_http_server

platform specific tests are name:
test_cio_linux_timer

rework websocket / http interaction

  • take out struct cio_http_client *client from struct cio_http_location_handler
  • take out bs, rb, loop from ws_private structure
  • rework close_server_websocket to use client pointer from websocket structure

Optimize writing in buffered_stream

Currently the writebuffer_heads are always copied before sending the data.

This could be optimized to copy only if not all data was sent.
Check with: valgrind --tool=callgrind ./examples/linux/uds_socket_ping_pong 1000000

Add cio_http_init test

Test that free handler of cio_http_location_hander is called if accept in cio_http_server fails (for instance because a timer could not be started).

Improve memory consumption for binary websocket messages.

Currently the read buffer in struct cio_http_client must be at least big enough to hold a complete binary/text message.

This is not necessary. IF we introduce a function read_at_most() in buffered_stream we can use this function when reading the payload of a websocket message and call the handler in read_message always if some data arrives.

Care must be taken that we do not read more data then announced via the websocket frame length.

The autobahn test server code should then run with just 1kbyte of buffer memory.

cio_httpserver unit test

  • Ensure correct keepalive handling if no handler for an URL was found and a correct request comes afterwards. So the test should receive a request with header and body which should be answered with 404. The client is not closed now. Then a second request comes in which should be answered with 200.

  • response_written within the context of on_message_complete (write succeeds immediately)

  • response_written comes after on_message_complete (write was blocked in socket write)

Handle http timeouts correctly.

If the http server sees an header/body timeout it should:

  • Rename read_header_timer to something that shows that this timer is used to check header and body
  • Send a response message with status code 408 (Request Timeout) even without a request coming in
  • the timeout message header should include the "Connection: close" field.
  • The TCP connection must be closed after the response message was sent.

Add read and write timeouts to http server

Some browsers (namely chrome) open multiple TCP connections and use only one. This currently leads to a memory leak because the memory allocated in alloc_http_client is never freed (because the socket connection is never closed).

Limit number of open http connections.

Should be done globally in http-server to prevent DOS as early as possible.
Two options:

  • Immediately close the socket connection after accept.
  • Close the server socket if above limit and reopen again if below limit.

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.