lighttpd2

repository·master·Indexed 19 days ago

https://github.com/lighttpd/lighttpd2

An experimental rewrite of the lighttpd web server featuring a complete internal rewrite and a new configuration language/syntax. Not intended for production use. The project includes the lighttpd2 binary, the lighttpd2-worker component, and a C API for managing the server lifecycle via the liServer object, including state machine transitions, socket management, and fetch database registration.

Tokens
3.1K
Snippets
16
Records
19
Agent score
68%

What's inside lighttpd2

  1. Build lighttpd2 from source

    master

    To build lighttpd2 from source, you must first ensure all build dependencies are installed. The build process uses the Meson build system.

    Build Dependencies

    Required:

    • c compiler
    • meson
    • pkg-config
    • libev
    • libidn
    • ragel
    • glib2.0 (>= 2.16)

    Optional:

    • lua >= 5.1 (highly recommended)
    • zlib (for mod_deflate deflate/gzip compression)
    • bzip2 (for mod_deflate bzip2 compression)
    • gnutls (for mod_gnutls)
    • openssl (for mod_openssl)
    # Setup a build directory
    meson setup build --prefix /usr/local
    
    # Compile
    meson compile -C build
    
    # Run tests
    meson test -C build
    
    # Install
    meson install -C build
  2. Manage server state transitions

    master

    The liServer operates as a state machine. You can trigger transitions to a desired state using li_server_goto_state.

    Available States:

    • LI_SERVER_INIT: Initial state.
    • LI_SERVER_LOADING: Loading configuration and preparing plugins.
    • LI_SERVER_SUSPENDED: Server is paused; listening is stopped.
    • LI_SERVER_WARMUP: Transitionary state before running.
    • LI_SERVER_RUNNING: The server is actively processing requests.
    • LI_SERVER_SUSPENDING: Transitionary state towards suspension.
    • LI_SERVER_STOPPING: Transitionary state towards shutdown.
    • LI_SERVER_DOWN: The server has shut down.

    Usage: To move the server towards a specific state (e.g., starting the server), use:

    li_server_goto_state(srv, LI_SERVER_RUNNING);
  3. Register prepare callbacks

    master

    Use li_server_register_prepare_cb to execute logic during the server's initialization phase.

    If the server is already in a running state, the callback is executed immediately. Otherwise, it is queued to run after initialization but before workers are started. If the server has not started, the callback is invoked with aborted = TRUE.

    Callback Signature: void callback(liServer *srv, gpointer data, gboolean aborted)

    void my_prepare_cb(liServer *srv, gpointer data, gboolean aborted) {
        if (aborted) return;
        // Perform initialization tasks
    }
    
    li_server_register_prepare_cb(srv, my_prepare_cb, my_data);
  4. Register a server prepare callback

    master

    Use li_server_register_prepare_cb to register a callback that should be executed during the server's initialization/loading phase.

    If the server is already past the LI_SERVER_INIT state, the callback is executed immediately. Otherwise, it is queued and executed when the server reaches the appropriate state.

    Parameters:

    • srv: The server instance.
    • cb: The callback function of type liServerPrepareCallbackCB.
    • data: User-provided data passed to the callback.
    void my_prepare_callback(liServer *srv, gpointer data, gboolean is_shutting_down) {
        /* initialization logic */
    }
    
    li_server_register_prepare_cb(srv, my_prepare_callback, my_data);
  5. Initialize a new liServer instance

    master

    Use li_server_new to create a new server instance. You must provide the directory where modules are located and specify if modules should be resident in memory.

    Parameters:

    • module_dir: Path to the directory containing server modules.
    • module_resident: A boolean indicating whether modules should be resident.

    Note that the server starts in the LI_SERVER_INIT state and requires further initialization steps like li_server_loop_init to become operational.

    liServer *srv = li_server_new("/path/to/modules", TRUE);
  6. Register and use fetch databases

    master

    The server supports registering custom backends for data fetching via liFetchDatabase.

    • li_server_register_fetch_database(srv, name, db): Registers a database backend with a specific name. Returns TRUE if the database was successfully inserted. This function is thread-safe.
    • li_server_get_fetch_database(srv, name): Retrieves a pointer to a registered liFetchDatabase. This returns a new reference that must be managed by the caller.

    Note: The database must return GString* entries.

  7. Manage server timestamp formats

    master

    The server allows adding custom timestamp formats for logging and other time-based operations using li_server_ts_format_add.

    Signature: guint li_server_ts_format_add(liServer *srv, GString* format)

    gstring *format = gstring_new("%Y-%m-%d %H:%M:%S");
    li_server_ts_format_add(srv, format);
  8. Initialize the server event loop

    master

    Call li_server_loop_init to set up the server's event loop (using libev), initialize the main worker, and set up signal handlers (SIGINT, SIGTERM, SIGPIPE) and timers.

    This must be called after li_server_new and before the server starts transitioning to a running state.

    li_server_loop_init(srv);
  9. Manage server listening sockets

    master

    You can add a file descriptor to the server's listening pool using li_server_listen. This creates a liServerSocket object and adds it to the server's internal socket array.

    Parameters:

    • srv: The server instance.
    • fd: The file descriptor to listen on.

    Returns: A pointer to the newly created liServerSocket.

    If the server is currently in LI_SERVER_RUNNING or LI_SERVER_WARMUP states, the socket will start listening immediately.

    liServerSocket *sock = li_server_listen(srv, listen_fd);
  10. Register and retrieve fetch databases

    master

    The server allows registering liFetchDatabase instances which can be retrieved later by name. This is useful for managing backend data sources.

    Register a database: Use li_server_register_fetch_database. Returns TRUE if successfully inserted, FALSE if a database with that name already exists.

    Retrieve a database: Use li_server_get_fetch_database. Returns a pointer to the liFetchDatabase or NULL if not found. Note that this increments the database's reference count; you must manage its lifecycle accordingly.

    Parameters for registration:

    • srv: The server instance.
    • name: A unique string identifier for the database.
    • db: The liFetchDatabase instance to register.
    // Register
    gboolean ok = li_server_register_fetch_database(srv, "my_db", my_db_ptr);
    
    // Retrieve
    liFetchDatabase *db = li_server_get_fetch_database(srv, "my_db");
    if (db) {
        /* use db */
    }
  11. Configure server listening sockets

    master

    Sockets are managed via the liServerSocket structure. You can register a file descriptor to be listened to by the server using li_server_listen.

    Socket Management

    • li_server_listen(srv, fd): Registers a file descriptor fd as a listening socket for the server. Returns a pointer to the liServerSocket.
    • li_server_socket_acquire(sock): Increments the reference count of a socket.
    • li_server_socket_release(sock): Decrements the reference count of a socket.
    • li_server_socket_release_cb: A callback type used to clean up custom socket data (e.g., SSL contexts) when the socket is released.
    • liConnectionNewCB: A callback type used to handle new connections on a socket. It is called with the liConnection object and the file descriptor.
    liServerSocket *sock = li_server_listen(srv, listen_fd);
    // ... use socket ...
    li_server_socket_release(sock);