/* Internal callback. called by stream->timeout_watcher */ static void on_timeout (EV_P_ ev_timer *watcher, int revents) { evcom_stream *stream = watcher->data; #if EV_MULTIPLICITY assert(stream->loop == loop); #endif assert(revents == EV_TIMEOUT); assert(watcher == &stream->timeout_watcher); if (PAUSED(stream)) { ev_timer_again(D_LOOP_(stream) &stream->timeout_watcher); return; } if (stream->on_timeout) stream->on_timeout(stream); // Hack to get error in Node on 'close' event. // should probably be made into a proper error code. stream->errorno = 1; ev_timer_stop(EV_A_ watcher); evcom_stream_force_close(stream); if (stream->on_close) stream->on_close(stream); }
/* Internal callback. called by stream->timeout_watcher */ static void on_timeout (EV_P_ ev_timer *watcher, int revents) { evcom_stream *stream = watcher->data; #if EV_MULTIPLICITY assert(stream->loop == loop); #endif assert(revents == EV_TIMEOUT); assert(watcher == &stream->timeout_watcher); if (PAUSED(stream)) { ev_timer_again(D_LOOP_(stream) &stream->timeout_watcher); return; } if (stream->on_timeout) stream->on_timeout(stream); evcom_stream_force_close(stream); if (stream->on_close) stream->on_close(stream); }
static int stream_recv__data (evcom_stream *stream) { char buf[EVCOM_CHUNKSIZE]; size_t buf_size = EVCOM_CHUNKSIZE; ssize_t recved; while (READABLE(stream)) { assert(CONNECTED(stream)); if (PAUSED(stream)) { stream->recv_action = stream_recv__wait_for_resume; return OKAY; } #if EVCOM_HAVE_GNUTLS if (SECURE(stream)) { recved = gnutls_record_recv(stream->session, buf, buf_size); if (gnutls_error_is_fatal(recved)) { stream->gnutls_errorno = recved; stream->recv_action = stream_recv__close; return OKAY; } if (recved == GNUTLS_E_INTERRUPTED || recved == GNUTLS_E_AGAIN) { if (1 == gnutls_record_get_direction((stream)->session)) { fprintf(stderr, "(evcom) gnutls recv: unexpected switch direction!\n"); ev_io_stop(D_LOOP_(stream) &(stream)->read_watcher); ev_io_start(D_LOOP_(stream) &(stream)->write_watcher); } return AGAIN; } /* A server may also receive GNUTLS_E_REHANDSHAKE when a client has * initiated a andshake. In that case the server can only initiate a * handshake or terminate the connection. */ if (recved == GNUTLS_E_REHANDSHAKE) { assert(WRITABLE(stream)); stream->recv_action = stream__handshake; stream->send_action = stream__handshake; return OKAY; } } else #endif /* EVCOM_HAVE_GNUTLS */ { recved = read(stream->recvfd, buf, buf_size); } if (recved < 0) { if (errno == EAGAIN || errno == EINTR) { assert(stream->recv_action == stream_recv__data); return AGAIN; } if (errno != ECONNRESET) { evcom_perror("recv()", stream->errorno); } stream->errorno = errno; stream->recv_action = stream_recv__close; return OKAY; } ev_timer_again(D_LOOP_(stream) &stream->timeout_watcher); assert(recved >= 0); if (recved == 0) { stream->flags &= ~EVCOM_READABLE; ev_io_stop(D_LOOP_(stream) &stream->read_watcher); stream->recv_action = stream_recv__wait_for_close; } /* NOTE: EOF is signaled with recved == 0 on callback */ if (stream->on_read) stream->on_read(stream, buf, recved); if (recved == 0) { return OKAY; } } return AGAIN; }