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]); }