master
c 623 lines 14.3 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 common.c
8
9 Abstract:
10
11 Common socket definitions and helper routines.
12
13 --*/
14
15 #include <stdlib.h>
16 #include <sys/socket.h>
17 #include <sys/epoll.h>
18 #include <stdbool.h>
19 #include "common.h"
20 #include "lxtcommon.h"
21
22 int LxtSocketEpoll(int Descriptor, int Event, int Timeout)
23
24 /*++
25
26 Routine Description:
27
28 This routine checks whether the given epoll is set in the file descriptor.
29
30 Arguments:
31
32 Descriptor - Supplies the descriptor.
33
34 Event - Supplies an event to check for.
35
36 Timeout - Supplies the timeout value in milliseconds.
37
38 Return Value:
39
40 0 on success, -1 on failure.
41
42 --*/
43
44 {
45
46 struct epoll_event EpollEvent;
47 int EpollFd;
48 int Iterator;
49 int NumberDescriptors;
50 int Result;
51
52 EpollFd = -1;
53 LxtCheckErrno(EpollFd = epoll_create(1));
54 EpollEvent.events = Event;
55 EpollEvent.data.fd = Descriptor;
56 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, Descriptor, &EpollEvent));
57 LxtCheckErrno(NumberDescriptors = epoll_wait(EpollFd, &EpollEvent, 1, Timeout));
58
59 //
60 // If no descriptors were ready within the timeout, that is an error condition
61 //
62
63 if (NumberDescriptors != 1)
64 {
65 LxtLogInfo("expecting epoll_wait to return 1, but it returned %d", NumberDescriptors);
66
67 Result = -1;
68 errno = EAGAIN;
69 goto ErrorExit;
70 }
71
72 if ((EpollEvent.events & Event) == 0)
73 {
74 LxtLogError("epoll event(%d) is not set. Epoll event(s) set: %d", Event, EpollEvent.events);
75
76 Result = -1;
77 errno = EINVAL;
78 goto ErrorExit;
79 }
80
81 Result = 0;
82
83 ErrorExit:
84 if (EpollFd != -1)
85 {
86 close(EpollFd);
87 }
88
89 return Result;
90 }
91
92 void* SocketBlockedReaderThread(void* Arg)
93
94 /*++
95
96 Routine Description:
97
98 This routine will call read on the given fd and block.
99
100 Arguments:
101
102 Arg - Supplies the argument for the datagram server to operate.
103
104 Return Value:
105
106 Returns 0 on success, -1 on failure.
107
108 --*/
109
110 {
111
112 char Buffer[10] = "123456789";
113 ssize_t BytesRead;
114 int Fd;
115 int Result = LXT_RESULT_FAILURE;
116 Fd = *(int*)Arg;
117 LxtCheckErrno(BytesRead = recv(Fd, Buffer, sizeof(Buffer), 0));
118 if (BytesRead != 0)
119 {
120 LxtLogError("recv should return 0 bytes read, but it returned %d bytes", BytesRead);
121
122 goto ErrorExit;
123 }
124
125 LxtLogInfo("recv unblocked");
126 Result = LXT_RESULT_SUCCESS;
127
128 ErrorExit:
129 pthread_exit((void*)(ssize_t)Result);
130 }
131
132 void* SocketBlockedReaderZeroBufferThread(void* Arg)
133
134 /*++
135
136 Routine Description:
137
138 This routine will call read on the given fd with a zero-byte receive buffer
139 and block.
140
141 Arguments:
142
143 Arg - Supplies the argument for the datagram server to operate.
144
145 Return Value:
146
147 Returns 0 on success, -1 on failure.
148
149 --*/
150
151 {
152
153 char Buffer[10] = "123456789";
154 ssize_t BytesRead;
155 int Fd;
156 int Result = LXT_RESULT_FAILURE;
157 Fd = *(int*)Arg;
158 LxtCheckErrno(BytesRead = recv(Fd, Buffer, 0, 0));
159 if (BytesRead != 0)
160 {
161 LxtLogError("recv should return 0 bytes read, but it returned %d bytes", BytesRead);
162
163 goto ErrorExit;
164 }
165
166 LxtLogInfo("recv unblocked");
167 Result = LXT_RESULT_SUCCESS;
168
169 ErrorExit:
170 pthread_exit((void*)(ssize_t)Result);
171 }
172
173 struct cmsghdr* SocketGetControlMessage(struct msghdr* MessageHeader, struct cmsghdr* StartControlMessage, int Level, int Type)
174
175 /*++
176
177 Routine Description:
178
179 This routine will return the control information at the given level and
180 type.
181
182 Arguments:
183
184 MessageHeader - Supplies the message header from which the control
185 information has to be extracted.
186
187 StartControlMessage - Supplies the control message from where to start.
188 NULL if the search has to start from the beginning.
189
190 Level - Supplies the level of the control information.
191
192 Type - Supplies the type of the control information.
193
194 Return Value:
195
196 Control message or NULL if it does not exist.
197
198 --*/
199
200 {
201
202 struct cmsghdr* ControlMessage;
203
204 //
205 // Use the system macros to extract receive the ip packet control info.
206 //
207
208 ControlMessage = NULL;
209
210 //
211 // If the start control message is provided use that, else get the first
212 // control message. This is automatically handled by MY_CMSG_NXTHDR.
213 //
214
215 for (ControlMessage = MY_CMSG_NXTHDR(MessageHeader, StartControlMessage); ControlMessage != NULL;
216 ControlMessage = MY_CMSG_NXTHDR(MessageHeader, ControlMessage))
217 {
218
219 if (ControlMessage->cmsg_len < sizeof(struct cmsghdr))
220 {
221 break;
222 }
223
224 //
225 // Look for a match.
226 //
227
228 if ((ControlMessage->cmsg_level == Level) && (ControlMessage->cmsg_type == Type))
229 {
230
231 return ControlMessage;
232 }
233 }
234
235 return NULL;
236 }
237
238 void* SocketBlockedWriterThread(void* Arg)
239
240 /*++
241
242 Routine Description:
243
244 This routine will call write on the given fd and block.
245
246 Arguments:
247
248 Arg - Supplies the argument for the datagram server to operate.
249
250 Return Value:
251
252 Returns 0 on success, -1 on failure.
253
254 --*/
255
256 {
257
258 char Buffer[10] = "123456789";
259 ssize_t BytesWritten;
260 int Fd;
261 int Result = LXT_RESULT_FAILURE;
262 Fd = *(int*)Arg;
263 LxtCheckErrnoFailure(send(Fd, Buffer, sizeof(Buffer), 0), EPIPE);
264 LxtLogInfo("send unblocked");
265 Result = LXT_RESULT_SUCCESS;
266
267 ErrorExit:
268 pthread_exit((void*)(ssize_t)Result);
269 }
270
271 int SocketGetSetBooleanSocketOption(int Socket, int OptionLevel, int OptionName, bool SmallerSizeAllowed)
272
273 /*++
274
275 Routine Description:
276
277 This routine tests the getsockopt() and setsockopt() API for the
278 any of the boolean socket option.
279
280 Arguments:
281
282 Socket - Supplies the socket.
283
284 OptionLevel - Supplies the level at which the option has to be applied.
285
286 Option - Supplies the option to test.
287
288 SmallerSizeAllowed - Supplies a boolean indicating whether sizes smaller
289 than the size of the option are allowed.
290
291 Return Value:
292
293 Returns 0 on success, -1 on failure.
294
295 --*/
296 {
297
298 int Result;
299 int Option;
300 socklen_t OptionLength;
301 long long int OptionLong;
302
303 Result = LXT_RESULT_FAILURE;
304
305 //
306 // Validate proper handling of boolean socket options.
307 //
308
309 Option = 1;
310 OptionLength = sizeof(Option);
311 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
312
313 Option = 0;
314 OptionLength = sizeof(Option);
315 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
316
317 LxtCheckEqual(Option, 1, "%d");
318
319 //
320 // Reset the option value to 0.
321 //
322
323 Option = 0;
324 OptionLength = sizeof(Option);
325 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
326
327 Option = 0;
328 OptionLength = sizeof(Option);
329 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
330
331 LxtCheckEqual(Option, 0, "%d");
332
333 //
334 // Since it is a boolean option, any value other than 0 is accepted for
335 // enabling the option. Try -ve.
336 //
337
338 Option = -1;
339 OptionLength = sizeof(Option);
340 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
341
342 Option = 0;
343 OptionLength = sizeof(Option);
344 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
345
346 LxtCheckEqual(Option, 1, "%d");
347
348 //
349 // Reset the option value to 0.
350 //
351
352 Option = 0;
353 OptionLength = sizeof(Option);
354 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
355
356 Option = 0;
357 OptionLength = sizeof(Option);
358 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
359
360 LxtCheckEqual(Option, 0, "%d");
361
362 //
363 // Since it is a boolean option, any value other than 0 is accepted for
364 // enabling the option. Try > 0.
365 //
366
367 Option = 15;
368 OptionLength = sizeof(Option);
369 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
370
371 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
372
373 LxtCheckEqual(Option, 1, "%d");
374
375 if (SmallerSizeAllowed == false)
376 {
377
378 //
379 // Validate that also 1,2 and 3 byte size is not a valid option size for
380 // boolean socket option.
381 //
382
383 OptionLength = 1;
384 LxtCheckErrnoFailure(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength), EINVAL);
385
386 OptionLength = 2;
387 LxtCheckErrnoFailure(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength), EINVAL);
388
389 OptionLength = 3;
390 LxtCheckErrnoFailure(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength), EINVAL);
391
392 OptionLength = sizeof(Option);
393 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
394
395 LxtCheckEqual(Option, 1, "%d");
396 }
397 else
398 {
399
400 //
401 // Supplying an option size of 1, 2 and 3 are also accepted.
402 //
403
404 Option = 1;
405 OptionLength = 1;
406 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
407
408 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
409
410 LxtCheckEqual(Option, 1, "%d");
411
412 //
413 // Reset the option value to 0.
414 //
415
416 Option = 0;
417 OptionLength = sizeof(Option);
418 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
419
420 //
421 // Option size of 2.
422 //
423
424 Option = 1;
425 OptionLength = 2;
426 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
427
428 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
429
430 LxtCheckEqual(Option, 1, "%d");
431
432 //
433 // Reset the option value to 0.
434 //
435
436 Option = 0;
437 OptionLength = sizeof(Option);
438 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
439
440 //
441 // Use option size of 3.
442 //
443
444 Option = 1;
445 OptionLength = 3;
446 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &Option, OptionLength));
447
448 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
449
450 LxtCheckEqual(Option, 1, "%d");
451 }
452
453 //
454 // Verify that anything above 4 bytes is ignored truncated.
455 //
456
457 OptionLong = 0x200000000;
458 OptionLength = sizeof(OptionLong);
459 LxtCheckErrno(setsockopt(Socket, OptionLevel, OptionName, &OptionLong, OptionLength));
460
461 OptionLength = sizeof(Option);
462 LxtCheckErrno(getsockopt(Socket, OptionLevel, OptionName, &Option, &OptionLength));
463
464 LxtCheckEqual(Option, 0, "%d");
465
466 ErrorExit:
467 return Result;
468 }
469
470 char* SocketGetTypeAsString(int Type)
471
472 /*++
473
474 Routine Description:
475
476 This routine returns the string equivalent for the give socket type.
477
478 Arguments:
479
480 Type - Supplies the socket type.
481
482 Return Value:
483
484 Returns the string equivalent for the type; NULL otherwise.
485
486 --*/
487 {
488
489 switch (Type)
490 {
491 case SOCK_STREAM:
492 return LXT_SOCKET_STREAM_STRING;
493
494 case SOCK_DGRAM:
495 return LXT_SOCKET_DGRAM_STRING;
496
497 case SOCK_RAW:
498 return LXT_SOCKET_RAW_STRING;
499
500 case SOCK_SEQPACKET:
501 return LXT_SOCKET_SEQPACKET_STRING;
502
503 case SOCK_PACKET:
504 return LXT_SOCKET_PACKET_STRING;
505
506 default:
507 return NULL;
508 }
509 }
510
511 int SocketStreamClientMsgWaitAll(int ConnectedSocket)
512
513 /*++
514
515 Routine Description:
516
517 This is a client helper routine testing MSG_WAITALL flag recv syscall.
518
519 Arguments:
520
521 ConnectedSocket - Supplies a socket fd.
522
523 Return Value:
524
525 0 on success, -1 on failure.
526
527 --*/
528
529 {
530 int FullMessageSize;
531 char* ReceiveBuffer;
532 int Result = LXT_RESULT_FAILURE;
533 char* SendBuffer;
534 int Size;
535
536 SendBuffer = LXT_SOCKET_DEFAULT_SEND_STRING;
537 FullMessageSize = 2 * strlen(SendBuffer);
538 ReceiveBuffer = malloc(FullMessageSize);
539 if (ReceiveBuffer == NULL)
540 {
541 goto ErrorExit;
542 }
543
544 LxtLogInfo("Client: 1. send");
545 LxtCheckErrno(Size = send(ConnectedSocket, SendBuffer, strlen(SendBuffer), 0));
546
547 //
548 // Sleep long enough that the second send won't be concatenated by WSK to
549 // test MSW_WAITALL code path, if the socket is inet socket.
550 //
551
552 sleep(1);
553 LxtLogInfo("Client: 2. delayed send");
554 LxtCheckErrno(Size = send(ConnectedSocket, SendBuffer, strlen(SendBuffer), 0));
555
556 memset(ReceiveBuffer, 0, FullMessageSize);
557 LxtLogInfo("Client: recv(MSG_WAITALL)");
558 LxtCheckErrno(Size = recv(ConnectedSocket, ReceiveBuffer, FullMessageSize, MSG_WAITALL));
559
560 LxtCheckMemoryEqual(SendBuffer, ReceiveBuffer, FullMessageSize / 2);
561 LxtCheckMemoryEqual(SendBuffer, ReceiveBuffer + FullMessageSize / 2, sizeof(SendBuffer));
562
563 Result = LXT_RESULT_SUCCESS;
564
565 ErrorExit:
566 if (ReceiveBuffer != NULL)
567 {
568 free(ReceiveBuffer);
569 }
570
571 return Result;
572 }
573
574 int SocketStreamServerMsgWaitAll(int AcceptedSocket)
575
576 /*++
577
578 Routine Description:
579
580 This is a server helper routine testing MSG_WAITALL flag recv syscall.
581
582 Arguments:
583
584 AcceptedSocket - Supplies a socket fd.
585
586 Return Value:
587
588 0 on success, -1 on failure.
589
590 --*/
591
592 {
593 int Index;
594 char* ReceiveBuffer;
595 int Result = LXT_RESULT_FAILURE;
596 int Size;
597 int FullMessageSize;
598 int Socket = 0;
599
600 ReceiveBuffer = LXT_SOCKET_DEFAULT_SEND_STRING;
601 FullMessageSize = 2 * strlen(ReceiveBuffer);
602 ReceiveBuffer = malloc(FullMessageSize);
603 if (ReceiveBuffer == NULL)
604 {
605 goto ErrorExit;
606 }
607
608 LxtLogInfo("Server: recv(MSG_WAITALL)");
609 memset(ReceiveBuffer, 0, sizeof(ReceiveBuffer));
610 LxtCheckErrno(Size = recv(AcceptedSocket, ReceiveBuffer, FullMessageSize, MSG_WAITALL));
611
612 LxtLogInfo("Server: write all back");
613 LxtCheckErrno(write(AcceptedSocket, ReceiveBuffer, Size));
614 Result = LXT_RESULT_SUCCESS;
615
616 ErrorExit:
617 if (ReceiveBuffer != NULL)
618 {
619 free(ReceiveBuffer);
620 }
621
622 return Result;
623 }