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

Diff for /omi/sock/sock.c between version 1.2 and 1.3

version 1.2, 2015/04/20 18:10:35 version 1.3, 2015/04/20 18:20:34
Line 50 
Line 50 
 #endif #endif
  
 #include <base/log.h> #include <base/log.h>
 #include <base/strings.h>  #include <pal/strings.h>
 #include <base/io.h>  #include <pal/format.h>
  
 #define T MI_T  // #define ENABLE_TRACING 1
   #ifdef ENABLE_TRACING
   # define TRACING_LEVEL 4
   # include <deprecated/logging/logging.h>
   #else
   # define LOGE2(a)
   # define LOGW2(a)
   # define LOGD2(a)
   # define LOGX2(a)
   #endif
   
   #define MINSOCKBUFSIZE 4096
  
 /* /*
 **============================================================================== **==============================================================================
Line 67 
Line 78 
 typedef int socklen_t; typedef int socklen_t;
 #endif #endif
  
   MI_INLINE int _GetErrorCode()
   {
   #if defined(CONFIG_OS_WINDOWS)
       return WSAGetLastError();
   #else
       return errno;
   #endif
   }
   
 MI_INLINE int _TestWOULDBLOCK() MI_INLINE int _TestWOULDBLOCK()
 { {
 #if defined(CONFIG_OS_WINDOWS) #if defined(CONFIG_OS_WINDOWS)
     return GetLastError() == WSAEWOULDBLOCK;      return WSAGetLastError() == WSAEWOULDBLOCK;
 #else #else
     return errno == EWOULDBLOCK || errno == EINPROGRESS;     return errno == EWOULDBLOCK || errno == EINPROGRESS;
 #endif #endif
Line 88 
Line 108 
 MI_INLINE int _TestEINTR() MI_INLINE int _TestEINTR()
 { {
 #if defined(CONFIG_OS_WINDOWS) #if defined(CONFIG_OS_WINDOWS)
     return GetLastError() == WSAEINTR;      return WSAGetLastError() == WSAEINTR;
 #else #else
     return errno == EINTR;     return errno == EINTR;
 #endif #endif
 } }
  
   MI_INLINE void _LogSockWriteError()
   {
   #if defined(CONFIG_OS_WINDOWS)
   #else
       trace_SockWrite_Failed(errno);
   #endif
   }
   
 MI_INLINE int _Read(Sock sock, void* data, size_t size) MI_INLINE int _Read(Sock sock, void* data, size_t size)
 { {
 #if defined(CONFIG_OS_WINDOWS) #if defined(CONFIG_OS_WINDOWS)
     return recv(sock, data, (int)size, 0);     return recv(sock, data, (int)size, 0);
 #else #else
     return read(sock, data, size);      int n = read(sock, data, size);
       if (n < 0)
       {
           if (errno == EAGAIN)
               LOGD2((ZT("_Read - read failed with EAGAIN. socket: %d"), sock));
           else
               LOGE2((ZT("_Read - read failed. socket: %d, errno: %d (%s)"), sock, errno, strerror(errno)));
       }
       return n;
 #endif #endif
 } }
  
Line 108 
Line 144 
 #if defined(CONFIG_OS_WINDOWS) #if defined(CONFIG_OS_WINDOWS)
     return send(sock, data, (int)size, 0);     return send(sock, data, (int)size, 0);
 #else #else
     return write(sock, data, size);      int n = write(sock, data, size);
       if (n < 0)
       {
           LOGE2((ZT("_Write - write failed. socket: %d, errno: %d (%s)"), sock, errno, strerror(errno)));
       }
       return n;
 #endif #endif
 } }
  
Line 208 
Line 249 
 #endif /* CONFIG_OS_WINDOWS */ #endif /* CONFIG_OS_WINDOWS */
 } }
  
 MI_Result Sock_Create(Sock* sock)  MI_Result Sock_Create(
       Sock* sock,
       MI_Boolean is_ipv6)
 { {
     *sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);      *sock = socket(is_ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
       if (*sock == INVALID_SOCK)
     if (*sock == -1)  
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
  
     if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))     if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))
     {          trace_fcntl_failed(errno);
         LOGW((T("fcntl(F_SETFD) failed")));  
     }  
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
Line 231 
Line 271 
 #else #else
     status = close(self);     status = close(self);
 #endif #endif
       trace_Sock_Close((int)self);
     return status == 0 ? MI_RESULT_OK : MI_RESULT_FAILED;     return status == 0 ? MI_RESULT_OK : MI_RESULT_FAILED;
 } }
  
 MI_Result Sock_Bind(Sock self, const Addr* addr)  MI_Result Sock_Bind(
       Sock self,
       const Addr* addr)
 { {
     int r;     int r;
  
     r = bind(self, (struct sockaddr*)addr, sizeof(*addr));      r = bind(self, &addr->u.sock_addr, (socklen_t)addr->sock_addr_size);
   
     if (r != 0)     if (r != 0)
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
  
Line 272 
Line 313 
     {     {
         if (_TestWOULDBLOCK() || _TestEAGAIN())         if (_TestWOULDBLOCK() || _TestEAGAIN())
             return MI_RESULT_WOULD_BLOCK;             return MI_RESULT_WOULD_BLOCK;
           else
               return MI_RESULT_FAILED;
     }     }
  
     if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))     if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))
     {     {
         LOGW((T("fcntl(F_SETFD) failed")));          trace_fcntl_failed(errno);
     }     }
       trace_Socket_Accept((int)*sock);
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
Line 306 
Line 349 
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
   
 MI_Result Sock_Connect( MI_Result Sock_Connect(
     Sock self,     Sock self,
     const Addr* addr)     const Addr* addr)
 { {
     int r;     int r;
       int flags;
       int isNonBlockingSocket = 0;
       int connectErrno;
   
       LOGD2((ZT("Sock_Connect - Begin. socket: %d"), self));
   //    lockMutex(self);
       flags = fcntl(self, F_GETFL, 0);
       if ((flags & O_NONBLOCK) != 0)
       {
           isNonBlockingSocket = 1;
           flags &= ~O_NONBLOCK;
           fcntl(self, F_SETFL, flags);
       }
  
     r = connect(self, (struct sockaddr*)addr, sizeof(*addr));      r = connect(self, &addr->u.sock_addr, (size_t)addr->sock_addr_size);
       connectErrno = errno;
  
     if (r != 0)      if (isNonBlockingSocket != 0)
     {     {
         if (_TestWOULDBLOCK() || _TestEAGAIN())          flags |= O_NONBLOCK;
             return MI_RESULT_WOULD_BLOCK;          fcntl(self, F_SETFL, flags);
       }
  
   //    unlockMutex(self);
       if (r < 0)
       {
           LOGE2((ZT("Sock_Connect - Error from connect. socket: %d: errno: %d (%s)"), self, connectErrno, strerror(connectErrno)));
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
  
       LOGD2((ZT("Sock_Connect - OK exit. socket: %d"), self));
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
Line 388 
Line 450 
 { {
     int n;     int n;
  
       LOGD2((ZT("Sock_Read - Begin. socket: %d, size: %u"), (int)self, (unsigned int)size));
   
     * sizeRead = 0;     * sizeRead = 0;
  
     for (;;)     for (;;)
Line 398 
Line 462 
         if (n >= 0)         if (n >= 0)
         {         {
             *sizeRead = n;             *sizeRead = n;
               LOGD2((ZT("Sock_Read - OK exit. %d bytes read"), n));
             return MI_RESULT_OK;             return MI_RESULT_OK;
         }         }
  
         /* Repeat operation if instruction interrupted */         /* Repeat operation if instruction interrupted */
         if (_TestEINTR())         if (_TestEINTR())
           {
               LOGD2((ZT("Sock_Read - _Read returned EINTR")));
             continue;             continue;
           }
  
         /* Check for would block error */         /* Check for would block error */
         if (_TestWOULDBLOCK() || _TestEAGAIN())         if (_TestWOULDBLOCK() || _TestEAGAIN())
           {
               LOGD2((ZT("Sock_Read - _Read returned WOULD_BLOCK")));
             return MI_RESULT_WOULD_BLOCK;             return MI_RESULT_WOULD_BLOCK;
           }
  
         /* Failed */         /* Failed */
           trace_SockRead_Failed( _GetErrorCode() );
         break;         break;
     };      }
   
       LOGE2((ZT("Sock_Read - _Read failed with errno: %d (%s)"), errno, strerror(errno)));
  
     return MI_RESULT_FAILED;     return MI_RESULT_FAILED;
 } }
Line 424 
Line 498 
 { {
     int n;     int n;
  
       LOGD2((ZT("Sock_Write - Begin. socket: %d, size: %u"), (int)self, (unsigned int)size));
   
     *sizeWritten = 0;     *sizeWritten = 0;
  
     for (;;)     for (;;)
     {     {
         /* Attempt to read bytes */          /* Attempt to write bytes */
         n = _Write(self, data, size);         n = _Write(self, data, size);
  
         if (n >= 0)         if (n >= 0)
         {         {
             *sizeWritten = n;              *sizeWritten = (size_t)n;
               LOGD2((ZT("Sock_Write - OK exit. %d bytes written"), n));
             return MI_RESULT_OK;             return MI_RESULT_OK;
         }         }
  
         /* Repeat operation if instruction interrupted */         /* Repeat operation if instruction interrupted */
         if (_TestEINTR())         if (_TestEINTR())
           {
               LOGD2((ZT("Sock_Write - _Write returned EINTR")));
             continue;             continue;
           }
  
         /* Check for would block error */         /* Check for would block error */
         if (_TestWOULDBLOCK() || _TestEAGAIN())         if (_TestWOULDBLOCK() || _TestEAGAIN())
           {
               LOGD2((ZT("Sock_Write - _Write returned WOULD_BLOCK")));
             return MI_RESULT_WOULD_BLOCK;             return MI_RESULT_WOULD_BLOCK;
           }
  
         /* Failed */         /* Failed */
           if (size > MINSOCKBUFSIZE)
           {
               /* Retry operation with smaller buffer size */
               size = size >> 1;
           }
           else
           {
               _LogSockWriteError();
         break;         break;
     };          }
       }
  
       LOGE2((ZT("Sock_Write - _Write failed with errno:L %d (%s)"), errno, strerror(errno)));
     return MI_RESULT_FAILED;     return MI_RESULT_FAILED;
 } }
  
Line 482 
Line 575 
             return MI_RESULT_WOULD_BLOCK;             return MI_RESULT_WOULD_BLOCK;
  
         /* Failed */         /* Failed */
           trace_SockReadV_Failed( _GetErrorCode() );
         break;         break;
     };      }
  
     return MI_RESULT_FAILED;     return MI_RESULT_FAILED;
 } }
