From: g0dil Date: Thu, 15 Feb 2007 16:49:26 +0000 (+0000) Subject: Fix TCPv6 SocketHandle and INet6Address X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=e9230af25004d2e3eb041778afc493c5b300c43b;p=senf.git Fix TCPv6 SocketHandle and INet6Address Complete TCPv6 unit testing git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@201 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Socket/INetAddressing.test.cc b/Socket/INetAddressing.test.cc index 2b8f9d3..b19990a 100644 --- a/Socket/INetAddressing.test.cc +++ b/Socket/INetAddressing.test.cc @@ -141,10 +141,10 @@ BOOST_AUTO_UNIT_TEST(inet6Address) BOOST_CHECK_EQUAL( addr.port(), 100u ); addr.host("::2"); BOOST_CHECK_EQUAL( addr.host(), "::2" ); - BOOST_CHECK_THROW( addr.address(""), InvalidINetAddressException ); - BOOST_CHECK_THROW( addr.address("[::1]"), InvalidINetAddressException ); - BOOST_CHECK_THROW( addr.address("[::1]1234"), InvalidINetAddressException ); - addr.address("[12::21@lo]:12345"); + BOOST_CHECK_THROW( addr = "", InvalidINetAddressException ); + BOOST_CHECK_THROW( addr = "[::1]", InvalidINetAddressException ); + BOOST_CHECK_THROW( addr = "[::1]1234", InvalidINetAddressException ); + addr = "[12::21@lo]:12345"; BOOST_CHECK_EQUAL( addr.address(), "[12::21@lo]:12345" ); BOOST_CHECK_EQUAL( addr.host(), "12::21" ); BOOST_CHECK_EQUAL( addr.port(), 12345u ); diff --git a/Socket/TCPSocketHandle.cc b/Socket/TCPSocketHandle.cc index 3023e2a..de4b0d4 100644 --- a/Socket/TCPSocketHandle.cc +++ b/Socket/TCPSocketHandle.cc @@ -97,7 +97,7 @@ prefix_ void senf::TCPv6SocketProtocol::init_client() } prefix_ void -senf::TCPv6SocketProtocol::init_client(INet6Address const & address) +senf::TCPv6SocketProtocol::init_client(INet6SocketAddress const & address) const { init_client(); @@ -107,14 +107,14 @@ senf::TCPv6SocketProtocol::init_client(INet6Address const & address) prefix_ void senf::TCPv6SocketProtocol::init_server() const { - int sock = ::socket(PF_INET,SOCK_STREAM,0); + int sock = ::socket(PF_INET6,SOCK_STREAM,0); if (sock < 0) throw SystemException(errno); body().fd(sock); } -prefix_ void senf::TCPv6SocketProtocol::init_server(INet6Address const & address, - unsigned backlog) +prefix_ void senf::TCPv6SocketProtocol::init_server(INet6SocketAddress const & address, + unsigned backlog) const { init_server(); diff --git a/Socket/TCPSocketHandle.hh b/Socket/TCPSocketHandle.hh index f94e439..47163b0 100644 --- a/Socket/TCPSocketHandle.hh +++ b/Socket/TCPSocketHandle.hh @@ -168,6 +168,7 @@ namespace senf { public BSDSocketProtocol, public AddressableBSDSocketProtocol { + public: /////////////////////////////////////////////////////////////////////////// // internal interface @@ -178,7 +179,7 @@ namespace senf { /**< \note This member is implicitly called from the ProtocolClientSocketHandle::ProtocolClientSocketHandle() constructor */ - void init_client(INet4Address const & address) const; + void init_client(INet6SocketAddress const & address) const; ///< Create client socket and connect /**< Creates a new client socket and connects to the given address. @@ -191,7 +192,7 @@ namespace senf { /**< \note This member is implicitly called from the ProtocolServerSocketHandle::ProtocolServerSocketHandle() constructor */ - void init_server(INet4Address const & address, unsigned backlog=1) const; + void init_server(INet6SocketAddress const & address, unsigned backlog=1) const; ///< Create server socket and listen /**< Creates a new server socket, binds to \a address end starts listening for new connections with a backlog of diff --git a/Socket/TCPSocketHandle.test.cc b/Socket/TCPSocketHandle.test.cc index ac9d2d8..8bf17fc 100644 --- a/Socket/TCPSocketHandle.test.cc +++ b/Socket/TCPSocketHandle.test.cc @@ -45,12 +45,12 @@ namespace { void error(char const * fn, char const * proc="") { - std::cerr << "\n" << proc << fn << ": " << strerror(errno) << std::endl; + std::cerr << "\n" << proc << ((*proc)?": ":"") << fn << ": " << strerror(errno) << std::endl; } - void fail(char const * fn) + void fail(char const * proc, char const * fn) { - error(fn,"server: "); + error(fn,proc); _exit(1); } @@ -76,8 +76,11 @@ namespace { void stop() { - kill(server_pid,9); - wait(); + if (server_pid) { + kill(server_pid,9); + wait(); + server_pid = 0; + } } } @@ -86,21 +89,22 @@ namespace { namespace { - void server() + void server_v4() { int serv = socket(PF_INET,SOCK_STREAM,0); - if (serv<0) fail("socket()"); + if (serv<0) fail("server_v4","socket()"); int v = 1; if (setsockopt(serv,SOL_SOCKET,SO_REUSEADDR,&v,sizeof(v))<0) - fail("setsockopt()"); + fail("server_v4","setsockopt()"); struct sockaddr_in sin; + ::memset(&sin,0,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(12345); sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - if (bind(serv,(struct sockaddr *)&sin,sizeof(sin))<0) fail("bind()"); - if (listen(serv,1)<0) fail("listen()"); + if (bind(serv,(struct sockaddr *)&sin,sizeof(sin))<0) fail("server_v4","bind()"); + if (listen(serv,1)<0) fail("server_v4","listen()"); int sock = accept(serv,0,0); - if (sock < 0) fail("accept()"); + if (sock < 0) fail("server_v4","accept()"); char buffer[1024]; while (1) { @@ -110,9 +114,39 @@ namespace { write(sock,buffer,n); } - if (shutdown(sock, SHUT_RDWR) < 0) fail("shutdown()"); - if (close(sock) < 0) fail("close()"); - if (close(serv) < 0) fail("close()"); + if (shutdown(sock, SHUT_RDWR) < 0) fail("server_v4","shutdown()"); + if (close(sock) < 0) fail("server_v4","close()"); + if (close(serv) < 0) fail("server_v4","close()"); + } + + void server_v6() + { + int serv = socket(PF_INET6,SOCK_STREAM,0); + if (serv<0) fail("server_v6","socket()"); + int v = 1; + if (setsockopt(serv,SOL_SOCKET,SO_REUSEADDR,&v,sizeof(v))<0) + fail("server_v6","setsockopt()"); + struct sockaddr_in6 sin; + ::memset(&sin,0,sizeof(sin)); + sin.sin6_family = AF_INET6; + sin.sin6_port = htons(12345); + sin.sin6_addr = in6addr_loopback; + if (bind(serv,(struct sockaddr *)&sin,sizeof(sin))<0) fail("server_v6","bind()"); + if (listen(serv,1)<0) fail("server_v6","listen()"); + int sock = accept(serv,0,0); + if (sock < 0) fail("server_v6","accept()"); + + char buffer[1024]; + while (1) { + int n = read(sock,buffer,1024); + if (n == 4 && strncmp(buffer,"QUIT",4) == 0) + break; + write(sock,buffer,n); + } + + if (shutdown(sock, SHUT_RDWR) < 0) fail("server_v6","shutdown()"); + if (close(sock) < 0) fail("server_v6","close()"); + if (close(serv) < 0) fail("server_v6","close()"); } } @@ -126,8 +160,9 @@ BOOST_AUTO_UNIT_TEST(tcpv4ClientSocketHandle) BOOST_CHECK_THROW( sock.protocol().connect("127.0.0.1:12345"), senf::SystemException ); } - { - start(server); + try { + alarm(10); + start(server_v4); senf::TCPv4ClientSocketHandle sock; BOOST_CHECK_NO_THROW( sock.bind("127.0.0.1:23456") ); BOOST_CHECK_NO_THROW( sock.connect("127.0.0.1:12345") ); @@ -150,6 +185,13 @@ BOOST_AUTO_UNIT_TEST(tcpv4ClientSocketHandle) BOOST_CHECK_EQUAL( sock.read(), "" ); BOOST_CHECK( sock.eof() ); BOOST_CHECK( !sock ); + alarm(0); + } catch (...) { + alarm(0); + sleep(1); + stop(); + sleep(1); + throw; } { @@ -182,20 +224,80 @@ BOOST_AUTO_UNIT_TEST(tcpv4ClientSocketHandle) } } +BOOST_AUTO_UNIT_TEST(tcpv6ClientSocketHandle) +{ + { + senf::TCPv6ClientSocketHandle sock; + + BOOST_CHECK_THROW( sock.connect(senf::INet6SocketAddress("[::1]:12345")), senf::SystemException ); + BOOST_CHECK_THROW( sock.protocol().connect("[::1]:12345"), senf::SystemException ); + } + + try { + alarm(10); + start(server_v6); + senf::TCPv6ClientSocketHandle sock; + BOOST_CHECK_NO_THROW( sock.bind("[::1]:23456") ); + BOOST_CHECK_NO_THROW( sock.connect("[::1]:12345") ); + BOOST_CHECK( sock.peer() == "[::1]:12345" ); + BOOST_CHECK( sock.local() == "[::1]:23456" ); + BOOST_CHECK( sock.blocking() ); + BOOST_CHECK_NO_THROW( sock.rcvbuf(2048) ); + BOOST_CHECK_EQUAL( sock.rcvbuf(), 2048u ); + BOOST_CHECK_NO_THROW( sock.sndbuf(2048) ); + BOOST_CHECK_EQUAL( sock.sndbuf(), 2048u ); + BOOST_CHECK_NO_THROW( sock.write("TEST-WRITE") ); + BOOST_CHECK_EQUAL( sock.read(), "TEST-WRITE" ); + // this fails with ENOFILE ... why ???? + // BOOST_CHECK_NO_THROW( sock.protocol().timestamp() ); + BOOST_CHECK( !sock.eof() ); + sock.write("QUIT"); + sleep(1); + stop(); + sleep(1); + BOOST_CHECK_EQUAL( sock.read(), "" ); + BOOST_CHECK( sock.eof() ); + BOOST_CHECK( !sock ); + alarm(0); + } catch (...) { + alarm(0); + sleep(1); + stop(); + sleep(1); + throw; + } + + { + senf::TCPv6ClientSocketHandle sock; + + // The following setsockopts are hard to REALLY test ... + BOOST_CHECK_NO_THROW( sock.protocol().nodelay(true) ); + BOOST_CHECK( sock.protocol().nodelay() ); + BOOST_CHECK_EQUAL( sock.protocol().siocinq(), 0u ); + BOOST_CHECK_EQUAL( sock.protocol().siocoutq(), 0u ); + + BOOST_CHECK_NO_THROW( sock.protocol().reuseaddr(true) ); + BOOST_CHECK( sock.protocol().reuseaddr() ); + BOOST_CHECK_NO_THROW( sock.protocol().linger(true,0) ); + BOOST_CHECK( sock.protocol().linger() == std::make_pair(true, 0u) ); + } +} + /////////////////////////////////////////////////////////////////////////// namespace { - void client() + void client_v4() { int sock = socket(PF_INET,SOCK_STREAM,0); - if (sock<0) fail("socket()"); + if (sock<0) fail("client_v4","socket()"); struct sockaddr_in sin; + ::memset(&sin,0,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(12346); sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (connect(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0) - fail("connect()"); + fail("client_v4","connect()"); char buffer[1024]; while (1) { @@ -205,19 +307,44 @@ namespace { write(sock,buffer,n); } - if (shutdown(sock, SHUT_RDWR) < 0) fail("shutdown()"); - if (close(sock) < 0) fail("close()"); + if (shutdown(sock, SHUT_RDWR) < 0) fail("client_v4","shutdown()"); + if (close(sock) < 0) fail("client_v4","close()"); + } + + void client_v6() + { + int sock = socket(PF_INET6,SOCK_STREAM,0); + if (sock<0) fail("client_v6","socket()"); + struct sockaddr_in6 sin; + ::memset(&sin,0,sizeof(sin)); + sin.sin6_family = AF_INET6; + sin.sin6_port = htons(12347); + sin.sin6_addr = in6addr_loopback; + if (connect(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0) + fail("client_v6","connect()"); + + char buffer[1024]; + while (1) { + int n = read(sock,buffer,1024); + if (n == 4 && strncmp(buffer,"QUIT",4) == 0) + break; + write(sock,buffer,n); + } + + if (shutdown(sock, SHUT_RDWR) < 0) fail("client_v6","shutdown()"); + if (close(sock) < 0) fail("client_v6","close()"); } } BOOST_AUTO_UNIT_TEST(tcpv4ServerSocketHandle) { - { + try { + alarm(10); BOOST_CHECKPOINT("Opening server socket"); senf::TCPv4ServerSocketHandle server ("127.0.0.1:12346"); BOOST_CHECKPOINT("Starting client"); - start(client); + start(client_v4); BOOST_CHECKPOINT("Accepting connection"); senf::TCPv4ClientSocketHandle client = server.accept(); @@ -226,6 +353,39 @@ BOOST_AUTO_UNIT_TEST(tcpv4ServerSocketHandle) BOOST_CHECKPOINT("Stopping client"); sleep(1); stop(); + alarm(0); + } catch (...) { + alarm(0); + sleep(1); + stop(); + sleep(1); + throw; + } +} + +BOOST_AUTO_UNIT_TEST(tcpv6ServerSocketHandle) +{ + try { + alarm(10); + BOOST_CHECKPOINT("Opening server socket"); + senf::TCPv6ServerSocketHandle server ("[::1]:12347"); + BOOST_CHECKPOINT("Starting client"); + start(client_v6); + + BOOST_CHECKPOINT("Accepting connection"); + senf::TCPv6ClientSocketHandle client = server.accept(); + BOOST_CHECK_NO_THROW(client.write("QUIT")); + + BOOST_CHECKPOINT("Stopping client"); + sleep(1); + stop(); + alarm(0); + } catch (...) { + alarm(0); + sleep(1); + stop(); + sleep(1); + throw; } }