Files

63 lines
1.6 KiB
C

#include "unparser.h"
struct wsd_Unparser {
int masking;
};
wsd_Unparser *wsd_Unparser_create(int masking)
{
wsd_Unparser *unparser = calloc(1, sizeof(wsd_Unparser));
if (unparser == NULL) return NULL;
unparser->masking = masking;
return unparser;
}
void wsd_Unparser_destroy(wsd_Unparser *unparser)
{
if (unparser == NULL) return;
free(unparser);
}
wsd_Chunk *wsd_Unparser_frame(wsd_Unparser *unparser, wsd_Frame *frame)
{
size_t flen = wsd_Chunk_length(frame->payload);
size_t lenlen = (flen <= 125) ? 0 : (flen <= 65535 ? 2 : 8);
size_t masklen = unparser->masking ? 4 : 0;
size_t buflen = 2 + lenlen + masklen + flen;
uint8_t mask = 0;
wsd_Chunk *chunk = wsd_Chunk_alloc(buflen);
if (chunk == NULL) return NULL;
wsd_Chunk_set(chunk, 0, (frame->final ? WSD_FIN : 0)
| (frame->rsv1 ? WSD_RSV1 : 0)
| (frame->rsv2 ? WSD_RSV2 : 0)
| (frame->rsv3 ? WSD_RSV3 : 0)
| frame->opcode);
if (unparser->masking) {
frame->masked = 1;
wsd_Frame_mask(frame);
mask = WSD_MASK;
}
if (lenlen == 0) {
wsd_Chunk_set(chunk, 1, mask | flen);
} else if (lenlen == 2) {
wsd_Chunk_set(chunk, 1, mask | 126);
wsd_Chunk_write_uint16(chunk, 2, flen);
} else {
wsd_Chunk_set(chunk, 1, mask | 127);
wsd_Chunk_write_uint64(chunk, 2, flen);
}
wsd_Chunk_copy(frame->masking_key, 0, chunk, 2 + lenlen, masklen);
wsd_Chunk_copy(frame->payload, 0, chunk, 2 + lenlen + masklen, flen);
return chunk;
}