Merge "Implementation of connectivity abstraction feature Release v0.5" into connecti...
[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, 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(char **ipAddress, int16_t *port, int32_t *serverFD)
559 {
560     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
561
562     //Input validation
563     VERIFY_NON_NULL(ipAddress, ETHERNET_SERVER_TAG, "ipAddress holder is NULL");
564     VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "port holder is NULL");
565     VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "serverID holder is NULL");
566
567     *ipAddress = gUnicastServerAddress;
568     *port = gUnicastServerPort;
569     *serverFD = gUnicastServerSocketDescriptor;
570
571     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
572     return CA_STATUS_OK;
573 }
574
575 void CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCallback callback)
576 {
577     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
578
579     gPacketReceivedCallback = callback;
580 }
581
582 void CAEthernetSetExceptionCallback(CAEthernetExceptionCallback callback)
583 {
584     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
585
586     gExceptionCallback = callback;
587 }
588
589 CAResult_t CAEthernetServerCreateMutex(void)
590 {
591     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
592
593     gMutexUnicastServerSocketDescriptor = u_mutex_new();
594     if (!gMutexUnicastServerSocketDescriptor)
595     {
596         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
597         return CA_STATUS_FAILED;
598     }
599
600     gMutexMulticastServerSocketDescriptor = u_mutex_new();
601     if (!gMutexMulticastServerSocketDescriptor)
602     {
603         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
604
605         CAEthernetServerDestroyMutex();
606         return CA_STATUS_FAILED;
607     }
608
609     gMutexStopUnicast = u_mutex_new();
610     if (!gMutexStopUnicast)
611     {
612         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
613
614         CAEthernetServerDestroyMutex();
615         return CA_STATUS_FAILED;
616     }
617
618     gMutexStopMulticast = u_mutex_new();
619     if (!gMutexStopMulticast)
620     {
621         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
622
623         CAEthernetServerDestroyMutex();
624         return CA_STATUS_FAILED;
625     }
626
627     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
628     return CA_STATUS_OK;
629 }
630
631 void CAEthernetServerDestroyMutex(void)
632 {
633     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
634
635     if (gMutexUnicastServerSocketDescriptor)
636     {
637         u_mutex_free(gMutexUnicastServerSocketDescriptor);
638         gMutexUnicastServerSocketDescriptor = NULL;
639     }
640
641     if (gMutexMulticastServerSocketDescriptor)
642     {
643         u_mutex_free(gMutexMulticastServerSocketDescriptor);
644         gMutexMulticastServerSocketDescriptor = NULL;
645     }
646
647     if (gMutexStopUnicast)
648     {
649         u_mutex_free(gMutexStopUnicast);
650         gMutexStopUnicast = NULL;
651     }
652
653     if (gMutexStopMulticast)
654     {
655         u_mutex_free(gMutexStopMulticast);
656         gMutexStopMulticast = NULL;
657     }
658
659     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
660 }
661
662 void *CAEthernetReceiveThreadForUnicast(void *data)
663 {
664     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
665
666     fd_set reads;
667     struct timeval timeout;
668
669     //keep listening for data
670     while (!gStopUnicast)
671     {
672         //OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Waiting for data..");
673
674         timeout.tv_sec = 1;
675         timeout.tv_usec = 0;
676
677         FD_ZERO(&reads);
678         FD_SET(gUnicastServerSocketDescriptor, &reads);
679
680         int32_t ret = select(gUnicastServerSocketDescriptor + 1, &reads, NULL, NULL, &timeout);
681         if (gStopUnicast)
682         {
683             OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Stop Unicast is called");
684             break;
685         }
686         if (ret < 0)
687         {
688             OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
689             continue;
690         }
691         if (!FD_ISSET(gUnicastServerSocketDescriptor, &reads))
692         {
693             //OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "No data to read");
694             continue;
695         }
696
697         memset(gUnicastRecvBuffer, 0, sizeof(char)*COAP_MAX_PDU_SIZE);
698
699         //Read data from socket
700         struct sockaddr_in srcSockAddress;
701         int32_t recvLen;
702         socklen_t srcAddressLen = sizeof(srcSockAddress);
703         if (-1 == (recvLen = recvfrom(gUnicastServerSocketDescriptor, gUnicastRecvBuffer,
704                                       COAP_MAX_PDU_SIZE, 0, (struct sockaddr *) &srcSockAddress,
705                                       &srcAddressLen)))
706         {
707             OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
708             continue;
709         }
710         else if (0 == recvLen)
711         {
712             OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Unicast server socket is shutdown !");
713
714             //Notify upper layer this exception
715             if (gExceptionCallback)
716             {
717                 gExceptionCallback(CA_UNICAST_SERVER);
718             }
719             return NULL;
720         }
721
722         const char *srcIPAddress = NULL;
723         int32_t srcPort = -1;
724
725         srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
726         srcPort = ntohs(srcSockAddress.sin_port);
727
728         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
729                   srcIPAddress, srcPort);
730         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
731                   gUnicastRecvBuffer, recvLen);
732
733         //Notify data to upper layer
734         if (gPacketReceivedCallback)
735         {
736             gPacketReceivedCallback(srcIPAddress, srcPort, gUnicastRecvBuffer, recvLen);
737         }
738     }
739
740     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
741     return NULL;
742 }
743
744 void *CAReceiveThreadForMulticast(void *data)
745 {
746     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
747
748     fd_set reads;
749     struct timeval timeout;
750
751     //keep listening for data
752     while (!gStopMulticast)
753     {
754         timeout.tv_sec = 1;
755         timeout.tv_usec = 0;
756
757         FD_ZERO(&reads);
758         FD_SET(gMulticastServerSocketDescriptor, &reads);
759
760         int32_t ret = select(gMulticastServerSocketDescriptor + 1, &reads, NULL, NULL, &timeout);
761         if (gStopMulticast)
762         {
763             OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Stop Multicast is called");
764             break;
765         }
766         if ( ret < 0)
767         {
768             OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
769             continue;
770         }
771         if (!FD_ISSET(gMulticastServerSocketDescriptor, &reads))
772         {
773             continue;
774         }
775
776         memset(gMulticastRecvBuffer, 0, sizeof(char)*COAP_MAX_PDU_SIZE);
777
778         //Read data from socket
779         struct sockaddr_in srcSockAddress;
780         int32_t recvLen;
781         socklen_t srcAddressLen = sizeof(srcSockAddress);
782         if (-1 == (recvLen = recvfrom(gMulticastServerSocketDescriptor, gMulticastRecvBuffer,
783                                       COAP_MAX_PDU_SIZE, 0, (struct sockaddr *) &srcSockAddress,
784                                       &srcAddressLen)))
785         {
786             OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
787             continue;
788         }
789         else if (0 == recvLen)
790         {
791             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast socket is shutdown, returning from \
792                 thread\n");
793
794             //Notify upper layer this exception
795             if (gExceptionCallback)
796             {
797                 gExceptionCallback(CA_MULTICAST_SERVER);
798             }
799             return NULL;
800         }
801
802         const char *srcIPAddress = NULL;
803         int32_t srcPort = -1;
804
805         srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
806         srcPort = ntohs(srcSockAddress.sin_port);
807
808         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
809                   srcIPAddress, srcPort);
810         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
811                   gMulticastRecvBuffer, recvLen);
812
813
814         //Notify data to upper layer
815         if (gPacketReceivedCallback)
816         {
817             gPacketReceivedCallback(srcIPAddress, srcPort, gMulticastRecvBuffer, recvLen);
818         }
819     }
820
821     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
822     return NULL;
823 }
824
825