SCTP Discussions

Text archives Help


[SCTP-Discussion] Test program showing a socketapi quirks.


Chronological Thread 
  • From: Ralph Loader <rcl AT ihug.co.nz>
  • To: discussion AT sctp.de
  • Subject: [SCTP-Discussion] Test program showing a socketapi quirks.
  • Date: Fri Aug 25 23:02:29 2006
  • List-id: SCTP Discussions <discussion.sctp.de>

Hi,

Attached is a test program showing a few quirks with the ext_socket api.

(1) Doing a socket/listen/getsockname [without a bind] the getsockname
fails.

After adding in bind()s to get the program creating associations:

(2) Closing a listen()ing socket seemed to cause problems for sockets
accepted on it.

(3) Doing a shutdown(SHUT_WR) on one end of a connection seemed to cause
a read() on the other end to hang. [It never got as far as testing
poll()...]

Ralph.

On Solaris 10 kernel, the program runs perfectly, it runs OK on Linux
kernel but shows a couple of poll() oddities, on the ext_socket api it
fails pretty badly :-(

// This is a test program to check the SCTP implementation:

// 1.  Is it usable?
// 2.  Does it have quirks such as not notifying poll() correctly.

#include <ext_socket.h>

#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <unistd.h>

template<typename T>
static T check (T value, const char * file, int line, const char * what)
{
    if (value != (T) -1)
        return value;

    fprintf (stderr, "%s:%i: %s: %s\n", file, line, what, strerror (errno));
    abort();
}

#define CHECK(X) (check (X, __FILE__, __LINE__, #X))


static void socket_pair (int & fd1, int & fd2, int proto)
{
    int listn = CHECK (ext_socket (PF_INET, SOCK_STREAM, proto));

    CHECK (ext_listen (listn, SOMAXCONN));

    sockaddr_in addr;
    socklen_t   addr_len = sizeof (addr);

    CHECK (ext_getsockname (listn, (sockaddr *) &addr, &addr_len));
    addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

    fd1 = CHECK (ext_socket (PF_INET, SOCK_STREAM, proto));

    CHECK (ext_connect (fd1, (sockaddr *) &addr, addr_len));

    fd2 = CHECK (accept (listn, NULL, 0));
    CHECK (ext_close (listn));
}



// The scenario:
// 1.  Build a connection.
// 2.  Shutdown one end with shutdown(SHUT_WR).
// 3.  Propagate shutdown.
// 4.  poll() for read should hit.
static bool shutdown_poll_test()
{
    int fd1;
    int fd2;
    socket_pair (fd1, fd2, IPPROTO_SCTP);

    CHECK (ext_shutdown (fd1, SHUT_WR));

    char c;
    int r = CHECK (ext_read (fd2, &c, 1));
    assert (r == 0);
    CHECK (ext_close (fd2));

    pollfd p;
    p.fd = fd1;
    p.events = POLLIN;

    CHECK (ext_poll (&p, 1, 1000));

    CHECK (ext_close (fd1));

    return (p.revents & POLLIN) != 0;
}



// The scenario:
// 1.  Build a connection.
// 2.  Abort one end.
// 4.  poll() for read should hit.
static bool abort_poll_test()
{
    int fd1;
    int fd2;
    socket_pair (fd1, fd2, IPPROTO_SCTP);

    linger l;
    l.l_onoff = 1;
    l.l_linger = 0;
    CHECK (ext_setsockopt (fd2, SOL_SOCKET, SO_LINGER, &l, sizeof (l)));
    CHECK (ext_close (fd2));

    CHECK (sleep (1));

    char c = 0;
    int r = ext_write (fd1, &c, 1);
    // Solaris 10 gives EPIPE not ECONNRESET here...
    assert (r == -1 && (errno == ECONNRESET || errno == EPIPE));

    pollfd p;
    p.fd = fd1;
    p.events = POLLIN;

    CHECK (ext_poll (&p, 1, 1000));

    CHECK (ext_close (fd1));

    return (p.revents & POLLIN) != 0;
}


static bool sctp_usable_test()
{
    int fd = ext_socket (PF_INET, SOCK_STREAM, IPPROTO_SCTP);
    if (fd == -1)
        return false;

    CHECK (ext_close (fd));
    return true;
}


static const char * P (bool b)
{
    return b ? "true" : "false";
}


int main (int argc, const char * const * argv)
{
    CHECK (alarm (60));

    CHECK (signal (SIGPIPE, SIG_IGN));

    bool usable = sctp_usable_test();

    bool shutdown_poll_guess = true;
    bool abort_poll_guess = true;

    printf (
        "// This file was generated by %s.  Do not edit. -*- C++ -*-\n"
        "\n"
        "#ifndef SCTP_QUIRKS_H\n"
        "#define SCTP_QUIRKS_H\n"
        "\n"
        "#define SCTP_USABLE_AT_BUILD %s\n"
        "#define SCTP_SHUTDOWN_POLL_OK %s\n"
        "#define SCTP_ABORT_POLL_OK %s\n"
        "\n"
        "#define SCTP_POLL_OK (SCTP_SHUTDOWN_POLL_OK && SCTP_ABORT_POLL_OK)\n"
        "\n"
        "#endif\n",
        argv[0],
        P (usable),
        P (usable ? shutdown_poll_test() : shutdown_poll_guess),
        P (usable ? abort_poll_test() : abort_poll_guess));

    return 0;
}



Archive powered by MHonArc 2.6.19+.

Top of page