sl@0: /* sl@0: * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * Test of AF_INET stream sockets sl@0: * sl@0: * sl@0: */ sl@0: sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include "CTEST.H" /* includes C interface to EPOC32 threads, and SpawnPosixServer */ sl@0: sl@0: test_Data; sl@0: sl@0: struct sockaddr_in testaddr; sl@0: sl@0: unsigned short int port = 2001; sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-STDLIB-CT-1059 sl@0: @SYMTestCaseDesc Tests for AF_INET stream sockets sl@0: @SYMTestPriority High sl@0: @SYMTestActions Tests for simple operations on stream sockets,open,bind,get socket name,listen operations and test for error code sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ0000 sl@0: */ sl@0: void testSimple() sl@0: { sl@0: int fd1, fd2; sl@0: sl@0: size_t addrsize; sl@0: int err; sl@0: struct sockaddr_in addr1, addr2; sl@0: int optionbuf[20]; sl@0: size_t optionsize; sl@0: sl@0: test_Next("Create stream sockets"); sl@0: fd1=socket(AF_INET, SOCK_STREAM, 0); sl@0: test_ok(fd1>=0); sl@0: sl@0: fd2=socket(AF_INET, SOCK_STREAM, 0); sl@0: test_ok(fd2>=0); sl@0: sl@0: test_Next("Some binding tests"); sl@0: sl@0: addr1.sin_family=2061; sl@0: addr1.sin_port=htons(65530); sl@0: addr1.sin_addr.s_addr=htonl(0x11223344); sl@0: err=bind(fd1, (struct sockaddr*)&addr1, sizeof(addr1)); /* wrong family, port out of range */ sl@0: test_errno(err<0,ENOENT); sl@0: sl@0: addr1=testaddr; sl@0: addr1.sin_port=htons(port); sl@0: err=bind(fd1, (struct sockaddr*)&addr1, sizeof(addr1)); sl@0: test_ok(err==0); sl@0: sl@0: addr1=testaddr; sl@0: addr1.sin_port=htons((unsigned short int)(port+1)); sl@0: err=bind(fd1, (struct sockaddr*)&addr1, sizeof(addr1)); /* already bound */ sl@0: test_errno(err!=0, EEXIST); sl@0: sl@0: test_Next("Get associated addresses"); sl@0: sl@0: addrsize=sizeof(addr2); sl@0: err=getsockname(fd1,(struct sockaddr*)&addr2,&addrsize); sl@0: test_ok(err==0); sl@0: test(addr2.sin_family==AF_INET); sl@0: test(addr2.sin_port==htons(port)); sl@0: test(addrsize<=sizeof(addr2)); sl@0: sl@0: addrsize=sizeof(addr2); sl@0: err=getpeername(fd1,(struct sockaddr*)&addr2,&addrsize); /* not connected */ sl@0: test_errno(err!=0,-2); /* OMISSION - can't report proper reason for failure */ sl@0: sl@0: addrsize=sizeof(addr2); sl@0: err=getsockname(fd2,(struct sockaddr*)&addr2,&addrsize); /* not bound */ sl@0: test_errno(err!=0,-2); /* OMISSION - can't report proper reason for failure */ sl@0: sl@0: test_Next("More binding"); sl@0: sl@0: addr1=testaddr; sl@0: addr1.sin_port=htons(port); sl@0: err=bind(fd2, (struct sockaddr*)&addr1, sizeof(addr1)); /* address in use */ sl@0: test_errno(err!=0, EACCES); sl@0: sl@0: addr1=testaddr; sl@0: addr1.sin_port=0; sl@0: err=bind(fd2, (struct sockaddr*)&addr1, sizeof(addr1)); /* unspecified port number */ sl@0: test_ok(err==0); sl@0: sl@0: addrsize=sizeof(addr2); sl@0: err=getsockname(fd2,(struct sockaddr*)&addr2,&addrsize); sl@0: test_ok(err==0); sl@0: test(addr2.sin_family==AF_INET); sl@0: test(addrsize<=sizeof(addr2)); sl@0: test(addr2.sin_port!=htons(port)); sl@0: test(addr2.sin_port!=0); sl@0: { sl@0: unsigned short port=ntohs(addr2.sin_port); sl@0: test(port>=IPPORT_RESERVED); sl@0: /* NB. TCPIP 030 has 9999 for IPPORT_USERRESERVED, but TCPIP 031 dropped it to 5000 */ sl@0: test(port<=IPPORT_USERRESERVED); sl@0: printf(" allocated port %d\n",port); sl@0: } sl@0: sl@0: err=listen(fd1,1); sl@0: test_ok(err==0); sl@0: sl@0: test_Next("Socket options"); sl@0: sl@0: optionbuf[0]=3500000; /* implausible size */ sl@0: optionsize=sizeof(optionbuf[0]); sl@0: err=getsockopt(fd1,SOL_SOCKET,SO_SNDBUF,optionbuf,&optionsize); sl@0: test_ok(err==0); sl@0: test(optionbuf[0]!=3500000); sl@0: sl@0: optionbuf[0]=7*1024; sl@0: optionsize=sizeof(optionbuf[0]); sl@0: err=setsockopt(fd1,SOL_SOCKET,SO_SNDBUF,optionbuf,optionsize); sl@0: test_ok(err==0); sl@0: sl@0: optionbuf[0]=3500000; /* implausible size */ sl@0: optionsize=sizeof(optionbuf[0]); sl@0: err=getsockopt(fd1,SOL_SOCKET,SO_SNDBUF,optionbuf,&optionsize); sl@0: test_ok(err==0); sl@0: test(optionbuf[0]==7*1024); sl@0: sl@0: optionbuf[0]=1; sl@0: optionsize=sizeof(optionbuf[0]); sl@0: err=getsockopt(fd1,SOL_SOCKET,1234,optionbuf,&optionsize); /* invalid option */ sl@0: test_errno(err<0,ENOSYS); sl@0: test(optionbuf[0]==1); sl@0: sl@0: optionbuf[0]=13; sl@0: optionsize=sizeof(optionbuf[0]); sl@0: err=setsockopt(fd1,SOL_SOCKET,1234,optionbuf,optionsize); /* invalid option */ sl@0: test_errno(err<0,ENOSYS); sl@0: test(optionbuf[0]==13); sl@0: sl@0: err=close(fd1); sl@0: test_ok(err==0); sl@0: sl@0: err=close(fd2); sl@0: test_ok(err==0); sl@0: } sl@0: sl@0: /* Client and server take it in turns to send, starting with the client. sl@0: * Each matches the message they receive with the string expected sl@0: */ sl@0: char *message_sequence[] = { sl@0: "Hello from client", sl@0: "Hello from server", sl@0: "Test of send", sl@0: "Test of recv", sl@0: "Try sendto", sl@0: "Try recvfrom", sl@0: "Try sendto again", sl@0: "Try recvfrom again", sl@0: "Send to shutdown socket", sl@0: "Send to closed socket", sl@0: 0 sl@0: }; sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-STDLIB-CT-1060 sl@0: @SYMTestCaseDesc Tests for server socket sl@0: @SYMTestPriority High sl@0: @SYMTestActions Create a steam socket,bind and test for a transmission process.Check for error codes sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ0000 sl@0: */ sl@0: void testServer() sl@0: { sl@0: int fd1,fd2,nbytes,i; sl@0: size_t addrsize; sl@0: int err; sl@0: struct sockaddr_in addr1, addr2; sl@0: char buf[80]; sl@0: char **mp = message_sequence; sl@0: static int randbuf[10000]; sl@0: sl@0: fd1=fd2=nbytes=i=0; sl@0: sl@0: /* Fill the buffer with a predetermined random number sequence */ sl@0: randbuf[0]=4441302; sl@0: srand(randbuf[0]); sl@0: for (i=1; i<10000; i++) sl@0: randbuf[i]=rand(); sl@0: sl@0: sl@0: test_Next("Create server socket"); sl@0: fd1=socket(AF_INET, SOCK_STREAM, 0); sl@0: test_ok(fd1>=0); sl@0: sl@0: #if 0 sl@0: /* causes ESOCK to panic the client */ sl@0: addrsize=sizeof(addr2); sl@0: fd2=accept(fd1,&addr2,&addrsize); /* can't accept on an unbound socket */ sl@0: test_ok(fd2<0); sl@0: #endif sl@0: sl@0: IN_SET_LOOPBACK_ADDR(&addr1); sl@0: addr1.sin_port=htons(port); sl@0: err=bind(fd1, (struct sockaddr*)&addr1, sizeof(addr1)); sl@0: test_ok(err==0); sl@0: sl@0: #if 0 sl@0: /* causes ESOCK to panic the client */ sl@0: addrsize=sizeof(addr2); sl@0: fd2=accept(fd1,&addr2,&addrsize); /* can't accept before listening */ sl@0: test_ok(fd2<0); sl@0: #endif sl@0: sl@0: err=listen(fd1,1); sl@0: test_ok(err==0); sl@0: sl@0: addrsize=sizeof(addr2); sl@0: fd2=accept(fd1,(struct sockaddr*)&addr2,&addrsize); sl@0: test_ok(fd2>=0); sl@0: test(addr2.sin_family==AF_INET); sl@0: test(addr2.sin_port!=htons(port)); sl@0: test(addr2.sin_port!=0); sl@0: test(addrsize<=sizeof(addr2)); sl@0: sl@0: test_Next("Server read/write"); sl@0: sl@0: /* read */ sl@0: nbytes=strlen(*mp); sl@0: err=read(fd2, buf, nbytes+1); sl@0: test_ok(err==nbytes+1); sl@0: test(strcmp(buf,*mp)==0); sl@0: sl@0: /* write */ sl@0: mp++; sl@0: nbytes=strlen(*mp); sl@0: for (i=0; i=0); sl@0: test(addr2.sin_family==AF_INET); sl@0: test(addr2.sin_port!=htons(port)); sl@0: test(addr2.sin_port!=0); sl@0: test(addrsize<=sizeof(addr2)); sl@0: sl@0: nbytes=sizeof(randbuf); sl@0: err=write(fd2,(const char*)randbuf,nbytes); sl@0: test_ok(err==nbytes); sl@0: sl@0: test_Next("Server close"); sl@0: sl@0: // err=shutdown(fd2,1); sl@0: // test_ok(err==0); sl@0: sl@0: // sleep(4); sl@0: sl@0: err=close(fd2); sl@0: test_ok(err==0); sl@0: sl@0: err=close(fd1); sl@0: test_ok(err==0); sl@0: } sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-STDLIB-CT-1061 sl@0: @SYMTestCaseDesc Tests for client socket sl@0: @SYMTestPriority High sl@0: @SYMTestActions Create a steam socket,bind and test for a transmission process.Check for error codes sl@0: @SYMTestExpectedResults Test must not fail sl@0: @SYMREQ REQ0000 sl@0: */ sl@0: void testClient() sl@0: { sl@0: int fd1, nbytes, nbytes2, i, status; sl@0: sl@0: size_t addrsize; sl@0: int err; sl@0: struct sockaddr_in addr1, addr2; sl@0: char buf[80]; sl@0: char **mp = message_sequence; sl@0: static int randbuf[10001]; sl@0: sl@0: test_Next("Create client socket"); sl@0: fd1=socket(AF_INET, SOCK_STREAM, 0); sl@0: test_ok(fd1>=0); sl@0: sl@0: sleep(5); /* give server a chance to run */ sl@0: sl@0: addr1=testaddr; sl@0: addr1.sin_port=htons(port); sl@0: addrsize=sizeof(addr1); sl@0: err=connect(fd1,(struct sockaddr*)&addr1,addrsize); sl@0: test_ok(err==0); sl@0: sl@0: addrsize=sizeof(addr2); sl@0: err=getpeername(fd1,(struct sockaddr*)&addr2,&addrsize); sl@0: test_ok(err==0); sl@0: test(addr2.sin_family==AF_INET); sl@0: test(addr2.sin_port==htons(port)); sl@0: test(addrsize<=sizeof(addr2)); sl@0: sl@0: addrsize=sizeof(addr2); sl@0: err=getsockname(fd1,(struct sockaddr*)&addr2,&addrsize); sl@0: test_ok(err==0); sl@0: test(addr2.sin_family==AF_INET); sl@0: test(addr2.sin_port!=htons(port)); sl@0: test(addr2.sin_port!=0); sl@0: test(addrsize<=sizeof(addr2)); sl@0: sl@0: test_Next("Client read/write"); sl@0: sl@0: /* write */ sl@0: nbytes=strlen(*mp); sl@0: err=write(fd1, *mp, nbytes+1); sl@0: test_ok(err==nbytes+1); sl@0: sl@0: /* read */ sl@0: mp++; sl@0: nbytes=strlen(*mp); sl@0: err=read(fd1, buf, nbytes+1); sl@0: test_ok(err==nbytes+1); sl@0: test(strcmp(buf,*mp)==0); sl@0: sl@0: test_Next("Client send/recv"); sl@0: sl@0: /* send */ sl@0: mp++; sl@0: nbytes=strlen(*mp); sl@0: err=send(fd1,*mp, nbytes+1,0); sl@0: test_ok(err==nbytes+1); sl@0: sl@0: /* recv - get the first 2 bytes so that we know the buffer is full */ sl@0: mp++; sl@0: nbytes=strlen(*mp); sl@0: err=recv(fd1,buf,2,0); sl@0: test_ok(err==2); sl@0: sl@0: /* ioctl */ sl@0: sl@0: nbytes2=-1; sl@0: err=ioctl(fd1,E32IONREAD,&nbytes2); sl@0: test_ok(err==0); sl@0: test(nbytes2==(nbytes+1-2)); sl@0: sl@0: nbytes2=E32SELECT_READ|E32SELECT_WRITE|E32SELECT_EXCEPT; sl@0: err=ioctl(fd1,E32IOSELECT,&nbytes2); sl@0: test_ok(err==0); sl@0: test(nbytes2==(E32SELECT_READ|E32SELECT_WRITE)); sl@0: sl@0: nbytes2=E32SELECT_READ|E32SELECT_WRITE|E32SELECT_EXCEPT; sl@0: err=async_ioctl(fd1,E32IOSELECT,&nbytes2,&status); sl@0: test_ok(err==0); sl@0: err=async_ioctl_completion(fd1,E32IOSELECT,&nbytes2,&status); sl@0: test_ok(err==0); sl@0: if (nbytes2!=(E32SELECT_READ|E32SELECT_WRITE)) sl@0: { sl@0: nbytes2=E32SELECT_READ|E32SELECT_WRITE|E32SELECT_EXCEPT; sl@0: err=ioctl(fd1,E32IOSELECT,&nbytes2); sl@0: test_ok(err==0); sl@0: test(nbytes2==(E32SELECT_READ|E32SELECT_WRITE)); sl@0: } sl@0: sl@0: /* recv - get the rest of the data */ sl@0: for (i=2; i=0); sl@0: sl@0: sleep(2); /* give server a chance to run */ sl@0: sl@0: addr1=testaddr; sl@0: addr1.sin_port=htons(port); sl@0: addrsize=sizeof(addr1); sl@0: sl@0: //this connect fails. Why is this? sl@0: err=connect(fd1,(struct sockaddr*)&addr1,addrsize); sl@0: test_ok(err==0); sl@0: sl@0: sl@0: addrsize=sizeof(addr2); sl@0: err=getpeername(fd1,(struct sockaddr*)&addr2,&addrsize); sl@0: test_ok(err==0); sl@0: test(addr2.sin_family==AF_INET); sl@0: test(addr2.sin_port==htons(port)); sl@0: test(addrsize<=sizeof(addr2)); sl@0: sl@0: addrsize=sizeof(addr2); sl@0: err=getsockname(fd1,(struct sockaddr*)&addr2,&addrsize); sl@0: test_ok(err==0); sl@0: test(addr2.sin_family==AF_INET); sl@0: test(addr2.sin_port!=htons(port)); sl@0: test(addr2.sin_port!=0); sl@0: test(addrsize<=sizeof(addr2)); sl@0: sl@0: nbytes=0; sl@0: { sl@0: int buf; sl@0: char * p; sl@0: sl@0: do sl@0: { sl@0: buf=sizeof(randbuf)-nbytes; sl@0: if (buf>4095) sl@0: buf=4095; sl@0: p = (char*)randbuf+nbytes; sl@0: // err=read(fd1, p, buf); sl@0: err=recv(fd1, p, buf, 0); sl@0: if (err>0) sl@0: nbytes+=err; sl@0: } sl@0: while (nbytes0); sl@0: } sl@0: sl@0: printf("\nnbytes=%d, err=%d, errno=%d\n", nbytes, err, errno); sl@0: sl@0: test_ok(err==0); /* want a graceful EOF */ sl@0: test(nbytes==sizeof(randbuf)-sizeof(int)); /* expect a smaller test data set */ sl@0: test(randbuf[0]==4441302); sl@0: srand(randbuf[0]); sl@0: for (i=1; i<10000; i++) sl@0: test(randbuf[i]==rand()); sl@0: sl@0: sl@0: sl@0: err=recv(fd1, (char*)randbuf, 1, 0); sl@0: test_ok(err==0); sl@0: sl@0: err=close(fd1); sl@0: test_ok(err==0); sl@0: sl@0: } sl@0: sl@0: int close_console=0; sl@0: void testConnection() sl@0: { sl@0: int err; sl@0: void* server; sl@0: char buf[100]; sl@0: sl@0: sprintf(buf, "TISTREAM server %d", close_console); sl@0: server=create_thread(testServer, buf); sl@0: test(server!=0); sl@0: start_thread(server); sl@0: sl@0: sleep(2); /* give the server a chance to get started */ sl@0: testClient(); sl@0: sl@0: err=wait_for_thread(server); sl@0: test(err==0); sl@0: sl@0: if (close_console) sl@0: { sl@0: test_Close(); sl@0: close(0); sl@0: close(1); sl@0: close(2); sl@0: } sl@0: } sl@0: sl@0: int main(int argc, char *argv[]) sl@0: { sl@0: void* client; sl@0: int err; sl@0: sl@0: test_Title("AF_INET Streams"); sl@0: sl@0: err=CommInit(0); /* ensure a workable comms environment */ sl@0: test(err==0); sl@0: sl@0: IN_SET_LOOPBACK_ADDR(&testaddr); sl@0: sl@0: if (argc==1) sl@0: { sl@0: // Run the test(s) without a CPosixServer first sl@0: testSimple(); sl@0: port +=2; sl@0: testConnection(); sl@0: port +=2; sl@0: } sl@0: sl@0: sl@0: test_Next("Test gethostname"); sl@0: { sl@0: char * hname; sl@0: hname = (char*)malloc(200); sl@0: if (hname) sl@0: { sl@0: err = gethostname(hname, 200); sl@0: sl@0: if (err) sl@0: printf("gethostname, err=%d, errno=%d\n", err, errno); sl@0: else sl@0: printf("host name is %s\n", hname); sl@0: sl@0: free(hname); } sl@0: else sl@0: printf("host name - malloc failure\n"); sl@0: sl@0: } sl@0: sl@0: test_Next("Do it again using the CPosixServer (for them, not me)"); sl@0: close_console=1; sl@0: sl@0: start_posix_server(); /* calls SpawnPosixServer from C++ code */ sl@0: sl@0: sl@0: client=create_thread(testSimple, "TISTREAM simple"); sl@0: test(client!=0); sl@0: start_thread(client); sl@0: err=wait_for_thread(client); sl@0: test(err==0); sl@0: port +=2; sl@0: sl@0: client=create_thread(testConnection, "TISTREAM client"); sl@0: test(client!=0); sl@0: start_thread(client); sl@0: err=wait_for_thread(client); sl@0: test(err==0); sl@0: sl@0: test_Close(); sl@0: return 0; sl@0: }