Line 494 
Line 588 
     size_t  iovcnt,     size_t  iovcnt,
     size_t* sizeWritten)     size_t* sizeWritten)
 { {
     int n;      int n, error;
  
     * sizeWritten = 0;     * sizeWritten = 0;
  
Line 518 
Line 612 
             return MI_RESULT_WOULD_BLOCK;             return MI_RESULT_WOULD_BLOCK;
  
         /* Failed */         /* Failed */
           error = _GetErrorCode();
           trace_SockWriteV_Failed(error);
   #ifdef CONFIG_OS_WINDOWS
           // On Windows initial send auth message can fail because the sockets is not connected yet
           // in that case we send this special error so it can be retried
           if (WSAENOTCONN == error)
           {
               return MI_RESULT_NOT_FOUND;
           }
   #endif
         break;         break;
     };      }
  
     return MI_RESULT_FAILED;     return MI_RESULT_FAILED;
 } }
Line 532 
Line 636 
  
     /* Create socket */     /* Create socket */
     {     {
         r = Sock_Create(sock);          r = Sock_Create(sock, addr->is_ipv6);
  
         if (r != MI_RESULT_OK)         if (r != MI_RESULT_OK)
             return r;             return r;
Line 588 
Line 692 
     MI_Result r;     MI_Result r;
     struct sockaddr_un addr;     struct sockaddr_un addr;
  
   
     *sock = socket(PF_UNIX, SOCK_STREAM, 0);     *sock = socket(PF_UNIX, SOCK_STREAM, 0);
  
     if (*sock == -1)     if (*sock == -1)
Line 596 
Line 699 
  
     if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))     if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))
     {     {
         LOGW((T("fcntl(F_SETFD) failed")));          trace_fcntl_failed(errno);
     }     }
  
     /* Reuse the address (to prevent binding failures) */     /* Reuse the address (to prevent binding failures) */
