• Oran Agra's avatar
    Merge: Fully abstract connection and make TLS dynamically loadable (#9320) · 41d9eb02
    Oran Agra authored
    There are many commits in this PR, the detailed changes is described
    in each commit message.
    
    ### Main changes in this PR
    
    * Fully abstract connection type, and hide connection type specified methods.
      Ex, currently TLS class looks like:
    ```
    static ConnectionType CT_TLS = {
        /* connection type */
        .get_type = connTLSGetType,
    
        /* connection type initialize & finalize & configure */
        .init = tlsInit,
        .cleanup = tlsCleanup,
        .configure = tlsConfigure,
    
        /* ae & accept & listen & error & address handler */
        .ae_handler = tlsEventHandler,
        .accept_handler = tlsAcceptHandler,
        .addr = connTLSAddr,
        .listen = connTLSListen,
    
        /* create/close connection */
        .conn_create = connCreateTLS,
        .conn_create_accepted = connCreateAcceptedTLS,
        .close = connTLSClose,
    
        /* connect & accept */
        .connect = connTLSConnect,
        .blocking_connect = connTLSBlockingConnect,
        .accept = connTLSAccept,
    
        /* IO */
        .read = connTLSRead,
        .write = connTLSWrite,
        .writev = connTLSWritev,
        .set_write_handler = connTLSSetWriteHandler,
        .set_read_handler = connTLSSetReadHandler,
        .get_last_error = connTLSGetLastError,
        .sync_write = connTLSSyncWrite,
        .sync_read = connTLSSyncRead,
        .sync_readline = connTLSSyncReadLine,
    
        /* pending data */
        .has_pending_data = tlsHasPendingData,
        .process_pending_data = tlsProcessPendingData,
    
        /* TLS specified methods */
        .get_peer_cert = connTLSGetPeerCert,
    };
    
    int RedisRegisterConnectionTypeTLS()
    {
        return connTypeRegister(&CT_TLS);
    }
    ```
    
    * Also abstract Unix socket class. Currently, the connection framework becomes like:
    ```
                           uplayer
                              |
                       connection layer
                         /    |     \
                       TCP   Unix   TLS
        
    ```
    
    * It's possible to build TLS as a shared library (`make BUILD_TLS=module`).
      Loading the shared library(redis-tls.so) into Redis by Redis module subsystem,
      and Redis starts to listen TLS port. Ex:
    ```
        ./src/redis-server --tls-port 6379 --port 0 \
            --tls-cert-file ./tests/tls/redis.crt \
            --tls-key-file ./tests/tls/redis.key \
            --tls-ca-cert-file ./tests/tls/ca.crt \
            --loadmodule src/redis-tls.so
    ```
    
    ### Interface changes
    * RM_GetContextFlags supports a new flag: REDISMODULE_CTX_FLAGS_SERVER_STARTUP
    * INFO SERVER includes a list of listeners:
    ```
    listener0:name=tcp,bind=127.0.0.1,port=6380
    listener1:name=unix,bind=/run/redis.sock
    listener2:name=tls,bind=127.0.0.1,port=6379
    ```
    
    ### Other notes
    
    * Fix wrong signature of RedisModuleDefragFunc, this could break
      compilation of a module, but not the ABI
    * Some reordering of initialization order in server.c:
      * Move initialization of listeners to be after loading the modules
      * Config TLS after initialization of listeners
      * Init cluster after initialization of listeners
    * Sentinel does not support the TLS module or any connection module
      since it uses hiredis for outbound connections, so when TLS is built as
      a module, sentinel lacks TLS support.
    41d9eb02
networking.c 168 KB