Fixing 2 issues in LifxLightBulb driver: 1) Detached thread handling (need to pass...
[iot2.git] / iotjava / iotruntime / cpp / socket / Socket.cpp
index ceac82ba57198698af312ac5b45db1fd25e4221a..667411a207d8e8c5c444b02b87baca56a529d19f 100644 (file)
@@ -27,6 +27,7 @@
   typedef char raw_type;       // Type used for raw data on this platform
 #else
   #include <sys/types.h>       // For data types
+  #include <sys/select.h>      // For select() - non-blocking socket
   #include <sys/socket.h>      // For socket(), connect(), send(), and recv()
   #include <netdb.h>           // For gethostbyname()
   #include <arpa/inet.h>       // For inet_addr()
@@ -37,6 +38,7 @@
 
 #include <errno.h>             // For errno
 #include <string.h>            // For memset
+#include <fcntl.h>             // For fcntl
 
 using namespace std;
 
@@ -351,6 +353,38 @@ int UDPSocket::recvFrom(void *buffer, int bufferLen, string &sourceAddress,
   return rtn;
 }
 
+int UDPSocket::recvFrom(void *buffer, int bufferLen, string &sourceAddress,
+    unsigned short &sourcePort, int timeOut) throw(SocketException) {
+
+  if(!(fcntl(sockDesc, F_GETFL) & O_NONBLOCK)) {
+  // If not non-blocking then put it into non-blocking
+     if(fcntl(sockDesc, F_SETFL, fcntl(sockDesc, F_GETFL) | O_NONBLOCK) < 0) {
+        throw SocketException("Set non-blocking failed (recvfrom())", true);
+     }
+  }
+  fd_set readFds;  // FD
+  FD_ZERO(&readFds);
+  FD_SET(sockDesc, &readFds);
+  struct timeval to;   // timeout
+  to.tv_sec = 0;
+  to.tv_usec = timeOut;
+  sockaddr_in clntAddr;
+  socklen_t addrLen = sizeof(clntAddr);
+  
+  int rv = select(sockDesc+1 ,&readFds, NULL, NULL, &to);
+  int rtn = -1;        // Assuming receive failure
+  if (rv == 1) {
+        if ((rtn = recvfrom(sockDesc, (raw_type *) buffer, bufferLen, 0, 
+                         (sockaddr *) &clntAddr, (socklen_t *) &addrLen)) < 0) {
+        throw SocketException("Receive failed (recvfrom())", true);
+        }
+        sourceAddress = inet_ntoa(clntAddr.sin_addr);
+        sourcePort = ntohs(clntAddr.sin_port);
+  }
+
+  return rtn;
+}
+
 void UDPSocket::setMulticastTTL(unsigned char multicastTTL) throw(SocketException) {
   if (setsockopt(sockDesc, IPPROTO_IP, IP_MULTICAST_TTL, 
                  (raw_type *) &multicastTTL, sizeof(multicastTTL)) < 0) {
@@ -381,3 +415,14 @@ void UDPSocket::leaveGroup(const string &multicastGroup) throw(SocketException)
     throw SocketException("Multicast group leave failed (setsockopt())", true);
   }
 }
+
+void UDPSocket::setTimeOut(int interval) throw(SocketException) {
+
+  struct timeval timeout;
+  timeout.tv_sec = 0;
+  timeout.tv_usec = interval;
+  if (setsockopt(sockDesc, SOL_SOCKET, SO_RCVTIMEO, &timeout, 
+                 sizeof(timeout)) < 0) {
+    throw SocketException("Multicast group join failed (setsockopt())", true);
+  }
+}