1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * PURPOSE:         Test for WSASocket
5  * PROGRAMMERS:     Peter Hater
6  */
7 
8 #include "ws2_32.h"
9 
10 void Test_CloseDuplicatedSocket()
11 {
12     char szBuf[10];
13     int err;
14     SOCKET sck, dup_sck;
15     WSAPROTOCOL_INFOW ProtocolInfo;
16     struct sockaddr_in to = { AF_INET, 2222, {{{ 0x7f, 0x00, 0x00, 0x01 }}} };
17 
18     /* Create the socket */
19     sck = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
20     if(sck == INVALID_SOCKET)
21     {
22         skip("socket failed %d. Aborting test.\n", WSAGetLastError());
23         return;
24     }
25 
26     err = sendto(sck, szBuf, _countof(szBuf), 0, (struct sockaddr *)&to, sizeof(to));
27     ok(err == _countof(szBuf), "sendto err = %d %d\n", err, WSAGetLastError());
28 
29     err = WSADuplicateSocketW(sck, GetCurrentProcessId(), &ProtocolInfo);
30     ok(err == 0, "WSADuplicateSocketW err = %d %d\n", err, WSAGetLastError());
31 
32     dup_sck = WSASocketW(0, 0, 0, &ProtocolInfo, 0, 0);
33     if (dup_sck == INVALID_SOCKET)
34     {
35         skip("WSASocketW failed %d. Aborting test.\n", WSAGetLastError());
36         closesocket(sck);
37         return;
38     }
39 
40     err = sendto(dup_sck, szBuf, _countof(szBuf), 0, (struct sockaddr *)&to, sizeof(to));
41     ok(err == _countof(szBuf), "sendto err = %d %d\n", err, WSAGetLastError());
42 
43     err = closesocket(sck);
44     ok(err == 0, "closesocket sck err = %d %d\n", err, WSAGetLastError());
45 
46     err = sendto(dup_sck, szBuf, _countof(szBuf), 0, (struct sockaddr *)&to, sizeof(to));
47     ok(err == _countof(szBuf), "sendto err = %d %d\n", err, WSAGetLastError());
48 
49     err = closesocket(dup_sck);
50     ok(err == 0, "closesocket dup_sck err = %d %d\n", err, WSAGetLastError());
51     return;
52 }
53 
54 // 100 ms
55 #define TIMEOUT_SEC 0
56 #define TIMEOUT_USEC 100000
57 
58 // 250 ms
59 #define TIME_SLEEP1 250
60 
61 #define THREAD_PROC_LOOPS 5
62 
63 #define LISTEN_PORT 22222
64 #define LISTEN_BACKLOG 5
65 
66 DWORD WINAPI thread_proc(void* param)
67 {
68     fd_set read, write, except;
69     struct timeval tval;
70     SOCKET sock = (SOCKET)param;
71     int i;
72 
73     tval.tv_sec = TIMEOUT_SEC;
74     tval.tv_usec = TIMEOUT_USEC;
75 
76     for (i = 0; i < THREAD_PROC_LOOPS; ++i)
77     {
78         FD_ZERO(&read); FD_ZERO(&write); FD_ZERO(&except);
79         // write will be empty
80         FD_SET(sock, &read); FD_SET(sock, &except);
81 
82         select(0, &read, &write, &except, &tval);
83     }
84 
85     return 0;
86 }
87 
88 void Test_CloseWhileSelectSameSocket()
89 {
90     int err;
91     SOCKET sock;
92     struct sockaddr_in addrin;
93     HANDLE hthread;
94 
95     /* Create the socket */
96     sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
97     if (sock == INVALID_SOCKET)
98     {
99         skip("socket failed %d. Aborting test.\n", WSAGetLastError());
100         return;
101     }
102 
103     memset(&addrin, 0, sizeof(struct sockaddr_in));
104     addrin.sin_family = AF_INET;
105     addrin.sin_addr.s_addr = inet_addr("127.0.0.1");
106     addrin.sin_port = htons(LISTEN_PORT);
107 
108     err = bind(sock, (struct sockaddr*)(&addrin), sizeof(struct sockaddr_in));
109     ok(err == 0, "bind err = %d %d\n", err, WSAGetLastError());
110     err = listen(sock, LISTEN_BACKLOG);
111     ok(err == 0, "listen err = %d %d\n", err, WSAGetLastError());
112 
113     hthread = CreateThread(NULL, 0, thread_proc, (void*)sock, 0, NULL);
114     ok(hthread != NULL, "CreateThread %ld\n", GetLastError());
115 
116     Sleep(TIME_SLEEP1);
117     err = closesocket(sock);
118     ok(err == 0, "closesocket err = %d %d\n", err, WSAGetLastError());
119 
120     WaitForSingleObject(hthread, INFINITE);
121     CloseHandle(hthread);
122     return;
123 }
124 
125 void Test_CloseWhileSelectDuplicatedSocket()
126 {
127     int err;
128     SOCKET sock, dup_sock;
129     WSAPROTOCOL_INFOW ProtocolInfo;
130     struct sockaddr_in addrin;
131     HANDLE hthread;
132 
133     /* Create the socket */
134     sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
135     if (sock == INVALID_SOCKET)
136     {
137         skip("socket failed %d. Aborting test.\n", WSAGetLastError());
138         return;
139     }
140 
141     memset(&addrin, 0, sizeof(struct sockaddr_in));
142     addrin.sin_family = AF_INET;
143     addrin.sin_addr.s_addr = inet_addr("127.0.0.1");
144     addrin.sin_port = htons(LISTEN_PORT);
145 
146     err = bind(sock, (struct sockaddr*)(&addrin), sizeof(struct sockaddr_in));
147     ok(err == 0, "bind err = %d %d\n", err, WSAGetLastError());
148     err = listen(sock, LISTEN_BACKLOG);
149     ok(err == 0, "listen err = %d %d\n", err, WSAGetLastError());
150 
151     err = WSADuplicateSocketW(sock, GetCurrentProcessId(), &ProtocolInfo);
152     ok(err == 0, "WSADuplicateSocketW err = %d %d\n", err, WSAGetLastError());
153 
154     dup_sock = WSASocketW(0, 0, 0, &ProtocolInfo, 0, 0);
155     if (dup_sock == INVALID_SOCKET)
156     {
157         skip("WSASocketW failed %d. Aborting test.\n", WSAGetLastError());
158         closesocket(sock);
159         return;
160     }
161 
162     hthread = CreateThread(NULL, 0, thread_proc, (void*)dup_sock, 0, NULL);
163     ok(hthread != NULL, "CreateThread %ld\n", GetLastError());
164 
165     err = closesocket(sock);
166     ok(err == 0, "closesocket err = %d %d\n", err, WSAGetLastError());
167 
168     Sleep(TIME_SLEEP1);
169     err = closesocket(dup_sock);
170     ok(err == 0, "closesocket err = %d %d\n", err, WSAGetLastError());
171 
172     WaitForSingleObject(hthread, INFINITE);
173     CloseHandle(hthread);
174     return;
175 }
176 
177 START_TEST(close)
178 {
179     int err;
180     WSADATA wdata;
181 
182     /* Start up Winsock */
183     err = WSAStartup(MAKEWORD(2, 2), &wdata);
184     ok(err == 0, "WSAStartup failed, iResult == %d %d\n", err, WSAGetLastError());
185 
186     Test_CloseDuplicatedSocket();
187     Test_CloseWhileSelectSameSocket();
188     Test_CloseWhileSelectDuplicatedSocket();
189 
190     WSACleanup();
191 }
192 
193