diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index 020fdafc..a6dc683e 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -1191,6 +1191,48 @@ int spdylay_session_server_new(spdylay_session **session_ptr, */ void spdylay_session_del(spdylay_session *session); +/** + * @enum + * + * Configuration options for :type:`spdylay_session`. + */ +typedef enum { + /** + * This option prevents the library from sending WINDOW_UPDATE + * automatically. If this option is set, the application is + * responsible for sending WINDOW_UPDATE using + * `spdylay_submit_window_update`. + */ + SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE = 1 +} spdylay_opt; + +/** + * @function + * + * Sets the configuration option for the |session|. The |optname| is + * one of :type:`spdylay_opt`. The |optval| is the pointer to the + * option value and the |optlen| is the size of |*optval|. The + * required type of |optval| varies depending on the |optname|. See + * below. + * + * The following |optname| are supported: + * + * :enum:`SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE` + * The |optval| must be ``int``. If |optval| is nonzero, the + * library will not send WINDOW_UPDATE automatically. Therefore, + * the application is responsible for sending WINDOW_UPDATE using + * `spdylay_submit_window_update`. This option defaults to 0. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT` + * The |optname| is not supported; or the |optval| and/or the + * |optlen| are invalid. + */ +int spdylay_session_set_option(spdylay_session *session, + int optname, void *optval, size_t optlen); + /** * @function * diff --git a/lib/spdylay_session.c b/lib/spdylay_session.c index 82c380ac..63fa4fcc 100644 --- a/lib/spdylay_session.c +++ b/lib/spdylay_session.c @@ -2640,3 +2640,26 @@ const spdylay_origin* spdylay_session_get_client_cert_origin { return spdylay_client_cert_vector_get_origin(&session->cli_certvec, slot); } + + +int spdylay_session_set_option(spdylay_session *session, + int optname, void *optval, size_t optlen) +{ + switch(optname) { + case SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE: + if(optlen == sizeof(int)) { + int intval = *(int*)optval; + if(intval) { + session->opt_flags |= SPDYLAY_OPTMASK_NO_AUTO_WINDOW_UPDATE; + } else { + session->opt_flags &= ~SPDYLAY_OPTMASK_NO_AUTO_WINDOW_UPDATE; + } + } else { + return SPDYLAY_ERR_INVALID_ARGUMENT; + } + break; + default: + return SPDYLAY_ERR_INVALID_ARGUMENT; + } + return 0; +} diff --git a/lib/spdylay_session.h b/lib/spdylay_session.h index 0f851c98..c5f8f263 100644 --- a/lib/spdylay_session.h +++ b/lib/spdylay_session.h @@ -50,6 +50,13 @@ */ #define SPDYLAY_PRI_LOWEST_SPDY3 7 +/* + * Option flags. + */ +typedef enum { + SPDYLAY_OPTMASK_NO_AUTO_WINDOW_UPDATE = 1 << 0 +} spdylay_optmask; + typedef struct { spdylay_outbound_item *item; /* Buffer for outbound frames. Used to pack one frame. The memory @@ -180,6 +187,9 @@ struct spdylay_session { /* Settings value of the local endpoint. */ uint32_t local_settings[SPDYLAY_SETTINGS_MAX+1]; + /* Option flags. This is bitwise-OR of 0 or more of spdylay_optmask. */ + uint32_t opt_flags; + /* Client certificate vector */ spdylay_client_cert_vector cli_certvec; diff --git a/tests/main.c b/tests/main.c index a9514c53..a6893e96 100644 --- a/tests/main.c +++ b/tests/main.c @@ -152,6 +152,8 @@ int main(int argc, char* argv[]) test_spdylay_submit_syn_stream_with_credential) || !CU_add_test(pSuite, "session_set_initial_client_cert_origin", test_spdylay_session_set_initial_client_cert_origin) || + !CU_add_test(pSuite, "session_set_option", + test_spdylay_session_set_option) || !CU_add_test(pSuite, "frame_unpack_nv_spdy2", test_spdylay_frame_unpack_nv_spdy2) || !CU_add_test(pSuite, "frame_unpack_nv_spdy3", diff --git a/tests/spdylay_session_test.c b/tests/spdylay_session_test.c index c76e2cac..0fb77ae1 100644 --- a/tests/spdylay_session_test.c +++ b/tests/spdylay_session_test.c @@ -2244,3 +2244,39 @@ void test_spdylay_session_set_initial_client_cert_origin(void) spdylay_session_del(session); } + +void test_spdylay_session_set_option(void) +{ + spdylay_session* session; + spdylay_session_callbacks callbacks; + int intval; + char charval; + memset(&callbacks, 0, sizeof(spdylay_session_callbacks)); + spdylay_session_client_new(&session, SPDYLAY_PROTO_SPDY3, &callbacks, NULL); + + intval = 1; + CU_ASSERT(0 == + spdylay_session_set_option(session, + SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE, + &intval, sizeof(intval))); + CU_ASSERT(session->opt_flags & SPDYLAY_OPTMASK_NO_AUTO_WINDOW_UPDATE); + + intval = 0; + CU_ASSERT(0 == + spdylay_session_set_option(session, + SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE, + &intval, sizeof(intval))); + CU_ASSERT((session->opt_flags & SPDYLAY_OPTMASK_NO_AUTO_WINDOW_UPDATE) == 0); + + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_session_set_option(session, 0, /* 0 is invalid optname */ + &intval, sizeof(intval))); + + charval = 1; + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_session_set_option(session, + SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE, + &charval, sizeof(charval))); + + spdylay_session_del(session); +} diff --git a/tests/spdylay_session_test.h b/tests/spdylay_session_test.h index ea1ff770..e7359706 100644 --- a/tests/spdylay_session_test.h +++ b/tests/spdylay_session_test.h @@ -67,5 +67,6 @@ void test_spdylay_session_get_outbound_queue_size(void); void test_spdylay_session_prep_credential(void); void test_spdylay_submit_syn_stream_with_credential(void); void test_spdylay_session_set_initial_client_cert_origin(void); +void test_spdylay_session_set_option(void); #endif /* SPDYLAY_SESSION_TEST_H */