< Previous by Date Date Index Next by Date >
  Thread Index Next in Thread >

[reSIProcate] TCP connection failure


AFAICT, there are two failure paths in the TCP code in
TcpBaseTransport::processSomeWries().  Windows returns a
socket exception when a write to a failed connection is
performed.  The Connection is deleted and falls back to the
UDP transport.

OS X and NetBSD don't return a socket exception and
Connection::performWrite() is expected to recognise the
missing connection.  Rather, it crashes on write() or
somewhat later in select().

I haven't found a solution to the problem yet.

It is easy to reproduce.  Try basicRegister (without the
outbound proxy line in the code) and attempt to register to
a proxy with a TCP SRV entry but without TCP support.

Alternatively, here's a unit test to demonstrate the
problem:

#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>

int
main()
{
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        assert(sock > 0);

        int flags = fcntl(sock, F_GETFL, 0);
        int err = fcntl(sock, F_SETFL, flags | O_NONBLOCK
);
        assert(err == 0);

        struct sockaddr_in servAddr;
        memset(&servAddr, 0, sizeof(struct sockaddr_in));
        servAddr.sin_family = AF_INET;
        servAddr.sin_addr.s_addr = htonl(0xc0a80080);
        servAddr.sin_port = htons(5060);

        err = connect(sock, (struct sockaddr*)&servAddr,
sizeof(struct sockaddr_in));
        if (err < 0)
                printf("error %d: %s\n", err,
strerror(errno));

        fd_set wfds;
        fd_set efds;
        FD_ZERO(&wfds);
        FD_ZERO(&efds);
        FD_SET(sock, &wfds);
        FD_SET(sock, &efds);

        err = select(sock+1, NULL, &wfds, &efds, NULL);
        if (err < 0)
                printf("select failed\n");

        if (FD_ISSET(sock, &wfds))
                printf("write set\n");
        if (FD_ISSET(sock, &efds))
                printf("exception set\n");

        char buffer[] = "hello";
        int n = write(sock, buffer, strlen(buffer));
        printf("n == %d\n", n);

        return 0;
}



-- Gregory McGarry <g.mcgarry@xxxxxxxx>

Send instant messages to your online friends http://au.messenger.yahoo.com