in c/experimental/raw_plus_tls2.c [355:433]
static void handle_incoming(jabber_connection_t* jc, bool rawc_input_closed_event) {
// There may be more received wire buffers than sent.
if (jc->input_done)
return;
bool wire_bytes = false;
const char *self = jc->is_server ? "server" : "client";
if (!rawc_input_closed_event) {
if (!buf_in_use(&jc->in_wire_buf) ||
pn_raw_connection_take_read_buffers(jc->rawc, &jc->in_wire_buf, 1) != 1)
return; // No wire buffer to process - come back later.
if (jc->in_wire_buf.size > 0)
wire_bytes = true;
}
if (!jc->tls) {
if (wire_bytes) {
// Use wire data directly
gobble_jabber(jc, &jc->in_wire_buf);
buf_reset(&jc->in_wire_buf);
} else {
if (!jc->orderly_close_initiated && jc->parent->current_jline == jlines_count)
jc->orderly_close_detected = true;
// Whether unexpected hangup or expected EOS, Jabber has no more data to send.
pn_raw_connection_close(jc->rawc);
jc->input_done = true;
}
} else {
// TLS case
if (wire_bytes) {
jcheck( pn_tls_get_decrypt_input_buffer_capacity(jc->tls) > 0 );
size_t consumed = pn_tls_give_decrypt_input_buffers(jc->tls, &jc->in_wire_buf, 1);
if (consumed == 0) {
if (pn_tls_is_input_closed(jc->tls))
// Library will not process anything after TLS EOS, and we are not expecting any trailing data.
printf("data after TLS EOF\n"); // Error by peer or garbage bytes from attacker.
else
printf("Unexpected TLS decrypt input buffer failure\n");
abort();
}
if (!jabber_tls_process(jc))
return;
if (jc->parent->alpn_enabled && !jc->alpn_protocol)
check_alpn(jc);
while (pn_tls_need_decrypt_output_buffers(jc->tls)) {
jcheck( pn_tls_give_decrypt_output_buffers(jc->tls, &jc->in_app_buf, 1) == 1 );
if (!jabber_tls_process(jc))
return;
jcheck( pn_tls_take_decrypt_output_buffers(jc->tls, &jc->in_app_buf, 1) == 1 );
jcheck( jc->in_app_buf.size > 0 );
gobble_jabber(jc, &jc->in_app_buf); // Application layer consumes all bytes.
buf_reset(&jc->in_app_buf);
}
// Reclaim and recycle the TLS encoded input buffer (from the wire) processed by the TLS library.
// If a partial TLS record remains, it is buffered in the TLS engine.
jcheck( pn_tls_take_decrypt_input_buffers(jc->tls, &jc->in_wire_buf, 1) == 1);
buf_reset(&jc->in_wire_buf);
if (pn_tls_is_input_closed(jc->tls) && !jc->orderly_close_initiated) {
printf("**%s: received TLS end of session notification from peer\n", self);
jc->orderly_close_detected = true;
jabber_tls_begin_close(jc);
}
} else {
// EOS
jc->input_done = true;
if (!pn_tls_is_input_closed(jc->tls) && !jc->orderly_close_initiated)
// Expecting graceful close with peer in this example.
printf("**%s: TLS session ended abruptly\n", self);
jabber_tls_begin_close(jc);
}
// TLS input can generate non-application output. Note that here.
jc->tls_has_output = pn_tls_is_encrypt_output_pending(jc->tls) > 0;
}
}