Merge "Fix compiler warnings" into connectivity-abstraction
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ethernet_adapter / linux / caethernetserver.c
1 /******************************************************************
2 *
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************/
20 #include "caethernetinterface.h"
21
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <sys/select.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
29 #include <errno.h>
30
31 #include "pdu.h"
32 #include "caadapterutils.h"
33 #include "umutex.h"
34
35 /**
36  * @def ETHERNET_SERVER_TAG
37  * @brief Logging tag for module name
38  */
39 #define ETHERNET_SERVER_TAG "ETHERNET_SERVER"
40
41 /**
42  * @def CA_UDP_BIND_RETRY_COUNT
43  * @brief Retry count in case of socket bind failure.
44  */
45 #define CA_UDP_BIND_RETRY_COUNT 10
46
47 /**
48  * @var gUnicastServerSocketDescriptor
49  * @brief socket descriptor for unicast server
50  */
51 static int32_t gUnicastServerSocketDescriptor = -1;
52
53 /**
54  * @var gUnicastServerSocketDescriptor
55  * @brief socket descriptor for unicast server
56  */
57 static char *gUnicastServerAddress = NULL;
58
59 /**
60  * @var gUnicastServerSocketDescriptor
61  * @brief socket descriptor for unicast server
62  */
63 static int16_t gUnicastServerPort = -1;
64
65 /**
66  * @var gMutexUnicastServerSocketDescriptor
67  * @brief Mutex for socket descriptor for unicast server
68  */
69 static u_mutex gMutexUnicastServerSocketDescriptor = NULL;
70 /**
71  * @var gMulticastServerSocketDescriptor
72  * @brief socket descriptor for multicast server
73  */
74 static int32_t gMulticastServerSocketDescriptor = -1;
75
76 /**
77  * @var gMutexMulticastServerSocketDescriptor
78  * @brief Mutex for socket descriptor for Multicast server
79  */
80 static u_mutex gMutexMulticastServerSocketDescriptor = NULL;
81
82 /**
83  * @var gThreadPool
84  * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
85  */
86 static u_thread_pool_t gThreadPool = NULL;
87
88 /**
89  * @var gMReq
90  * @brief ip_mreq structure passed to join a multicast group
91  */
92 static struct ip_mreq gMReq;
93
94 /**
95  * @var gStopUnicast
96  * @brief Flag to control the Receive Unicast Data Thread
97  */
98 static bool gStopUnicast = false;
99
100 /**
101  * @var gMutexStopUnicast
102  * @brief Mutex for gStopUnicast
103  */
104 static u_mutex gMutexStopUnicast = NULL;
105
106 /**
107  * @var gStopMulticast
108  * @brief Flag to control the Receive Multicast Data Thread
109  */
110 static bool gStopMulticast = false;
111
112 /**
113  * @var gMutexStopMulticast
114  * @brief Mutex for gStopMulticast
115  */
116 static u_mutex gMutexStopMulticast = NULL;
117
118 /**
119  * @var gPacketReceivedCallback
120  * @brief Callback for notifying the upper layer on receival data from remote OIC device
121  */
122 static CAEthernetPacketReceivedCallback gPacketReceivedCallback = NULL;
123
124 /**
125  * @var gExceptionCallback
126  * @brief Callback for notifying the upper layer when unicast/multicast server encounters exception
127  */
128 static CAEthernetExceptionCallback gExceptionCallback = NULL;
129
130 /**
131  * @var gUnicastRecvBuffer
132  * @brief Character buffer used for receiving unicast data from network
133  */
134 static char gUnicastRecvBuffer[COAP_MAX_PDU_SIZE] = {0};
135
136 /**
137  * @var gMulticastRecvBuffer
138  * @brief Character buffer used for receiving multicast data from network
139  */
140 static char gMulticastRecvBuffer[COAP_MAX_PDU_SIZE] = {0};
141
142 /**
143  * @fn CAEthernetServerCreateMutex
144  * @brief Creates and initializes mutex
145  */
146 static CAResult_t CAEthernetServerCreateMutex(void);
147
148 /**
149  * @fn CAEthernetServerDestroyMutex
150  * @brief Releases all created mutex
151  */
152 static void CAEthernetServerDestroyMutex(void);
153
154 /**
155  * @fn CAReceiveThreadForMulticast
156  * @brief Handler thread for receiving data on multicast server
157  */
158 static void *CAReceiveThreadForMulticast(void *data);
159
160 /**
161  * @fn CAEthernetReceiveThreadForUnicast
162  * @brief Handler thread for receiving data on unicast server
163  */
164 static void *CAEthernetReceiveThreadForUnicast(void *data);
165
166 CAResult_t CAEthernetInitializeServer(const u_thread_pool_t threadPool)
167 {
168     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
169
170     //Input validation
171     VERIFY_NON_NULL(threadPool, ETHERNET_SERVER_TAG, "Thread pool handle is NULL");
172
173     //Initialize mutex
174     if (CA_STATUS_OK != CAEthernetServerCreateMutex())
175     {
176         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create mutex!");
177         return CA_STATUS_FAILED;
178     }
179
180     gThreadPool = threadPool;
181
182     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
183     return CA_STATUS_OK;
184 }
185
186 void CAEthernetTerminateServer(void)
187 {
188     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
189
190     gThreadPool = NULL;
191
192     //Destroy mutex
193     CAEthernetServerDestroyMutex();
194
195     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
196 }
197
198 CAResult_t CAEthernetStartMulticastServer(const char *localAddress, const char *multicastAddress,
199         const int16_t multicastPort, int32_t *serverFD)
200 {
201     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
202
203     if (gMulticastServerSocketDescriptor != -1)
204     {
205         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast Server is already running!");
206         return CA_SERVER_STARTED_ALREADY;
207     }
208
209     VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "Local address is NULL");
210     VERIFY_NON_NULL(multicastAddress, ETHERNET_SERVER_TAG, "Multicast address is NULL");
211
212     if (0 >= multicastPort)
213     {
214         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: Multicast port is invalid!");
215         return CA_STATUS_INVALID_PARAM;
216     }
217
218     // Create a datagram socket on which to recv/send.
219     u_mutex_lock(gMutexStopMulticast);
220     gStopMulticast = false;
221     u_mutex_unlock(gMutexStopMulticast);
222
223     u_mutex_lock(gMutexMulticastServerSocketDescriptor);
224
225     // create a UDP socket
226     if ((gMulticastServerSocketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
227     {
228         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to Create Socket, Error code: %s",
229                   strerror(errno));
230         u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
231         return CA_SOCKET_OPERATION_FAILED;
232     }
233
234     // Make the socket non-blocking
235     if (-1 == fcntl(gMulticastServerSocketDescriptor, F_SETFL, O_NONBLOCK))
236     {
237         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
238                   strerror(errno));
239         close(gMulticastServerSocketDescriptor);
240         gMulticastServerSocketDescriptor = -1;
241         u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
242         return CA_STATUS_FAILED;
243     }
244
245     OIC_LOG(INFO, ETHERNET_SERVER_TAG, "socket creation success");
246
247     int32_t setOptionOn = 1;
248     if (-1 == setsockopt(gMulticastServerSocketDescriptor, SOL_SOCKET, SO_REUSEADDR,
249                          (char *) &setOptionOn,
250                          sizeof(setOptionOn)))
251     {
252         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to setsockopt for SO_REUSEADDR, Error code: %s",
253                   strerror(errno));
254         close(gMulticastServerSocketDescriptor);
255         gMulticastServerSocketDescriptor = -1;
256         u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
257         return CA_SOCKET_OPERATION_FAILED;
258     }
259
260     struct sockaddr_in sockAddr;
261     memset((char *) &sockAddr, 0, sizeof(sockAddr));
262
263     sockAddr.sin_family = AF_INET;
264     sockAddr.sin_port = htons(multicastPort);
265     sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
266
267     //bind socket to multicast port
268     if (-1 == bind(gMulticastServerSocketDescriptor, (struct sockaddr *) &sockAddr,
269                    sizeof(sockAddr)))
270     {
271         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to Bind Socket! Return Code[%d]",
272                   CA_SOCKET_OPERATION_FAILED);
273         close(gMulticastServerSocketDescriptor);
274         gMulticastServerSocketDescriptor = -1;
275         u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
276         return CA_SOCKET_OPERATION_FAILED;
277     }
278
279     OIC_LOG(INFO, ETHERNET_SERVER_TAG, "socket bind success");
280
281     //Add membership to receiving socket (join group)
282     memset(&gMReq, 0, sizeof(struct ip_mreq));
283     gMReq.imr_interface.s_addr = htonl(INADDR_ANY);
284     inet_aton(multicastAddress, &gMReq.imr_multiaddr);
285
286     if (-1 == setsockopt(gMulticastServerSocketDescriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP,
287                          (char *) &gMReq,
288                          sizeof(struct ip_mreq)))
289     {
290         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",
291                   strerror(errno));
292         close(gMulticastServerSocketDescriptor);
293         gMulticastServerSocketDescriptor = -1;
294         u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
295         return CA_SOCKET_OPERATION_FAILED;
296     }
297
298     /**
299       * The task to listen to data from multicastcast socket is added to the thread pool.
300       * This is a blocking call is made where we try to receive some data.. We will keep waiting until some data is received.
301       * This task will be terminated when thread pool is freed on stopping the adapters.
302       */
303     if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, (void *) CAReceiveThreadForMulticast,
304             (void *)NULL))
305     {
306         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "[testThreadPool] thread_pool_add_task failed!");
307
308         close(gMulticastServerSocketDescriptor);
309         gMulticastServerSocketDescriptor = -1;
310         u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
311         return CA_STATUS_FAILED;
312     }
313
314     *serverFD = gMulticastServerSocketDescriptor;
315     u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
316
317     OIC_LOG(INFO, ETHERNET_SERVER_TAG, "thread_pool_add_task done");
318     OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast Server Started Successfully");
319
320     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
321     return CA_STATUS_OK;
322
323 }
324
325 CAResult_t CAEthernetStartUnicastServer(const char *localAddress, int16_t *port,
326                                         const bool forceStart, const bool secured, int32_t *serverFD)
327 {
328     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
329
330     if (gUnicastServerSocketDescriptor != -1)
331     {
332         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already! Return Code[%d]",
333                   CA_SERVER_STARTED_ALREADY);
334         return CA_SERVER_STARTED_ALREADY;
335     }
336
337     VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "Invalid argument : localAddress is NULL");
338     VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "Invalid argument : port is NULL");
339
340     if (*port < 0)
341     {
342         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: port is invalid!");
343         return CA_STATUS_INVALID_PARAM;
344     }
345
346     u_mutex_lock(gMutexStopUnicast);
347     gStopUnicast = false;
348     u_mutex_unlock(gMutexStopUnicast);
349
350     u_mutex_lock(gMutexUnicastServerSocketDescriptor);
351     // Create a UDP socket
352     if ((gUnicastServerSocketDescriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
353     {
354         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to Create Socket, Error code: %s",
355                   strerror(errno));
356         u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
357         return CA_SOCKET_OPERATION_FAILED;
358     }
359
360     // Make the socket non-blocking
361     if (-1 == fcntl(gUnicastServerSocketDescriptor, F_SETFL, O_NONBLOCK))
362     {
363         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
364                   strerror(errno));
365         close(gUnicastServerSocketDescriptor);
366         gUnicastServerSocketDescriptor = -1;
367         u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
368         return CA_STATUS_FAILED;
369     }
370
371     OIC_LOG(INFO, ETHERNET_SERVER_TAG, "socket creation success");
372
373     if (true == forceStart)
374     {
375         int32_t setOptionOn = 1;
376         if (-1 == setsockopt(gUnicastServerSocketDescriptor, SOL_SOCKET, SO_REUSEADDR,
377                              (char *) &setOptionOn,
378                              sizeof(setOptionOn)))
379         {
380             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
381                       strerror(errno));
382             close(gUnicastServerSocketDescriptor);
383             gUnicastServerSocketDescriptor = -1;
384             u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
385             return CA_SOCKET_OPERATION_FAILED;
386         }
387     }
388
389     struct sockaddr_in sockAddr;
390     bool isBound = false;
391     int16_t serverPort = *port;
392
393     memset((char *) &sockAddr, 0, sizeof(sockAddr));
394     sockAddr.sin_family = AF_INET;
395     sockAddr.sin_port = htons(serverPort);
396     sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
397
398     //Trying for bind in a loop
399     int16_t i;
400     for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
401     {
402         if (-1 == bind(gUnicastServerSocketDescriptor, (struct sockaddr *) &sockAddr,
403                        sizeof(sockAddr)))
404         {
405             if (false == forceStart)
406             {
407                 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]. Trying again... ",
408                           strerror(errno));
409
410                 //Set the port to next one
411                 serverPort += 1;
412                 sockAddr.sin_port = htons(serverPort);
413                 continue;
414             }
415             else
416             {
417                 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]!",
418                           strerror(errno));
419                 break;
420             }
421         }
422
423         isBound = true;
424         break;
425     }
426
427     if (false == isBound)
428     {
429         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind Socket! Return code[%d]",
430                   CA_SOCKET_OPERATION_FAILED);
431         close(gUnicastServerSocketDescriptor);
432         gUnicastServerSocketDescriptor = -1;
433         u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
434         return CA_SOCKET_OPERATION_FAILED;
435     }
436
437     OIC_LOG(INFO, ETHERNET_SERVER_TAG, "socket bind success");
438
439     socklen_t len = 0;
440     char *serverAddress = NULL;
441     if (-1 != getsockname(gUnicastServerSocketDescriptor, (struct sockaddr *)&sockAddr, &len))
442     {
443         serverPort = ntohs(sockAddr.sin_port);
444         serverAddress = inet_ntoa(sockAddr.sin_addr);
445     }
446
447     /**
448       * The task to listen for data from unicast socket is added to the thread pool.
449       * This is a blocking call is made where we try to receive some data..
450       * We will keep waiting until some data is received.
451       * This task will be terminated when thread pool is freed on stopping the adapters.
452       */
453     if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, (void *) CAEthernetReceiveThreadForUnicast,
454             (void *) NULL))
455     {
456         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "[testThreadPool] thread_pool_add_task failed!");
457
458         close(gUnicastServerSocketDescriptor);
459         gUnicastServerSocketDescriptor = -1;
460         u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
461         return CA_STATUS_FAILED;
462     }
463
464     //Free the server address previously stored
465     OICFree(gUnicastServerAddress);
466     gUnicastServerAddress = NULL;
467     gUnicastServerPort = serverPort;
468     gUnicastServerAddress = (serverAddress) ? strndup(serverAddress, strlen(serverAddress)) :
469                             NULL;
470     *port = serverPort;
471     *serverFD = gUnicastServerSocketDescriptor;
472     u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
473
474     OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Unicast Server Started Successfully");
475     return CA_STATUS_OK;
476 }
477
478 CAResult_t CAEthernetStopMulticastServer(void)
479 {
480     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
481
482     u_mutex_lock(gMutexMulticastServerSocketDescriptor);
483
484     if (gMulticastServerSocketDescriptor == -1)
485     {
486         OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast Server is not yet Started");
487         u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
488         return CA_SERVER_NOT_STARTED;
489     }
490
491     u_mutex_lock(gMutexStopMulticast);
492     gStopMulticast = true;
493
494     // leave the group after you are done
495     if (-1 == setsockopt(gMulticastServerSocketDescriptor, IPPROTO_IP, IP_DROP_MEMBERSHIP,
496                          (char *)&gMReq,
497                          sizeof(struct ip_mreq)))
498     {
499         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "cannot leave multicast group, Error code: %s\n",
500                   strerror(errno));
501     }
502
503     // close the socket
504     if (-1 == close(gMulticastServerSocketDescriptor))
505     {
506         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast Server socket close failed, Error code: %s\n",
507                   strerror(errno));
508         u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
509         u_mutex_unlock(gMutexStopMulticast);
510         return CA_SOCKET_OPERATION_FAILED;
511     }
512
513     u_mutex_unlock(gMutexStopMulticast);
514
515     gMulticastServerSocketDescriptor = -1;
516     u_mutex_unlock(gMutexMulticastServerSocketDescriptor);
517
518     OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast Server Stopped Successfully");
519
520     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
521     return CA_STATUS_OK;
522
523 }
524
525 CAResult_t CAEthernetStopUnicastServer()
526 {
527     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
528     u_mutex_lock(gMutexUnicastServerSocketDescriptor);
529
530     if (gUnicastServerSocketDescriptor == -1)
531     {
532         OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Unicast Server is not yet Started");
533         u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
534         return CA_SERVER_NOT_STARTED;
535     }
536     u_mutex_lock(gMutexStopUnicast);
537     gStopUnicast = true;
538
539     // close the socket
540     if (-1 == close(gUnicastServerSocketDescriptor))
541     {
542         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server socket close failed, Error code: %s\n",
543                   strerror(errno));
544         u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
545         u_mutex_unlock(gMutexStopUnicast);
546         return CA_SOCKET_OPERATION_FAILED;
547     }
548
549     u_mutex_unlock(gMutexStopUnicast);
550     gUnicastServerSocketDescriptor = -1;
551
552     u_mutex_unlock(gMutexUnicastServerSocketDescriptor);
553
554     OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Unicast Server Stopped Successfully");
555     return CA_STATUS_OK;
556 }
557
558 CAResult_t CAEthernetGetUnicastServerInfo(const bool secure, char **ipAddress, int16_t *port,
559                                           int32_t *serverFD)
560 {
561     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
562
563     //Input validation
564     VERIFY_NON_NULL(ipAddress, ETHERNET_SERVER_TAG, "ipAddress holder is NULL");
565     VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "port holder is NULL");
566     VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "serverID holder is NULL");
567
568     *ipAddress = gUnicastServerAddress;
569     *port = gUnicastServerPort;
570     *serverFD = gUnicastServerSocketDescriptor;
571
572     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
573     return CA_STATUS_OK;
574 }
575
576 void CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCallback callback)
577 {
578     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
579
580     gPacketReceivedCallback = callback;
581 }
582
583 void CAEthernetSetExceptionCallback(CAEthernetExceptionCallback callback)
584 {
585     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
586
587     gExceptionCallback = callback;
588 }
589
590 CAResult_t CAEthernetServerCreateMutex(void)
591 {
592     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
593
594     gMutexUnicastServerSocketDescriptor = u_mutex_new();
595     if (!gMutexUnicastServerSocketDescriptor)
596     {
597         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
598         return CA_STATUS_FAILED;
599     }
600
601     gMutexMulticastServerSocketDescriptor = u_mutex_new();
602     if (!gMutexMulticastServerSocketDescriptor)
603     {
604         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
605
606         CAEthernetServerDestroyMutex();
607         return CA_STATUS_FAILED;
608     }
609
610     gMutexStopUnicast = u_mutex_new();
611     if (!gMutexStopUnicast)
612     {
613         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
614
615         CAEthernetServerDestroyMutex();
616         return CA_STATUS_FAILED;
617     }
618
619     gMutexStopMulticast = u_mutex_new();
620     if (!gMutexStopMulticast)
621     {
622         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
623
624         CAEthernetServerDestroyMutex();
625         return CA_STATUS_FAILED;
626     }
627
628     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
629     return CA_STATUS_OK;
630 }
631
632 void CAEthernetServerDestroyMutex(void)
633 {
634     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
635
636     if (gMutexUnicastServerSocketDescriptor)
637     {
638         u_mutex_free(gMutexUnicastServerSocketDescriptor);
639         gMutexUnicastServerSocketDescriptor = NULL;
640     }
641
642     if (gMutexMulticastServerSocketDescriptor)
643     {
644         u_mutex_free(gMutexMulticastServerSocketDescriptor);
645         gMutexMulticastServerSocketDescriptor = NULL;
646     }
647
648     if (gMutexStopUnicast)
649     {
650         u_mutex_free(gMutexStopUnicast);
651         gMutexStopUnicast = NULL;
652     }
653
654     if (gMutexStopMulticast)
655     {
656         u_mutex_free(gMutexStopMulticast);
657         gMutexStopMulticast = NULL;
658     }
659
660     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
661 }
662
663 void *CAEthernetReceiveThreadForUnicast(void *data)
664 {
665     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
666
667     fd_set reads;
668     struct timeval timeout;
669
670     //keep listening for data
671     while (!gStopUnicast)
672     {
673         //OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Waiting for data..");
674
675         timeout.tv_sec = 1;
676         timeout.tv_usec = 0;
677
678         FD_ZERO(&reads);
679         FD_SET(gUnicastServerSocketDescriptor, &reads);
680
681         int32_t ret = select(gUnicastServerSocketDescriptor + 1, &reads, NULL, NULL, &timeout);
682         if (gStopUnicast)
683         {
684             OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Stop Unicast is called");
685             break;
686         }
687         if (ret < 0)
688         {
689             OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
690             continue;
691         }
692         if (!FD_ISSET(gUnicastServerSocketDescriptor, &reads))
693         {
694             //OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "No data to read");
695             continue;
696         }
697
698         memset(gUnicastRecvBuffer, 0, sizeof(char)*COAP_MAX_PDU_SIZE);
699
700         //Read data from socket
701         struct sockaddr_in srcSockAddress;
702         int32_t recvLen;
703         socklen_t srcAddressLen = sizeof(srcSockAddress);
704         if (-1 == (recvLen = recvfrom(gUnicastServerSocketDescriptor, gUnicastRecvBuffer,
705                                       COAP_MAX_PDU_SIZE, 0, (struct sockaddr *) &srcSockAddress,
706                                       &srcAddressLen)))
707         {
708             OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
709             continue;
710         }
711         else if (0 == recvLen)
712         {
713             OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Unicast server socket is shutdown !");
714
715             //Notify upper layer this exception
716             if (gExceptionCallback)
717             {
718                 gExceptionCallback(CA_UNICAST_SERVER);
719             }
720             return NULL;
721         }
722
723         const char *srcIPAddress = NULL;
724         int32_t srcPort = -1;
725
726         srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
727         srcPort = ntohs(srcSockAddress.sin_port);
728
729         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
730                   srcIPAddress, srcPort);
731         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
732                   gUnicastRecvBuffer, recvLen);
733
734         //Notify data to upper layer
735         if (gPacketReceivedCallback)
736         {
737             gPacketReceivedCallback(srcIPAddress, srcPort, gUnicastRecvBuffer, recvLen);
738         }
739     }
740
741     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
742     return NULL;
743 }
744
745 void *CAReceiveThreadForMulticast(void *data)
746 {
747     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
748
749     fd_set reads;
750     struct timeval timeout;
751
752     //keep listening for data
753     while (!gStopMulticast)
754     {
755         timeout.tv_sec = 1;
756         timeout.tv_usec = 0;
757
758         FD_ZERO(&reads);
759         FD_SET(gMulticastServerSocketDescriptor, &reads);
760
761         int32_t ret = select(gMulticastServerSocketDescriptor + 1, &reads, NULL, NULL, &timeout);
762         if (gStopMulticast)
763         {
764             OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Stop Multicast is called");
765             break;
766         }
767         if ( ret < 0)
768         {
769             OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
770             continue;
771         }
772         if (!FD_ISSET(gMulticastServerSocketDescriptor, &reads))
773         {
774             continue;
775         }
776
777         memset(gMulticastRecvBuffer, 0, sizeof(char)*COAP_MAX_PDU_SIZE);
778
779         //Read data from socket
780         struct sockaddr_in srcSockAddress;
781         int32_t recvLen;
782         socklen_t srcAddressLen = sizeof(srcSockAddress);
783         if (-1 == (recvLen = recvfrom(gMulticastServerSocketDescriptor, gMulticastRecvBuffer,
784                                       COAP_MAX_PDU_SIZE, 0, (struct sockaddr *) &srcSockAddress,
785                                       &srcAddressLen)))
786         {
787             OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
788             continue;
789         }
790         else if (0 == recvLen)
791         {
792             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast socket is shutdown, returning from \
793                 thread\n");
794
795             //Notify upper layer this exception
796             if (gExceptionCallback)
797             {
798                 gExceptionCallback(CA_MULTICAST_SERVER);
799             }
800             return NULL;
801         }
802
803         const char *srcIPAddress = NULL;
804         int32_t srcPort = -1;
805
806         srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
807         srcPort = ntohs(srcSockAddress.sin_port);
808
809         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
810                   srcIPAddress, srcPort);
811         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
812                   gMulticastRecvBuffer, recvLen);
813
814
815         //Notify data to upper layer
816         if (gPacketReceivedCallback)
817         {
818             gPacketReceivedCallback(srcIPAddress, srcPort, gMulticastRecvBuffer, recvLen);
819         }
820     }
821
822     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
823     return NULL;
824 }
825
826