private.h: rename to contain dir
[platform/upstream/libwebsockets.git] / lib / plat / windows / windows-sockets.c
1 #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
2 #define _WINSOCK_DEPRECATED_NO_WARNINGS
3 #endif
4 #include "private-lib-core.h"
5
6
7 LWS_VISIBLE int
8 lws_send_pipe_choked(struct lws *wsi)
9 {       struct lws *wsi_eff;
10
11 #if defined(LWS_WITH_HTTP2)
12         wsi_eff = lws_get_network_wsi(wsi);
13 #else
14         wsi_eff = wsi;
15 #endif
16         /* the fact we checked implies we avoided back-to-back writes */
17         wsi_eff->could_have_pending = 0;
18
19         /* treat the fact we got a truncated send pending as if we're choked */
20         if (lws_has_buffered_out(wsi_eff)
21 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
22             ||wsi->http.comp_ctx.buflist_comp ||
23               wsi->http.comp_ctx.may_have_more
24 #endif
25         )
26                 return 1;
27
28         return (int)wsi_eff->sock_send_blocking;
29 }
30
31 int
32 lws_poll_listen_fd(struct lws_pollfd *fd)
33 {
34         fd_set readfds;
35         struct timeval tv = { 0, 0 };
36
37         assert((fd->events & LWS_POLLIN) == LWS_POLLIN);
38
39         FD_ZERO(&readfds);
40         FD_SET(fd->fd, &readfds);
41
42         return select(((int)fd->fd) + 1, &readfds, NULL, NULL, &tv);
43 }
44
45 int
46 lws_plat_set_nonblocking(int fd)
47 {
48         u_long optl = 1;
49
50         return !!ioctlsocket(fd, FIONBIO, &optl);
51 }
52
53 int
54 lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
55                             int unix_skt)
56 {
57         int optval = 1;
58         int optlen = sizeof(optval);
59         DWORD dwBytesRet;
60         struct tcp_keepalive alive;
61         int protonbr;
62 #ifndef _WIN32_WCE
63         struct protoent *tcp_proto;
64 #endif
65
66         if (vhost->ka_time) {
67                 /* enable keepalive on this socket */
68                 optval = 1;
69                 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
70                                (const char *)&optval, optlen) < 0)
71                         return 1;
72
73                 alive.onoff = TRUE;
74                 alive.keepalivetime = vhost->ka_time * 1000;
75                 alive.keepaliveinterval = vhost->ka_interval * 1000;
76
77                 if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
78                              NULL, 0, &dwBytesRet, NULL, NULL))
79                         return 1;
80         }
81
82         /* Disable Nagle */
83         optval = 1;
84 #ifndef _WIN32_WCE
85         tcp_proto = getprotobyname("TCP");
86         if (!tcp_proto) {
87                 lwsl_err("getprotobyname() failed with error %d\n", LWS_ERRNO);
88                 return 1;
89         }
90         protonbr = tcp_proto->p_proto;
91 #else
92         protonbr = 6;
93 #endif
94
95         setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen);
96
97         return lws_plat_set_nonblocking(fd);
98 }
99
100
101 LWS_EXTERN int
102 lws_interface_to_sa(int ipv6,
103                 const char *ifname, struct sockaddr_in *addr, size_t addrlen)
104 {
105 #ifdef LWS_WITH_IPV6
106         struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
107
108         if (ipv6) {
109                 if (lws_plat_inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) {
110                         return LWS_ITOSA_USABLE;
111                 }
112         }
113 #endif
114
115         long long address = inet_addr(ifname);
116
117         if (address == INADDR_NONE) {
118                 struct hostent *entry = gethostbyname(ifname);
119                 if (entry)
120                         address = ((struct in_addr *)entry->h_addr_list[0])->s_addr;
121         }
122
123         if (address == INADDR_NONE)
124                 return LWS_ITOSA_NOT_EXIST;
125
126         addr->sin_addr.s_addr = (unsigned long)(lws_intptr_t)address;
127
128         return LWS_ITOSA_USABLE;
129 }
130
131 void
132 lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
133 {
134         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
135         int n = LWS_POLLIN | LWS_POLLHUP | FD_CONNECT;
136
137         if (wsi->udp) {
138                 lwsl_info("%s: UDP\n", __func__);
139                 n = LWS_POLLIN;
140         }
141
142         pt->fds[pt->fds_count++].revents = 0;
143         WSAEventSelect(wsi->desc.sockfd, pt->events, n);
144 }
145
146 void
147 lws_plat_delete_socket_from_fds(struct lws_context *context,
148                                                 struct lws *wsi, int m)
149 {
150         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
151
152         pt->fds_count--;
153 }
154
155
156 int
157 lws_plat_check_connection_error(struct lws *wsi)
158 {
159         int optVal;
160         int optLen = sizeof(int);
161
162         if (getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR,
163                            (char*)&optVal, &optLen) != SOCKET_ERROR && optVal &&
164                 optVal != LWS_EALREADY && optVal != LWS_EINPROGRESS &&
165                 optVal != LWS_EWOULDBLOCK && optVal != WSAEINVAL) {
166                    lwsl_debug("Connect failed SO_ERROR=%d\n", optVal);
167                    return 1;
168         }
169
170         return 0;
171 }
172
173 int
174 lws_plat_change_pollfd(struct lws_context *context,
175                           struct lws *wsi, struct lws_pollfd *pfd)
176 {
177         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
178         long e = LWS_POLLHUP | FD_CONNECT;
179
180         if ((pfd->events & LWS_POLLIN))
181                 e |= LWS_POLLIN;
182
183         if ((pfd->events & LWS_POLLOUT))
184                 e |= LWS_POLLOUT;
185
186         if (WSAEventSelect(wsi->desc.sockfd, pt->events, e) != SOCKET_ERROR)
187                 return 0;
188
189         lwsl_err("WSAEventSelect() failed with error %d\n", LWS_ERRNO);
190
191         return 1;
192 }
193
194 const char *
195 lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
196 {
197         WCHAR *buffer;
198         DWORD bufferlen = cnt;
199         BOOL ok = FALSE;
200
201         buffer = lws_malloc(bufferlen * 2, "inet_ntop");
202         if (!buffer) {
203                 lwsl_err("Out of memory\n");
204                 return NULL;
205         }
206
207         if (af == AF_INET) {
208                 struct sockaddr_in srcaddr;
209                 memset(&srcaddr, 0, sizeof(srcaddr));
210                 srcaddr.sin_family = AF_INET;
211                 memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
212
213                 if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen))
214                         ok = TRUE;
215 #ifdef LWS_WITH_IPV6
216         } else if (af == AF_INET6) {
217                 struct sockaddr_in6 srcaddr;
218                 memset(&srcaddr, 0, sizeof(srcaddr));
219                 srcaddr.sin6_family = AF_INET6;
220                 memcpy(&(srcaddr.sin6_addr), src, sizeof(srcaddr.sin6_addr));
221
222                 if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen))
223                         ok = TRUE;
224 #endif
225         } else
226                 lwsl_err("Unsupported type\n");
227
228         if (!ok) {
229                 int rv = WSAGetLastError();
230                 lwsl_err("WSAAddressToString() : %d\n", rv);
231         } else {
232                 if (WideCharToMultiByte(CP_ACP, 0, buffer, bufferlen, dst, cnt, 0, NULL) <= 0)
233                         ok = FALSE;
234         }
235
236         lws_free(buffer);
237         return ok ? dst : NULL;
238 }
239
240 int
241 lws_plat_inet_pton(int af, const char *src, void *dst)
242 {
243         WCHAR *buffer;
244         DWORD bufferlen = (int)strlen(src) + 1;
245         BOOL ok = FALSE;
246
247         buffer = lws_malloc(bufferlen * 2, "inet_pton");
248         if (!buffer) {
249                 lwsl_err("Out of memory\n");
250                 return -1;
251         }
252
253         if (MultiByteToWideChar(CP_ACP, 0, src, bufferlen, buffer, bufferlen) <= 0) {
254                 lwsl_err("Failed to convert multi byte to wide char\n");
255                 lws_free(buffer);
256                 return -1;
257         }
258
259         if (af == AF_INET) {
260                 struct sockaddr_in dstaddr;
261                 int dstaddrlen = sizeof(dstaddr);
262
263                 memset(&dstaddr, 0, sizeof(dstaddr));
264                 dstaddr.sin_family = AF_INET;
265
266                 if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
267                         ok = TRUE;
268                         memcpy(dst, &dstaddr.sin_addr, sizeof(dstaddr.sin_addr));
269                 }
270 #ifdef LWS_WITH_IPV6
271         } else if (af == AF_INET6) {
272                 struct sockaddr_in6 dstaddr;
273                 int dstaddrlen = sizeof(dstaddr);
274
275                 memset(&dstaddr, 0, sizeof(dstaddr));
276                 dstaddr.sin6_family = AF_INET6;
277
278                 if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
279                         ok = TRUE;
280                         memcpy(dst, &dstaddr.sin6_addr, sizeof(dstaddr.sin6_addr));
281                 }
282 #endif
283         } else
284                 lwsl_err("Unsupported type\n");
285
286         if (!ok) {
287                 int rv = WSAGetLastError();
288                 lwsl_err("WSAAddressToString() : %d\n", rv);
289         }
290
291         lws_free(buffer);
292         return ok ? 1 : -1;
293 }