Страницы

воскресенье, 17 января 2016 г.

Manual socketpair implementation for AF_INET sockets

Here is my manual implementation of socketpair system call that can create AF_INET sockets needed to implement some temporary workaround; don't know is it completely safe and robust, but it is okay for testing purposes.



int inet_socketpair(int type, int protocol, int sv[2])
{
    int lfd;
    int sfd;
    int cfd;
    struct sockaddr_in saddr;
    struct sockaddr_in caddr;
    socklen_t saddrlen;

    /* initialize all fds with -1 to simplify cleanup */
    lfd = -1;
    sfd = -1;
    cfd = -1;

    /* create listening socket and client socket */
    lfd = socket(AF_INET, type, protocol);
    cfd = socket(AF_INET, type, protocol);
    if ((lfd == -1) || (cfd == -1)) {
        goto err;
    }

    /* start listen */
    if (listen(lfd, 1) == -1) {
        goto err;
    }

    /* get ephemeral port number allocated to listening socket */
    memset(&saddr, 0, sizeof(saddr));
    saddrlen = sizeof(saddr);
    if (getsockname(lfd, (struct sockaddr*)&saddr, &saddrlen) == -1) {
        goto err;
    }

    /* prepare server address needed to connect client socket */
    memset(&caddr, 0, sizeof(caddr));
    caddr.sin_family = AF_INET;
    caddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    caddr.sin_port = saddr.sin_port;

    /* connect client socket */
    if (connect(cfd, (struct sockaddr*)&caddr, sizeof(caddr)) == -1) {
        goto err;
    }

    /* accept server socket */
    sfd = accept(lfd, NULL, NULL);
    if (sfd == -1) {
        goto err;
    }

    close(lfd);
    sv[0] = sfd;
    sv[1] = cfd;
    return 0;

err:
    close(lfd);
    close(sfd);
    close(cfd);
    return -1;
}


Комментариев нет: