2 #include <sys/socket.h>
10 #include <netinet/in.h>
12 #include <arpa/inet.h>
14 #include <sys/ioctl.h>
17 #include "cawificore.h"
19 #include "uthreadpool.h" /* for thread pool */
21 #include "caqueueingthread.h"
22 #include "oic_malloc.h"
27 #define CA_MAX_BUFFER_SIZE 512 // Max length of buffer
28 #define CA_UNICAST_PORT 5000 // The port on which to listen for incoming data
29 #define CA_MULTICAST_ADDR "224.0.1.187"
30 #define CA_MULTICAST_PORT 5683
34 CA_UNICAST = 1, CA_MULTICAST
35 } CATransmissionType_t;
39 CATransmissionType_t transmissionType; // 0: none, 1: unicast, 2: multicast
51 int32_t status; // 0: stopped, 1: running
54 static int gUnicastPort = 0;
56 int32_t unicast_receive_socket; // unicast server, unicast client, multicast client
57 struct sockaddr_in multicast_send_interface_addr;
59 int32_t multicast_receive_socket; // multicast server
60 struct sockaddr_in multicast_receive_interface_addr;
62 static CAPacketReceiveCallback gPacketReceiveCallback = NULL;
64 static u_thread_pool_t gThreadPoolHandle = NULL;
66 // message handler main thread
67 static CAQueueingThread_t gSendThread;
68 static CAQueueingThread_t gReceiveThread;
70 static CATask_t unicastListenTask;
71 static CATask_t multicastListenTask;
73 static void CASendProcess(void* threadData)
75 OIC_LOG(DEBUG, TAG, "CASendThreadProcess");
77 CAThreadData_t* data = (CAThreadData_t*) threadData;
80 OIC_LOG(DEBUG, TAG, "thread data is error!");
84 if (data->transmissionType == CA_UNICAST)
87 CASendUnicastMessageImpl(data->address, data->port, (char*) (data->data), data->len);
89 else if (data->transmissionType == CA_MULTICAST)
92 CASendMulticastMessageImpl((char*) (data->data), data->len);
96 static void CAReceiveProcess(void* threadData)
98 OIC_LOG(DEBUG, TAG, "CAReceiveProcess");
100 CAThreadData_t* data = (CAThreadData_t*) threadData;
103 OIC_LOG(DEBUG, TAG, "thread data is error!");
107 if (gPacketReceiveCallback != NULL)
109 gPacketReceiveCallback(data->address, data->port, (char*) (data->data), data->len);
113 void CAWiFiSetCallback(CAPacketReceiveCallback callback)
115 gPacketReceiveCallback = callback;
118 void CAWiFiInitMutex()
120 OIC_LOG(DEBUG, TAG, "CAWiFiInitMutex");
122 unicastListenTask.threadMutex = u_mutex_new();
123 unicastListenTask.threadCond = u_cond_new();
124 unicastListenTask.isStop = FALSE;
125 unicastListenTask.status = 0; // stopped
127 multicastListenTask.threadMutex = u_mutex_new();
128 multicastListenTask.threadCond = u_cond_new();
129 multicastListenTask.isStop = FALSE;
130 multicastListenTask.status = 0; // stopped
133 static void CAUnicastListenThread(void* threadData)
135 OIC_LOG(DEBUG, TAG, "CAUnicastListenThread");
137 char buf[CA_MAX_BUFFER_SIZE];
142 struct sockaddr_in si_other;
143 socklen_t slen = sizeof(si_other);
146 struct timeval timeout;
150 u_mutex_lock(unicastListenTask.threadMutex);
151 int32_t isStop = unicastListenTask.isStop;
152 u_mutex_unlock(unicastListenTask.threadMutex);
156 // OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, Waiting for data...");
158 memset(buf, 0, sizeof(char) * CA_MAX_BUFFER_SIZE);
165 // Use select for polling the socket fd
166 FD_SET(unicast_receive_socket, &reads);
168 ret = select(unicast_receive_socket + 1, &reads, NULL, NULL, &timeout);
171 // OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, select API failed");
175 if (!FD_ISSET(unicast_receive_socket, &reads))
177 // OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, No data to read");
181 // try to receive some data
182 if ((recv_len = recvfrom(unicast_receive_socket, buf, CA_MAX_BUFFER_SIZE, 0,
183 (struct sockaddr *) &si_other, &slen)) == -1)
185 OIC_LOG_V(DEBUG, TAG, "%s\n", strerror(errno));
188 else if (0 == recv_len)
190 OIC_LOG(DEBUG, TAG, "Unicast socket is shutdown, returning from thread\n");
194 // print details of the client/peer and the data received
195 OIC_LOG_V(DEBUG, TAG, "CAUnicastListenThread, Received packet from %s:%d",
196 inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
197 OIC_LOG_V(DEBUG, TAG, "CAUnicastListenThread, Data: %s", buf);
199 // store the data at queue.
200 CAThreadData_t* td = NULL;
201 td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
202 memset(td, 0, sizeof(CAThreadData_t));
203 td->transmissionType = 1; // unicast
205 char* _address = inet_ntoa(si_other.sin_addr);
206 int len = strlen(_address);
207 td->address = (char*) OICMalloc(sizeof(char) * (len + 1));
208 memset(td->address, 0, len + 1);
209 memcpy(td->address, _address, len);
211 td->port = ntohs(si_other.sin_port);
213 td->data = (void*) OICMalloc(sizeof(void) * CA_MAX_BUFFER_SIZE);
214 memset(td->data, 0, CA_MAX_BUFFER_SIZE);
215 memcpy(td->data, buf, sizeof(buf));
218 CAQueueingThreadAddData(&gReceiveThread, td, sizeof(CAThreadData_t));
221 u_cond_signal(unicastListenTask.threadCond);
222 OIC_LOG(DEBUG, TAG, "end of CAUnicastListenThread");
225 static void CAMulticastListenThread(void* threadData)
227 OIC_LOG(DEBUG, TAG, "CAMulticastListenThread");
229 char msgbuf[CA_MAX_BUFFER_SIZE];
231 struct sockaddr_in client;
232 int32_t addrlen = sizeof(client);
235 struct timeval timeout;
239 u_mutex_lock(multicastListenTask.threadMutex);
240 int32_t isStop = multicastListenTask.isStop;
241 u_mutex_unlock(multicastListenTask.threadMutex);
250 // Use select for polling the socket fd
251 FD_SET(multicast_receive_socket, &reads);
253 int32_t ret = select(multicast_receive_socket + 1, &reads, NULL, NULL, &timeout);
256 // OIC_LOG_V(FATAL, TAG, "CAMulticastListenThread, select API failed");
259 if (!FD_ISSET(multicast_receive_socket, &reads))
261 // OIC_LOG_V(DEBUG, TAG, "CAMulticastListenThread, No data to read");
265 // try to receive some data
266 int32_t recv_bytes = 0;
267 if ((recv_bytes = recvfrom(multicast_receive_socket, msgbuf, CA_MAX_BUFFER_SIZE, 0,
268 (struct sockaddr *) &client, (socklen_t *) &addrlen)) == -1)
270 OIC_LOG_V(DEBUG, TAG, "%s\n", strerror(errno));
273 else if (0 == recv_bytes)
275 OIC_LOG_V(ERROR, TAG, "Multicast socket is shutdown, returning from thread\n");
276 OIC_LOG(DEBUG, TAG, "return here ");
280 OIC_LOG_V(DEBUG, TAG, "Received msg: %s, size: %d", msgbuf, recv_bytes);
282 // store the data at queue.
283 CAThreadData_t* td = NULL;
284 td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
285 memset(td, 0, sizeof(CAThreadData_t));
286 td->transmissionType = 2; // multicast
288 char* _address = inet_ntoa(client.sin_addr);
289 int len = strlen(_address);
290 td->address = (char*) OICMalloc(sizeof(char) * (len + 1));
291 memset(td->address, 0, len + 1);
292 memcpy(td->address, _address, len);
293 td->port = ntohs(client.sin_port);
295 td->data = (void*) OICMalloc(sizeof(void) * CA_MAX_BUFFER_SIZE);
296 memset(td->data, 0, CA_MAX_BUFFER_SIZE);
297 memcpy(td->data, msgbuf, sizeof(msgbuf));
298 td->len = recv_bytes;
300 CAQueueingThreadAddData(&gReceiveThread, td, sizeof(CAThreadData_t));
304 // leave the group after you are done
305 int16_t result = setsockopt(multicast_receive_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
306 (struct sockaddr *) &multicast_receive_interface_addr,
307 sizeof(multicast_receive_interface_addr));
310 OIC_LOG_V(DEBUG, TAG,
311 "CAWiFiStopMulticastServer, cannot leave multicast group, Error code: %s\n",
314 u_cond_signal(multicastListenTask.threadCond);
316 OIC_LOG(DEBUG, TAG, "end of CAMulticastListenThread");
319 void CAWiFiInitialize(u_thread_pool_t handle)
321 OIC_LOG(DEBUG, TAG, "CAWiFiInitialize");
323 gThreadPoolHandle = handle;
325 // unicast/multicast send queue
326 CAQueueingThreadInitialize(&gSendThread, gThreadPoolHandle, CASendProcess);
329 CAResult_t res = CAQueueingThreadStart(&gSendThread);
330 if (res != CA_STATUS_OK)
332 OIC_LOG(DEBUG, TAG, "thread start is error (send thread)");
337 // unicast/multicast receive queue
338 CAQueueingThreadInitialize(&gReceiveThread, gThreadPoolHandle, CAReceiveProcess);
341 res = CAQueueingThreadStart(&gReceiveThread);
342 if (res != CA_STATUS_OK)
344 OIC_LOG(DEBUG, TAG, "thread start is error (receive thread)");
350 int32_t CABindUnicastSocket()
353 for (i = 0; i < 100; i++)
355 int32_t port = CA_UNICAST_PORT + i;
357 struct sockaddr_in si_me;
358 memset((char *) &si_me, 0, sizeof(si_me));
359 si_me.sin_family = AF_INET;
360 si_me.sin_port = htons(port);
361 si_me.sin_addr.s_addr = htonl(INADDR_ANY);
363 // bind socket to port
364 if (bind(unicast_receive_socket, (struct sockaddr*) &si_me, sizeof(si_me)) == 0)
366 OIC_LOG_V(DEBUG, TAG, "CABindUnicastSocket, socket binded, port: %d", port);
375 OIC_LOG(DEBUG, TAG, "CABindUnicastSocket, binding socket failed");
380 void CAWiFiTerminate()
382 OIC_LOG(DEBUG, TAG, "CAWiFiTerminate");
384 close(unicast_receive_socket);
385 close(multicast_receive_socket);
388 CAQueueingThreadStop(&gSendThread);
389 // delete thread data
390 CAQueueingThreadDestroy(&gSendThread);
393 CAQueueingThreadStop(&gReceiveThread);
394 // delete thread data
395 CAQueueingThreadDestroy(&gReceiveThread);
397 u_mutex_free(unicastListenTask.threadMutex);
399 u_mutex_free(multicastListenTask.threadMutex);
401 OIC_LOG(DEBUG, TAG, "end of CAWiFiTerminate");
404 int32_t CAWiFiSendUnicastMessage(const char* address, const int port, char* data, uint32_t lengh)
406 // store the data at queue.
407 CAThreadData_t* td = NULL;
408 td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
414 memset(td, 0, sizeof(CAThreadData_t));
415 td->transmissionType = CA_UNICAST; // unicast type
416 int len = strlen(address);
417 td->address = (char*) OICMalloc(sizeof(char) * (len + 1));
418 if (td->address != NULL)
420 memset(td->address, 0, len + 1);
421 memcpy(td->address, address, len);
425 OIC_LOG_V(DEBUG, TAG, "Memory Full");
435 CAQueueingThreadAddData(&gSendThread, td, sizeof(CAThreadData_t));
440 int32_t CAWiFiSendMulticastMessage(const char* m_address, char* data, uint32_t dataLen)
442 // store the data at queue.
443 CAThreadData_t* td = NULL;
444 td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
450 memset(td, 0, sizeof(CAThreadData_t));
451 td->transmissionType = CA_MULTICAST; // multicast type
457 CAQueueingThreadAddData(&gSendThread, td, sizeof(CAThreadData_t));
462 int32_t CAWiFiStartUnicastServer()
464 OIC_LOG_V(DEBUG, TAG, "CAWiFiStartUnicastServer");
466 // check the server status
467 if (unicastListenTask.status == 1)
469 OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer, already running");
474 // 1. create a UDP socket
475 if ((unicast_receive_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
477 OIC_LOG_V(DEBUG, TAG, "CAWiFiInitialize, creating socket failed");
482 OIC_LOG(DEBUG, TAG, "CAWiFiInitialize, socket created");
484 // 2. Make the socket non-blocking
486 if ((status = fcntl(unicast_receive_socket, F_SETFL, O_NONBLOCK)) < 0)
488 OIC_LOG_V(ERROR, TAG,
489 "CAWiFiInitialize, fcntl to make the socket non-blocking failed, Error code: %s",
492 close(unicast_receive_socket);
497 OIC_LOG(DEBUG, TAG, "CAWiFiInitialize, socket creation success");
499 // 3. set socket option // This is will allow server , client bining on same socket
500 /* uint32_t multiTTL = 1;
501 int32_t ret_val = setsockopt(unicast_receive_socket, SOL_SOCKET, SO_REUSEADDR, &multiTTL,
505 OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to set REUSEADDR");
506 close(unicast_receive_socket);
512 if (CABindUnicastSocket() == -1)
514 close(unicast_receive_socket);
519 // unicast listen thread
520 CAResult_t res = u_thread_pool_add_task(gThreadPoolHandle, CAUnicastListenThread, NULL);
521 if (res != CA_STATUS_OK)
523 OIC_LOG(DEBUG, TAG, "adding task to thread pool is error (unicast listen thread)");
527 unicastListenTask.status = 1; // running
528 OIC_LOG_V(DEBUG, TAG, "CAWiFiStartUnicastServer(%s, %d)", "Local Address", gUnicastPort);
533 int32_t CAWiFiStartMulticastServer()
535 OIC_LOG_V(DEBUG, TAG, "CAWiFiStartMulticastServer(%s, %d)", "0.0.0.0", CA_MULTICAST_PORT);
537 // check the server status
538 if (multicastListenTask.status == 1)
540 OIC_LOG(DEBUG, TAG, "CAWiFiStartMulticastServer, already running");
545 memset(&multicast_send_interface_addr, 0, sizeof(multicast_send_interface_addr));
546 multicast_send_interface_addr.sin_family = AF_INET;
547 multicast_send_interface_addr.sin_addr.s_addr = inet_addr(CA_MULTICAST_ADDR);
548 multicast_send_interface_addr.sin_port = htons(CA_MULTICAST_PORT);
550 // 1. Create a typical UDP socket and set Non-blocking for reading
551 multicast_receive_socket = socket(AF_INET, SOCK_DGRAM, 0);
552 if (multicast_receive_socket == -1)
554 OIC_LOG(DEBUG, TAG, "CAWiFiInit, Socket error");
559 // 2. Make the socket non-blocking
561 if ((status = fcntl(multicast_receive_socket, F_SETFL, O_NONBLOCK)) < 0)
563 OIC_LOG_V(ERROR, TAG, "fcntl to make the socket non-blocking failed, Error code: %s",
565 close(multicast_receive_socket);
570 // 2. Allow multiple sockets to use the same port number
571 uint32_t multiTTL = 1;
572 int32_t ret_val = setsockopt(multicast_receive_socket, SOL_SOCKET, SO_REUSEADDR, &multiTTL,
576 OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to set REUSEADDR");
577 close(multicast_receive_socket);
582 // 3. Set up the interface
583 memset(&multicast_receive_interface_addr, 0, sizeof(multicast_receive_interface_addr));
584 multicast_receive_interface_addr.sin_family = AF_INET;
585 multicast_receive_interface_addr.sin_addr.s_addr = htonl(INADDR_ANY);
586 multicast_receive_interface_addr.sin_port = htons(CA_MULTICAST_PORT);
588 // 4. Bind to the interface
589 ret_val = bind(multicast_receive_socket, (struct sockaddr *) &multicast_receive_interface_addr,
590 sizeof(multicast_receive_interface_addr));
593 OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to bind socket");
594 close(multicast_receive_socket);
599 // 5. Join the multicast group
601 memset(&mreq, 0, sizeof(mreq));
602 mreq.imr_multiaddr.s_addr = inet_addr(CA_MULTICAST_ADDR);
603 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
604 ret_val = setsockopt(multicast_receive_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
608 OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to join multicast group");
609 close(multicast_receive_socket);
614 // multicast listen thread
615 CAResult_t res = u_thread_pool_add_task(gThreadPoolHandle, CAMulticastListenThread, NULL);
616 if (res != CA_STATUS_OK)
618 OIC_LOG(DEBUG, TAG, "adding task to thread pool is error (multicast listen thread)");
622 multicastListenTask.status = 1;
627 int32_t CAWiFiStopUnicastServer()
629 OIC_LOG(DEBUG, TAG, "CAWiFiStopUnicastServer");
631 // check the server status
632 if (unicastListenTask.status == 0)
634 OIC_LOG(DEBUG, TAG, "CAWiFiStopUnicastServer, already stopped");
640 u_mutex_lock(unicastListenTask.threadMutex);
643 unicastListenTask.isStop = TRUE;
645 u_cond_wait(unicastListenTask.threadCond, unicastListenTask.threadMutex);
648 // u_cond_signal(unicastListenTask.threadCond);
651 u_mutex_unlock(unicastListenTask.threadMutex);
653 unicastListenTask.status = 0; // stopped
655 // close(unicast_receive_socket);
660 int32_t CAWiFiStopMulticastServer()
662 OIC_LOG(DEBUG, TAG, "CAWiFiStopMulticastServer");
664 // check the server status
665 if (multicastListenTask.status == 0)
667 OIC_LOG(DEBUG, TAG, "CAWiFiStopMulticastServer, already stopped");
673 u_mutex_lock(multicastListenTask.threadMutex);
676 multicastListenTask.isStop = TRUE;
678 u_cond_wait(multicastListenTask.threadCond, multicastListenTask.threadMutex);
681 u_mutex_unlock(multicastListenTask.threadMutex);
683 multicastListenTask.status = 0; // stopped
688 void CAGetLocalAddress(char* addressBuffer)
690 //char addressBuffer[INET_ADDRSTRLEN];
691 memset(addressBuffer, 0, INET_ADDRSTRLEN);
693 struct ifaddrs* ifAddrStruct = NULL;
694 struct ifaddrs* ifa = NULL;
695 void* tmpAddrPtr = NULL;
697 getifaddrs(&ifAddrStruct);
699 for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
706 if (ifa->ifa_addr->sa_family == AF_INET)
708 // is a valid IP4 Address
709 tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
711 memset(addressBuffer, 0, INET_ADDRSTRLEN);
712 inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
714 if (strcmp(addressBuffer, "127.0.0.1") == 0)
719 if (ifAddrStruct != NULL)
720 freeifaddrs(ifAddrStruct);
723 int32_t CASendUnicastMessageImpl(const char* address, const int port, const char* data,
726 OIC_LOG_V(DEBUG, TAG, "CASendUnicastMessageImpl, address: %s:%d, data: %s", address, port,
731 struct sockaddr_in si_other;
732 int32_t slen = sizeof(si_other);
734 memset((char *) &si_other, 0, sizeof(si_other));
736 si_other.sin_family = AF_INET;
737 si_other.sin_port = htons(port);
738 if (inet_aton(address, &si_other.sin_addr) == 0)
740 OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, inet_aton, error...");
744 OIC_LOG_V(DEBUG, TAG, "CASendUnicastMessageImpl, sendto, to: %s, data: %s", address, data);
745 if (sendto(unicast_receive_socket, data, len, 0, (struct sockaddr *) &si_other, slen) == -1)
747 OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, sendto, error...");
755 int32_t CASendMulticastMessageImpl(const char* msg, uint32_t len)
757 OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, sendto, data: %s", msg);
759 int32_t result = sendto(unicast_receive_socket, msg, len, 0,
760 (struct sockaddr *) &multicast_send_interface_addr,
761 sizeof(multicast_send_interface_addr));
764 OIC_LOG(DEBUG, TAG, "CASendMulticastMessageImpl, sending message error...");
772 CAResult_t CAGetWIFIInterfaceInfo(CALocalConnectivity_t **info, uint32_t* size)
774 uint32_t cnt, req_cnt = REQ_CNT;
776 uint32_t cmd = SIOCGIFCONF;
777 uint32_t resSize = 0;
778 char* localIPAddress;
779 struct sockaddr_in *sock;
783 memset((void *) &ifc, 0, sizeof(struct ifconf));
784 ifc.ifc_len = sizeof(struct ifconf) * req_cnt;
786 ifc.ifc_buf = malloc(ifc.ifc_len);
788 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
790 OIC_LOG(DEBUG, TAG, "create socket error!");
791 return CA_STATUS_FAILED;
794 if (ioctl(fd, cmd, &ifc) < 0)
796 OIC_LOG(DEBUG, TAG, "SIOCGIFCONF fail");
798 return CA_STATUS_FAILED;
802 if (ifc.ifc_len > (sizeof(struct ifreq) * req_cnt))
804 req_cnt = ifc.ifc_len;
805 ifc.ifc_buf = realloc(ifc.ifc_buf, req_cnt);
809 for (cnt = 0; cnt < ifc.ifc_len; cnt += sizeof(struct ifreq), ifr++)
811 sock = (struct sockaddr_in *) &ifr->ifr_addr;
813 // except loopback address
814 if (ntohl(sock->sin_addr.s_addr) == INADDR_LOOPBACK)
818 localIPAddress = inet_ntoa(sock->sin_addr);
820 CALocalConnectivity_t* localInfo;
823 localInfo = (CALocalConnectivity_t*) OICMalloc(sizeof(CALocalConnectivity_t));
824 if (localInfo == NULL)
826 OIC_LOG_V(DEBUG, TAG, "memory alloc error!!");
828 return CA_STATUS_FAILED;
830 memset(localInfo, 0, sizeof(CALocalConnectivity_t));
832 if (strlen(localIPAddress) > CA_IPADDR_SIZE)
834 OIC_LOG_V(DEBUG, TAG, "address size is wrong!!");
836 return CA_STATUS_FAILED;
838 // set local ip address
839 strncpy(localInfo->addressInfo.IP.ipAddress, localIPAddress, strlen(localIPAddress));
842 localInfo->type = CA_WIFI;