@@ -641,7 +641,7 @@ int picoqmux_prepare_packet(picoquic_cnx_t* cnx, uint64_t current_time, uint8_t*
641641}
642642
643643/* Prepare the next packets to send in the current buffer */
644- int picoqmux_prepare_packets (picoquic_cnx_t * cnx , uint64_t current_time , uint8_t * send_buffer , size_t send_buffer_max , size_t * send_length , uint64_t * next_wake_time )
644+ int picoqmux_prepare_cnx_packets (picoquic_cnx_t * cnx , uint64_t current_time , uint8_t * send_buffer , size_t send_buffer_max , size_t * send_length , uint64_t * next_wake_time )
645645{
646646 int ret = 0 ;
647647 * send_length = 0 ;
@@ -837,7 +837,7 @@ int picoqmux_decode_frames(picoquic_cnx_t* cnx, picoquic_path_t* path_x, const u
837837 return bytes != NULL ? 0 : PICOQUIC_ERROR_DETECTED ;
838838}
839839
840- int picoqmux_incoming_packet (picoquic_cnx_t * cnx , uint64_t current_time ,
840+ int picoqmux_incoming_cnx_packet (picoquic_cnx_t * cnx , uint64_t current_time ,
841841 const uint8_t * receive_buffer , size_t receive_length , uint64_t * next_wake_time )
842842{
843843 int ret = 0 ;
@@ -852,3 +852,167 @@ int picoqmux_incoming_packet(picoquic_cnx_t* cnx, uint64_t current_time,
852852 }
853853 return ret ;
854854}
855+
856+ /* Connection context:
857+ * The link between a QMUX connection context and a socket_id is
858+ * tracked in the table "table_cnx_by_socket_id". This is a hash table
859+ * in the QUIC context, with the "socket_id" used as the key.
860+ *
861+ * The socket_id in NULL when the connection is created.
862+ * It is added to the context via the call to picoqmux_set_cnx_socket,
863+ * and removed from the context when the connection is deleted, or
864+ * if the socket_id for the connection is reset to a NULL value.
865+ * (TODO: synchronize QUIC context and socket loop.)
866+ */
867+
868+ static uint64_t picoquic_socket_id_hash (const void * key , const uint8_t * hash_seed )
869+ {
870+ uint64_t h ;
871+ uint8_t bytes [sizeof (void * )];
872+ const picoquic_cnx_t * cnx = (const picoquic_cnx_t * )key ;
873+ /* Using siphash, because CNX ID and IP address are chosen by third parties*/
874+ h = picohash_siphash (& cnx -> qmux_socket_id , (uint32_t )sizeof (void * ), hash_seed );
875+ return h ;
876+ }
877+
878+ static int picoquic_socket_id_compare (const void * key1 , const void * key2 )
879+ {
880+ const picoquic_cnx_t * cnx1 = (const picoquic_cnx_t * )key1 ;
881+ const picoquic_cnx_t * cnx2 = (const picoquic_cnx_t * )key2 ;
882+ int ret = cnx1 -> qmux_socket_id == cnx2 -> qmux_socket_id ;
883+
884+ return ret ;
885+ }
886+
887+ static picohash_item * picoquic_socket_id_to_item (const void * key )
888+ {
889+ picoquic_cnx_t * cnx = (picoquic_cnx_t * )key ;
890+
891+ return & cnx -> registered_socket_id_item ;
892+ }
893+
894+ int picoquic_register_socket_id (picoquic_quic_t * quic , picoquic_cnx_t * cnx , void * socket_id )
895+ {
896+ int ret = 0 ;
897+ picoquic_cnx_t dummy_cnx = { 0 };
898+ picohash_item * item ;
899+
900+ dummy_cnx .qmux_socket_id = socket_id ;
901+ item = picohash_retrieve (quic -> table_cnx_by_socket_id , & dummy_cnx );
902+ if (item != NULL ) {
903+ ret = -1 ;
904+ }
905+ else {
906+ cnx -> qmux_socket_id = socket_id ;
907+ ret = picohash_insert (quic -> table_cnx_by_socket_id , cnx );
908+ }
909+
910+ return ret ;
911+ }
912+
913+ void picoquic_unregister_socket_id (picoquic_cnx_t * cnx )
914+ {
915+ if (cnx -> qmux_socket_id != NULL ) {
916+ picohash_item * item = picohash_retrieve (cnx -> quic -> table_cnx_by_socket_id , cnx );
917+ if (item != NULL ) {
918+ picohash_delete_item (cnx -> quic -> table_cnx_by_socket_id , item , 0 );
919+ }
920+ cnx -> qmux_socket_id = NULL ;
921+ memset (& cnx -> registered_socket_id_item , 0 , sizeof (cnx -> registered_socket_id_item ));
922+ }
923+ }
924+
925+
926+ /* Initiation of a QUIC context to make it QMUX ready.
927+ */
928+ int picoqmux_set_context (picoquic_quic_t * quic )
929+ {
930+ int ret = 0 ;
931+
932+ if ((quic -> table_cnx_by_icid = picohash_create_ex ((size_t )quic -> max_number_connections ,
933+ picoquic_socket_id_hash , picoquic_socket_id_compare , picoquic_socket_id_to_item , quic -> hash_seed )) == NULL ) {
934+ ret = -1 ;
935+ }
936+
937+ return ret ;
938+ }
939+
940+ int picoqmux_start_sockets (picoquic_quic_t * quic )
941+ {
942+ /* Go through the list of pending qmux connections and start the
943+ * required sockets */
944+ }
945+
946+ int picoqmux_clear_context (picoquic_quic_t * quic )
947+ {
948+ /* Terminate the pending sockets */
949+ /* Terminate the active sockets */
950+ /* Clear the socket_id table */
951+ }
952+
953+ /*
954+ * QMux outgoing connection creation.
955+ * When creating a QMUx connection, the code needs to create an additional
956+ * TCP socket in the "socket loop" context.
957+ *
958+ * We want to preserve the possibility of using different variations of the
959+ * socket loop code. We do that by adding a call from the socket loop
960+ * to the QUIC context to set the "socket create" function and context.
961+ *
962+ * The socket create function allows for creation of new sockets from the
963+ * QUIC context. The main parameter is a socket address to which the
964+ * connection should be connected. (Questions: should there be an option
965+ * to bind the address to a specific local address before setting the
966+ * connect call? Should there be an option to create an extra UDP socket,
967+ * or just TCP?)
968+ *
969+ * This code assumes that the socket loop is created already. We need a special
970+ * logic to manage "pending" connections created before the socket loop
971+ * starts. Probably a queue of pending connection, which will be moved
972+ * to active connections as soon as sockets can be created.
973+ */
974+
975+ int picoqmux_create_cnx (picoquic_cnx_t * cnx )
976+ {
977+ int ret = 0 ;
978+ if (cnx -> quic -> create_socket_fn == NULL ) {
979+ /* queue to the qmux pending list */
980+ }
981+ else {
982+ /* create the required socket */
983+ /* set the other qmux parameters */
984+ /* register the socket */
985+ }
986+ return 0 ;
987+ }
988+
989+
990+ /*
991+ * QMux input call, from the socket loop.
992+ */
993+ int picoqmux_incoming_cnx_packet (picoquic_quic_t * quic , uint64_t socket_id ,
994+ uint64_t current_time , const uint8_t * receive_buffer , size_t receive_length )
995+ {
996+ /* Find the connection based on the socket ID.
997+ * Possibly, create a connection if this is a new socket?
998+ */
999+
1000+ /* submit the data to the connection context. */
1001+
1002+ /* return an error if this socket should be closed. */
1003+ }
1004+
1005+ /*
1006+ * QMux prepare call, from the socket loop.
1007+ */
1008+ int picoqmux_prepare_packet (picoquic_quic_t * quic , uint64_t socket_id , uint64_t current_time ,
1009+ uint8_t * send_buffer , size_t send_buffer_max , size_t * send_length )
1010+ {
1011+ /* Find the connection based on the socket ID.
1012+ * Possibly, create a connection if this is a new socket?
1013+ */
1014+
1015+ /* obtain the data from connection context. */
1016+
1017+ /* return an error if this socket should be closed. */
1018+ }
0 commit comments