Skip to content

Adopting/transferring in a file descriptor #172

@abrownsword

Description

@abrownsword

For a project I've just been working on, I needed to be able to transfer in a socket that I created outside of uWebSockets/uSockets. I modified loop.c by moving the guts of the accept loop into a new function (us_socket_transfer) which is externally callable. The contents of the accept loop becomes just a call to this function, but if I create an accepted socket elsewhere in my program (transferred from another process, in my case) then I can call this function and the uWS::Loop "adopts" it. I haven't done extensive testing yet (and my code is just for an internal prototype so its not likely to become production code), but it seems to be working well. I thought I would suggest the change in case others might find it useful (I saw one issue mentioning inter-process socket transfers).

int us_socket_transfer(int client_fd, struct us_listen_socket_t *listen_socket, void *internal_addr)
{
    struct bsd_addr_t *addr = (struct bsd_addr_t*)internal_addr;
    struct bsd_addr_t bsd_addr;
    if (addr == NULL)
    {
        addr = &bsd_addr;
        if (bsd_remote_addr(client_fd, &bsd_addr) == -1)
            return -1;
    }

    struct us_poll_t *accepted_p = us_create_poll(us_socket_context(0, &listen_socket->s)->loop, 0, sizeof(struct us_socket_t) - sizeof(struct us_poll_t) + listen_socket->socket_ext_size);
    us_poll_init(accepted_p, client_fd, POLL_TYPE_SOCKET);
    us_poll_start(accepted_p, listen_socket->s.context->loop, LIBUS_SOCKET_READABLE);

    struct us_socket_t *s = (struct us_socket_t *) accepted_p;

    s->context = listen_socket->s.context;
    s->timeout = 0;
    s->low_prio_state = 0;

    /* We always use nodelay */
    bsd_socket_nodelay(client_fd, 1);

    us_internal_socket_context_link(listen_socket->s.context, s);

    listen_socket->s.context->on_open(s, 0, bsd_addr_get_ip(addr), bsd_addr_get_ip_length(addr));

    /* Exit accept loop if listen socket was closed in on_open handler */
    return us_socket_is_closed(0, &listen_socket->s);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions