enum protolayer_event_type event, void **baton,
struct session2 *session, void *sess_data)
{
- if (event == PROTOLAYER_EVENT_STATS_SEND_ERR) {
+ switch (event) {
+ case PROTOLAYER_EVENT_STATS_SEND_ERR:
the_worker->stats.err_tcp += 1;
return PROTOLAYER_EVENT_CONSUME;
- } else if (event == PROTOLAYER_EVENT_STATS_QRY_OUT) {
+ case PROTOLAYER_EVENT_STATS_QRY_OUT:
the_worker->stats.tcp += 1;
return PROTOLAYER_EVENT_CONSUME;
+ case PROTOLAYER_EVENT_OS_BUFFER_FULL:
+ session2_force_close(session);
+ return PROTOLAYER_EVENT_CONSUME;
+ default:
+ return PROTOLAYER_EVENT_PROPAGATE;
}
- return PROTOLAYER_EVENT_PROPAGATE;
}
__attribute__((constructor))
session2_transport_event(s, event, baton);
}
-void session2_event_unwrap(struct session2 *s, ssize_t start_ix, enum protolayer_event_type event, void *baton)
+static void session2_event_unwrap(struct session2 *s, ssize_t start_ix, enum protolayer_event_type event, void *baton)
{
bool cont;
const struct protolayer_grp *grp = &protolayer_grps[s->proto];
*
* TODO: This might be undesirable for cases with sub-sessions - the
* current idea is for the layers managing sub-sessions to just return
- * `false` on `event_unwrap`, but a more "automatic" mechanism may be
- * added when this is relevant, to make it less error-prone. */
+ * `PROTOLAYER_EVENT_CONSUME` on `event_unwrap`, but a more "automatic"
+ * mechanism may be added when this is relevant, to make it less
+ * error-prone. */
session2_event_wrap(s, event, baton);
}
} else {
int ret = uv_udp_try_send((uv_udp_t*)handle,
(uv_buf_t *)iov, iovcnt, comm->comm_addr);
- if (ret == UV_EAGAIN)
+ if (ret == UV_EAGAIN) {
ret = kr_error(ENOBUFS);
+ session2_event(s, PROTOLAYER_EVENT_OS_BUFFER_FULL, NULL);
+ }
if (false && ret == UV_EAGAIN) { // XXX: see uv_try_write() below
uv_udp_send_t *req = malloc(sizeof(*req));
// We were missing any handling of partial write success, too.
if (ret == UV_EAGAIN || (ret >= 0 && ret != iovec_sum(iov, iovcnt))) {
ret = kr_error(ENOBUFS);
- session2_force_close(s);
+ session2_event(s, PROTOLAYER_EVENT_OS_BUFFER_FULL, NULL);
}
if (false && ret == UV_EAGAIN) {
* Event types are used to distinguish different events that can be passed to
* sessions using `session2_event()`. */
#define PROTOLAYER_EVENT_MAP(XX) \
- XX(CLOSE) /**< Sending this event closes the session gracefully -
- * i.e. layers add their standard disconnection
- * ceremony (e.g. `gnutls_bye()`). */\
- XX(FORCE_CLOSE) /**< Sending this event closes the session forcefully -
- * i.e. layers SHOULD NOT add any disconnection
- * ceremony, if avoidable. */\
- XX(CONNECT_TIMEOUT) /**< Signal that a connection could not be
- * established due to a timeout. */\
- XX(GENERAL_TIMEOUT) /**< Signal that a general application-defined
- * timeout has occurred. */\
- XX(CONNECT) /**< Signal that a connection has been established. */\
- XX(CONNECT_FAIL) /**< Signal that a connection could not have been
- * established. */\
- XX(MALFORMED) /**< Signal that a malformed request has been received. */\
- XX(DISCONNECT) /**< Signal that a connection has ended. */\
- XX(STATS_SEND_ERR) /**< Failed task send - update stats. */\
- XX(STATS_QRY_OUT) /**< Outgoing query submission - update stats. */
+ /** Closes the session gracefully - i.e. layers add their standard
+ * disconnection ceremony (e.g. `gnutls_bye()`). */\
+ XX(CLOSE) \
+ /** Closes the session forcefully - i.e. layers SHOULD NOT add any
+ * disconnection ceremony, if avoidable. */\
+ XX(FORCE_CLOSE) \
+ /** Signal that a connection could not be established due to a timeout. */\
+ XX(CONNECT_TIMEOUT) \
+ /** Signal that a general application-defined timeout has occurred. */\
+ XX(GENERAL_TIMEOUT) \
+ /** Signal that a connection has been established. */\
+ XX(CONNECT) \
+ /** Signal that a connection could not have been established. */\
+ XX(CONNECT_FAIL) \
+ /** Signal that a malformed request has been received. */\
+ XX(MALFORMED) \
+ /** Signal that a connection has ended. */\
+ XX(DISCONNECT) \
+ /** Failed task send - update stats. */\
+ XX(STATS_SEND_ERR) \
+ /** Outgoing query submission - update stats. */\
+ XX(STATS_QRY_OUT) \
+ /** OS buffers are full, so not sending any more data. */\
+ XX(OS_BUFFER_FULL) \
+ //
/** Event type, to be interpreted by a layer. */
enum protolayer_event_type {