// 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+.