(file) Return to sock.c CVS log (file) (dir) Up to [OMI] / omi / protocol

  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           }

ViewCVS 0.9.2