From 24eb3a3b36a2f3bc3e14f9ff838a1faa0bee33fd Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 1 Feb 2012 01:13:17 +0900 Subject: [PATCH] SETTINGS ID is little endian in wire format despite the fact that spec/2 says it is network byte order. --- lib/spdylay_frame.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/spdylay_frame.c b/lib/spdylay_frame.c index e4c15722..1caaf27b 100644 --- a/lib/spdylay_frame.c +++ b/lib/spdylay_frame.c @@ -690,7 +690,16 @@ ssize_t spdylay_frame_pack_settings(uint8_t **buf_ptr, spdylay_settings *frame) spdylay_put_uint32be(&framebuf[8], frame->niv); for(i = 0; i < frame->niv; ++i) { int off = i*8; - spdylay_put_uint32be(&framebuf[12+off], frame->iv[i].settings_id << 8); + /* spdy/2 spec says ID is network byte order, but publicly + deployed server sends little endian host byte order. */ + char *id_ptr = (char*)(&frame->iv[i].settings_id); +#ifdef WORDS_BIGENDIAN + framebuf[12+off] = id_ptr[3]; + framebuf[12+off+1] = id_ptr[2]; + framebuf[12+off+2] = id_ptr[1]; +#else /* !WORDS_BIGENDIAN */ + memcpy(&framebuf[12+off], id_ptr, 3); +#endif /* !WORDS_BIGENDIAN */ framebuf[15+off] = frame->iv[i].flags; spdylay_put_uint32be(&framebuf[16+off], frame->iv[i].value); } @@ -717,7 +726,16 @@ int spdylay_frame_unpack_settings(spdylay_settings *frame, } for(i = 0; i < frame->niv; ++i) { int off = i*8; - frame->iv[i].settings_id = (spdylay_get_uint32(&payload[4+off]) >> 8); + /* ID is little endian. See comments in + spdylay_frame_pack_settings(). */ + frame->iv[i].settings_id = 0; +#ifdef WORDS_BIGENDIAN + *(char*)(&frame->iv[i].settings_id[1]) = &payload[4+off+2]; + *(char*)(&frame->iv[i].settings_id[2]) = &payload[4+off+1]; + *(char*)(&frame->iv[i].settings_id[3]) = &payload[4+off+0]; +#else /* !WORDS_BIGENDIAN */ + memcpy(&frame->iv[i].settings_id, &payload[4+off], 3); +#endif /* !WORDS_BIGENDIAN */ frame->iv[i].flags = payload[7+off]; frame->iv[i].value = spdylay_get_uint32(&payload[8+off]); }