Merge branch 'master' into connectivity-abstraction
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / wifi_adapter / linux / cawificore.c
1 #include <stdio.h>
2 #include <sys/socket.h>
3 #include <arpa/inet.h>
4 #include <string.h>
5 #include <pthread.h>
6 #include <unistd.h>
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <ifaddrs.h>
10 #include <netinet/in.h>
11 #include <string.h>
12 #include <arpa/inet.h>
13 #include <fcntl.h>
14 #include <sys/ioctl.h>
15 #include <net/if.h>
16
17 #include "cawificore.h"
18 #include "logger.h"
19 #include "uthreadpool.h" /* for thread pool */
20 #include "umutex.h"
21 #include "caqueueingthread.h"
22 #include "oic_malloc.h"
23
24 #define TAG PCF("CA")
25
26 #define REQ_CNT 20
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
31
32 typedef enum
33 {
34     CA_UNICAST = 1, CA_MULTICAST
35 } CATransmissionType_t;
36
37 typedef struct
38 {
39     CATransmissionType_t transmissionType; // 0: none, 1: unicast, 2: multicast
40     char* address;
41     int port;
42     void* data;
43     uint32_t len;
44 } CAThreadData_t;
45
46 typedef struct
47 {
48     u_mutex threadMutex;
49     u_cond threadCond;
50     int32_t isStop;
51     int32_t status; // 0: stopped, 1: running
52 } CATask_t;
53
54 static int gUnicastPort = 0;
55
56 int32_t unicast_receive_socket; // unicast server, unicast client, multicast client
57 struct sockaddr_in multicast_send_interface_addr;
58
59 int32_t multicast_receive_socket; // multicast server
60 struct sockaddr_in multicast_receive_interface_addr;
61
62 static CAPacketReceiveCallback gPacketReceiveCallback = NULL;
63
64 static u_thread_pool_t gThreadPoolHandle = NULL;
65
66 // message handler main thread
67 static CAQueueingThread_t gSendThread;
68 static CAQueueingThread_t gReceiveThread;
69
70 static CATask_t unicastListenTask;
71 static CATask_t multicastListenTask;
72
73 static void CASendProcess(void* threadData)
74 {
75     OIC_LOG(DEBUG, TAG, "CASendThreadProcess");
76
77     CAThreadData_t* data = (CAThreadData_t*) threadData;
78     if (data == NULL)
79     {
80         OIC_LOG(DEBUG, TAG, "thread data is error!");
81         return;
82     }
83
84     if (data->transmissionType == CA_UNICAST)
85     {
86         // unicast
87         CASendUnicastMessageImpl(data->address, data->port, (char*) (data->data), data->len);
88     }
89     else if (data->transmissionType == CA_MULTICAST)
90     {
91         // multicast
92         CASendMulticastMessageImpl((char*) (data->data), data->len);
93     }
94 }
95
96 static void CAReceiveProcess(void* threadData)
97 {
98     OIC_LOG(DEBUG, TAG, "CAReceiveProcess");
99
100     CAThreadData_t* data = (CAThreadData_t*) threadData;
101     if (data == NULL)
102     {
103         OIC_LOG(DEBUG, TAG, "thread data is error!");
104         return;
105     }
106
107     if (gPacketReceiveCallback != NULL)
108     {
109         gPacketReceiveCallback(data->address, data->port, (char*) (data->data), data->len);
110     }
111 }
112
113 void CAWiFiSetCallback(CAPacketReceiveCallback callback)
114 {
115     gPacketReceiveCallback = callback;
116 }
117
118 void CAWiFiInitMutex()
119 {
120     OIC_LOG(DEBUG, TAG, "CAWiFiInitMutex");
121
122     unicastListenTask.threadMutex = u_mutex_new();
123     unicastListenTask.threadCond = u_cond_new();
124     unicastListenTask.isStop = FALSE;
125     unicastListenTask.status = 0; // stopped
126
127     multicastListenTask.threadMutex = u_mutex_new();
128     multicastListenTask.threadCond = u_cond_new();
129     multicastListenTask.isStop = FALSE;
130     multicastListenTask.status = 0; // stopped
131 }
132
133 static void CAUnicastListenThread(void* threadData)
134 {
135     OIC_LOG(DEBUG, TAG, "CAUnicastListenThread");
136
137     char buf[CA_MAX_BUFFER_SIZE];
138     uint32_t recv_len;
139
140     int32_t ret = 0;
141
142     struct sockaddr_in si_other;
143     socklen_t slen = sizeof(si_other);
144
145     fd_set reads;
146     struct timeval timeout;
147
148     while (1)
149     {
150         u_mutex_lock(unicastListenTask.threadMutex);
151         int32_t isStop = unicastListenTask.isStop;
152         u_mutex_unlock(unicastListenTask.threadMutex);
153         if (isStop)
154             break;
155
156         // OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, Waiting for data...");
157
158         memset(buf, 0, sizeof(char) * CA_MAX_BUFFER_SIZE);
159
160         timeout.tv_sec = 1;
161         timeout.tv_usec = 0;
162
163         FD_ZERO(&reads);
164
165         // Use select for polling the socket fd
166         FD_SET(unicast_receive_socket, &reads);
167
168         ret = select(unicast_receive_socket + 1, &reads, NULL, NULL, &timeout);
169         if (ret < 0)
170         {
171             // OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, select API failed");
172
173             continue;
174         }
175         if (!FD_ISSET(unicast_receive_socket, &reads))
176         {
177             // OIC_LOG(DEBUG, TAG, "CAUnicastListenThread, No data to read");
178             continue;
179         }
180
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)
184         {
185             OIC_LOG_V(DEBUG, TAG, "%s\n", strerror(errno));
186             continue;
187         }
188         else if (0 == recv_len)
189         {
190             OIC_LOG(DEBUG, TAG, "Unicast socket is shutdown, returning from thread\n");
191             return;
192         }
193
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);
198
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
204
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);
210
211         td->port = ntohs(si_other.sin_port);
212
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));
216         td->len = recv_len;
217
218         CAQueueingThreadAddData(&gReceiveThread, td, sizeof(CAThreadData_t));
219     }
220
221     u_cond_signal(unicastListenTask.threadCond);
222     OIC_LOG(DEBUG, TAG, "end of CAUnicastListenThread");
223 }
224
225 static void CAMulticastListenThread(void* threadData)
226 {
227     OIC_LOG(DEBUG, TAG, "CAMulticastListenThread");
228
229     char msgbuf[CA_MAX_BUFFER_SIZE];
230
231     struct sockaddr_in client;
232     int32_t addrlen = sizeof(client);
233
234     fd_set reads;
235     struct timeval timeout;
236
237     while (1)
238     {
239         u_mutex_lock(multicastListenTask.threadMutex);
240         int32_t isStop = multicastListenTask.isStop;
241         u_mutex_unlock(multicastListenTask.threadMutex);
242         if (isStop)
243             break;
244
245         timeout.tv_sec = 1;
246         timeout.tv_usec = 0;
247
248         FD_ZERO(&reads);
249
250         // Use select for polling the socket fd
251         FD_SET(multicast_receive_socket, &reads);
252
253         int32_t ret = select(multicast_receive_socket + 1, &reads, NULL, NULL, &timeout);
254         if (ret < 0)
255         {
256             // OIC_LOG_V(FATAL, TAG, "CAMulticastListenThread, select API failed");
257             continue;
258         }
259         if (!FD_ISSET(multicast_receive_socket, &reads))
260         {
261             // OIC_LOG_V(DEBUG, TAG, "CAMulticastListenThread, No data to read");
262             continue;
263         }
264
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)
269         {
270             OIC_LOG_V(DEBUG, TAG, "%s\n", strerror(errno));
271             continue;
272         }
273         else if (0 == recv_bytes)
274         {
275             OIC_LOG_V(ERROR, TAG, "Multicast socket is shutdown, returning from thread\n");
276             OIC_LOG(DEBUG, TAG, "return here ");
277             return;
278         }
279
280         OIC_LOG_V(DEBUG, TAG, "Received msg: %s, size: %d", msgbuf, recv_bytes);
281
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
287
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);
294
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;
299
300         CAQueueingThreadAddData(&gReceiveThread, td, sizeof(CAThreadData_t));
301
302     }
303
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));
308     if (result < 0)
309     {
310         OIC_LOG_V(DEBUG, TAG,
311                 "CAWiFiStopMulticastServer, cannot leave multicast group, Error code: %s\n",
312                 strerror(errno));
313     }
314     u_cond_signal(multicastListenTask.threadCond);
315
316     OIC_LOG(DEBUG, TAG, "end of CAMulticastListenThread");
317 }
318
319 void CAWiFiInitialize(u_thread_pool_t handle)
320 {
321     OIC_LOG(DEBUG, TAG, "CAWiFiInitialize");
322
323     gThreadPoolHandle = handle;
324
325     // unicast/multicast send queue
326     CAQueueingThreadInitialize(&gSendThread, gThreadPoolHandle, CASendProcess);
327
328     // start send thread
329     CAResult_t res = CAQueueingThreadStart(&gSendThread);
330     if (res != CA_STATUS_OK)
331     {
332         OIC_LOG(DEBUG, TAG, "thread start is error (send thread)");
333         // return res;
334         return;
335     }
336
337     // unicast/multicast receive queue
338     CAQueueingThreadInitialize(&gReceiveThread, gThreadPoolHandle, CAReceiveProcess);
339
340     // start send thread
341     res = CAQueueingThreadStart(&gReceiveThread);
342     if (res != CA_STATUS_OK)
343     {
344         OIC_LOG(DEBUG, TAG, "thread start is error (receive thread)");
345         // return res;
346         return;
347     }
348 }
349
350 int32_t CABindUnicastSocket()
351 {
352     int32_t i;
353     for (i = 0; i < 100; i++)
354     {
355         int32_t port = CA_UNICAST_PORT + i;
356
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);
362
363         // bind socket to port
364         if (bind(unicast_receive_socket, (struct sockaddr*) &si_me, sizeof(si_me)) == 0)
365         {
366             OIC_LOG_V(DEBUG, TAG, "CABindUnicastSocket, socket binded, port: %d", port);
367
368             gUnicastPort = port;
369
370             return 0;
371         }
372
373     }
374
375     OIC_LOG(DEBUG, TAG, "CABindUnicastSocket, binding socket failed");
376
377     return -1;
378 }
379
380 void CAWiFiTerminate()
381 {
382     OIC_LOG(DEBUG, TAG, "CAWiFiTerminate");
383
384     close(unicast_receive_socket);
385     close(multicast_receive_socket);
386
387     // stop thread
388     CAQueueingThreadStop(&gSendThread);
389     // delete thread data
390     CAQueueingThreadDestroy(&gSendThread);
391
392     // stop thread
393     CAQueueingThreadStop(&gReceiveThread);
394     // delete thread data
395     CAQueueingThreadDestroy(&gReceiveThread);
396
397     u_mutex_free(unicastListenTask.threadMutex);
398
399     u_mutex_free(multicastListenTask.threadMutex);
400
401     OIC_LOG(DEBUG, TAG, "end of CAWiFiTerminate");
402 }
403
404 int32_t CAWiFiSendUnicastMessage(const char* address, const int port, char* data, uint32_t lengh)
405 {
406     // store the data at queue.
407     CAThreadData_t* td = NULL;
408     td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
409     if (td == NULL)
410     {
411         OICFree(data);
412         return 0;
413     }
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)
419     {
420         memset(td->address, 0, len + 1);
421         memcpy(td->address, address, len);
422     }
423     else
424     {
425         OIC_LOG_V(DEBUG, TAG, "Memory Full");
426         OICFree(td);
427         OICFree(data);
428         return 0;
429     }
430
431     td->port = port;
432     td->data = data;
433     td->len = lengh;
434
435     CAQueueingThreadAddData(&gSendThread, td, sizeof(CAThreadData_t));
436
437     return 0;
438 }
439
440 int32_t CAWiFiSendMulticastMessage(const char* m_address, char* data, uint32_t dataLen)
441 {
442     // store the data at queue.
443     CAThreadData_t* td = NULL;
444     td = (CAThreadData_t*) OICMalloc(sizeof(CAThreadData_t));
445     if (td == NULL)
446     {
447         OICFree(data);
448         return 0;
449     }
450     memset(td, 0, sizeof(CAThreadData_t));
451     td->transmissionType = CA_MULTICAST; // multicast type
452     td->address = NULL;
453     td->port = 0;
454     td->data = data;
455     td->len = dataLen;
456
457     CAQueueingThreadAddData(&gSendThread, td, sizeof(CAThreadData_t));
458
459     return 0;
460 }
461
462 int32_t CAWiFiStartUnicastServer()
463 {
464     OIC_LOG_V(DEBUG, TAG, "CAWiFiStartUnicastServer");
465
466     // check the server status
467     if (unicastListenTask.status == 1)
468     {
469         OIC_LOG(DEBUG, TAG, "CAWiFiStartUnicastServer, already running");
470
471         return 0;
472     }
473
474     // 1. create a UDP socket
475     if ((unicast_receive_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
476     {
477         OIC_LOG_V(DEBUG, TAG, "CAWiFiInitialize, creating socket failed");
478
479         return -1;
480     }
481
482     OIC_LOG(DEBUG, TAG, "CAWiFiInitialize, socket created");
483
484     // 2. Make the socket non-blocking
485     int16_t status = 0;
486     if ((status = fcntl(unicast_receive_socket, F_SETFL, O_NONBLOCK)) < 0)
487     {
488         OIC_LOG_V(ERROR, TAG,
489                 "CAWiFiInitialize, fcntl to make the socket non-blocking failed, Error code: %s",
490                 strerror(errno));
491
492         close(unicast_receive_socket);
493
494         return -1;
495     }
496
497     OIC_LOG(DEBUG, TAG, "CAWiFiInitialize, socket creation success");
498
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,
502      sizeof(multiTTL));
503      if (ret_val < 0)
504      {
505      OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to set REUSEADDR");
506      close(unicast_receive_socket);
507
508      return -1;
509      }*/
510
511     // 4. bind socket
512     if (CABindUnicastSocket() == -1)
513     {
514         close(unicast_receive_socket);
515
516         return -1;
517     }
518
519     // unicast listen thread
520     CAResult_t res = u_thread_pool_add_task(gThreadPoolHandle, CAUnicastListenThread, NULL);
521     if (res != CA_STATUS_OK)
522     {
523         OIC_LOG(DEBUG, TAG, "adding task to thread pool is error (unicast listen thread)");
524         return res;
525     }
526
527     unicastListenTask.status = 1; // running
528     OIC_LOG_V(DEBUG, TAG, "CAWiFiStartUnicastServer(%s, %d)", "Local Address", gUnicastPort);
529
530     return 0;
531 }
532
533 int32_t CAWiFiStartMulticastServer()
534 {
535     OIC_LOG_V(DEBUG, TAG, "CAWiFiStartMulticastServer(%s, %d)", "0.0.0.0", CA_MULTICAST_PORT);
536
537     // check the server status
538     if (multicastListenTask.status == 1)
539     {
540         OIC_LOG(DEBUG, TAG, "CAWiFiStartMulticastServer, already running");
541
542         return 0;
543     }
544
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);
549
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)
553     {
554         OIC_LOG(DEBUG, TAG, "CAWiFiInit, Socket error");
555
556         return -1;
557     }
558
559     // 2. Make the socket non-blocking
560     int16_t status = 0;
561     if ((status = fcntl(multicast_receive_socket, F_SETFL, O_NONBLOCK)) < 0)
562     {
563         OIC_LOG_V(ERROR, TAG, "fcntl to make the socket non-blocking failed, Error code: %s",
564                 strerror(errno));
565         close(multicast_receive_socket);
566
567         return -1;
568     }
569
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,
573             sizeof(multiTTL));
574     if (ret_val < 0)
575     {
576         OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to set REUSEADDR");
577         close(multicast_receive_socket);
578
579         return -1;
580     }
581
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);
587
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));
591     if (ret_val < 0)
592     {
593         OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to bind socket");
594         close(multicast_receive_socket);
595
596         return -1;
597     }
598
599     // 5. Join the multicast group
600     struct ip_mreq mreq;
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,
605             sizeof(mreq));
606     if (ret_val < 0)
607     {
608         OIC_LOG(DEBUG, TAG, "CAWiFiInit, Failed to join multicast group");
609         close(multicast_receive_socket);
610
611         return -1;
612     }
613
614     // multicast listen thread
615     CAResult_t res = u_thread_pool_add_task(gThreadPoolHandle, CAMulticastListenThread, NULL);
616     if (res != CA_STATUS_OK)
617     {
618         OIC_LOG(DEBUG, TAG, "adding task to thread pool is error (multicast listen thread)");
619         return res;
620     }
621
622     multicastListenTask.status = 1;
623
624     return 0;
625 }
626
627 int32_t CAWiFiStopUnicastServer()
628 {
629     OIC_LOG(DEBUG, TAG, "CAWiFiStopUnicastServer");
630
631     // check the server status
632     if (unicastListenTask.status == 0)
633     {
634         OIC_LOG(DEBUG, TAG, "CAWiFiStopUnicastServer, already stopped");
635
636         return 0;
637     }
638
639     // mutex lock
640     u_mutex_lock(unicastListenTask.threadMutex);
641
642     // set stop flag
643     unicastListenTask.isStop = TRUE;
644
645     u_cond_wait(unicastListenTask.threadCond, unicastListenTask.threadMutex);
646
647     // notity the thread
648     // u_cond_signal(unicastListenTask.threadCond);
649
650     // mutex unlock
651     u_mutex_unlock(unicastListenTask.threadMutex);
652
653     unicastListenTask.status = 0; // stopped
654
655     // close(unicast_receive_socket);
656
657     return 0;
658 }
659
660 int32_t CAWiFiStopMulticastServer()
661 {
662     OIC_LOG(DEBUG, TAG, "CAWiFiStopMulticastServer");
663
664     // check the server status
665     if (multicastListenTask.status == 0)
666     {
667         OIC_LOG(DEBUG, TAG, "CAWiFiStopMulticastServer, already stopped");
668
669         return 0;
670     }
671
672     // mutex lock
673     u_mutex_lock(multicastListenTask.threadMutex);
674
675     // set stop flag
676     multicastListenTask.isStop = TRUE;
677
678     u_cond_wait(multicastListenTask.threadCond, multicastListenTask.threadMutex);
679
680     // mutex unlock
681     u_mutex_unlock(multicastListenTask.threadMutex);
682
683     multicastListenTask.status = 0; // stopped
684
685     return 0;
686 }
687
688 void CAGetLocalAddress(char* addressBuffer)
689 {
690     //char addressBuffer[INET_ADDRSTRLEN];
691     memset(addressBuffer, 0, INET_ADDRSTRLEN);
692
693     struct ifaddrs* ifAddrStruct = NULL;
694     struct ifaddrs* ifa = NULL;
695     void* tmpAddrPtr = NULL;
696
697     getifaddrs(&ifAddrStruct);
698
699     for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
700     {
701         if (!ifa->ifa_addr)
702         {
703             continue;
704         }
705
706         if (ifa->ifa_addr->sa_family == AF_INET)
707         { // check it is IP4
708           // is a valid IP4 Address
709             tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
710
711             memset(addressBuffer, 0, INET_ADDRSTRLEN);
712             inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
713
714             if (strcmp(addressBuffer, "127.0.0.1") == 0)
715                 continue;
716         }
717     }
718
719     if (ifAddrStruct != NULL)
720         freeifaddrs(ifAddrStruct);
721 }
722
723 int32_t CASendUnicastMessageImpl(const char* address, const int port, const char* data,
724         uint32_t len)
725 {
726     OIC_LOG_V(DEBUG, TAG, "CASendUnicastMessageImpl, address: %s:%d, data: %s", address, port,
727             data);
728
729     // [UDP Client]
730
731     struct sockaddr_in si_other;
732     int32_t slen = sizeof(si_other);
733
734     memset((char *) &si_other, 0, sizeof(si_other));
735
736     si_other.sin_family = AF_INET;
737     si_other.sin_port = htons(port);
738     if (inet_aton(address, &si_other.sin_addr) == 0)
739     {
740         OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, inet_aton, error...");
741         return 0;
742     }
743
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)
746     {
747         OIC_LOG(DEBUG, TAG, "CASendUnicastMessageImpl, sendto, error...");
748
749         return 0;
750     }
751
752     return 0;
753 }
754
755 int32_t CASendMulticastMessageImpl(const char* msg, uint32_t len)
756 {
757     OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, sendto, data: %s", msg);
758
759     int32_t result = sendto(unicast_receive_socket, msg, len, 0,
760             (struct sockaddr *) &multicast_send_interface_addr,
761             sizeof(multicast_send_interface_addr));
762     if (result < 0)
763     {
764         OIC_LOG(DEBUG, TAG, "CASendMulticastMessageImpl, sending message error...");
765
766         return -1;
767     }
768
769     return 0;
770 }
771
772 CAResult_t CAGetWIFIInterfaceInfo(CALocalConnectivity_t **info, uint32_t* size)
773 {
774     uint32_t cnt, req_cnt = REQ_CNT;
775     int32_t fd;
776     uint32_t cmd = SIOCGIFCONF;
777     uint32_t resSize = 0;
778     char* localIPAddress;
779     struct sockaddr_in *sock;
780     struct ifconf ifc;
781     struct ifreq *ifr;
782
783     memset((void *) &ifc, 0, sizeof(struct ifconf));
784     ifc.ifc_len = sizeof(struct ifconf) * req_cnt;
785     ifc.ifc_buf = NULL;
786     ifc.ifc_buf = malloc(ifc.ifc_len);
787
788     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
789     {
790         OIC_LOG(DEBUG, TAG, "create socket error!");
791         return CA_STATUS_FAILED;
792     }
793
794     if (ioctl(fd, cmd, &ifc) < 0)
795     {
796         OIC_LOG(DEBUG, TAG, "SIOCGIFCONF fail");
797         close(fd);
798         return CA_STATUS_FAILED;
799     }
800     close(fd);
801
802     if (ifc.ifc_len > (sizeof(struct ifreq) * req_cnt))
803     {
804         req_cnt = ifc.ifc_len;
805         ifc.ifc_buf = realloc(ifc.ifc_buf, req_cnt);
806     }
807
808     ifr = ifc.ifc_req;
809     for (cnt = 0; cnt < ifc.ifc_len; cnt += sizeof(struct ifreq), ifr++)
810     {
811         sock = (struct sockaddr_in *) &ifr->ifr_addr;
812
813         // except loopback address
814         if (ntohl(sock->sin_addr.s_addr) == INADDR_LOOPBACK)
815             continue;
816
817         // get local address
818         localIPAddress = inet_ntoa(sock->sin_addr);
819
820         CALocalConnectivity_t* localInfo;
821
822         // memory allocation
823         localInfo = (CALocalConnectivity_t*) OICMalloc(sizeof(CALocalConnectivity_t));
824         if (localInfo == NULL)
825         {
826             OIC_LOG_V(DEBUG, TAG, "memory alloc error!!");
827             free(localInfo);
828             return CA_STATUS_FAILED;
829         }
830         memset(localInfo, 0, sizeof(CALocalConnectivity_t));
831
832         if (strlen(localIPAddress) > CA_IPADDR_SIZE)
833         {
834             OIC_LOG_V(DEBUG, TAG, "address size is wrong!!");
835             free(localInfo);
836             return CA_STATUS_FAILED;
837         }
838         // set local ip address
839         strncpy(localInfo->addressInfo.IP.ipAddress, localIPAddress, strlen(localIPAddress));
840
841         // set network type
842         localInfo->type = CA_WIFI;
843
844         *info = localInfo;
845
846         resSize++;
847     }
848
849     *size = resSize;
850
851     return CA_STATUS_OK;
852 }