static void handle_incoming()

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;
  }
}