static void handle_outgoing()

in c/experimental/raw_plus_tls2.c [271:352]


static void handle_outgoing(jabber_connection_t* jc) {
  // For this simplified example, 1 buffer of application output is dealt
  // with at a time.

  jabber_t *j = jc->parent;
  if (buf_in_use(&jc->out_wire_buf)) {
    // See if raw connection done with the buffer
    if (1 == pn_raw_connection_take_written_buffers(jc->rawc, &jc->out_wire_buf, 1)) {
      buf_reset(&jc->out_wire_buf);
    } else {
      return;  // Nothing to do until notified of future raw connection write completion
    }
  }

  if (!jc->jabber_turn && !jc->tls_has_output && !jc->need_rawc_write_close)
    return;  // nothing to send at this time

  if (!jc->tls) {
    line_of_jabber(jc, &jc->out_wire_buf);
    if (jc->out_wire_buf.size > 0) {
      jc->jabber_turn = false;    // Peer gets to do next jabber.
      jcheck( pn_raw_connection_write_buffers(jc->rawc, &jc->out_wire_buf, 1) == 1 );
      buf_set_in_use(&jc->out_wire_buf, true);
    }
    // If no more application data to write, start orderly close.
    if (j->current_jline == jlines_count) {
      pn_raw_connection_write_close(jc->rawc);
      jc->orderly_close_initiated = true;
    }
  } else {
    // TLS

    // Reacquire encryption buffer if TLS library is done with it.
    if (buf_in_use(&jc->out_app_buf) && pn_tls_take_encrypt_input_buffers(jc->tls, &jc->out_app_buf, 1) == 1)
      buf_reset(&jc->out_app_buf);

    if (pn_tls_is_secure(jc->tls) && jc->jabber_turn && !jc->tls_closing) {
      jcheck( jc->alpn_protocol || !jc->parent->alpn_enabled );
      // Add jabber data if there is room.
      if (buf_unused(&jc->out_app_buf)) {
        line_of_jabber(jc, &jc->out_app_buf);
        if (jc->out_app_buf.size > 0) {
          jc->jabber_turn = false;  // Peer gets to do next jabber.
          buf_set_in_use(&jc->out_app_buf, true);
          size_t consumed = pn_tls_give_encrypt_input_buffers(jc->tls, &jc->out_app_buf, 1);
          if (consumed != 1) abort();

          // If no more application data to write, start orderly close.
          // For TLS, indicate we are done writing to generate the protocol's EOS (closure alert).
          if (j->current_jline == jlines_count) {
            jc->orderly_close_initiated = true;
            jabber_tls_begin_close(jc);
          }

          jabber_tls_process(jc);
        }
      }
    }

    // Even if no application output just queued for processing (i.e. no call to
    // pn_tls_give_encrypt_input_buffers()), there may be straggling encrypted output.
    // Also possible we are flushing TLS error information to peer.
    if (buf_unused(&jc->out_wire_buf) && pn_tls_need_encrypt_output_buffers(jc->tls)) {
      pn_tls_give_encrypt_output_buffers(jc->tls, &jc->out_wire_buf, 1);
      jabber_tls_process(jc);
      jcheck( pn_tls_take_encrypt_output_buffers(jc->tls, &jc->out_wire_buf, 1) == 1 );

      // Write the application data we just encrypted.
      jcheck( pn_raw_connection_write_buffers(jc->rawc, &jc->out_wire_buf, 1) == 1);
      buf_set_in_use(&jc->out_wire_buf, true);
    }

    // Remember whether we missed some output buffered in the TLS library and need to come back.
    jc->tls_has_output = pn_tls_is_encrypt_output_pending(jc->tls) > 0;

    if (jc->need_rawc_write_close && !jc->tls_has_output) {
      // We have written to the raw connection all the output the TLS library can ever give us.
      pn_raw_connection_write_close(jc->rawc);
      jc->need_rawc_write_close = false;
    }
  }
}