Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 1 | #include "private-libwebsockets.h" |
| 2 | |
Andy Green | 3a9f79e | 2015-03-04 16:16:41 +0800 | [diff] [blame] | 3 | #include <pwd.h> |
| 4 | #include <grp.h> |
| 5 | |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 6 | /* |
| 7 | * included from libwebsockets.c for unix builds |
| 8 | */ |
| 9 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 10 | unsigned long long time_in_microseconds(void) |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 11 | { |
| 12 | struct timeval tv; |
| 13 | gettimeofday(&tv, NULL); |
Imo Farcher | 97a748a | 2015-01-26 15:39:36 +0800 | [diff] [blame] | 14 | return ((unsigned long long)tv.tv_sec * 1000000LL) + tv.tv_usec; |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 15 | } |
| 16 | |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 17 | LWS_VISIBLE int lws_get_random(struct lws_context *context, |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 18 | void *buf, int len) |
| 19 | { |
| 20 | return read(context->fd_random, (char *)buf, len); |
| 21 | } |
| 22 | |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 23 | LWS_VISIBLE int lws_send_pipe_choked(struct lws *wsi) |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 24 | { |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 25 | struct lws_pollfd fds; |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 26 | |
| 27 | /* treat the fact we got a truncated send pending as if we're choked */ |
| 28 | if (wsi->truncated_send_len) |
| 29 | return 1; |
| 30 | |
| 31 | fds.fd = wsi->sock; |
| 32 | fds.events = POLLOUT; |
| 33 | fds.revents = 0; |
| 34 | |
| 35 | if (poll(&fds, 1, 0) != 1) |
| 36 | return 1; |
| 37 | |
| 38 | if ((fds.revents & POLLOUT) == 0) |
| 39 | return 1; |
| 40 | |
| 41 | /* okay to send another packet without blocking */ |
| 42 | |
| 43 | return 0; |
| 44 | } |
| 45 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 46 | LWS_VISIBLE int |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 47 | lws_poll_listen_fd(struct lws_pollfd *fd) |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 48 | { |
| 49 | return poll(fd, 1, 0); |
| 50 | } |
| 51 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 52 | /* |
| 53 | * This is just used to interrupt poll waiting |
| 54 | * we don't have to do anything with it. |
| 55 | */ |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 56 | static void lws_sigusr2(int sig) |
| 57 | { |
| 58 | } |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 59 | |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 60 | /** |
Andy Green | 6230476 | 2015-12-04 08:43:54 +0800 | [diff] [blame] | 61 | * lws_cancel_service() - Cancel servicing of pending websocket activity |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 62 | * @context: Websocket context |
| 63 | * |
Andy Green | 6230476 | 2015-12-04 08:43:54 +0800 | [diff] [blame] | 64 | * This function let a call to lws_service() waiting for a timeout |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 65 | * immediately return. |
| 66 | */ |
| 67 | LWS_VISIBLE void |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 68 | lws_cancel_service(struct lws_context *context) |
Andy Green | bfaea95 | 2014-03-31 11:01:32 +0800 | [diff] [blame] | 69 | { |
| 70 | char buf = 0; |
| 71 | |
| 72 | if (write(context->dummy_pipe_fds[1], &buf, sizeof(buf)) != 1) |
| 73 | lwsl_err("Cannot write to dummy pipe"); |
| 74 | } |
| 75 | |
| 76 | LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line) |
| 77 | { |
| 78 | int syslog_level = LOG_DEBUG; |
| 79 | |
| 80 | switch (level) { |
| 81 | case LLL_ERR: |
| 82 | syslog_level = LOG_ERR; |
| 83 | break; |
| 84 | case LLL_WARN: |
| 85 | syslog_level = LOG_WARNING; |
| 86 | break; |
| 87 | case LLL_NOTICE: |
| 88 | syslog_level = LOG_NOTICE; |
| 89 | break; |
| 90 | case LLL_INFO: |
| 91 | syslog_level = LOG_INFO; |
| 92 | break; |
| 93 | } |
| 94 | syslog(syslog_level, "%s", line); |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 95 | } |
| 96 | |
| 97 | LWS_VISIBLE int |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 98 | lws_plat_service(struct lws_context *context, int timeout_ms) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 99 | { |
| 100 | int n; |
| 101 | int m; |
| 102 | char buf; |
Andy Green | 30edd91 | 2015-01-29 09:42:22 +0800 | [diff] [blame] | 103 | #ifdef LWS_OPENSSL_SUPPORT |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 104 | struct lws *wsi, *wsi_next; |
Andy Green | 30edd91 | 2015-01-29 09:42:22 +0800 | [diff] [blame] | 105 | #endif |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 106 | |
| 107 | /* stay dead once we are dead */ |
| 108 | |
Andy Green | a717df2 | 2014-04-11 13:14:37 +0800 | [diff] [blame] | 109 | if (!context) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 110 | return 1; |
| 111 | |
Andy Green | a717df2 | 2014-04-11 13:14:37 +0800 | [diff] [blame] | 112 | lws_libev_run(context); |
| 113 | |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 114 | context->service_tid = context->protocols[0].callback(context, NULL, |
| 115 | LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); |
| 116 | |
Andy Green | 609ec85 | 2014-10-09 08:29:22 +0800 | [diff] [blame] | 117 | #ifdef LWS_OPENSSL_SUPPORT |
| 118 | /* if we know we have non-network pending data, do not wait in poll */ |
Andy Green | 5281560 | 2015-01-29 08:36:18 +0800 | [diff] [blame] | 119 | if (lws_ssl_anybody_has_buffered_read(context)) |
Andy Green | 609ec85 | 2014-10-09 08:29:22 +0800 | [diff] [blame] | 120 | timeout_ms = 0; |
| 121 | #endif |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 122 | n = poll(context->fds, context->fds_count, timeout_ms); |
| 123 | context->service_tid = 0; |
| 124 | |
Andy Green | 609ec85 | 2014-10-09 08:29:22 +0800 | [diff] [blame] | 125 | #ifdef LWS_OPENSSL_SUPPORT |
Andy Green | 5281560 | 2015-01-29 08:36:18 +0800 | [diff] [blame] | 126 | if (!lws_ssl_anybody_has_buffered_read(context) && n == 0) { |
Andy Green | 609ec85 | 2014-10-09 08:29:22 +0800 | [diff] [blame] | 127 | #else |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 128 | if (n == 0) /* poll timeout */ { |
Andy Green | 609ec85 | 2014-10-09 08:29:22 +0800 | [diff] [blame] | 129 | #endif |
Andy Green | 6230476 | 2015-12-04 08:43:54 +0800 | [diff] [blame] | 130 | lws_service_fd(context, NULL); |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 131 | return 0; |
| 132 | } |
| 133 | |
| 134 | if (n < 0) { |
| 135 | if (LWS_ERRNO != LWS_EINTR) |
| 136 | return -1; |
| 137 | return 0; |
| 138 | } |
| 139 | |
Andy Green | 5281560 | 2015-01-29 08:36:18 +0800 | [diff] [blame] | 140 | #ifdef LWS_OPENSSL_SUPPORT |
| 141 | /* |
| 142 | * For all guys with buffered SSL read data already saved up, if they |
| 143 | * are not flowcontrolled, fake their POLLIN status so they'll get |
| 144 | * service to use up the buffered incoming data, even though their |
| 145 | * network socket may have nothing |
| 146 | */ |
| 147 | |
| 148 | wsi = context->pending_read_list; |
| 149 | while (wsi) { |
| 150 | wsi_next = wsi->pending_read_list_next; |
Thomas Greenslade | a2a4b0b | 2015-10-12 16:06:26 +0800 | [diff] [blame] | 151 | context->fds[wsi->position_in_fds_table].revents |= |
| 152 | context->fds[wsi->position_in_fds_table].events & POLLIN; |
| 153 | if (context->fds[wsi->position_in_fds_table].revents & POLLIN) { |
Andy Green | 5281560 | 2015-01-29 08:36:18 +0800 | [diff] [blame] | 154 | /* |
| 155 | * he's going to get serviced now, take him off the |
| 156 | * list of guys with buffered SSL. If he still has some |
| 157 | * at the end of the service, he'll get put back on the |
| 158 | * list then. |
| 159 | */ |
| 160 | lws_ssl_remove_wsi_from_buffered_list(context, wsi); |
| 161 | } |
| 162 | wsi = wsi_next; |
| 163 | } |
| 164 | #endif |
| 165 | |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 166 | /* any socket with events to service? */ |
| 167 | |
| 168 | for (n = 0; n < context->fds_count; n++) { |
Andy Green | 5281560 | 2015-01-29 08:36:18 +0800 | [diff] [blame] | 169 | |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 170 | if (!context->fds[n].revents) |
| 171 | continue; |
| 172 | |
| 173 | if (context->fds[n].fd == context->dummy_pipe_fds[0]) { |
| 174 | if (read(context->fds[n].fd, &buf, 1) != 1) |
| 175 | lwsl_err("Cannot read from dummy pipe."); |
| 176 | continue; |
| 177 | } |
| 178 | |
Andy Green | 6230476 | 2015-12-04 08:43:54 +0800 | [diff] [blame] | 179 | m = lws_service_fd(context, &context->fds[n]); |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 180 | if (m < 0) |
| 181 | return -1; |
| 182 | /* if something closed, retry this slot */ |
| 183 | if (m) |
| 184 | n--; |
| 185 | } |
| 186 | |
| 187 | return 0; |
| 188 | } |
| 189 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 190 | LWS_VISIBLE int |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 191 | lws_plat_set_socket_options(struct lws_context *context, int fd) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 192 | { |
| 193 | int optval = 1; |
| 194 | socklen_t optlen = sizeof(optval); |
| 195 | |
geq | d6827f7 | 2014-05-28 04:52:18 +0000 | [diff] [blame] | 196 | #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ |
| 197 | defined(__OpenBSD__) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 198 | struct protoent *tcp_proto; |
| 199 | #endif |
| 200 | |
| 201 | if (context->ka_time) { |
| 202 | /* enable keepalive on this socket */ |
| 203 | optval = 1; |
| 204 | if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, |
| 205 | (const void *)&optval, optlen) < 0) |
| 206 | return 1; |
| 207 | |
geq | d6827f7 | 2014-05-28 04:52:18 +0000 | [diff] [blame] | 208 | #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ |
| 209 | defined(__CYGWIN__) || defined(__OpenBSD__) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 210 | |
| 211 | /* |
| 212 | * didn't find a way to set these per-socket, need to |
| 213 | * tune kernel systemwide values |
| 214 | */ |
| 215 | #else |
| 216 | /* set the keepalive conditions we want on it too */ |
| 217 | optval = context->ka_time; |
Aurelian Pop | d07ea3b | 2014-07-29 15:36:06 +0300 | [diff] [blame] | 218 | if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 219 | (const void *)&optval, optlen) < 0) |
| 220 | return 1; |
| 221 | |
| 222 | optval = context->ka_interval; |
Aurelian Pop | d07ea3b | 2014-07-29 15:36:06 +0300 | [diff] [blame] | 223 | if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 224 | (const void *)&optval, optlen) < 0) |
| 225 | return 1; |
| 226 | |
| 227 | optval = context->ka_probes; |
Aurelian Pop | d07ea3b | 2014-07-29 15:36:06 +0300 | [diff] [blame] | 228 | if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 229 | (const void *)&optval, optlen) < 0) |
| 230 | return 1; |
| 231 | #endif |
| 232 | } |
| 233 | |
| 234 | /* Disable Nagle */ |
| 235 | optval = 1; |
geq | d6827f7 | 2014-05-28 04:52:18 +0000 | [diff] [blame] | 236 | #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \ |
| 237 | !defined(__OpenBSD__) |
Andy Green | abb4811 | 2014-11-30 13:06:09 +0800 | [diff] [blame] | 238 | if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0) |
| 239 | return 1; |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 240 | #else |
| 241 | tcp_proto = getprotobyname("TCP"); |
Andy Green | abb4811 | 2014-11-30 13:06:09 +0800 | [diff] [blame] | 242 | if (setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen) < 0) |
| 243 | return 1; |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 244 | #endif |
| 245 | |
| 246 | /* We are nonblocking... */ |
Andy Green | 956a08a | 2014-11-30 13:02:32 +0800 | [diff] [blame] | 247 | if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) |
| 248 | return 1; |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 249 | |
| 250 | return 0; |
| 251 | } |
| 252 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 253 | LWS_VISIBLE void |
| 254 | lws_plat_drop_app_privileges(struct lws_context_creation_info *info) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 255 | { |
Andy Green | 3a9f79e | 2015-03-04 16:16:41 +0800 | [diff] [blame] | 256 | if (info->uid != -1) { |
| 257 | struct passwd *p = getpwuid(info->uid); |
| 258 | |
| 259 | if (p) { |
| 260 | initgroups(p->pw_name, info->gid); |
| 261 | if (setuid(info->uid)) |
| 262 | lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO)); |
| 263 | else |
| 264 | lwsl_notice(" Set privs to user '%s'\n", p->pw_name); |
| 265 | } else |
| 266 | lwsl_warn("getpwuid: unable to find uid %d", info->uid); |
| 267 | } |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 268 | if (info->gid != -1) |
| 269 | if (setgid(info->gid)) |
| 270 | lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO)); |
Andy Green | 3a9f79e | 2015-03-04 16:16:41 +0800 | [diff] [blame] | 271 | |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 272 | } |
| 273 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 274 | LWS_VISIBLE int |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 275 | lws_plat_init_lookup(struct lws_context *context) |
=?UTF-8?q?Joakim=20S=C3=B6derberg?= | caf7e3d | 2015-06-25 17:51:07 +0200 | [diff] [blame] | 276 | { |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 277 | context->lws_lookup = lws_zalloc(sizeof(struct lws *) * context->max_fds); |
=?UTF-8?q?Joakim=20S=C3=B6derberg?= | caf7e3d | 2015-06-25 17:51:07 +0200 | [diff] [blame] | 278 | if (context->lws_lookup == NULL) { |
| 279 | lwsl_err( |
| 280 | "Unable to allocate lws_lookup array for %d connections\n", |
| 281 | context->max_fds); |
| 282 | return 1; |
| 283 | } |
| 284 | |
| 285 | return 0; |
| 286 | } |
| 287 | |
| 288 | LWS_VISIBLE int |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 289 | lws_plat_init_fd_tables(struct lws_context *context) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 290 | { |
Pokrovskiy | 20636ec | 2015-04-21 00:53:59 -0700 | [diff] [blame] | 291 | context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY); |
| 292 | if (context->fd_random < 0) { |
| 293 | lwsl_err("Unable to open random device %s %d\n", |
| 294 | SYSTEM_RANDOM_FILEPATH, context->fd_random); |
| 295 | return 1; |
| 296 | } |
| 297 | |
Andy Green | a717df2 | 2014-04-11 13:14:37 +0800 | [diff] [blame] | 298 | if (lws_libev_init_fd_table(context)) |
| 299 | /* libev handled it instead */ |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 300 | return 0; |
Andy Green | a717df2 | 2014-04-11 13:14:37 +0800 | [diff] [blame] | 301 | |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 302 | if (pipe(context->dummy_pipe_fds)) { |
| 303 | lwsl_err("Unable to create pipe\n"); |
| 304 | return 1; |
| 305 | } |
| 306 | |
| 307 | /* use the read end of pipe as first item */ |
| 308 | context->fds[0].fd = context->dummy_pipe_fds[0]; |
| 309 | context->fds[0].events = LWS_POLLIN; |
| 310 | context->fds[0].revents = 0; |
| 311 | context->fds_count = 1; |
Aurelian Pop | d07ea3b | 2014-07-29 15:36:06 +0300 | [diff] [blame] | 312 | |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 313 | return 0; |
| 314 | } |
| 315 | |
| 316 | static void sigpipe_handler(int x) |
| 317 | { |
| 318 | } |
| 319 | |
| 320 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 321 | LWS_VISIBLE int |
| 322 | lws_plat_context_early_init(void) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 323 | { |
| 324 | sigset_t mask; |
| 325 | |
| 326 | signal(SIGUSR2, lws_sigusr2); |
| 327 | sigemptyset(&mask); |
| 328 | sigaddset(&mask, SIGUSR2); |
| 329 | |
| 330 | sigprocmask(SIG_BLOCK, &mask, NULL); |
Aurelian Pop | d07ea3b | 2014-07-29 15:36:06 +0300 | [diff] [blame] | 331 | |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 332 | signal(SIGPIPE, sigpipe_handler); |
| 333 | |
| 334 | return 0; |
| 335 | } |
| 336 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 337 | LWS_VISIBLE void |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 338 | lws_plat_context_early_destroy(struct lws_context *context) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 339 | { |
| 340 | } |
| 341 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 342 | LWS_VISIBLE void |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 343 | lws_plat_context_late_destroy(struct lws_context *context) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 344 | { |
=?UTF-8?q?Joakim=20S=C3=B6derberg?= | caf7e3d | 2015-06-25 17:51:07 +0200 | [diff] [blame] | 345 | if (context->lws_lookup) |
| 346 | lws_free(context->lws_lookup); |
| 347 | |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 348 | close(context->dummy_pipe_fds[0]); |
| 349 | close(context->dummy_pipe_fds[1]); |
| 350 | close(context->fd_random); |
| 351 | } |
| 352 | |
| 353 | /* cast a struct sockaddr_in6 * into addr for ipv6 */ |
| 354 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 355 | LWS_VISIBLE int |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 356 | interface_to_sa(struct lws_context *context, |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 357 | const char *ifname, struct sockaddr_in *addr, size_t addrlen) |
| 358 | { |
| 359 | int rc = -1; |
| 360 | |
| 361 | struct ifaddrs *ifr; |
| 362 | struct ifaddrs *ifc; |
| 363 | #ifdef LWS_USE_IPV6 |
| 364 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; |
| 365 | #endif |
| 366 | |
| 367 | getifaddrs(&ifr); |
| 368 | for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) { |
| 369 | if (!ifc->ifa_addr) |
| 370 | continue; |
| 371 | |
| 372 | lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname); |
| 373 | |
| 374 | if (strcmp(ifc->ifa_name, ifname)) |
| 375 | continue; |
| 376 | |
| 377 | switch (ifc->ifa_addr->sa_family) { |
| 378 | case AF_INET: |
| 379 | #ifdef LWS_USE_IPV6 |
| 380 | if (LWS_IPV6_ENABLED(context)) { |
| 381 | /* map IPv4 to IPv6 */ |
| 382 | bzero((char *)&addr6->sin6_addr, |
| 383 | sizeof(struct in6_addr)); |
| 384 | addr6->sin6_addr.s6_addr[10] = 0xff; |
| 385 | addr6->sin6_addr.s6_addr[11] = 0xff; |
| 386 | memcpy(&addr6->sin6_addr.s6_addr[12], |
| 387 | &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr, |
| 388 | sizeof(struct in_addr)); |
| 389 | } else |
| 390 | #endif |
| 391 | memcpy(addr, |
| 392 | (struct sockaddr_in *)ifc->ifa_addr, |
| 393 | sizeof(struct sockaddr_in)); |
| 394 | break; |
| 395 | #ifdef LWS_USE_IPV6 |
| 396 | case AF_INET6: |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 397 | memcpy(&addr6->sin6_addr, |
| 398 | &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr, |
| 399 | sizeof(struct in6_addr)); |
| 400 | break; |
| 401 | #endif |
| 402 | default: |
| 403 | continue; |
| 404 | } |
| 405 | rc = 0; |
| 406 | } |
| 407 | |
| 408 | freeifaddrs(ifr); |
Aurelian Pop | d07ea3b | 2014-07-29 15:36:06 +0300 | [diff] [blame] | 409 | |
vpeter4 | 7cc7ae4 | 2014-04-27 12:32:15 +0200 | [diff] [blame] | 410 | if (rc == -1) { |
| 411 | /* check if bind to IP adddress */ |
| 412 | #ifdef LWS_USE_IPV6 |
| 413 | if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) |
| 414 | rc = 0; |
| 415 | else |
| 416 | #endif |
| 417 | if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1) |
| 418 | rc = 0; |
| 419 | } |
| 420 | |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 421 | return rc; |
| 422 | } |
| 423 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 424 | LWS_VISIBLE void |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 425 | lws_plat_insert_socket_into_fds(struct lws_context *context, |
| 426 | struct lws *wsi) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 427 | { |
Andy Green | a717df2 | 2014-04-11 13:14:37 +0800 | [diff] [blame] | 428 | lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ); |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 429 | context->fds[context->fds_count++].revents = 0; |
| 430 | } |
| 431 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 432 | LWS_VISIBLE void |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 433 | lws_plat_delete_socket_from_fds(struct lws_context *context, |
| 434 | struct lws *wsi, int m) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 435 | { |
| 436 | } |
| 437 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 438 | LWS_VISIBLE void |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 439 | lws_plat_service_periodic(struct lws_context *context) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 440 | { |
| 441 | /* if our parent went down, don't linger around */ |
| 442 | if (context->started_with_parent && |
| 443 | kill(context->started_with_parent, 0) < 0) |
| 444 | kill(getpid(), SIGTERM); |
| 445 | } |
| 446 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 447 | LWS_VISIBLE int |
Andy Green | 4b85c1d | 2015-12-04 11:08:32 +0800 | [diff] [blame^] | 448 | lws_plat_change_pollfd(struct lws_context *context, |
| 449 | struct lws *wsi, struct lws_pollfd *pfd) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 450 | { |
| 451 | return 0; |
| 452 | } |
| 453 | |
Andy Green | e40aa9b | 2014-04-02 21:02:54 +0800 | [diff] [blame] | 454 | LWS_VISIBLE int |
| 455 | lws_plat_open_file(const char* filename, unsigned long* filelen) |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 456 | { |
| 457 | struct stat stat_buf; |
| 458 | int ret = open(filename, O_RDONLY); |
| 459 | |
| 460 | if (ret < 0) |
| 461 | return LWS_INVALID_FILE; |
| 462 | |
Andy Green | 24109f4 | 2014-11-30 13:03:45 +0800 | [diff] [blame] | 463 | if (fstat(ret, &stat_buf) < 0) { |
| 464 | close(ret); |
| 465 | return LWS_INVALID_FILE; |
| 466 | } |
Andy Green | 158e804 | 2014-04-02 14:25:10 +0800 | [diff] [blame] | 467 | *filelen = stat_buf.st_size; |
| 468 | return ret; |
Andy Green | 1cd3ba6 | 2014-04-02 23:03:23 +0800 | [diff] [blame] | 469 | } |
Andy Green | a654fc0 | 2014-04-03 07:16:40 +0800 | [diff] [blame] | 470 | |
Andy Green | 1cd3ba6 | 2014-04-02 23:03:23 +0800 | [diff] [blame] | 471 | LWS_VISIBLE const char * |
| 472 | lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt) |
Aurelian Pop | d07ea3b | 2014-07-29 15:36:06 +0300 | [diff] [blame] | 473 | { |
Andy Green | 1cd3ba6 | 2014-04-02 23:03:23 +0800 | [diff] [blame] | 474 | return inet_ntop(af, src, dst, cnt); |
| 475 | } |