1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "sock.h"
26 #include <string.h>
27
28 /* Include network headers */
29 #if defined(CONFIG_OS_WINDOWS)
30 # include <winsock2.h>
31 #elif defined(CONFIG_POSIX)
32 # include <unistd.h>
33 # include <errno.h>
34 # include <sys/socket.h>
35 # include <netinet/tcp.h>
36 # include <netinet/in.h>
37 # include <sys/time.h>
38 # include <sys/types.h>
39 # include <netdb.h>
40 # include <fcntl.h>
41 # include <arpa/inet.h>
42 # include <signal.h>
43 mike 1.1 // readv/writev headers
44 # include <sys/uio.h>
45
46 # include <sys/socket.h>
47 # include <sys/un.h>
48 # include <unistd.h>
49 # include <sys/stat.h>
50 #endif
51
52 #include <base/log.h>
53 #include <base/strings.h>
54 #include <base/io.h>
55
56 #define T MI_T
57
58 /*
59 **==============================================================================
60 **
61 ** Local definitions.
62 **
63 **==============================================================================
64 mike 1.1 */
65
66 #if defined(CONFIG_OS_WINDOWS)
67 typedef int socklen_t;
68 #endif
69
70 MI_INLINE int _TestWOULDBLOCK()
71 {
72 #if defined(CONFIG_OS_WINDOWS)
73 return GetLastError() == WSAEWOULDBLOCK;
74 #else
75 return errno == EWOULDBLOCK || errno == EINPROGRESS;
76 #endif
77 }
78
79 MI_INLINE int _TestEAGAIN()
80 {
81 #if defined(CONFIG_OS_WINDOWS)
82 return 0;
83 #else
84 return errno == EAGAIN;
85 mike 1.1 #endif
86 }
87
88 MI_INLINE int _TestEINTR()
89 {
90 #if defined(CONFIG_OS_WINDOWS)
91 return GetLastError() == WSAEINTR;
92 #else
93 return errno == EINTR;
94 #endif
95 }
96
97 MI_INLINE int _Read(Sock sock, void* data, size_t size)
98 {
99 #if defined(CONFIG_OS_WINDOWS)
100 return recv(sock, data, (int)size, 0);
101 #else
102 return read(sock, data, size);
103 #endif
104 }
105
106 mike 1.1 MI_INLINE int _Write(Sock sock, const void* data, size_t size)
107 {
108 #if defined(CONFIG_OS_WINDOWS)
109 return send(sock, data, (int)size, 0);
110 #else
111 return write(sock, data, size);
112 #endif
113 }
114
115 MI_INLINE int _ReadV(Sock sock, const IOVec* iov, size_t iovcnt)
116 {
117 #if defined(CONFIG_OS_WINDOWS)
118 int res = 0;
119 int total = 0;
120 size_t index = 0;
121
122 for (; index < iovcnt; index++ )
123 {
124 res = recv(sock, iov[index].ptr, (int)iov[index].len, 0);
125
126 if ( res < 0 && 0 == total )
127 mike 1.1 return res;
128
129 if ( res < 0 )
130 return total;
131
132 total += res;
133
134 if ( res == 0 || (size_t)res != iov[index].len)
135 return total;
136 }
137 return total;
138 #else
139 return readv(sock, (struct iovec*)iov, iovcnt);
140 #endif
141 }
142
143 MI_INLINE int _WriteV(Sock sock, const IOVec* iov, size_t iovcnt)
144 {
145 #if defined(CONFIG_OS_WINDOWS)
146 int res = 0;
147 int total = 0;
148 mike 1.1 size_t index = 0;
149
150 for (; index < iovcnt; index++ )
151 {
152 res = send(sock, iov[index].ptr, (int)iov[index].len, 0);
153 if ( res < 0 && 0 == total )
154 return res;
155
156 if ( res < 0 )
157 return total;
158
159 total += res;
160
161 if ( res == 0 || (size_t)res != iov[index].len)
162 return total;
163 }
164 return total;
165 #else
166 return writev(sock, (struct iovec*)iov, iovcnt);
167 #endif
168 }
169 mike 1.1
170 /*
171 **==============================================================================
172 **
173 ** Public definitions.
174 **
175 **==============================================================================
176 */
177
178 MI_Result Sock_Start()
179 {
180 #if defined(CONFIG_OS_WINDOWS)
181 WORD version = MAKEWORD(2, 0);
182 WSADATA data;
183 int rc;
184
185 rc = WSAStartup (version, &data);
186
187 if (rc != 0)
188 return MI_RESULT_FAILED;
189
190 mike 1.1 #else
191 /* ignore PIPE signal */
192 struct sigaction sig_acts;
193
194 sig_acts.sa_handler = SIG_IGN;
195 sigfillset(&(sig_acts.sa_mask));
196 sig_acts.sa_flags = 0;
197
198 sigaction(SIGPIPE, &sig_acts, NULL);
199
200 #endif /* CONFIG_OS_WINDOWS */
201 return MI_RESULT_OK;
202 }
203
204 void Sock_Stop()
205 {
206 #if defined(CONFIG_OS_WINDOWS)
207 WSACleanup();
208 #endif /* CONFIG_OS_WINDOWS */
209 }
210
211 mike 1.1 MI_Result Sock_Create(Sock* sock)
212 {
213 *sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
214
215 if (*sock == -1)
216 return MI_RESULT_FAILED;
217
218 if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))
219 {
220 LOGW((T("fcntl(F_SETFD) failed")));
221 }
222
223 return MI_RESULT_OK;
224 }
225
226 MI_Result Sock_Close(Sock self)
227 {
228 int status;
229 #if defined(CONFIG_OS_WINDOWS)
230 status = closesocket(self);
231 #else
232 mike 1.1 status = close(self);
233 #endif
234
235 return status == 0 ? MI_RESULT_OK : MI_RESULT_FAILED;
236 }
237
238 MI_Result Sock_Bind(Sock self, const Addr* addr)
239 {
240 int r;
241
242 r = bind(self, (struct sockaddr*)addr, sizeof(*addr));
243
244 if (r != 0)
245 return MI_RESULT_FAILED;
246
247 return MI_RESULT_OK;
248 }
249
250 MI_Result Sock_Listen(Sock self)
251 {
252 int r;
253 mike 1.1
254 r = listen(self, 15);
255
256 if (r != 0)
257 return MI_RESULT_FAILED;
258
259 return MI_RESULT_OK;
260 }
261
262 MI_Result Sock_Accept(
263 Sock self,
264 Sock* sock,
265 Addr* addr)
266 {
267 socklen_t addrlen = sizeof(*addr);
268
269 *sock = accept(self, (struct sockaddr*)addr, &addrlen);
270
271 if (*sock == -1)
272 {
273 if (_TestWOULDBLOCK() || _TestEAGAIN())
274 mike 1.1 return MI_RESULT_WOULD_BLOCK;
275 }
276
277 if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))
278 {
279 LOGW((T("fcntl(F_SETFD) failed")));
280 }
281
282 return MI_RESULT_OK;
283 }
284
285 MI_Result Sock_SetCloseOnExec(
286 Sock self,
287 MI_Boolean closeOnExec)
288 {
289 #if defined(CONFIG_OS_WINDOWS)
290 MI_UNUSED(self);
291 MI_UNUSED(closeOnExec);
292 #else
293 int sock_flags;
294 if ((sock_flags = fcntl(self, F_GETFD, 0)) < 0)
295 mike 1.1 return MI_RESULT_FAILED;
296
297 if (closeOnExec)
298 sock_flags |= FD_CLOEXEC;
299 else
300 sock_flags &= ~FD_CLOEXEC;
301
302 if (fcntl(self, F_SETFD, sock_flags) < 0)
303 return MI_RESULT_FAILED;
304 #endif
305
306 return MI_RESULT_OK;
307 }
308
309
310 MI_Result Sock_Connect(
311 Sock self,
312 const Addr* addr)
313 {
314 int r;
315
316 mike 1.1 r = connect(self, (struct sockaddr*)addr, sizeof(*addr));
317
318 if (r != 0)
319 {
320 if (_TestWOULDBLOCK() || _TestEAGAIN())
321 return MI_RESULT_WOULD_BLOCK;
322
323 return MI_RESULT_FAILED;
324 }
325
326 return MI_RESULT_OK;
327 }
328
329 MI_Result Sock_ReuseAddr(
330 Sock self,
331 MI_Boolean flag_)
332 {
333 int flag = flag_ ? 1 : 0;
334 int r;
335
336 r = setsockopt(self, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag));
337 mike 1.1
338 if (r != 0)
339 return MI_RESULT_FAILED;
340
341 return MI_RESULT_OK;
342 }
343
344 MI_Result Sock_SetBlocking(
345 Sock self,
346 MI_Boolean flag_)
347 {
348 #if defined(CONFIG_OS_WINDOWS)
349 unsigned long flag = flag_ ? 0 : 1;
350
351 if (ioctlsocket(self, FIONBIO, &flag) != 0)
352 return MI_RESULT_FAILED;
353 #else
354 int flags = fcntl(self, F_GETFL, 0);
355
356 if (flag_)
357 flags &= ~O_NONBLOCK;
358 mike 1.1 else
359 flags |= O_NONBLOCK;
360
361 if (fcntl(self, F_SETFL, flags) == -1)
362 return MI_RESULT_FAILED;
363 #endif
364
365 return MI_RESULT_OK;
366 }
367
368 MI_Result Sock_SetNoDelay(
369 Sock self,
370 MI_Boolean flag)
371 {
372 int opt = flag ? 1 : 0;
373 int r;
374
375 r = setsockopt(self, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt));
376
377 if (r != 0)
378 return MI_RESULT_FAILED;
379 mike 1.1
380 return MI_RESULT_OK;
381 }
382
383 MI_Result Sock_Read(
384 Sock self,
385 void* data,
386 size_t size,
387 size_t* sizeRead)
388 {
389 int n;
390
391 * sizeRead = 0;
392
393 for (;;)
394 {
395 /* Attempt to read bytes */
396 n = _Read(self, data, size);
397
398 if (n >= 0)
399 {
400 mike 1.1 *sizeRead = n;
401 return MI_RESULT_OK;
402 }
403
404 /* Repeat operation if instruction interrupted */
405 if (_TestEINTR())
406 continue;
407
408 /* Check for would block error */
409 if (_TestWOULDBLOCK() || _TestEAGAIN())
410 return MI_RESULT_WOULD_BLOCK;
411
412 /* Failed */
413 break;
414 };
415
416 return MI_RESULT_FAILED;
417 }
418
419 MI_Result Sock_Write(
420 Sock self,
421 mike 1.1 const void* data,
422 size_t size,
423 size_t* sizeWritten)
424 {
425 int n;
426
427 * sizeWritten = 0;
428
429 for (;;)
430 {
431 /* Attempt to read bytes */
432 n = _Write(self, data, size);
433
434 if (n >= 0)
435 {
436 *sizeWritten = n;
437 return MI_RESULT_OK;
438 }
439
440 /* Repeat operation if instruction interrupted */
441 if (_TestEINTR())
442 mike 1.1 continue;
443
444 /* Check for would block error */
445 if (_TestWOULDBLOCK() || _TestEAGAIN())
446 return MI_RESULT_WOULD_BLOCK;
447
448 /* Failed */
449 break;
450 };
451
452 return MI_RESULT_FAILED;
453 }
454
455 MI_Result Sock_ReadV(
456 Sock self,
457 const IOVec* iov,
458 size_t iovcnt,
459 size_t* sizeRead)
460 {
461 int n;
462
463 mike 1.1 * sizeRead = 0;
464
465 for (;;)
466 {
467 /* Attempt to read bytes */
468 n = _ReadV(self, iov, iovcnt);
469
470 if (n >= 0)
471 {
472 *sizeRead = n;
473 return MI_RESULT_OK;
474 }
475
476 /* Repeat operation if instruction interrupted */
477 if (_TestEINTR())
478 continue;
479
480 /* Check for would block error */
481 if (_TestWOULDBLOCK() || _TestEAGAIN())
482 return MI_RESULT_WOULD_BLOCK;
483
484 mike 1.1 /* Failed */
485 break;
486 };
487
488 return MI_RESULT_FAILED;
489 }
490
491 MI_Result Sock_WriteV(
492 Sock self,
493 const IOVec* iov,
494 size_t iovcnt,
495 size_t* sizeWritten)
496 {
497 int n;
498
499 * sizeWritten = 0;
500
501 for (;;)
502 {
503 /* Attempt to read bytes */
504 n = _WriteV(self, iov, iovcnt);
505 mike 1.1
506 if (n >= 0)
507 {
508 *sizeWritten = n;
509 return MI_RESULT_OK;
510 }
511
512 /* Repeat operation if instruction interrupted */
513 if (_TestEINTR())
514 continue;
515
516 /* Check for would block error */
517 if (_TestWOULDBLOCK() || _TestEAGAIN())
518 return MI_RESULT_WOULD_BLOCK;
519
520 /* Failed */
521 break;
522 };
523
524 return MI_RESULT_FAILED;
525 }
526 mike 1.1
527 MI_Result Sock_CreateListener(
528 Sock* sock,
529 const Addr* addr)
530 {
531 MI_Result r;
532
533 /* Create socket */
534 {
535 r = Sock_Create(sock);
536
537 if (r != MI_RESULT_OK)
538 return r;
539 }
540
541 /* Reuse the address (to prevent binding failures) */
542 {
543 r = Sock_ReuseAddr(*sock, MI_TRUE);
544
545 if (r != MI_RESULT_OK)
546 {
547 mike 1.1 Sock_Close(*sock);
548 return r;
549 }
550 }
551
552 /* Bind the socket to the address */
553 {
554 r = Sock_Bind(*sock, addr);
555
556 if (r != MI_RESULT_OK)
557 {
558 Sock_Close(*sock);
559 return r;
560 }
561 }
562
563 /* Listen on this socket for connections */
564 {
565 r = Sock_Listen(*sock);
566
567 if (r != MI_RESULT_OK)
568 mike 1.1 {
569 Sock_Close(*sock);
570 return r;
571 }
572 }
573
574 return MI_RESULT_OK;
575 }
576
577 MI_Result Sock_CreateLocalListener(
578 Sock* sock,
579 const char* socketName)
580 {
581 #if defined(CONFIG_OS_WINDOWS)
582 unsigned short port = (unsigned short)atol(socketName);
583 Addr addr;
584
585 Addr_InitAny(&addr, port);
586 return Sock_CreateListener(sock, &addr);
587 #else
588 MI_Result r;
589 mike 1.1 struct sockaddr_un addr;
590
591
592 *sock = socket(PF_UNIX, SOCK_STREAM, 0);
593
594 if (*sock == -1)
595 return MI_RESULT_FAILED;
596
597 if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))
598 {
599 LOGW((T("fcntl(F_SETFD) failed")));
600 }
601
602 /* Reuse the address (to prevent binding failures) */
603 {
604 r = Sock_ReuseAddr(*sock, MI_TRUE);
605
606 if (r != MI_RESULT_OK)
607 {
608 Sock_Close(*sock);
609 return r;
610 mike 1.1 }
611 }
612
613 memset(&addr, 0, sizeof(addr));
614
615 addr.sun_family = AF_UNIX;
616
617 if (Strlcpy(addr.sun_path, socketName, sizeof(addr.sun_path))
618 >= sizeof(addr.sun_path))
619 {
620 Sock_Close(*sock);
621 LOGE((T("socket file path too long (> %u): '%s'"),
622 (int)(sizeof(addr.sun_path)-1), socketName));
623 return MI_RESULT_FAILED;
624 }
625
626 unlink(socketName);
627
628 if (0 != bind(*sock, (struct sockaddr *) &addr, sizeof(addr)))
629 {
630 Sock_Close(*sock);
631 mike 1.1 return MI_RESULT_FAILED;
632 }
633
634 /* Change mode to allow non-root to connect to it (they need 'w' to connect) */
635
636 chmod(socketName, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH );
637
638 /* Listen on this socket for connections */
639 {
640 r = Sock_Listen(*sock);
641
642 if (r != MI_RESULT_OK)
643 {
644 Sock_Close(*sock);
645 return r;
646 }
647 }
648
649 return MI_RESULT_OK;
650 #endif
651 }
652 mike 1.1
653 MI_Result Sock_CreateLocalConnector(
654 Sock* sock,
655 const char* socketName)
656 {
657 #if defined(CONFIG_OS_WINDOWS)
658 unsigned short port = (unsigned short)atol(socketName);
659 Addr addr;
660 MI_Result r;
661
662 // Initialize address.
663 r = Addr_Init(&addr, "127.0.0.1", port);
664 if (r != MI_RESULT_OK)
665 return MI_RESULT_FAILED;
666
667 // Create client socket.
668 r = Sock_Create(sock);
669 if (r != MI_RESULT_OK)
670 {
671 Sock_Close(*sock);
672 return MI_RESULT_FAILED;
673 mike 1.1 }
674
675 r = Sock_SetBlocking(*sock, MI_FALSE);
676 if (r != MI_RESULT_OK)
677 {
678 Sock_Close(*sock);
679 return MI_RESULT_FAILED;
680 }
681
682 // Connect to server.
683 r = Sock_Connect(*sock, &addr);
684 if (r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK)
685 {
686 Sock_Close(*sock);
687 return MI_RESULT_FAILED;
688 }
689 return r;
690 #else
691 struct sockaddr_un addr;
692 MI_Result r;
693
694 mike 1.1 *sock = socket(PF_UNIX, SOCK_STREAM, 0);
695
696 if (*sock == -1)
697 return MI_RESULT_FAILED;
698
699 if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))
700 {
701 LOGW((T("fcntl(F_SETFD) failed")));
702 }
703
704 r = Sock_SetBlocking(*sock, MI_FALSE);
705 if (r != MI_RESULT_OK)
706 {
707 Sock_Close(*sock);
708 return MI_RESULT_FAILED;
709 }
710
711 memset(&addr, 0, sizeof(addr));
712
713 addr.sun_family = AF_UNIX;
714 strncpy(addr.sun_path, socketName, sizeof(addr.sun_path)-1);
715 mike 1.1
716 if (0 != connect(*sock, (struct sockaddr *) &addr, sizeof(addr)))
717 {
718 if (_TestWOULDBLOCK() || _TestEAGAIN())
719 return MI_RESULT_WOULD_BLOCK;
720
721 Sock_Close(*sock);
722 return MI_RESULT_FAILED;
723 }
724
725 return MI_RESULT_OK;
726 #endif
727 }
|