static void on_socket_connect (lw_server server, lw_server_client client) { lnserver ctx = lw_server_tag (server); lnserver_client client_ctx = lnserver_client_new (ctx, client); if (!client_ctx) { /* failed to allocate client context */ lw_stream_close (client, lw_true); return; } lw_stream_set_tag (client, client_ctx); }
static void read_ready (void * tag) { lw_fdstream ctx = tag; if (ctx->flags & lwp_fdstream_flag_reading) return; ctx->flags |= lwp_fdstream_flag_reading; lwp_retain (ctx, "fdstream read_ready"); /* TODO : Use a buffer on the heap instead? */ char buffer [lwp_default_buffer_size]; lw_bool close_stream = lw_false; while (ctx->reading_size == -1 || ctx->reading_size > 0) { if (ctx->fd == -1) break; size_t to_read = sizeof (buffer); if (ctx->reading_size != -1 && to_read > ctx->reading_size) to_read = ctx->reading_size; int bytes = read (ctx->fd, buffer, to_read); if (bytes == 0) { close_stream = lw_true; break; } if (bytes == -1) { if (errno == EAGAIN) break; close_stream = lw_true; break; } if (ctx->reading_size != -1) { if (bytes > ctx->reading_size) ctx->reading_size = 0; else ctx->reading_size -= bytes; } lw_stream_data ((lw_stream) ctx, buffer, bytes); /* Calling Data or Close may result in destruction of the Stream - * see FDStream destructor. */ if (! (ctx->flags & lwp_fdstream_flag_reading)) break; } ctx->flags &= ~ lwp_fdstream_flag_reading; if (lwp_release (ctx, "fdstream read_ready") || ctx->stream.flags & lwp_stream_flag_dead) return; if (close_stream) lw_stream_close ((lw_stream) ctx, lw_true); }
void lw_fdstream_set_fd (lw_fdstream ctx, lw_fd fd, lw_pump_watch watch, lw_bool auto_close) { if (ctx->watch) { lw_pump_remove (lw_stream_pump ((lw_stream) ctx), ctx->watch); ctx->watch = 0; } if ( (ctx->flags & lwp_fdstream_flag_autoclose) && ctx->fd != -1) lw_stream_close ((lw_stream) ctx, lw_true); ctx->fd = fd; if (auto_close) ctx->flags |= lwp_fdstream_flag_autoclose; else ctx->flags &= ~ lwp_fdstream_flag_autoclose; if (ctx->fd == -1) return; fcntl (fd, F_SETFL, fcntl (fd, F_GETFL, 0) | O_NONBLOCK); #if HAVE_DECL_SO_NOSIGPIPE { int b = 1; setsockopt (fd, SOL_SOCKET, SO_NOSIGPIPE, (char *) &b, sizeof (b)); } #endif { int b = (ctx->flags & lwp_fdstream_flag_nagle) ? 0 : 1; setsockopt (fd, SOL_SOCKET, TCP_NODELAY, (char *) &b, sizeof (b)); } struct stat stat; fstat (fd, &stat); if (S_ISSOCK (stat.st_mode)) { ctx->flags |= lwp_fdstream_flag_is_socket; } else { ctx->flags &= ~ lwp_fdstream_flag_is_socket; if ((ctx->size = stat.st_size) > 0) return; /* Not a socket, and size is 0. Is it really just an empty file? */ if (S_ISREG (stat.st_mode)) return; } /* Assuming this is something we can watch for readiness. */ ctx->size = -1; lw_pump pump = lw_stream_pump ((lw_stream) ctx); if (watch) { /* Given an existing pump watch - change it to use our callbacks */ ctx->watch = watch; lw_pump_update_callbacks (pump, ctx->watch, ctx, read_ready, write_ready, lw_true); } else { ctx->watch = lw_pump_add (pump, fd, ctx, read_ready, write_ready, lw_true); } }