Line 618 
Line 721 
         >= sizeof(addr.sun_path))         >= sizeof(addr.sun_path))
     {     {
         Sock_Close(*sock);         Sock_Close(*sock);
         LOGE((T("socket file path too long (> %u): '%s'"),          trace_SocketFilePathTooLong(
             (int)(sizeof(addr.sun_path)-1), socketName));              (int)(sizeof(addr.sun_path)-1), scs(socketName));
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
     }     }
  
     unlink(socketName);     unlink(socketName);
  
     if (0 != bind(*sock, (struct sockaddr *) &addr, sizeof(addr)))      // if (bind(*sock, (const struct sockaddr_un*)&addr, (socklen_t)sizeof (struct sockaddr_un)) != 0)
       if (bind(*sock, (const struct sockaddr*)&addr, (socklen_t)sizeof (struct sockaddr_un)) != 0)
     {     {
         Sock_Close(*sock);         Sock_Close(*sock);
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
Line 660 
Line 764 
     MI_Result r;     MI_Result r;
  
     // Initialize address.     // Initialize address.
     r = Addr_Init(&addr, "127.0.0.1", port);      r = Addr_Init(&addr, "127.0.0.1", port, MI_FALSE);
     if (r != MI_RESULT_OK)     if (r != MI_RESULT_OK)
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
  
     // Create client socket.     // Create client socket.
     r = Sock_Create(sock);      r = Sock_Create(sock, MI_FALSE);
     if (r != MI_RESULT_OK)     if (r != MI_RESULT_OK)
     {     {
         Sock_Close(*sock);         Sock_Close(*sock);
Line 694 
Line 798 
     *sock = socket(PF_UNIX, SOCK_STREAM, 0);     *sock = socket(PF_UNIX, SOCK_STREAM, 0);
  
     if (*sock == -1)     if (*sock == -1)
       {
           trace_LocalSocketFailed(socketName);
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
       }
  
     if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))     if (MI_RESULT_OK != Sock_SetCloseOnExec(*sock,MI_TRUE))
     {     {
         LOGW((T("fcntl(F_SETFD) failed")));          trace_LocalSocket_SetOnExecFailed(socketName);
           trace_fcntl_failed(errno);
     }     }
  
     r = Sock_SetBlocking(*sock, MI_FALSE);     r = Sock_SetBlocking(*sock, MI_FALSE);
     if (r != MI_RESULT_OK)     if (r != MI_RESULT_OK)
     {     {
           trace_LocalSocket_SetBlockingFailed(socketName);
         Sock_Close(*sock);         Sock_Close(*sock);
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
Line 711 
Line 820 
     memset(&addr, 0, sizeof(addr));     memset(&addr, 0, sizeof(addr));
  
     addr.sun_family = AF_UNIX;     addr.sun_family = AF_UNIX;
     strncpy(addr.sun_path, socketName, sizeof(addr.sun_path)-1);      strncpy(addr.sun_path, socketName, sizeof addr.sun_path - 1);
  
     if (0 != connect(*sock, (struct sockaddr *) &addr, sizeof(addr)))      // if (connect(*sock, (const struct sockaddr_un*)&addr, (socklen_t)sizeof (struct sockaddr_un)) != 0)
       if (connect(*sock, (const struct sockaddr*)&addr, (socklen_t)sizeof (struct sockaddr_un)) != 0)
     {     {
         if (_TestWOULDBLOCK() || _TestEAGAIN())         if (_TestWOULDBLOCK() || _TestEAGAIN())
             return MI_RESULT_WOULD_BLOCK;             return MI_RESULT_WOULD_BLOCK;
  
           trace_LocalSocket_ConnectFailed(socketName, errno);
   
         Sock_Close(*sock);         Sock_Close(*sock);
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
Line 725 
Line 837 
     return MI_RESULT_OK;     return MI_RESULT_OK;
 #endif #endif
 } }
   
   static MI_Result _CreateSocketAndConnect(
       Sock* s,
       Addr* addr)
   {
       MI_Result r;
   
       // Create client socket.
       r = Sock_Create(s, addr->is_ipv6);
       if (r != MI_RESULT_OK)
       {
           LOGE2((ZT("_CreateSocketAndConnect - Sock_Create failed. result: %d (%s)"), r, mistrerror(r)));
           return r;
       }
   
       r = Sock_SetBlocking(*s, MI_FALSE);
       if (r != MI_RESULT_OK)
           return r;
   
       r = Sock_Connect(*s, addr);
       if (r != MI_RESULT_OK)
       {
           if (r == MI_RESULT_WOULD_BLOCK)
           {
               LOGW2((ZT("_CreateSocketAndConnect - Sock_Connect would block")));
           }
           else
           {
               LOGE2((ZT("_CreateSocketAndConnect - Sock_Connect failed. result: %d (%s)"), r, mistrerror(r)));
           }
       }
   
       return r;
   }
   
   MI_Result Sock_CreateIPConnector(
       Sock* s,
       const char* hostAndPort)
   {
       /* create a connector to a remote address given in the form _host_:_port_ */
       Addr addr;
       MI_Result r;
       unsigned short port;
       size_t len;
       char host[128];
       /* TODO: detect IPv6 numeric addresses, in the form XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX/dd */
       const char* posColon = strchr(hostAndPort, ':');
   
       if (posColon == NULL)
           return MI_RESULT_INVALID_PARAMETER;
       len = (size_t)(posColon - hostAndPort);
       if (len >= sizeof host)
           return MI_RESULT_INVALID_PARAMETER;
       port = (unsigned short)atol(posColon + 1);
           memcpy(host, hostAndPort, len);
       host[len] = '\0';
   
       /* This code tries to connect using the primary addressing family */
                   /* (IPv4 or IPv6). If that fails and Addr_Init has a secondary */
                   /* addressing family, it tries using the secondary family next. */
   
       /* Initialize primary family address. */
       r = Addr_Init(&addr, host, port, MI_FALSE);
       if (r != MI_RESULT_OK)
           return r;
   
       /* Connect to server. */
       r = _CreateSocketAndConnect(s, &addr);
       if (r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK)
       {
           MI_Result r2;
   
           Sock_Close(*s);
   
           /* Initialize secondary address. */
           r2 = Addr_Init(&addr, host, port, MI_TRUE);
           if (r2 != MI_RESULT_OK)
               return r;               /* on error, return original failure */
           r2 = _CreateSocketAndConnect(s, &addr);
           if (r2 != MI_RESULT_OK && r2 != MI_RESULT_WOULD_BLOCK)
           {
               Sock_Close(*s);
   
               return r;               /* on error, return original failure */
           }
           r = r2;
       }
   
   #ifdef ENABLE_TRACING
       if (r != MI_RESULT_OK)
           LOGD2((ZT("_CreateConnector - Connect failure. host: %s, result: %d (%s)"), host, (int)r, mistrerror(r)));
   #endif
   
       return r;
   }


Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

ViewCVS 0.9.2