@@ -348,6 +348,12 @@ static void session_inbound_frame_reset(nghttp2_session *session) {
348
348
}
349
349
nghttp2_frame_altsvc_free (& iframe -> frame .ext , mem );
350
350
break ;
351
+ case NGHTTP2_ORIGIN :
352
+ if ((session -> builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN ) == 0 ) {
353
+ break ;
354
+ }
355
+ nghttp2_frame_origin_free (& iframe -> frame .ext , mem );
356
+ break ;
351
357
}
352
358
}
353
359
@@ -1749,6 +1755,13 @@ static int session_predicate_altsvc_send(nghttp2_session *session,
1749
1755
return 0 ;
1750
1756
}
1751
1757
1758
+ static int session_predicate_origin_send (nghttp2_session * session ) {
1759
+ if (session_is_closing (session )) {
1760
+ return NGHTTP2_ERR_SESSION_CLOSING ;
1761
+ }
1762
+ return 0 ;
1763
+ }
1764
+
1752
1765
/* Take into account settings max frame size and both connection-level
1753
1766
flow control here */
1754
1767
static ssize_t
@@ -2280,6 +2293,18 @@ static int session_prep_frame(nghttp2_session *session,
2280
2293
2281
2294
nghttp2_frame_pack_altsvc (& session -> aob .framebufs , & frame -> ext );
2282
2295
2296
+ return 0 ;
2297
+ case NGHTTP2_ORIGIN :
2298
+ rv = session_predicate_origin_send (session );
2299
+ if (rv != 0 ) {
2300
+ return rv ;
2301
+ }
2302
+
2303
+ rv = nghttp2_frame_pack_origin (& session -> aob .framebufs , & frame -> ext );
2304
+ if (rv != 0 ) {
2305
+ return rv ;
2306
+ }
2307
+
2283
2308
return 0 ;
2284
2309
default :
2285
2310
/* Unreachable here */
@@ -4385,6 +4410,12 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
4385
4410
return session_call_on_frame_received (session , frame );
4386
4411
}
4387
4412
4413
+ if (!session -> remote_settings_received ) {
4414
+ session -> remote_settings .max_concurrent_streams =
4415
+ NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ;
4416
+ session -> remote_settings_received = 1 ;
4417
+ }
4418
+
4388
4419
for (i = 0 ; i < frame -> settings .niv ; ++ i ) {
4389
4420
nghttp2_settings_entry * entry = & frame -> settings .iv [i ];
4390
4421
@@ -4821,6 +4852,11 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
4821
4852
return session_call_on_frame_received (session , frame );
4822
4853
}
4823
4854
4855
+ int nghttp2_session_on_origin_received (nghttp2_session * session ,
4856
+ nghttp2_frame * frame ) {
4857
+ return session_call_on_frame_received (session , frame );
4858
+ }
4859
+
4824
4860
static int session_process_altsvc_frame (nghttp2_session * session ) {
4825
4861
nghttp2_inbound_frame * iframe = & session -> iframe ;
4826
4862
nghttp2_frame * frame = & iframe -> frame ;
@@ -4836,6 +4872,25 @@ static int session_process_altsvc_frame(nghttp2_session *session) {
4836
4872
return nghttp2_session_on_altsvc_received (session , frame );
4837
4873
}
4838
4874
4875
+ static int session_process_origin_frame (nghttp2_session * session ) {
4876
+ nghttp2_inbound_frame * iframe = & session -> iframe ;
4877
+ nghttp2_frame * frame = & iframe -> frame ;
4878
+ nghttp2_mem * mem = & session -> mem ;
4879
+ int rv ;
4880
+
4881
+ rv = nghttp2_frame_unpack_origin_payload (& frame -> ext , iframe -> lbuf .pos ,
4882
+ nghttp2_buf_len (& iframe -> lbuf ), mem );
4883
+ if (rv != 0 ) {
4884
+ if (nghttp2_is_fatal (rv )) {
4885
+ return rv ;
4886
+ }
4887
+ /* Ignore ORIGIN frame which cannot be parsed. */
4888
+ return 0 ;
4889
+ }
4890
+
4891
+ return nghttp2_session_on_origin_received (session , frame );
4892
+ }
4893
+
4839
4894
static int session_process_extension_frame (nghttp2_session * session ) {
4840
4895
int rv ;
4841
4896
nghttp2_inbound_frame * iframe = & session -> iframe ;
@@ -5746,6 +5801,42 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
5746
5801
iframe -> state = NGHTTP2_IB_READ_NBYTE ;
5747
5802
inbound_frame_set_mark (iframe , 2 );
5748
5803
5804
+ break ;
5805
+ case NGHTTP2_ORIGIN :
5806
+ if (!(session -> builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN )) {
5807
+ busy = 1 ;
5808
+ iframe -> state = NGHTTP2_IB_IGN_PAYLOAD ;
5809
+ break ;
5810
+ }
5811
+
5812
+ DEBUGF ("recv: ORIGIN\n" );
5813
+
5814
+ iframe -> frame .ext .payload = & iframe -> ext_frame_payload .origin ;
5815
+
5816
+ if (session -> server || iframe -> frame .hd .stream_id ||
5817
+ (iframe -> frame .hd .flags & 0xf0 )) {
5818
+ busy = 1 ;
5819
+ iframe -> state = NGHTTP2_IB_IGN_PAYLOAD ;
5820
+ break ;
5821
+ }
5822
+
5823
+ iframe -> frame .hd .flags = NGHTTP2_FLAG_NONE ;
5824
+
5825
+ if (iframe -> payloadleft ) {
5826
+ iframe -> raw_lbuf = nghttp2_mem_malloc (mem , iframe -> payloadleft );
5827
+
5828
+ if (iframe -> raw_lbuf == NULL ) {
5829
+ return NGHTTP2_ERR_NOMEM ;
5830
+ }
5831
+
5832
+ nghttp2_buf_wrap_init (& iframe -> lbuf , iframe -> raw_lbuf ,
5833
+ iframe -> payloadleft );
5834
+ } else {
5835
+ busy = 1 ;
5836
+ }
5837
+
5838
+ iframe -> state = NGHTTP2_IB_READ_ORIGIN_PAYLOAD ;
5839
+
5749
5840
break ;
5750
5841
default :
5751
5842
busy = 1 ;
@@ -6583,7 +6674,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
6583
6674
DEBUGF ("recv: [IB_READ_ALTSVC_PAYLOAD]\n" );
6584
6675
6585
6676
readlen = inbound_frame_payload_readlen (iframe , in , last );
6586
-
6587
6677
if (readlen > 0 ) {
6588
6678
iframe -> lbuf .last = nghttp2_cpymem (iframe -> lbuf .last , in , readlen );
6589
6679
@@ -6601,11 +6691,44 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
6601
6691
}
6602
6692
6603
6693
rv = session_process_altsvc_frame (session );
6694
+ if (nghttp2_is_fatal (rv )) {
6695
+ return rv ;
6696
+ }
6697
+
6698
+ session_inbound_frame_reset (session );
6699
+
6700
+ break ;
6701
+ case NGHTTP2_IB_READ_ORIGIN_PAYLOAD :
6702
+ DEBUGF ("recv: [IB_READ_ORIGIN_PAYLOAD]\n" );
6703
+
6704
+ readlen = inbound_frame_payload_readlen (iframe , in , last );
6705
+
6706
+ if (readlen > 0 ) {
6707
+ iframe -> lbuf .last = nghttp2_cpymem (iframe -> lbuf .last , in , readlen );
6708
+
6709
+ iframe -> payloadleft -= readlen ;
6710
+ in += readlen ;
6711
+ }
6712
+
6713
+ DEBUGF ("recv: readlen=%zu, payloadleft=%zu\n" , readlen ,
6714
+ iframe -> payloadleft );
6715
+
6716
+ if (iframe -> payloadleft ) {
6717
+ assert (nghttp2_buf_avail (& iframe -> lbuf ) > 0 );
6718
+
6719
+ break ;
6720
+ }
6721
+
6722
+ rv = session_process_origin_frame (session );
6604
6723
6605
6724
if (nghttp2_is_fatal (rv )) {
6606
6725
return rv ;
6607
6726
}
6608
6727
6728
+ if (iframe -> state == NGHTTP2_IB_IGN_ALL ) {
6729
+ return (ssize_t )inlen ;
6730
+ }
6731
+
6609
6732
session_inbound_frame_reset (session );
6610
6733
6611
6734
break ;
@@ -7085,12 +7208,42 @@ int nghttp2_session_set_stream_user_data(nghttp2_session *session,
7085
7208
int32_t stream_id ,
7086
7209
void * stream_user_data ) {
7087
7210
nghttp2_stream * stream ;
7211
+ nghttp2_frame * frame ;
7212
+ nghttp2_outbound_item * item ;
7213
+
7088
7214
stream = nghttp2_session_get_stream (session , stream_id );
7089
- if (!stream ) {
7215
+ if (stream ) {
7216
+ stream -> stream_user_data = stream_user_data ;
7217
+ return 0 ;
7218
+ }
7219
+
7220
+ if (session -> server || !nghttp2_session_is_my_stream_id (session , stream_id ) ||
7221
+ !nghttp2_outbound_queue_top (& session -> ob_syn )) {
7090
7222
return NGHTTP2_ERR_INVALID_ARGUMENT ;
7091
7223
}
7092
- stream -> stream_user_data = stream_user_data ;
7093
- return 0 ;
7224
+
7225
+ frame = & nghttp2_outbound_queue_top (& session -> ob_syn )-> frame ;
7226
+ assert (frame -> hd .type == NGHTTP2_HEADERS );
7227
+
7228
+ if (frame -> hd .stream_id > stream_id ||
7229
+ (uint32_t )stream_id >= session -> next_stream_id ) {
7230
+ return NGHTTP2_ERR_INVALID_ARGUMENT ;
7231
+ }
7232
+
7233
+ for (item = session -> ob_syn .head ; item ; item = item -> qnext ) {
7234
+ if (item -> frame .hd .stream_id < stream_id ) {
7235
+ continue ;
7236
+ }
7237
+
7238
+ if (item -> frame .hd .stream_id > stream_id ) {
7239
+ break ;
7240
+ }
7241
+
7242
+ item -> aux_data .headers .stream_user_data = stream_user_data ;
7243
+ return 0 ;
7244
+ }
7245
+
7246
+ return NGHTTP2_ERR_INVALID_ARGUMENT ;
7094
7247
}
7095
7248
7096
7249
int nghttp2_session_resume_data (nghttp2_session * session , int32_t stream_id ) {
0 commit comments