Tizen 2.1 base
[sdk/target/sdbd.git] / src / socket_loopback_server.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 // libs/cutils/socket_loopback_server.c
17
18 #include "sockets.h"
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <stddef.h>
26
27 #define LISTEN_BACKLOG 4
28 #define LOOPBACK_UP 1
29 #define LOOPBACK_DOWN 0
30
31 #ifndef HAVE_WINSOCK
32 #include <sys/socket.h>
33 #include <sys/select.h>
34 #include <sys/types.h>
35 #include <netinet/in.h>
36 #include <sys/ioctl.h>
37 #include <net/if.h>
38 #include <arpa/inet.h>
39 #endif
40 #include "sysdeps.h"
41
42 int get_loopback_status(void) {
43
44     int           s;
45     struct ifconf ifc;
46     struct ifreq *ifr;
47     int           ifcnt;
48     char          buf[1024];
49     int i;
50
51     s = socket(AF_INET, SOCK_DGRAM, 0);
52     if(s < 0)
53     {
54         perror("socket");
55         return LOOPBACK_DOWN;
56     }
57
58     // query available interfaces
59     ifc.ifc_len = sizeof(buf);
60     ifc.ifc_buf = buf;
61     if(ioctl(s, SIOCGIFCONF, &ifc) < 0)
62     {
63         perror("ioctl(SIOCGIFCONF)");
64         sdb_close(s);
65         return LOOPBACK_DOWN;
66     }
67
68     // iterate the list of interfaces
69     ifr = ifc.ifc_req;
70     ifcnt = ifc.ifc_len / sizeof(struct ifreq);
71     for(i = 0; i < ifcnt; i++)
72     {
73         struct sockaddr_in *addr;
74         addr = (struct sockaddr_in *)&ifr->ifr_addr;
75
76         if (ntohl(addr->sin_addr.s_addr) == INADDR_LOOPBACK)
77         {
78             sdb_close(s);
79             return LOOPBACK_UP;
80         }
81     }
82     sdb_close(s);
83     return LOOPBACK_DOWN;
84 }
85
86 /* open listen() port on loopback interface */
87 int socket_loopback_server(int port, int type)
88 {
89     struct sockaddr_in addr;
90     int s, n;
91     int cnt_max = 30;
92
93     /* tizen specific */
94 #if !SDB_HOST
95     // check the loopback interface has been up in 30 sec
96     while(cnt_max > 0) {
97         if(get_loopback_status() == LOOPBACK_DOWN) {
98             cnt_max--;
99             sdb_sleep_ms(1000);
100         }
101         else {
102             break;
103         }
104     }
105 #endif
106     memset(&addr, 0, sizeof(addr));
107     addr.sin_family = AF_INET;
108     addr.sin_port = htons(port);
109
110     if(cnt_max ==0) {
111         addr.sin_addr.s_addr = htonl(INADDR_ANY);
112     } else {
113         addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
114     }
115     s = socket(AF_INET, type, 0);
116     if(s < 0) {
117         return -1;
118     }
119
120     n = 1;
121     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) < 0) {
122         sdb_close(s);
123         return -1;
124     }
125
126     if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
127         sdb_close(s);
128         return -1;
129     }
130
131     if (type == SOCK_STREAM) {
132         int ret;
133
134         ret = listen(s, LISTEN_BACKLOG);
135
136         if (ret < 0) {
137             sdb_close(s);
138             return -1; 
139         }
140     }
141
142     return s;
143 }
144