Skip to content

Commit 9b48076

Browse files
committed
Merge branch 'master' into long-random-hash
2 parents ea7b096 + f3f7312 commit 9b48076

File tree

17 files changed

+873
-125
lines changed

17 files changed

+873
-125
lines changed

UnitTest1/unittest1.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,6 +2042,55 @@ namespace UnitTest1
20422042
Assert::AreEqual(ret, 0);
20432043
}
20442044

2045+
TEST_METHOD(cc_ns_asym)
2046+
{
2047+
int ret = cc_ns_asym_test();
2048+
2049+
Assert::AreEqual(ret, 0);
2050+
}
2051+
2052+
TEST_METHOD(cc_ns_blackhole)
2053+
{
2054+
int ret = cc_ns_blackhole_test();
2055+
2056+
Assert::AreEqual(ret, 0);
2057+
}
2058+
2059+
TEST_METHOD(cc_ns_drop_and_back)
2060+
{
2061+
int ret = cc_ns_drop_and_back_test();
2062+
2063+
Assert::AreEqual(ret, 0);
2064+
}
2065+
2066+
TEST_METHOD(cc_ns_low_and_up)
2067+
{
2068+
int ret = cc_ns_low_and_up_test();
2069+
2070+
Assert::AreEqual(ret, 0);
2071+
}
2072+
2073+
TEST_METHOD(cc_ns_wifi_fade)
2074+
{
2075+
int ret = cc_ns_wifi_fade_test();
2076+
2077+
Assert::AreEqual(ret, 0);
2078+
}
2079+
2080+
TEST_METHOD(cc_ns_wifi_suspension)
2081+
{
2082+
int ret = cc_ns_wifi_suspension_test();
2083+
2084+
Assert::AreEqual(ret, 0);
2085+
}
2086+
2087+
TEST_METHOD(cc_ns_varylink)
2088+
{
2089+
int ret = cc_ns_varylink_test();
2090+
2091+
Assert::AreEqual(ret, 0);
2092+
}
2093+
20452094
TEST_METHOD(fastcc)
20462095
{
20472096
int ret = fastcc_test();

doc/socket_loop.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ int picoquic_packet_loop_v2(picoquic_quic_t* quic,
3838
```
3939

4040
The loop will execute,
41-
calling the Picoquic Netowrking API functions `picoquic_prepare_next_packet_ex`
41+
calling the Picoquic Networking API functions `picoquic_prepare_next_packet_ex`
4242
to ask the stack whether packets are ready to be sent and
4343
`picoquic_incoming_packet_ex` when packets are received from the network.
4444

@@ -101,8 +101,8 @@ It exposes a series of callback events:
101101
it wants to be called for a time check before the loops waits for timers or incoming packets.
102102
* `picoquic_packet_loop_after_receive`: Called after packets have been received, enabling the application
103103
to perform picoquic API calls triggered by the received data.
104-
* `picoquic_packet_loop_after_send`: Called after packets have been received, enabling the application
105-
to perform picoquic API calls triggered by the received data.
104+
* `picoquic_packet_loop_after_send`: Called after packets have been sent, enabling the application
105+
to perform picoquic API calls triggered by the sent data.
106106
* `picoquic_packet_loop_port_update`: Provides a "loopback" socket address corresponding to the main
107107
socket. Can be used to learn the port number associated with that socket.
108108
* `picoquic_packet_loop_time_check`: Called before the packet loop starts waiting for a new packet or a

doc/usage.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ On Linux after building, the following executables are available in the project
1010
## HTTP Client and Server Usage
1111
* client: ./picoquicdemo servername serverportnumber HTTPpath
1212
* downloaded files will be in current directory. use -o for another folder
13-
* exemple: ./picoquicdemo -o ../received 192.0.2.1 4433 index.html
13+
* example: ./picoquicdemo -o ../received 192.0.2.1 4433 index.html
1414
* server: ./picoquicdemo -p portnumber
1515
* -p argument tells the program that it is acting as a server
1616
* HTML root folder is current directory by default. use -w for another folder
1717
* keys and certs are specified by -k and -c. See -h for more details.
18-
* exemple: ./picoquicdemo -w ../htmlroot -p 4433
18+
* example: ./picoquicdemo -w ../htmlroot -p 4433
1919
* additional useful information for HTTP usage is available at:
2020
* [Without DNS Names Or Certs](https://github.com/private-octopus/picoquic/wiki/Testing-without-DNS-names-or-Certificates)
2121
* [Certs Using Lets Encrypt](https://github.com/private-octopus/picoquic/wiki/Import-key-and-cert-on-server-from-Let's-encrypt)

picohttp/democlient.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,9 @@ int picoquic_demo_client_callback(picoquic_cnx_t* cnx,
633633

634634
break;
635635
}
636+
case picoquic_callback_next_path_allowed:
637+
/* This event should be handled according to the application's requirements */
638+
break;
636639
default:
637640
/* unexpected */
638641
break;

picohttp/democlient.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ typedef struct st_picoquic_demo_client_callback_ctx_t {
8888
int no_print;
8989
int connection_ready;
9090
int connection_closed;
91+
92+
/* Context extension for handling asynchronous creation of paths */
93+
void (*handle_path_allowed)(picoquic_cnx_t* cnx, void* ctx);
94+
void* path_allowed_context;
9195
} picoquic_demo_callback_ctx_t;
9296

9397
picoquic_alpn_enum picoquic_parse_alpn(char const * alpn);

picohttp_t/picohttp_t.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,14 @@ static const picoquic_test_def_t test_table[] = {
110110
{ "quicperf_overflow", quicperf_overflow_test },
111111
{ "cc_compete_cubic2", cc_compete_cubic2_test },
112112
{ "cc_compete_prague2", cc_compete_prague2_test },
113-
{ "cc_compete_d_cubic", cc_compete_d_cubic_test }
113+
{ "cc_compete_d_cubic", cc_compete_d_cubic_test },
114+
{ "cc_ns_asym", cc_ns_asym_test },
115+
{ "cc_ns_blackhole", cc_ns_blackhole_test },
116+
{ "cc_ns_drop_and_back", cc_ns_drop_and_back_test },
117+
{ "cc_ns_low_and_up", cc_ns_low_and_up_test },
118+
{ "cc_ns_wifi_fade", cc_ns_wifi_fade_test },
119+
{ "cc_ns_wifi_suspension", cc_ns_wifi_suspension_test },
120+
{ "cc_ns_varylink", cc_ns_varylink_test }
114121
};
115122

116123
static size_t const nb_tests = sizeof(test_table) / sizeof(picoquic_test_def_t);

picoquic/frames.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -498,10 +498,13 @@ const uint8_t* picoquic_decode_new_connection_id_frame(picoquic_cnx_t* cnx, cons
498498
else {
499499
uint64_t transport_error = picoquic_add_remote_cnxid_to_stash(cnx, remote_cnxid_stash, retire_before,
500500
sequence, cid_length, cnxid_bytes, secret_bytes, NULL);
501-
if (transport_error == 0 && remote_cnxid_stash->retire_cnxid_before < retire_before) {
502-
/* retire the now deprecated CIDs */
503-
remote_cnxid_stash->retire_cnxid_before = retire_before;
504-
transport_error = picoquic_remove_not_before_cid(cnx, unique_path_id, retire_before, current_time);
501+
if (transport_error == 0) {
502+
picoquic_test_and_signal_new_path_allowed(cnx);
503+
if (remote_cnxid_stash->retire_cnxid_before < retire_before) {
504+
/* retire the now deprecated CIDs */
505+
remote_cnxid_stash->retire_cnxid_before = retire_before;
506+
transport_error = picoquic_remove_not_before_cid(cnx, unique_path_id, retire_before, current_time);
507+
}
505508
}
506509
if (transport_error != 0) {
507510
picoquic_connection_error(cnx, transport_error,

picoquic/picoquic.h

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ extern "C" {
104104
#define PICOQUIC_ERROR_PATH_ID_INVALID (PICOQUIC_ERROR_CLASS + 60)
105105
#define PICOQUIC_ERROR_RETRY_NEEDED (PICOQUIC_ERROR_CLASS + 61)
106106
#define PICOQUIC_ERROR_SERVER_BUSY (PICOQUIC_ERROR_CLASS + 62)
107+
#define PICOQUIC_ERROR_PATH_DUPLICATE (PICOQUIC_ERROR_CLASS + 63)
108+
#define PICOQUIC_ERROR_PATH_ID_BLOCKED (PICOQUIC_ERROR_CLASS + 64)
109+
#define PICOQUIC_ERROR_PATH_CID_BLOCKED (PICOQUIC_ERROR_CLASS + 65)
110+
#define PICOQUIC_ERROR_PATH_ADDRESS_FAMILY (PICOQUIC_ERROR_CLASS + 66)
111+
#define PICOQUIC_ERROR_PATH_NOT_READY (PICOQUIC_ERROR_CLASS + 67)
112+
#define PICOQUIC_ERROR_PATH_LIMIT_EXCEEDED (PICOQUIC_ERROR_CLASS + 68)
107113

108114
/*
109115
* Protocol errors defined in the QUIC spec
@@ -274,7 +280,8 @@ typedef enum {
274280
picoquic_callback_path_deleted, /* An existing path has been deleted */
275281
picoquic_callback_path_quality_changed, /* Some path quality parameters have changed */
276282
picoquic_callback_path_address_observed, /* The peer has reported an address for the path */
277-
picoquic_callback_app_wakeup /* wakeup timer set by application has expired */
283+
picoquic_callback_app_wakeup, /* wakeup timer set by application has expired */
284+
picoquic_callback_next_path_allowed /* There are enough path_id and connection ID available for the next path */
278285
} picoquic_call_back_event_t;
279286

280287
typedef struct st_picoquic_tp_prefered_address_t {
@@ -858,6 +865,47 @@ void picoquic_set_rejected_version(picoquic_cnx_t* cnx, uint32_t rejected_versio
858865
* Like all user-level networking API, the "probe new path" API assumes that the
859866
* port numbers in the socket addresses structures are expressed in network order.
860867
*
868+
* If an error occurs during a call to picoquic_probe_new_path_ex,
869+
* the function returns an error code describing the issue:
870+
*
871+
* PICOQUIC_ERROR_PATH_DUPLICATE: there is already an existing path with
872+
* the same 4 tuple. This error only happens if the multipath extensions
873+
* are not negotiated, because the multipath extensions allow creation of
874+
* multiple paths with the same 4 tuple.
875+
*
876+
* PICOQUIC_ERROR_PATH_ID_BLOCKED: when using the multipath extension,
877+
* the peers manage a max_path_id value. The code cannot create a new path
878+
* if the path_id would exceed the limit negotiated with the peer. Applications
879+
* encountering that error code should wait until the peer has increased the limit.
880+
* They may want to signal the issue to the peer by queuing a PATHS_BLOCKED frame.
881+
*
882+
* PICOQUIC_ERROR_PATH_CID_BLOCKED: when using the multipath extension,
883+
* the peers use NEW_PATH_CONNECTION_ID frame to provide CIDs associated with each
884+
* valid path_id. The error occurs when the peer has not yet provided CIDs for the
885+
* next path_id. Applications encountering the error should wait until the peer
886+
* provides CID for the path. They may want to signal the issue to the peer by
887+
* queuing a PATH_CIDS_BLOCKED frame.
888+
*
889+
* PICOQUIC_ERROR_PATH_ADDRESS_FAMILY: API error. The application is trying
890+
* to use a four tuple with different address family for source and destination.
891+
*
892+
* PICOQUIC_ERROR_PATH_NOT_READY: API error. The application is trying to create
893+
* paths before the connection handshake is complete. The application should wait
894+
* until it is notified that the connection is ready.
895+
*
896+
* PICOQUIC_ERROR_PATH_LIMIT_EXCEEDED: The application is trying to create more
897+
* simultaneous paths than allowed. It will need to close one of the existing paths
898+
* before creating a new one.
899+
*
900+
* The errors PICOQUIC_ERROR_PATH_ID_BLOCKED, PICOQUIC_ERROR_PATH_CID_BLOCKED.
901+
* PICOQUIC_ERROR_PATH_NOT_READY and PICOQUIC_ERROR_PATH_LIMIT_EXCEEDED are transient.
902+
* The application can use the `picoquic_check_new_path_allowed` API to check whether
903+
* a new path may be created. This function will return 1 if the path creation
904+
* can be attempted immediately, 0 otherwise. If the return code is 0, the stack
905+
* will issue a callback `picoquic_callback_next_path_ready` when the transient
906+
* issues are resolved and `picoquic_probe_new_path_ex` could be called
907+
* again.
908+
*
861909
* Path event callbacks can be enabled by calling "picoquic_enable_path_callbacks".
862910
* This can be set as the default for new connections by calling
863911
* "picoquic_enable_path_callbacks_default". If enabled, the folling events
@@ -893,10 +941,9 @@ void picoquic_set_rejected_version(picoquic_cnx_t* cnx, uint32_t rejected_versio
893941
* maintain path data in an app specific context, it will use a call to
894942
* "picoquic_set_app_path_ctx" to document it. The path created during
895943
* the connection setup has the unique_path_id 0.
896-
897-
*
944+
*
898945
* If an error occurs, such as reference to an obsolete unique path id,
899-
* all the functions return -1.
946+
* all the path management functions return -1.
900947
*
901948
* The call to "refresh the connection ID" will trigger a renewal of the connection
902949
* ID used for sending packets on that path. This API is mostly used in test
@@ -918,6 +965,8 @@ int picoquic_abandon_path(picoquic_cnx_t* cnx, uint64_t unique_path_id,
918965
int picoquic_refresh_path_connection_id(picoquic_cnx_t* cnx, uint64_t unique_path_id);
919966
int picoquic_set_stream_path_affinity(picoquic_cnx_t* cnx, uint64_t stream_id, uint64_t unique_path_id);
920967
int picoquic_set_path_status(picoquic_cnx_t* cnx, uint64_t unique_path_id, picoquic_path_status_enum status);
968+
int picoquic_subscribe_new_path_allowed(picoquic_cnx_t* cnx, int* is_already_allowed);
969+
921970
/* The get path addr API provides the IP addresses used by a specific path.
922971
* The "local" argument determines whether the APi returns the local address
923972
* (local == 1), the address of the peer (local == 2) or the address observed by the peer (local == 3).

picoquic/picoquic_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,8 @@ typedef struct st_picoquic_cnx_t {
13131313
unsigned int is_forced_probe_up_required : 1; /* application wants "probe up" if CC requests it */
13141314
unsigned int is_address_discovery_provider : 1; /* send the address discovery extension */
13151315
unsigned int is_address_discovery_receiver : 1; /* receive the address discovery extension */
1316+
unsigned int is_subscribed_to_path_allowed : 1; /* application wants to be advised if it is now possible to create a path */
1317+
unsigned int is_notified_that_path_is_allowed : 1; /* application wants to be advised if it is now possible to create a path */
13161318

13171319
/* PMTUD policy */
13181320
picoquic_pmtud_policy_enum pmtud_policy;
@@ -2043,6 +2045,8 @@ const uint8_t* picoquic_skip_path_abandon_frame(const uint8_t* bytes, const uint
20432045
const uint8_t* picoquic_skip_path_available_or_standby_frame(const uint8_t* bytes, const uint8_t* bytes_max);
20442046
int picoquic_queue_path_available_or_standby_frame(
20452047
picoquic_cnx_t* cnx, picoquic_path_t* path_x, picoquic_path_status_enum status);
2048+
/* Internal only API, notify that next path is now allowed. */
2049+
void picoquic_test_and_signal_new_path_allowed(picoquic_cnx_t* cnx);
20462050

20472051
int picoquic_decode_closing_frames(picoquic_cnx_t* cnx, uint8_t* bytes, size_t bytes_max, int* closing_received);
20482052

picoquic/picoquic_utils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ typedef struct st_picoquictest_sim_link_t {
297297
/* Variable for multipath simulation */
298298
int is_switched_off;
299299
int is_unreachable;
300+
/* variable for simulating suspension */
301+
int is_suspended;
300302
} picoquictest_sim_link_t;
301303

302304
picoquictest_sim_link_t* picoquictest_sim_link_create(double data_rate_in_gps,

0 commit comments

Comments
 (0)