]> git.mxchange.org Git - simgear.git/blobdiff - simgear/io/raw_socket.cxx
Add optional attribute condition to "copyProperties".
[simgear.git] / simgear / io / raw_socket.cxx
index 7af6c695b372d8326e9376fe347be85732b52ca0..971ff31f70e7129659399e6a39a3397d33a626ff 100644 (file)
@@ -190,6 +190,25 @@ bool Socket::open ( bool stream )
 {
   close () ;
   handle = ::socket ( AF_INET, (stream? SOCK_STREAM: SOCK_DGRAM), 0 ) ;
+
+  // Jan 26, 2010: Patch to avoid the problem of the socket resource not
+  // yet being available if the program is restarted quickly after being
+  // killed.
+  //
+  // Reference: http://www.unixguide.net/network/socketfaq/4.5.shtml
+  // --
+  // Also required for joining multicast domains
+  if ( stream ) {
+    int opt_boolean = 1;
+#if defined(_WIN32) || defined(__CYGWIN__)
+    setsockopt( handle, SOL_SOCKET, SO_REUSEADDR, (char *)&opt_boolean,
+               sizeof(opt_boolean) );
+#else
+    setsockopt( handle, SOL_SOCKET, SO_REUSEADDR, &opt_boolean,
+               sizeof(opt_boolean) );
+#endif
+  }
+
   return (handle != -1);
 }
 
@@ -238,9 +257,44 @@ void Socket::setBroadcast ( bool broadcast )
 
 int Socket::bind ( const char* host, int port )
 {
+  int result;
   assert ( handle != -1 ) ;
   IPAddress addr ( host, port ) ;
-  return ::bind(handle,(const sockaddr*)&addr,sizeof(IPAddress));
+
+#if !defined(WINSOCK)
+  if( (result = ::bind(handle,(const sockaddr*)&addr,sizeof(IPAddress))) < 0 ) {
+    SG_LOG(SG_IO, SG_ALERT, "bind(" << host << ":" << port << ") failed. Errno " << errno << " (" << strerror(errno) << ")");
+    return result;
+  }
+#endif
+
+  // 224.0.0.0 - 239.255.255.255 are multicast   
+  // Usage of 239.x.x.x is recommended for local scope
+  // Reference: http://tools.ietf.org/html/rfc5771
+  if( ntohl(addr.getIP()) >= 0xe0000000 && ntohl(addr.getIP()) <= 0xefffffff ) {
+
+#if defined(WINSOCK)
+    struct sockaddr_in a;
+    a.sin_addr.S_un.S_addr = INADDR_ANY;
+    a.sin_family = AF_INET;
+    a.sin_port = htons(port);
+      
+    if( (result = ::bind(handle,(const sockaddr*)&a,sizeof(a))) < 0 ) {
+      SG_LOG(SG_IO, SG_ALERT, "bind(any:" << port << ") failed. Errno " << errno << " (" << strerror(errno) << ")");
+      return result;
+    }
+#endif
+
+    struct ip_mreq mreq;
+    mreq.imr_multiaddr.s_addr = addr.getIP();
+    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+    if( (result=::setsockopt(getHandle(), IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq))) != 0 ) {
+      SG_LOG(SG_IO, SG_ALERT, "setsockopt(IP_ADD_MEMBERSHIP) failed. Errno " << errno << " (" << strerror(errno) << ")");
+      return result;
+    }
+  }
+
+  return 0;
 }
 
 
@@ -331,7 +385,7 @@ bool Socket::isNonBlockingError ()
   if ( wsa_errno != 0 )
   {
     WSASetLastError(0);
-    ulSetError(UL_WARNING,"WSAGetLastError() => %d",wsa_errno);
+       SG_LOG(SG_IO, SG_WARN, "isNonBlockingError: WSAGetLastError():" << wsa_errno);
     switch (wsa_errno) {
     case WSAEWOULDBLOCK: // always == NET_EAGAIN?
     case WSAEALREADY:
@@ -474,8 +528,7 @@ int Socket::initSockets()
        WSADATA wsaData;
 
        if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
-               ulSetError(UL_WARNING,"Couldn't initialize Winsock 1.1");
-               return(-1);
+               throw sg_exception("WinSock initialization failed");
        }
 #endif