@@ -131,7 +131,7 @@ static uint64_t validate_outbound_message(const qdr_delivery_t *out_dlv);
131
131
static void on_accept (qd_adaptor_listener_t * listener , pn_listener_t * pn_listener , void * context );
132
132
static void on_tls_connection_secured (qd_tls_t * tls , void * user_context );
133
133
static char * get_tls_negotiated_alpn (qd_message_t * msg ); // caller must free() returned string!
134
-
134
+ static int setup_tls_session ( tcplite_connection_t * conn , const qd_tls_domain_t * parent_domain , const char * alpn_protocol );
135
135
136
136
//=================================================================================
137
137
// Thread assertions
@@ -484,34 +484,58 @@ static void free_connection_IO(void *context)
484
484
free_tcp_resource (& conn -> common );
485
485
}
486
486
487
-
488
- static void close_raw_connection_XSIDE_IO (tcplite_connection_t * conn )
487
+ // Initate close of the raw connection.
488
+ //
489
+ // The close will be complete when the PN_RAW_CONNECTION_DISCONNECTED event is handled. At that point any associated
490
+ // connection condition information will be read from the raw conn and written to the flow log.
491
+ //
492
+ // @param conn Holds the raw connection to close
493
+ // @param condition Optional condition identifying the reason the connection was closed
494
+ // @param description Optional description assocated with condition
495
+ //
496
+ static void close_raw_connection (tcplite_connection_t * conn , const char * condition , const char * description )
489
497
{
490
498
ASSERT_RAW_IO ;
491
- if (conn -> state != XSIDE_CLOSING ) {
492
- set_state_XSIDE_IO (conn , XSIDE_CLOSING );
493
- if (!!conn -> raw_conn ) {
494
- CLEAR_ATOMIC_FLAG (& conn -> raw_opened );
495
- pn_raw_connection_close (conn -> raw_conn );
496
- drain_read_buffers_XSIDE_IO (conn -> raw_conn );
497
- drain_write_buffers_XSIDE_IO (conn -> raw_conn );
498
-
499
- // note: this disables the raw connection event handler. No further PN_RAW_CONNECTION_* events will occur,
500
- // including DISCONNECTED!
501
- sys_mutex_lock (& conn -> activation_lock );
502
- pn_raw_connection_set_context (conn -> raw_conn , 0 );
503
- conn -> raw_conn = 0 ;
504
- sys_mutex_unlock (& conn -> activation_lock );
499
+
500
+ assert (conn -> raw_conn );
501
+ if (condition ) {
502
+ pn_condition_t * cond = pn_raw_connection_condition (conn -> raw_conn );
503
+ if (!!cond ) {
504
+ (void ) pn_condition_set_name (cond , condition );
505
+ if (description ) {
506
+ (void ) pn_condition_set_description (cond , description );
507
+ }
505
508
}
506
509
}
510
+
511
+ CLEAR_ATOMIC_FLAG (& conn -> raw_opened );
512
+ pn_raw_connection_close (conn -> raw_conn );
513
+
514
+ // Connection cleanup occurs on the PN_RAW_CONNECTION_DISCONNECTED event
507
515
}
508
516
509
517
// Note: if no_delay is true, conn will be freed by this function
510
518
//
511
519
static void close_connection_XSIDE_IO (tcplite_connection_t * conn , bool no_delay )
512
520
{
513
521
ASSERT_RAW_IO ;
514
- close_raw_connection_XSIDE_IO (conn );
522
+
523
+ if (conn -> state != XSIDE_CLOSING )
524
+ set_state_XSIDE_IO (conn , XSIDE_CLOSING );
525
+
526
+ if (!!conn -> raw_conn ) {
527
+ CLEAR_ATOMIC_FLAG (& conn -> raw_opened );
528
+ pn_raw_connection_close (conn -> raw_conn );
529
+ drain_read_buffers_XSIDE_IO (conn -> raw_conn );
530
+ drain_write_buffers_XSIDE_IO (conn -> raw_conn );
531
+
532
+ // note: this disables the raw connection event handler. No further PN_RAW_CONNECTION_* events will occur,
533
+ // including DISCONNECTED!
534
+ sys_mutex_lock (& conn -> activation_lock );
535
+ pn_raw_connection_set_context (conn -> raw_conn , 0 );
536
+ conn -> raw_conn = 0 ;
537
+ sys_mutex_unlock (& conn -> activation_lock );
538
+ }
515
539
516
540
free (conn -> reply_to );
517
541
@@ -1119,55 +1143,16 @@ static uint64_t handle_first_outbound_delivery_CSIDE(tcplite_connector_t *cr, qd
1119
1143
return dispo ;
1120
1144
}
1121
1145
1146
+ qd_log (LOG_TCP_ADAPTOR , QD_LOG_DEBUG , DLV_FMT " CSIDE new outbound delivery" , DLV_ARGS (delivery ));
1147
+
1122
1148
qd_message_t * msg = qdr_delivery_message (delivery );
1123
1149
tcplite_connection_t * conn = new_tcplite_connection_t ();
1124
1150
ZERO (conn );
1125
1151
1126
- conn -> conn_id = qd_server_allocate_connection_id (tcplite_context -> server );
1127
-
1128
- // Catch TLS configuration issues early so we can avoid initializing the entire
1129
- // connection.
1130
- //
1131
- if (cr -> tls_domain ) {
1132
- bool failed = true;
1133
- // note qd_tls_domain_clone() will log error if it fails
1134
- conn -> tls_domain = qd_tls_domain_clone (cr -> tls_domain );
1135
- if (conn -> tls_domain ) {
1136
- int rc = 0 ;
1137
- assert (!conn -> alpn_protocol );
1138
- conn -> alpn_protocol = get_tls_negotiated_alpn (msg );
1139
- if (conn -> alpn_protocol ) {
1140
- const char * alpn_protocols [] = {conn -> alpn_protocol };
1141
- rc = qd_tls_set_alpn_protocols (conn -> tls_domain , alpn_protocols , 1 );
1142
- if (rc != 0 ) {
1143
- qd_log (LOG_TCP_ADAPTOR , QD_LOG_ERROR ,
1144
- "[%" PRIu64 "] tcpConnector %s: failed to configure ALPN protocol '%s' (%d)" ,
1145
- conn -> conn_id , cr -> adaptor_config -> name , conn -> alpn_protocol , rc );
1146
- }
1147
- }
1148
- if (rc == 0 ) {
1149
- // note: qd_tls() will log error if it fails
1150
- conn -> tls = qd_tls (conn -> tls_domain , conn , conn -> conn_id , on_tls_connection_secured );
1151
- if (conn -> tls ) {
1152
- failed = false;
1153
- }
1154
- }
1155
- }
1156
- if (failed ) {
1157
- qd_tls_domain_decref (conn -> tls_domain );
1158
- qd_tls_free2 (conn -> tls );
1159
- free (conn -> alpn_protocol );
1160
- free_tcplite_connection_t (conn );
1161
- qd_message_set_send_complete (msg );
1162
- return PN_RELEASED ; // redeliver somewhere else!
1163
- }
1164
- }
1165
-
1166
- qd_log (LOG_TCP_ADAPTOR , QD_LOG_DEBUG , DLV_FMT " CSIDE new outbound delivery" , DLV_ARGS (delivery ));
1167
-
1168
1152
qdr_delivery_incref (delivery , "CORE_deliver_outbound CSIDE" );
1169
1153
qdr_delivery_set_context (delivery , conn );
1170
1154
1155
+ conn -> conn_id = qd_server_allocate_connection_id (tcplite_context -> server );
1171
1156
conn -> common .context_type = TL_CONNECTION ;
1172
1157
conn -> common .parent = (tcplite_common_t * ) cr ;
1173
1158
@@ -1587,10 +1572,17 @@ static void connection_run_LSIDE_IO(tcplite_connection_t *conn)
1587
1572
switch (conn -> state ) {
1588
1573
case LSIDE_INITIAL :
1589
1574
if (IS_ATOMIC_FLAG_SET (& conn -> raw_opened )) { // raw connection is active
1590
- if (conn -> tls ) {
1591
- qd_log (LOG_TCP_ADAPTOR , QD_LOG_DEBUG , "[C%" PRIu64 "] LSIDE_IO performing TLS handshake" , conn -> conn_id );
1592
- set_state_XSIDE_IO (conn , LSIDE_TLS_HANDSHAKE );
1593
- repeat = true;
1575
+ tcplite_listener_t * li = (tcplite_listener_t * ) conn -> common .parent ;
1576
+ if (li -> tls_domain ) {
1577
+ if (setup_tls_session (conn , li -> tls_domain , 0 ) != 0 ) {
1578
+ // TLS setup failed: check logs for details
1579
+ close_raw_connection (conn , "TLS-connection-failed" , "Error loading credentials" );
1580
+ set_state_XSIDE_IO (conn , XSIDE_CLOSING ); // prevent further connection I/O
1581
+ } else {
1582
+ qd_log (LOG_TCP_ADAPTOR , QD_LOG_DEBUG , "[C%" PRIu64 "] LSIDE_IO performing TLS handshake" , conn -> conn_id );
1583
+ set_state_XSIDE_IO (conn , LSIDE_TLS_HANDSHAKE );
1584
+ repeat = true;
1585
+ }
1594
1586
} else {
1595
1587
link_setup_LSIDE_IO (conn );
1596
1588
set_state_XSIDE_IO (conn , LSIDE_LINK_SETUP );
@@ -1614,6 +1606,7 @@ static void connection_run_LSIDE_IO(tcplite_connection_t *conn)
1614
1606
// TLS failed! Error logged, raw connection close initiated and error condition set. Clean up in
1615
1607
// DISCONNECTED raw connection event.
1616
1608
//
1609
+ set_state_XSIDE_IO (conn , XSIDE_CLOSING ); // prevent further connection I/O
1617
1610
} else if (qd_tls_is_secure (conn -> tls )) {
1618
1611
//
1619
1612
// Handshake completed, begin the setup of the inbound and outbound links for this connection.
@@ -1687,6 +1680,19 @@ static void connection_run_CSIDE_IO(tcplite_connection_t *conn)
1687
1680
switch (conn -> state ) {
1688
1681
case CSIDE_INITIAL :
1689
1682
if (IS_ATOMIC_FLAG_SET (& conn -> raw_opened )) { // raw connection is active
1683
+ tcplite_connector_t * cr = (tcplite_connector_t * ) conn -> common .parent ;
1684
+ if (cr -> tls_domain ) {
1685
+ assert (conn -> outbound_stream );
1686
+ char * alpn = get_tls_negotiated_alpn (conn -> outbound_stream );
1687
+ int rc = setup_tls_session (conn , cr -> tls_domain , alpn );
1688
+ free (alpn );
1689
+ if (rc != 0 ) {
1690
+ // TLS setup failed: check logs for details
1691
+ close_raw_connection (conn , "TLS-connection-failed" , "Error loading credentials" );
1692
+ set_state_XSIDE_IO (conn , XSIDE_CLOSING ); // prevent further connection I/O
1693
+ break ;
1694
+ }
1695
+ }
1690
1696
link_setup_CSIDE_IO (conn , conn -> outbound_delivery );
1691
1697
set_state_XSIDE_IO (conn , CSIDE_LINK_SETUP );
1692
1698
}
@@ -1793,8 +1799,12 @@ static void on_tls_connection_secured(qd_tls_t *tls, void *user_context)
1793
1799
if (conn -> core_conn && conn -> core_conn -> connection_info ) {
1794
1800
qd_tls_update_connection_info (conn -> tls , conn -> core_conn -> connection_info );
1795
1801
}
1796
- if (!conn -> alpn_protocol )
1802
+
1803
+ // check if we need to propagate client ALPN to server
1804
+ if (conn -> listener_side ) {
1805
+ assert (!conn -> alpn_protocol );
1797
1806
qd_tls_get_alpn_protocol (conn -> tls , & conn -> alpn_protocol );
1807
+ }
1798
1808
}
1799
1809
1800
1810
// Check for the ALPN value negotiated on the CSIDE TLS connection (optional).
@@ -1830,6 +1840,37 @@ static char *get_tls_negotiated_alpn(qd_message_t *msg)
1830
1840
return alpn_protocol ;
1831
1841
}
1832
1842
1843
+ /**
1844
+ * Create a new TLS session for the given connection.
1845
+ *
1846
+ * @param parent_domain Reference to parent connector/listener TLS domain context
1847
+ * @param alpn_protocol If CSIDE the optional alpn protocol value to pass to the remote server
1848
+ *
1849
+ * @return 0 on success, non-zero on error
1850
+ */
1851
+ static int setup_tls_session (tcplite_connection_t * conn , const qd_tls_domain_t * parent_domain , const char * alpn_protocol )
1852
+ {
1853
+ conn -> tls_domain = qd_tls_domain_clone (parent_domain );
1854
+ if (!conn -> tls_domain )
1855
+ return -1 ; // error logged in qd_tls_domain_clone()
1856
+
1857
+ if (alpn_protocol ) {
1858
+ const char * alpn_protocols [] = {alpn_protocol };
1859
+ int rc = qd_tls_set_alpn_protocols (conn -> tls_domain , alpn_protocols , 1 );
1860
+ if (rc != 0 ) {
1861
+ qd_log (LOG_TCP_ADAPTOR , QD_LOG_ERROR ,
1862
+ "[%" PRIu64 "] failed to configure ALPN protocol '%s' (%d)" , conn -> conn_id , alpn_protocol , rc );
1863
+ return -1 ;
1864
+ }
1865
+ }
1866
+
1867
+ conn -> tls = qd_tls (conn -> tls_domain , conn , conn -> conn_id , on_tls_connection_secured );
1868
+ if (!conn -> tls )
1869
+ return -1 ; // error logged in qd_tls()
1870
+
1871
+ return 0 ;
1872
+ }
1873
+
1833
1874
1834
1875
//=================================================================================
1835
1876
// Handlers for events from the Raw Connections
@@ -1915,29 +1956,6 @@ static void on_accept(qd_adaptor_listener_t *listener, pn_listener_t *pn_listene
1915
1956
1916
1957
ZERO (conn );
1917
1958
conn -> conn_id = qd_server_allocate_connection_id (tcplite_context -> server );
1918
-
1919
- // Catch TLS configuration issues early so we can avoid initializing the entire
1920
- // connection.
1921
- //
1922
- if (li -> tls_domain ) {
1923
- bool failed = true;
1924
- conn -> tls_domain = qd_tls_domain_clone (li -> tls_domain );
1925
- if (conn -> tls_domain ) {
1926
- conn -> tls = qd_tls (conn -> tls_domain , conn , conn -> conn_id , on_tls_connection_secured );
1927
- if (conn -> tls ) {
1928
- failed = false;
1929
- } else {
1930
- qd_tls_domain_decref (conn -> tls_domain );
1931
- }
1932
- }
1933
- if (failed ) {
1934
- // qd_tls(_domain_clone) will log the appropriate error message
1935
- free_tcplite_connection_t (conn );
1936
- qd_adaptor_listener_deny_conn (listener , pn_listener );
1937
- return ;
1938
- }
1939
- }
1940
-
1941
1959
conn -> common .context_type = TL_CONNECTION ;
1942
1960
conn -> common .parent = (tcplite_common_t * ) li ;
1943
1961
@@ -2129,14 +2147,7 @@ static void CORE_delivery_update(void *context, qdr_delivery_t *dlv, uint64_t di
2129
2147
if (final_outcome && disp != PN_ACCEPTED ) {
2130
2148
// The delivery failed - this is unrecoverable.
2131
2149
if (!!conn -> raw_conn ) {
2132
- // set the raw connection condition info so it will appear in the vanflow logs
2133
- // when the connection disconnects
2134
- pn_condition_t * cond = pn_raw_connection_condition (conn -> raw_conn );
2135
- if (!!cond ) {
2136
- (void ) pn_condition_set_name (cond , "delivery-failed" );
2137
- (void ) pn_condition_set_description (cond , "destination unreachable" );
2138
- }
2139
- pn_raw_connection_close (conn -> raw_conn );
2150
+ close_raw_connection (conn , "delivery-failed" , "destination unreachable" );
2140
2151
// clean stuff up when DISCONNECT event arrives
2141
2152
}
2142
2153
} else {
0 commit comments