Added spdylay_submit_settings
This commit is contained in:
parent
82e20192d8
commit
02924b6dd0
|
@ -662,7 +662,7 @@ void* spdylay_session_get_stream_user_data(spdylay_session *session,
|
|||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* SPDYLAY_ERR_INVALID_FRAME
|
||||
* SPDYLAY_ERR_INVALID_ARGUMENT
|
||||
* |pri| is invalid.
|
||||
* SPDYLAY_ERR_NOMEM
|
||||
* Out of memory.
|
||||
|
@ -728,7 +728,7 @@ int spdylay_submit_response(spdylay_session *session,
|
|||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* SPDYLAY_ERR_INVALID_FRAME
|
||||
* SPDYLAY_ERR_INVALID_ARGUMENT
|
||||
* |pri| is invalid.
|
||||
* SPDYLAY_ERR_NOMEM
|
||||
* Out of memory.
|
||||
|
@ -830,6 +830,23 @@ int spdylay_submit_ping(spdylay_session *session);
|
|||
*/
|
||||
int spdylay_submit_goaway(spdylay_session *session, uint32_t status_code);
|
||||
|
||||
/*
|
||||
* Stores local settings and submits SETTINGS frame. The |iv| is the
|
||||
* pointer to the array of spdylay_settings_entry. The |niv| indicates
|
||||
* the number of spdylay_settings_entry. The |flags| is bitwise-OR of
|
||||
* one or more values from spdylay_settings_flag.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* SPDYLAY_ERR_INVALID_ARGUMENT
|
||||
* The |iv| contains duplicate settings ID or invalid value.
|
||||
* SPDYLAY_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int spdylay_submit_settings(spdylay_session *session, uint8_t flags,
|
||||
const spdylay_settings_entry *iv, size_t niv);
|
||||
|
||||
/*
|
||||
* A helper function for dealing with NPN in client side.
|
||||
* |in| contains server's protocol in preferable order.
|
||||
|
|
|
@ -1000,3 +1000,14 @@ spdylay_settings_entry* spdylay_frame_iv_copy(const spdylay_settings_entry *iv,
|
|||
memcpy(iv_copy, iv, len);
|
||||
return iv_copy;
|
||||
}
|
||||
|
||||
static int spdylay_settings_entry_compar(const void *lhs, const void *rhs)
|
||||
{
|
||||
return ((spdylay_settings_entry *)lhs)->settings_id
|
||||
-((spdylay_settings_entry *)rhs)->settings_id;
|
||||
}
|
||||
|
||||
void spdylay_frame_iv_sort(spdylay_settings_entry *iv, size_t niv)
|
||||
{
|
||||
qsort(iv, niv, sizeof(spdylay_settings_entry), spdylay_settings_entry_compar);
|
||||
}
|
||||
|
|
|
@ -618,4 +618,11 @@ void spdylay_frame_nv_2to3(char **nv);
|
|||
spdylay_settings_entry* spdylay_frame_iv_copy(const spdylay_settings_entry *iv,
|
||||
size_t niv);
|
||||
|
||||
/*
|
||||
* Sorts the |iv| with the ascending order of the settings_id member.
|
||||
* The number of the element in the array pointed by the |iv| is given
|
||||
* by the |niv|.
|
||||
*/
|
||||
void spdylay_frame_iv_sort(spdylay_settings_entry *iv, size_t niv);
|
||||
|
||||
#endif /* SPDYLAY_FRAME_H */
|
||||
|
|
|
@ -328,6 +328,7 @@ int spdylay_session_add_frame(spdylay_session *session,
|
|||
}
|
||||
case SPDYLAY_SETTINGS:
|
||||
/* Should SPDYLAY_SETTINGS have higher priority? */
|
||||
item->pri = -1;
|
||||
break;
|
||||
case SPDYLAY_NOOP:
|
||||
/* We don't have any public API to add NOOP, so here is
|
||||
|
@ -1542,6 +1543,17 @@ static void spdylay_session_update_initial_window_size
|
|||
vals);
|
||||
}
|
||||
|
||||
void spdylay_session_update_local_settings(spdylay_session *session,
|
||||
spdylay_settings_entry *iv,
|
||||
size_t niv)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < niv; ++i) {
|
||||
assert(iv[i].settings_id > 0 && iv[i].settings_id <= SPDYLAY_SETTINGS_MAX);
|
||||
session->local_settings[iv[i].settings_id] = iv[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
int spdylay_session_on_settings_received(spdylay_session *session,
|
||||
spdylay_frame *frame)
|
||||
{
|
||||
|
|
|
@ -483,4 +483,14 @@ spdylay_outbound_item* spdylay_session_get_next_ob_item
|
|||
*/
|
||||
uint8_t spdylay_session_get_pri_lowest(spdylay_session *session);
|
||||
|
||||
/*
|
||||
* Updates local settings with the |iv|. The number of elements in the
|
||||
* array pointed by the |iv| is given by the |niv|. This function
|
||||
* assumes that the all settings_id member in |iv| are in range 1 to
|
||||
* SPDYLAY_SETTINGS_MAX, inclusive.
|
||||
*/
|
||||
void spdylay_session_update_local_settings(spdylay_session *session,
|
||||
spdylay_settings_entry *iv,
|
||||
size_t niv);
|
||||
|
||||
#endif /* SPDYLAY_SESSION_H */
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
*/
|
||||
#include "spdylay_submit.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "spdylay_session.h"
|
||||
#include "spdylay_frame.h"
|
||||
|
||||
|
@ -183,6 +185,44 @@ int spdylay_submit_goaway(spdylay_session *session, uint32_t status_code)
|
|||
status_code);
|
||||
}
|
||||
|
||||
int spdylay_submit_settings(spdylay_session *session, uint8_t flags,
|
||||
const spdylay_settings_entry *iv, size_t niv)
|
||||
{
|
||||
spdylay_frame *frame;
|
||||
spdylay_settings_entry *iv_copy;
|
||||
int check[SPDYLAY_SETTINGS_MAX+1];
|
||||
int i, r;
|
||||
memset(check, 0, sizeof(check));
|
||||
for(i = 0; i < niv; ++i) {
|
||||
if(iv[i].settings_id > SPDYLAY_SETTINGS_MAX || iv[i].settings_id == 0 ||
|
||||
check[iv[i].settings_id] == 1) {
|
||||
return SPDYLAY_ERR_INVALID_ARGUMENT;
|
||||
} else {
|
||||
check[iv[i].settings_id] = 1;
|
||||
}
|
||||
}
|
||||
frame = malloc(sizeof(spdylay_frame));
|
||||
if(frame == NULL) {
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
iv_copy = spdylay_frame_iv_copy(iv, niv);
|
||||
if(iv_copy == NULL) {
|
||||
free(frame);
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
spdylay_frame_iv_sort(iv_copy, niv);
|
||||
spdylay_frame_settings_init(&frame->settings, session->version,
|
||||
flags, iv_copy, niv);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_SETTINGS, frame, NULL);
|
||||
if(r == 0) {
|
||||
spdylay_session_update_local_settings(session, iv_copy, niv);
|
||||
} else {
|
||||
spdylay_frame_settings_free(&frame->settings);
|
||||
free(frame);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int spdylay_submit_request(spdylay_session *session, uint8_t pri,
|
||||
const char **nv,
|
||||
const spdylay_data_provider *data_prd,
|
||||
|
|
|
@ -140,6 +140,8 @@ int main(int argc, char* argv[])
|
|||
test_spdylay_session_on_ctrl_not_send) ||
|
||||
!CU_add_test(pSuite, "session_on_settings_received",
|
||||
test_spdylay_session_on_settings_received) ||
|
||||
!CU_add_test(pSuite, "session_submit_settings",
|
||||
test_spdylay_submit_settings) ||
|
||||
!CU_add_test(pSuite, "frame_unpack_nv_spdy2",
|
||||
test_spdylay_frame_unpack_nv_spdy2) ||
|
||||
!CU_add_test(pSuite, "frame_unpack_nv_spdy3",
|
||||
|
|
|
@ -1898,3 +1898,77 @@ void test_spdylay_session_on_settings_received()
|
|||
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
||||
void test_spdylay_submit_settings()
|
||||
{
|
||||
spdylay_session *session;
|
||||
spdylay_session_callbacks callbacks;
|
||||
my_user_data ud;
|
||||
spdylay_outbound_item *item;
|
||||
spdylay_frame *frame;
|
||||
spdylay_settings_entry iv[3];
|
||||
|
||||
iv[0].settings_id = SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||
iv[0].value = 50;
|
||||
iv[0].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE;
|
||||
|
||||
iv[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||
iv[1].value = 16*1024;
|
||||
iv[1].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE;
|
||||
|
||||
/* This is duplicate entry */
|
||||
iv[2].settings_id = SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||
iv[2].value = 150;
|
||||
iv[2].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE;
|
||||
|
||||
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
callbacks.on_ctrl_send_callback = on_ctrl_send_callback;
|
||||
spdylay_session_server_new(&session, SPDYLAY_PROTO_SPDY3, &callbacks, &ud);
|
||||
|
||||
CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT ==
|
||||
spdylay_submit_settings(session, SPDYLAY_FLAG_SETTINGS_NONE,
|
||||
iv, 3));
|
||||
|
||||
/* Make sure that local settings are not changed */
|
||||
CU_ASSERT(SPDYLAY_CONCURRENT_STREAMS_MAX ==
|
||||
session->local_settings[SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS]);
|
||||
CU_ASSERT(SPDYLAY_INITIAL_WINDOW_SIZE ==
|
||||
session->local_settings[SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE]);
|
||||
|
||||
CU_ASSERT(0 == spdylay_submit_settings(session,
|
||||
SPDYLAY_FLAG_SETTINGS_CLEAR_SETTINGS,
|
||||
iv, 2));
|
||||
|
||||
/* Make sure that local settings are changed */
|
||||
CU_ASSERT(50 ==
|
||||
session->local_settings[SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS]);
|
||||
CU_ASSERT(16*1024 ==
|
||||
session->local_settings[SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE]);
|
||||
|
||||
item = spdylay_session_get_next_ob_item(session);
|
||||
|
||||
CU_ASSERT(SPDYLAY_SETTINGS == item->frame_type);
|
||||
|
||||
frame = item->frame;
|
||||
CU_ASSERT(2 == frame->settings.niv);
|
||||
CU_ASSERT(SPDYLAY_FLAG_SETTINGS_CLEAR_SETTINGS == frame->settings.hd.flags);
|
||||
|
||||
CU_ASSERT(50 == frame->settings.iv[0].value);
|
||||
CU_ASSERT(SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS ==
|
||||
frame->settings.iv[0].settings_id);
|
||||
CU_ASSERT(SPDYLAY_FLAG_SETTINGS_NONE ==
|
||||
frame->settings.iv[0].flags);
|
||||
|
||||
CU_ASSERT(16*1024 == frame->settings.iv[1].value);
|
||||
CU_ASSERT(SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE ==
|
||||
frame->settings.iv[1].settings_id);
|
||||
CU_ASSERT(SPDYLAY_FLAG_SETTINGS_NONE ==
|
||||
frame->settings.iv[1].flags);
|
||||
|
||||
ud.ctrl_send_cb_called = 0;
|
||||
CU_ASSERT(0 == spdylay_session_send(session));
|
||||
CU_ASSERT(1 == ud.ctrl_send_cb_called);
|
||||
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
|
|
@ -62,5 +62,6 @@ void test_spdylay_session_defer_data();
|
|||
void test_spdylay_session_flow_control();
|
||||
void test_spdylay_session_on_ctrl_not_send();
|
||||
void test_spdylay_session_on_settings_received();
|
||||
void test_spdylay_submit_settings();
|
||||
|
||||
#endif // SPDYLAY_SESSION_TEST_H
|
||||
|
|
Loading…
Reference in New Issue