• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #include "private-lib-core.h"
26 
27 int
lws_send_pipe_choked(struct lws * wsi)28 lws_send_pipe_choked(struct lws *wsi)
29 {
30 	struct lws *wsi_eff = wsi;
31 	fd_set writefds;
32 	struct timeval tv = { 0, 0 };
33 	int n;
34 #if defined(LWS_WITH_HTTP2)
35 	wsi_eff = lws_get_network_wsi(wsi);
36 #endif
37 
38 	/* the fact we checked implies we avoided back-to-back writes */
39 	wsi_eff->could_have_pending = 0;
40 
41 	/* treat the fact we got a truncated send pending as if we're choked */
42 	if (lws_has_buffered_out(wsi)
43 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
44 	    || wsi->http.comp_ctx.buflist_comp ||
45 	       wsi->http.comp_ctx.may_have_more
46 #endif
47 	)
48 		return 1;
49 
50 	FD_ZERO(&writefds);
51 	FD_SET(wsi_eff->desc.sockfd, &writefds);
52 
53 	n = select(wsi_eff->desc.sockfd + 1, NULL, &writefds, NULL, &tv);
54 	if (n < 0)
55 		return 1; /* choked */
56 
57 	return !n; /* n = 0 = not writable = choked */
58 }
59 
60 int
lws_poll_listen_fd(struct lws_pollfd * fd)61 lws_poll_listen_fd(struct lws_pollfd *fd)
62 {
63 	fd_set readfds;
64 	struct timeval tv = { 0, 0 };
65 
66 	FD_ZERO(&readfds);
67 	FD_SET(fd->fd, &readfds);
68 
69 	return select(fd->fd + 1, &readfds, NULL, NULL, &tv);
70 }
71 
72 int
lws_plat_set_nonblocking(lws_sockfd_type fd)73 lws_plat_set_nonblocking(lws_sockfd_type fd)
74 {
75 	return fcntl(fd, F_SETFL, O_NONBLOCK) < 0;
76 }
77 
78 int
lws_plat_set_socket_options(struct lws_vhost * vhost,int fd,int unix_skt)79 lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt)
80 {
81 	int optval = 1;
82 	socklen_t optlen = sizeof(optval);
83 
84 #if defined(__APPLE__) || \
85     defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
86     defined(__NetBSD__) || \
87     defined(__OpenBSD__)
88 	struct protoent *tcp_proto;
89 #endif
90 
91 	if (vhost->ka_time) {
92 		/* enable keepalive on this socket */
93 		optval = 1;
94 		if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
95 			       (const void *)&optval, optlen) < 0)
96 			return 1;
97 
98 #if defined(__APPLE__) || \
99     defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
100     defined(__NetBSD__) || \
101         defined(__CYGWIN__) || defined(__OpenBSD__) || defined (__sun)
102 
103 		/*
104 		 * didn't find a way to set these per-socket, need to
105 		 * tune kernel systemwide values
106 		 */
107 #else
108 		/* set the keepalive conditions we want on it too */
109 		optval = vhost->ka_time;
110 		if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
111 			       (const void *)&optval, optlen) < 0)
112 			return 1;
113 
114 		optval = vhost->ka_interval;
115 		if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
116 			       (const void *)&optval, optlen) < 0)
117 			return 1;
118 
119 		optval = vhost->ka_probes;
120 		if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
121 			       (const void *)&optval, optlen) < 0)
122 			return 1;
123 #endif
124 	}
125 
126 	/* Disable Nagle */
127 	optval = 1;
128 	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, optlen) < 0)
129 		return 1;
130 
131 	return lws_plat_set_nonblocking(fd);
132 }
133 
134 /* cast a struct sockaddr_in6 * into addr for ipv6 */
135 
136 int
lws_interface_to_sa(int ipv6,const char * ifname,struct sockaddr_in * addr,size_t addrlen)137 lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
138 		    size_t addrlen)
139 {
140 #if 0
141 	int rc = LWS_ITOSA_NOT_EXIST;
142 
143 	struct ifaddrs *ifr;
144 	struct ifaddrs *ifc;
145 #ifdef LWS_WITH_IPV6
146 	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
147 #endif
148 
149 	getifaddrs(&ifr);
150 	for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
151 		if (!ifc->ifa_addr)
152 			continue;
153 
154 		lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
155 
156 		if (strcmp(ifc->ifa_name, ifname))
157 			continue;
158 
159 		switch (ifc->ifa_addr->sa_family) {
160 		case AF_INET:
161 #ifdef LWS_WITH_IPV6
162 			if (ipv6) {
163 				/* map IPv4 to IPv6 */
164 				memset((char *)&addr6->sin6_addr, 0,
165 						sizeof(struct in6_addr));
166 				addr6->sin6_addr.s6_addr[10] = 0xff;
167 				addr6->sin6_addr.s6_addr[11] = 0xff;
168 				memcpy(&addr6->sin6_addr.s6_addr[12],
169 					&((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
170 							sizeof(struct in_addr));
171 			} else
172 #endif
173 				memcpy(addr,
174 					(struct sockaddr_in *)ifc->ifa_addr,
175 						    sizeof(struct sockaddr_in));
176 			break;
177 #ifdef LWS_WITH_IPV6
178 		case AF_INET6:
179 			memcpy(&addr6->sin6_addr,
180 			  &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
181 						       sizeof(struct in6_addr));
182 			break;
183 #endif
184 		default:
185 			continue;
186 		}
187 		rc = LWS_ITOSA_USABLE;
188 	}
189 
190 	freeifaddrs(ifr);
191 
192 	if (rc == LWS_ITOSA_NOT_EXIST) {
193 		/* check if bind to IP address */
194 #ifdef LWS_WITH_IPV6
195 		if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
196 			rc = LWS_ITOSA_USABLE;
197 		else
198 #endif
199 		if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1)
200 			rc = LWS_ITOSA_USABLE;
201 	}
202 
203 	return rc;
204 #endif
205 
206 	return LWS_ITOSA_NOT_EXIST;
207 }
208 
209 const char *
lws_plat_inet_ntop(int af,const void * src,char * dst,int cnt)210 lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
211 {
212 	return inet_ntop(af, src, dst, cnt);
213 }
214 
215 int
lws_plat_inet_pton(int af,const char * src,void * dst)216 lws_plat_inet_pton(int af, const char *src, void *dst)
217 {
218 	return 1; //  inet_pton(af, src, dst);
219 }
220 
221 int
lws_plat_ifname_to_hwaddr(int fd,const char * ifname,uint8_t * hwaddr,int len)222 lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len)
223 {
224 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
225 
226 	return -1;
227 }
228 
229 int
lws_plat_rawudp_broadcast(uint8_t * p,const uint8_t * canned,int canned_len,int n,int fd,const char * iface)230 lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, int canned_len,
231 			  int n, int fd, const char *iface)
232 {
233 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
234 
235 	return -1;
236 }
237 
238 int
lws_plat_if_up(const char * ifname,int fd,int up)239 lws_plat_if_up(const char *ifname, int fd, int up)
240 {
241 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
242 
243 	return -1;
244 }
245 
246 int
lws_plat_BINDTODEVICE(lws_sockfd_type fd,const char * ifname)247 lws_plat_BINDTODEVICE(lws_sockfd_type fd, const char *ifname)
248 {
249 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
250 
251 	return -1;
252 }
253 
254 int
lws_plat_ifconfig_ip(const char * ifname,int fd,uint8_t * ip,uint8_t * mask_ip,uint8_t * gateway_ip)255 lws_plat_ifconfig_ip(const char *ifname, int fd, uint8_t *ip, uint8_t *mask_ip,
256 			uint8_t *gateway_ip)
257 {
258 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
259 
260 	return -1;
261 }
262