//============================================================================== // // Copyright (C) 2004 Dick van Oudheusden // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this program; if not, write to the Free // Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // //============================================================================== // // $Date: 2006/08/21 17:10:20 $ $Revision: 1.13 $ // //============================================================================== #include #include #include "ofc/config.h" #include "ofc/DSocket.h" #include "ofc/DTimer.h" #include "DTest.h" #define WITH_THREADS //-Wrapper--------------------------------------------------------------------- @interface SocketTester : Object { } - init; - TCPServer; - TCPClient; #ifndef WIN32 - UDPServer; - UDPClient; #endif @end @implementation SocketTester //---------------------------------------------------------------------------- - init { [super init]; return self; } //---------------------------------------------------------------------------- - TCPServer { DSocket *local = [DSocket new]; DSocket *peer = nil; DInetSocketAddress *address = [DInetSocketAddress new]; [address any :7000]; TEST([local open :[address family] :DSK_STREAM :[DSocket protocol :"tcp"]]); // printf("Server.Open: %d\n", [local error]); TEST([local reuseAddr :YES]); TEST([local bind :address]); // printf("Server.Bind: %d\n", [local error]); TEST([local listen :5]); // printf("Server.Listen: %d\n", [local error]); peer = [local accept]; // printf("Server.Accept: %d\n", [local error]); TEST(peer != nil); if (peer != nil) { DData *data = [peer recv :50 :0]; TEST(data != nil); if (data != nil) { // printf("Server.Receive: %s\n", [data data]); TEST([data bcompare :"Hello there.." :14] == 0); [data free]; } // printf("Server.Send: %d - %d\n", [peer send :"Going to exit.." :16 :0], [peer error]); TEST([peer send :"Going to exit.." :16 :0] == 16); TEST([peer close]); [peer free]; } TEST([local close]); [local free]; [address free]; #ifdef WITH_THREADS objc_thread_exit(); #endif return self; } //---------------------------------------------------------------------------- - TCPClient { DSocket *local = [DSocket new]; DInetSocketAddress *address = [DInetSocketAddress new]; BOOL connected = NO; [DTimer delay :50]; // small delay for the server to start up [address loopback :7000]; TEST([local open :[address family] :DSK_STREAM :[DSocket protocol :"tcp"]]); // printf("Client.Open: %d\n", [local error]); TEST([local reuseAddr :YES]); connected = [local connect :address]; // printf("Client.Connected: %d\n", [local error]); TEST(connected); if (connected) { DData *data = nil; TEST([local send :"Hello there.." :14 :0] == 14); // printf("Client.Send: %d - %d\n", [local send :"Hello there.." :14 :0], [local error]); data = [local recv :50 :0]; TEST(data != nil); if (data != nil) { // printf("Client.Received: %s - %ld\n", [data data], [data length]); TEST([data bcompare :"Going to exit.." :16] == 0); [data free]; } TEST([local shutdown :DSK_SHUT_RDWR]); TEST([local close]); } [local free]; [address free]; #ifdef WITH_THREADS objc_thread_exit(); #endif return self; } //---------------------------------------------------------------------------- #ifndef WIN32 - UDPServer { DSocket *local = [DSocket new]; DUnixSocketAddress *address = [DUnixSocketAddress new]; DUnixSocketAddress *peer = [DUnixSocketAddress new]; DData *data = nil; [address filename :"udp1"]; //printf("Open family: %d\n", [address family]); TEST([local open :[address family] :DSK_DGRAM :0]); //printf("Server.Open: %d\n", [local error]); TEST([local bind :address]); //printf("Server.Bind: %d\n", [local error]); data = [local recvfrom :peer :50 :0]; TEST([[peer host] ccompare :"udp2"] == 0); //printf("Peername: %s\n", [[peer host] cstring]); TEST(data != nil); if (data != nil) { //printf("Server.Receive: %s\n", [data data]); TEST([data bcompare :"Hello there.." :14] == 0); [data free]; } // printf("Server.Send: %d - %d\n", [local sendto :peer :"Going to exit.." :16 :0], [local error]); TEST([local sendto :peer :"Going to exit.." :16 :0] == 16); TEST([local close]); [address close]; [local free]; [address free]; [peer free]; #ifdef WITH_THREADS objc_thread_exit(); #endif return self; } //---------------------------------------------------------------------------- - UDPClient { DSocket *local = [DSocket new]; DUnixSocketAddress *address = [DUnixSocketAddress new]; DUnixSocketAddress *peer = [DUnixSocketAddress new]; DData *data = nil; [DTimer delay :50]; // small delay for the server to start up [address filename :"udp2"]; [peer filename :"udp1"]; TEST([local open :[address family] :DSK_DGRAM :0]); //printf("Client.Open: %d\n", [local error]); // AF_UNIX: also client bind!!! TEST([local bind :address]); //printf("Client.Bind: %d\n", [local error]); TEST([local sendto :peer :"Hello there.." :14 :0] == 14); //printf("Client.Send: %d - %d\n", [local sendto :peer :"Hello there.." :14 :0], [local error]); data = [local recvfrom :peer :50 :0]; TEST(data != nil); if (data != nil) { //printf("Client.Received: %s - %ld\n", [data data], [data length]); TEST([data bcompare :"Going to exit.." :16] == 0); [data free]; } TEST([local shutdown :DSK_SHUT_RDWR]); TEST([local close]); [address close]; [local free]; [address free]; [peer free]; #ifdef WITH_THREADS objc_thread_exit(); #endif return self; } #endif @end //---------------------------------------------------------------------------- static void TCPTester() { #ifdef WITH_THREADS SocketTester *tester = [SocketTester new]; if ((objc_thread_detach(@selector(TCPServer), tester, nil) == NULL) || (objc_thread_detach(@selector(TCPClient), tester, nil) == NULL)) { printf("Unable to detach threads..\n"); } #else int child = fork(); if (child < 0) { printf("Unable to fork...\n"); } else if (child == 0) // child { SocketTester *tester = [SocketTester new]; [tester TCPServer]; exit(0); } else // father { SocketTester *tester = [SocketTester new]; [tester TCPClient]; } #endif } //---------------------------------------------------------------------------- #ifndef WIN32 static void UDPTester() { #ifdef WITH_THREADS SocketTester *tester = [SocketTester new]; if ((objc_thread_detach(@selector(UDPServer), tester, nil) == NULL) || (objc_thread_detach(@selector(UDPClient), tester, nil) == NULL)) { printf("Unable to detach threads..\n"); } #else int child = fork(); if (child < 0) { printf("Unable to fork...\n"); } else if (child == 0) // child { SocketTester *tester = [SocketTester new]; [tester UDPServer]; exit(0); } else // father { SocketTester *tester = [SocketTester new]; [tester UDPClient]; } #endif } #endif //---------------------------------------------------------------------------- void DSocket_test() { DSocket *socket = [DSocket new]; DInetSocketAddress *address = [DInetSocketAddress new]; STARTTEST(); #ifdef WIN32 TEST([DSocket protocol :"pup"] == 12); #else TEST([DSocket protocol :"ddp"] == 37); #endif TEST([socket open :[address family] :DSK_STREAM :[DSocket protocol :"tcp"]]); TEST([socket reuseAddr :YES ]); TEST([socket sendBufferSize :4096]); TEST([socket receiveBufferSize :8192]); TEST([socket keepAlive :YES ]); TEST([socket blocking :NO ]); TEST([socket reuseAddr] == YES); TEST(([socket sendBufferSize ] == 4096) || ([socket sendBufferSize] == 8192)); TEST(([socket receiveBufferSize] == 8192) || ([socket receiveBufferSize] == 16384)); TEST([socket keepAlive] == YES); TEST([socket blocking] == NO); TEST([socket close]); TCPTester(); [DTimer delay :250]; #ifndef WIN32 UDPTester(); [DTimer delay :250]; #endif #ifdef DSA_AF_INET6 { DInet6SocketAddress *address6 = [DInet6SocketAddress new]; BOOL isOpen = NO; [address6 any :3210 :0 :0]; isOpen = [socket open :[address6 family] :DSK_STREAM :[DSocket protocol :"tcp"]]; TEST(isOpen); // Error indicates no IPv6 support if (isOpen) { TEST([socket reuseAddr :YES]); TEST([socket bind :address6]); TEST([socket close]); } [address6 close]; [address6 free]; } { DInet6SocketAddress *address6 = [DInet6SocketAddress new]; int port; unsigned long flowInfo; unsigned long scopeId; unsigned long u32[4]; unsigned u16[8]; unsigned char u8[16]; [address6 any :4008 :2 :1]; [address6 get :u32 :u32+1 :u32+2 :u32+3 :&port :&flowInfo :&scopeId]; TEST(u32[0] == 0); TEST(u32[1] == 0); TEST(u32[2] == 0); TEST(u32[3] == 0); TEST(port == 4008); TEST(flowInfo == 2); TEST(scopeId == 1); [address6 loopback: 6430 : 1 :2]; [address6 get16 :u16 :&port :&flowInfo :&scopeId]; TEST(u16[0] == 0); TEST(u16[1] == 0); TEST(u16[2] == 0); TEST(u16[3] == 0); TEST(u16[4] == 0); TEST(u16[5] == 0); TEST(u16[6] == 0); TEST(u16[7] == 1); TEST(port == 6430); TEST(flowInfo == 1); TEST(scopeId == 2); [address6 get :u8 :&port :&flowInfo :&scopeId]; TEST(u8[0] == 0); TEST(u8[1] == 0); TEST(u8[2] == 0); TEST(u8[3] == 0); TEST(u8[4] == 0); TEST(u8[5] == 0); TEST(u8[6] == 0); TEST(u8[7] == 0); TEST(u8[8] == 0); TEST(u8[9] == 0); TEST(u8[10] == 0); TEST(u8[11] == 0); TEST(u8[12] == 0); TEST(u8[13] == 0); TEST(u8[14] == 0); TEST(u8[15] == 1); TEST(port == 6430); TEST(flowInfo == 1); TEST(scopeId == 2); [address6 free]; } #endif [socket free]; [address free]; STOPTEST(); }