lwp_sslclient lwp_sslclient_new (SSL_CTX * server_context, lw_stream socket, lwp_sslclient_on_handshook on_handshook, void * tag) { lwp_sslclient ctx = calloc (sizeof (*ctx), 1); if (!ctx) return 0; ctx->write_condition = -1; #ifdef _lacewing_npn *ctx->npn = 0; #endif ctx->server_context = server_context; ctx->ssl = SSL_new (server_context); ctx->on_handshook = on_handshook; ctx->tag = tag; /* TODO : I'm not really happy with the extra layer of buffering * that BIO pairs introduce. Is there a better way to do this? */ BIO_new_bio_pair (&ctx->bio_internal, 0, &ctx->bio_external, 0); SSL_set_bio (ctx->ssl, ctx->bio_internal, ctx->bio_internal); SSL_set_accept_state (ctx->ssl); lwp_stream_init (&ctx->upstream, &def_upstream, 0); lwp_stream_init (&ctx->downstream, &def_downstream, 0); /* Retain our streams indefinitely, since we'll be in charge of releasing * their memory. This doesn't stop stream_delete from working. */ lwp_retain (&ctx->upstream); lwp_retain (&ctx->downstream); lw_stream_add_filter_upstream (socket, &ctx->upstream, lw_false, lw_false); lw_stream_add_filter_downstream (socket, &ctx->downstream, lw_false, lw_false); pump (ctx); assert (! (ctx->flags & lwp_sslclient_flag_dead)); return ctx; }
static lw_bool def_close (lw_stream stream_ctx, lw_bool immediate) { lw_fdstream ctx = (lw_fdstream) stream_ctx; lwp_trace ("FDStream::Close for FD %d", ctx->fd); lwp_retain (ctx, "fdstream close"); /* Remove the watch to make sure we don't get any more * callbacks from the pump. */ if (ctx->watch) { lw_pump_remove (lw_stream_pump ((lw_stream) ctx), ctx->watch); ctx->watch = 0; } int fd = ctx->fd; ctx->fd = -1; if (fd != -1) { if (ctx->flags & lwp_fdstream_flag_autoclose) { shutdown (fd, SHUT_RDWR); close (fd); } } lwp_release (ctx, "fdstream close"); return lw_true; }
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); }