diff --git a/src/ase/ase.c b/src/ase/ase.c index d72583bc..58b1407f 100644 --- a/src/ase/ase.c +++ b/src/ase/ase.c @@ -482,9 +482,9 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded) ASE_DecodedImage result = Zi; BB_Buff bb = BB_BuffFromString(encoded); - BB_Reader br = BB_ReaderFromBuffNoDebug(&bb); + BB_Reader bbr = BB_ReaderFromBuffNoDebug(&bb); ASE_Header ase_header; - BB_ReadBytes(&br, StringFromStruct(&ase_header)); + BB_ReadBytes(&bbr, StringFromStruct(&ase_header)); if (ase_header.magic != 0xA5E0) { @@ -530,7 +530,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded) for (u16 i = 0; i < ase_header.frames; ++i) { ASE_FrameHeader frame_header; - BB_ReadBytes(&br, StringFromStruct(&frame_header)); + BB_ReadBytes(&bbr, StringFromStruct(&frame_header)); u32 num_chunks = frame_header.chunks_new; if (num_chunks == 0) @@ -544,20 +544,20 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded) for (u32 j = 0; j < num_chunks; ++j) { - u32 chunk_size = BB_ReadUBits(&br, 32); - ASE_ChunkKind chunk_type = BB_ReadUBits(&br, 16); + u32 chunk_size = BB_ReadUBits(&bbr, 32); + ASE_ChunkKind chunk_type = BB_ReadUBits(&bbr, 16); // Chunk size includes size & type Assert(chunk_size >= 6); chunk_size -= 6; - u64 chunk_end_pos = BB_GetCurrentReaderByte(&br) + chunk_size; + u64 chunk_end_pos = BB_GetCurrentReaderByte(&bbr) + chunk_size; switch (chunk_type) { default: { - BB_ReadSeekToByte(&br, chunk_end_pos); + BB_ReadSeekToByte(&bbr, chunk_end_pos); } break; ////////////////////////////// @@ -569,14 +569,14 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded) layer->next = layer_head; layer_head = layer; - layer->flags = BB_ReadUBits(&br, 16); - layer->type = BB_ReadUBits(&br, 16); - layer->child_level = BB_ReadUBits(&br, 16); + layer->flags = BB_ReadUBits(&bbr, 16); + layer->type = BB_ReadUBits(&bbr, 16); + layer->child_level = BB_ReadUBits(&bbr, 16); // Ignoring layer default width & height - BB_ReadSeekBytes(&br, sizeof(u16) * 2); + BB_ReadSeekBytes(&bbr, sizeof(u16) * 2); - layer->blend_mode = BB_ReadUBits(&br, 16); + layer->blend_mode = BB_ReadUBits(&bbr, 16); if (layer->blend_mode != 0) { ASE_PushError( @@ -587,21 +587,21 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded) goto abort; } - layer->opacity = BB_ReadUBits(&br, 8); + layer->opacity = BB_ReadUBits(&bbr, 8); if (!(ase_header.flags & 1)) { layer->opacity = 255; } - BB_ReadSeekBytes(&br, sizeof(u8) * 3); + BB_ReadSeekBytes(&bbr, sizeof(u8) * 3); - u16 str_len = BB_ReadUBits(&br, 16); + u16 str_len = BB_ReadUBits(&bbr, 16); layer->name = (String) { str_len, PushStructsNoZero(scratch.arena, u8, str_len) }; - BB_ReadBytes(&br, layer->name); + BB_ReadBytes(&bbr, layer->name); if (layer->type == 2) { - layer->tileset_index = BB_ReadUBits(&br, 32); + layer->tileset_index = BB_ReadUBits(&bbr, 32); } layer->index = num_layers++; @@ -623,13 +623,13 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded) } cel_tail = cel; - cel->layer_index = BB_ReadUBits(&br, 16); - cel->x_pos = BB_ReadIBits(&br, 16); - cel->y_pos = BB_ReadIBits(&br, 16); - cel->opacity = BB_ReadUBits(&br, 8); - cel->type = BB_ReadUBits(&br, 16); - cel->z_index = BB_ReadIBits(&br, 16); - BB_ReadSeekBytes(&br, sizeof(u8) * 5); + cel->layer_index = BB_ReadUBits(&bbr, 16); + cel->x_pos = BB_ReadIBits(&bbr, 16); + cel->y_pos = BB_ReadIBits(&bbr, 16); + cel->opacity = BB_ReadUBits(&bbr, 8); + cel->type = BB_ReadUBits(&bbr, 16); + cel->z_index = BB_ReadIBits(&bbr, 16); + BB_ReadSeekBytes(&bbr, sizeof(u8) * 5); cel->frame_index = num_frames; @@ -638,22 +638,22 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded) case ASE_CelKind_RawImage: { // Unsupported - BB_ReadSeekToByte(&br, chunk_end_pos); + BB_ReadSeekToByte(&bbr, chunk_end_pos); } break; case ASE_CelKind_Linked: { - cel->frame_pos = BB_ReadUBits(&br, 16); + cel->frame_pos = BB_ReadUBits(&bbr, 16); // Actual linking happens later after iteration } break; case ASE_CelKind_CompressedImage: { - cel->width = BB_ReadUBits(&br, 16); - cel->height = BB_ReadUBits(&br, 16); + cel->width = BB_ReadUBits(&bbr, 16); + cel->height = BB_ReadUBits(&bbr, 16); cel->pixels = PushStructsNoZero(scratch.arena, u32, cel->width * cel->height); - u8 *huffman_encoded = BB_ReadBytesRaw(&br, chunk_end_pos - BB_GetCurrentReaderByte(&br)); + u8 *huffman_encoded = BB_ReadBytesRaw(&bbr, chunk_end_pos - BB_GetCurrentReaderByte(&bbr)); if (huffman_encoded) { ASE_Inflate((u8 *)cel->pixels, huffman_encoded); @@ -770,7 +770,7 @@ ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded) } // Assert all data was read - Assert(BB_NumBytesRemaining(&br) == 0); + Assert(BB_NumBytesRemaining(&bbr) == 0); abort: @@ -791,9 +791,9 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded) ASE_DecodedSheet result = Zi; BB_Buff bb = BB_BuffFromString(encoded); - BB_Reader br = BB_ReaderFromBuffNoDebug(&bb); + BB_Reader bbr = BB_ReaderFromBuffNoDebug(&bb); ASE_Header ase_header; - BB_ReadBytes(&br, StringFromStruct(&ase_header)); + BB_ReadBytes(&bbr, StringFromStruct(&ase_header)); if (ase_header.magic != 0xA5E0) { @@ -825,7 +825,7 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded) for (u16 i = 0; i < ase_header.frames; ++i) { ASE_FrameHeader frame_header; - BB_ReadBytes(&br, StringFromStruct(&frame_header)); + BB_ReadBytes(&bbr, StringFromStruct(&frame_header)); u32 num_chunks = frame_header.chunks_new; if (num_chunks == 0) @@ -857,27 +857,27 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded) for (u32 j = 0; j < num_chunks; ++j) { - u32 chunk_size = BB_ReadUBits(&br, 32); - ASE_ChunkKind chunk_type = BB_ReadUBits(&br, 16); + u32 chunk_size = BB_ReadUBits(&bbr, 32); + ASE_ChunkKind chunk_type = BB_ReadUBits(&bbr, 16); // Chunk size includes size & type Assert(chunk_size >= 6); chunk_size -= 6; - u64 chunk_end_pos = BB_GetCurrentReaderByte(&br) + chunk_size; + u64 chunk_end_pos = BB_GetCurrentReaderByte(&bbr) + chunk_size; switch (chunk_type) { default: { - BB_ReadSeekToByte(&br, chunk_end_pos); + BB_ReadSeekToByte(&bbr, chunk_end_pos); } break; //- Decode tags case ASE_ChunkKind_Tags: { - u16 frame_span_count = BB_ReadUBits(&br, 16); - BB_ReadSeekBytes(&br, 8); + u16 frame_span_count = BB_ReadUBits(&bbr, 16); + BB_ReadSeekBytes(&bbr, 8); for (u16 k = 0; k < frame_span_count; ++k) { @@ -885,13 +885,13 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded) span->next = first_span; first_span = span; - span->start = BB_ReadUBits(&br, 16); - span->end = BB_ReadUBits(&br, 16); - BB_ReadSeekBytes(&br, 13); + span->start = BB_ReadUBits(&bbr, 16); + span->end = BB_ReadUBits(&bbr, 16); + BB_ReadSeekBytes(&bbr, 13); - u16 str_len = BB_ReadUBits(&br, 16); + u16 str_len = BB_ReadUBits(&bbr, 16); span->name = (String) { str_len, PushStructsNoZero(arena, u8, str_len) }; - BB_ReadBytes(&br, span->name); + BB_ReadBytes(&bbr, span->name); ++num_spans; } @@ -907,15 +907,15 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded) slice_key->next = first_slice_key; first_slice_key = slice_key; - u32 num_slices = BB_ReadUBits(&br, 32); + u32 num_slices = BB_ReadUBits(&bbr, 32); slice_key->num_slices = num_slices; - u32 flags = BB_ReadUBits(&br, 32); - BB_ReadSeekBytes(&br, 4); + u32 flags = BB_ReadUBits(&bbr, 32); + BB_ReadSeekBytes(&bbr, 4); - u16 str_len = BB_ReadUBits(&br, 16); + u16 str_len = BB_ReadUBits(&bbr, 16); slice_key->name = (String) { str_len, PushStructsNoZero(arena, u8, str_len) }; - BB_ReadBytes(&br, slice_key->name); + BB_ReadBytes(&bbr, slice_key->name); for (u32 k = 0; k < num_slices; ++k) { @@ -923,20 +923,20 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded) slice->next = slice_key->first_slice; slice_key->first_slice = slice; - u32 start = BB_ReadUBits(&br, 32); - i32 x = BB_ReadIBits(&br, 32); - i32 y = BB_ReadIBits(&br, 32); - u32 width = BB_ReadUBits(&br, 32); - u32 height = BB_ReadUBits(&br, 32); + u32 start = BB_ReadUBits(&bbr, 32); + i32 x = BB_ReadIBits(&bbr, 32); + i32 y = BB_ReadIBits(&bbr, 32); + u32 width = BB_ReadUBits(&bbr, 32); + u32 height = BB_ReadUBits(&bbr, 32); if (flags & 0x01) { // Skip 9-patches info - BB_ReadSeekBytes(&br, 128); + BB_ReadSeekBytes(&bbr, 128); } if (flags & 0x02) { // Skip pivot info - BB_ReadSeekBytes(&br, 64); + BB_ReadSeekBytes(&bbr, 64); } slice->start = start; @@ -955,7 +955,7 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded) } // Assert all data was read - Assert(BB_NumBytesRemaining(&br) == 0); + Assert(BB_NumBytesRemaining(&bbr) == 0); result.image_size = VEC2(image_width, image_height); result.frame_size = VEC2(frame_width, frame_height); diff --git a/src/base/base_bitbuff.c b/src/base/base_bitbuff.c index e8da2387..49611a2d 100644 --- a/src/base/base_bitbuff.c +++ b/src/base/base_bitbuff.c @@ -59,46 +59,56 @@ BB_Writer BB_WriterFromBuffNoDebug(BB_Buff *bb) return result; } -// FIXME: Handle overflowed bw -u64 BB_GetNumBitsWritten(BB_Writer *bw) +void BB_ResetWriter(BB_Writer *bbw) { - return bw->cur_bit; + bbw->overflowed = 0; + bbw->cur_bit = 0; + if (bbw->bb->is_backed_by_arena) + { + ResetArena(bbw->bb->arena); + } } -// FIXME: Handle overflowed bw -u64 BB_GetNumBytesWritten(BB_Writer *bw) +// FIXME: Handle overflowed bbw +u64 BB_GetNumBitsWritten(BB_Writer *bbw) { - return (bw->cur_bit + 7) >> 3; + return bbw->cur_bit; } -// FIXME: Handle overflowed bw -String BB_GetWritten(Arena *arena, BB_Writer *bw) +// FIXME: Handle overflowed bbw +u64 BB_GetNumBytesWritten(BB_Writer *bbw) +{ + return (bbw->cur_bit + 7) >> 3; +} + +// FIXME: Handle overflowed bbw +String BB_GetWritten(Arena *arena, BB_Writer *bbw) { String result = Zi; - result.len = (bw->cur_bit + 7) >> 3; + result.len = (bbw->cur_bit + 7) >> 3; result.text = PushStructsNoZero(arena, u8, result.len); - CopyBytes(result.text, bw->base, result.len); + CopyBytes(result.text, bbw->base, result.len); return result; } -// FIXME: Handle overflowed bw -u8 *BB_GetWrittenRaw(BB_Writer *bw) +// FIXME: Handle overflowed bbw +u8 *BB_GetWrittenRaw(BB_Writer *bbw) { - return bw->base; + return bbw->base; } // Returns 1 if num_bits would cause the writer to overflow its fixed buffer size (if writer is not backed by a dynamic arena bitbuff) -b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits) +b32 BB_CheckWriterOverflowBits(BB_Writer *bbw, u64 num_bits) { b32 result = 0; - BB_Buff *bb = bw->bb; - if (bw->overflowed) + BB_Buff *bb = bbw->bb; + if (bbw->overflowed) { result = 1; } else { - u64 bytes_needed = (bw->cur_bit + num_bits + 7) >> 3; + u64 bytes_needed = (bbw->cur_bit + num_bits + 7) >> 3; if (bb->is_backed_by_arena) { Arena *arena = bb->arena; @@ -119,8 +129,8 @@ b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits) Assert(0); #endif result = 1; - bw->cur_bit = max_len << 3; - bw->overflowed = 1; + bbw->cur_bit = max_len << 3; + bbw->overflowed = 1; } } } @@ -131,74 +141,74 @@ b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits) //~ Align writer // Align the pos to the next byte -void BB_WriteAlignToNextByte(BB_Writer *bw) +void BB_WriteAlignToNextByte(BB_Writer *bbw) { #if BITBUFF_DEBUG - if ((bw->cur_bit & 7) != 0) + if ((bbw->cur_bit & 7) != 0) { - BB_WriteDebugMagic(bw, BB_DebugMagicKind_AlignNextByte, 0); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_AlignNextByte, 0); } #endif - bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7; + bbw->cur_bit += (8 - (bbw->cur_bit & 7)) & 7; } -void BB_WriteAlignBytes(BB_Writer *bw, u64 align) +void BB_WriteAlignBytes(BB_Writer *bbw, u64 align) { - BB_WriteAlignToNextByte(bw); - BB_WriteDebugMagic(bw, BB_DebugMagicKind_AlignBytes, align); + BB_WriteAlignToNextByte(bbw); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_AlignBytes, align); if (align > 0) { - u64 new_pos = (bw->cur_bit >> 3); + u64 new_pos = (bbw->cur_bit >> 3); new_pos += (align - 1); new_pos -= new_pos % align; - if (BB_CheckWriterOverflowBits(bw, (new_pos << 3) - bw->cur_bit)) + if (BB_CheckWriterOverflowBits(bbw, (new_pos << 3) - bbw->cur_bit)) { return; } - bw->cur_bit = new_pos << 3; + bbw->cur_bit = new_pos << 3; } } //////////////////////////////////////////////////////////// //~ Write bits -void BB_WriteUBitsNoMagic(BB_Writer *bw, u64 value, u8 num_bits) +void BB_WriteUBitsNoMagic(BB_Writer *bbw, u64 value, u8 num_bits) { Assert(num_bits > 0 && (num_bits == 64 || value <= ~(U64Max << num_bits))); // Bit count must be able to hold value - if (BB_CheckWriterOverflowBits(bw, num_bits)) + if (BB_CheckWriterOverflowBits(bbw, num_bits)) { return; } - u8 offset = bw->cur_bit & 7; + u8 offset = bbw->cur_bit & 7; if (offset != 0) { // Write unaligned bits - u8 *at = bw->base + (bw->cur_bit >> 3); + u8 *at = bbw->base + (bbw->cur_bit >> 3); u8 num_mix_bits = MinU8((8 - offset), num_bits); u8 mix_byte = (u8)((value & ((1 << num_mix_bits) - 1)) << offset); *at |= mix_byte; value >>= num_mix_bits; num_bits -= num_mix_bits; - bw->cur_bit += num_mix_bits; + bbw->cur_bit += num_mix_bits; } // cur_bit is now aligned to byte - u8 *at = bw->base + (bw->cur_bit >> 3); + u8 *at = bbw->base + (bbw->cur_bit >> 3); u8 num_bytes = (num_bits + 7) >> 3; CopyBytes(at, &value, num_bytes); - bw->cur_bit += num_bits; + bbw->cur_bit += num_bits; } -void BB_WriteUBits(BB_Writer *bw, u64 value, u8 num_bits) +void BB_WriteUBits(BB_Writer *bbw, u64 value, u8 num_bits) { - BB_WriteDebugMagic(bw, BB_DebugMagicKind_UBits, num_bits); - BB_WriteUBitsNoMagic(bw, value, num_bits); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_UBits, num_bits); + BB_WriteUBitsNoMagic(bbw, value, num_bits); } -void BB_WriteIBits(BB_Writer *bw, i64 value, u8 num_bits) +void BB_WriteIBits(BB_Writer *bbw, i64 value, u8 num_bits) { - BB_WriteDebugMagic(bw, BB_DebugMagicKind_IBits, num_bits); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_IBits, num_bits); u64 ubits; if (value >= 0) { @@ -208,13 +218,13 @@ void BB_WriteIBits(BB_Writer *bw, i64 value, u8 num_bits) { ubits = BB_TwosComplimentFromUint(-value, num_bits); } - BB_WriteUBits(bw, ubits, num_bits); + BB_WriteUBits(bbw, ubits, num_bits); } // Returns written bit to make writing delta encoding logic cleaner -b32 BB_WriteBit(BB_Writer *bw, u8 value) +b32 BB_WriteBit(BB_Writer *bbw, u8 value) { - BB_WriteUBits(bw, value, 1); + BB_WriteUBits(bbw, value, 1); return value; } @@ -223,24 +233,24 @@ b32 BB_WriteBit(BB_Writer *bw, u8 value) // Writes a variable length unsigned integer. // Value is written in chunks of 7 bits w/ 8th bit signaling continuation. -void BB_WriteUV(BB_Writer *bw, u64 value) +void BB_WriteUV(BB_Writer *bbw, u64 value) { - BB_WriteDebugMagic(bw, BB_DebugMagicKind_UV, 0); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_UV, 0); while (value > 0x7F) { u8 cont_byte = 0x80 | (value & 0x7F); - BB_WriteUBits(bw, cont_byte, 8); + BB_WriteUBits(bbw, cont_byte, 8); value >>= 7; } - BB_WriteUBits(bw, value, 8); + BB_WriteUBits(bbw, value, 8); } // Writes a variable length signed integer. // Similar to BB_WriteUV, except the 7th bit of the first byte is a sign bit // indicating that the value is stored in twos compliment. -void BB_WriteIV(BB_Writer *bw, i64 value) +void BB_WriteIV(BB_Writer *bbw, i64 value) { - BB_WriteDebugMagic(bw, BB_DebugMagicKind_IV, 0); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_IV, 0); u8 sign_bit; u64 tc; if (value >= 0) @@ -268,107 +278,107 @@ void BB_WriteIV(BB_Writer *bw, i64 value) tc >>= 6; first_byte |= (tc > 0) << 7; // Cont bit first_byte |= sign_bit << 6; // Sign bit - BB_WriteUBits(bw, first_byte, 8); + BB_WriteUBits(bbw, first_byte, 8); if (tc > 0) { while (tc > 0x7F) { u8 cont_byte = 0x80 | (tc & 0x7F); - BB_WriteUBits(bw, cont_byte, 8); + BB_WriteUBits(bbw, cont_byte, 8); tc >>= 7; } - BB_WriteUBits(bw, tc, 8); + BB_WriteUBits(bbw, tc, 8); } } //////////////////////////////////////////////////////////// //~ Write floating point -void BB_WriteF32(BB_Writer *bw, f32 value) +void BB_WriteF32(BB_Writer *bbw, f32 value) { - BB_WriteDebugMagic(bw, BB_DebugMagicKind_F32, 0); - BB_WriteUBits(bw, *(u32 *)&value, 32); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_F32, 0); + BB_WriteUBits(bbw, *(u32 *)&value, 32); } -void BB_WriteF64(BB_Writer *bw, f64 value) +void BB_WriteF64(BB_Writer *bbw, f64 value) { - BB_WriteDebugMagic(bw, BB_DebugMagicKind_F64, 0); - BB_WriteUBits(bw, *(u64 *)&value, 64); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_F64, 0); + BB_WriteUBits(bbw, *(u64 *)&value, 64); } //////////////////////////////////////////////////////////// //~ Write Uid -void BB_WriteUid(BB_Writer *bw, Uid value) +void BB_WriteUid(BB_Writer *bbw, Uid value) { - BB_WriteDebugMagic(bw, BB_DebugMagicKind_Uid, 128); - BB_WriteUBits(bw, value.hi, 64); - BB_WriteUBits(bw, value.lo, 64); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_Uid, 128); + BB_WriteUBits(bbw, value.hi, 64); + BB_WriteUBits(bbw, value.lo, 64); } //////////////////////////////////////////////////////////// //~ Write raw data -void BB_WriteString(BB_Writer *bw, String s) +void BB_WriteString(BB_Writer *bbw, String s) { - BB_WriteDebugMagic(bw, BB_DebugMagicKind_String, 0); - BB_WriteUV(bw, s.len); - BB_WriteBytes(bw, s); + BB_WriteDebugMagic(bbw, BB_DebugMagicKind_String, 0); + BB_WriteUV(bbw, s.len); + BB_WriteBytes(bbw, s); } -void BB_WriteBytes(BB_Writer *bw, String bytes) +void BB_WriteBytes(BB_Writer *bbw, String bytes) { // Align start of bytes - BB_WriteAlignToNextByte(bw); + BB_WriteAlignToNextByte(bbw); u64 num_bits = bytes.len << 3; - if (BB_CheckWriterOverflowBits(bw, num_bits)) + if (BB_CheckWriterOverflowBits(bbw, num_bits)) { return; } - u8 *at = bw->base + (bw->cur_bit >> 3); + u8 *at = bbw->base + (bbw->cur_bit >> 3); CopyBytes(at, bytes.text, bytes.len); - bw->cur_bit += num_bits; + bbw->cur_bit += num_bits; } -void BB_WriteSeekBytes(BB_Writer *bw, u64 num_bytes) +void BB_WriteSeekBytes(BB_Writer *bbw, u64 num_bytes) { - BB_WriteAlignToNextByte(bw); + BB_WriteAlignToNextByte(bbw); u64 num_bits = num_bytes << 3; - if (BB_CheckWriterOverflowBits(bw, num_bits)) + if (BB_CheckWriterOverflowBits(bbw, num_bits)) { return; } - bw->cur_bit += num_bits; + bbw->cur_bit += num_bits; } //////////////////////////////////////////////////////////// //~ Writer debug #if BITBUFF_DEBUG -void BB_WriteDebugMarker(BB_Writer *bw, String name) +void BB_WriteDebugMarker(BB_Writer *bbw, String name) { - bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7; + bbw->cur_bit += (8 - (bbw->cur_bit & 7)) & 7; for (u64 i = 0; i < name.len; ++i) { - BB_WriteUBitsNoMagic(bw, name.text[i], 8); + BB_WriteUBitsNoMagic(bbw, name.text[i], 8); } } -void BB_WriteDebugMagic(BB_Writer *bw, BB_DebugMagicKind magic, u8 num_bits) +void BB_WriteDebugMagic(BB_Writer *bbw, BB_DebugMagicKind magic, u8 num_bits) { - if (bw->debug_enabled) + if (bbw->debug_enabled) { - if (BB_CheckWriterOverflowBits(bw, 24)) + if (BB_CheckWriterOverflowBits(bbw, 24)) { return; } u64 magic_ubits = (u64)magic | ((u64)num_bits << 16); - BB_WriteUBitsNoMagic(bw, magic_ubits, 24); + BB_WriteUBitsNoMagic(bbw, magic_ubits, 24); } } #endif @@ -408,44 +418,44 @@ BB_Reader BB_ReaderFromBuffNoDebug(BB_Buff *bb) } // Returns the number of bits read from the bitbuff -// FIXME: Handle overflowed br -u64 BB_GetCurrentReaderBit(BB_Reader *br) +// FIXME: Handle overflowed bbr +u64 BB_GetCurrentReaderBit(BB_Reader *bbr) { - return br->cur_bit; + return bbr->cur_bit; } // Returns the number of *full* bytes read from the bitbuff -// FIXME: Handle overflowed br -u64 BB_GetCurrentReaderByte(BB_Reader *br) +// FIXME: Handle overflowed bbr +u64 BB_GetCurrentReaderByte(BB_Reader *bbr) { - return br->cur_bit >> 3; + return bbr->cur_bit >> 3; } // Returns the number of bits left until the bitbuff overflows -// FIXME: Handle overflowed br -u64 BB_NumBitsRemaining(BB_Reader *br) +// FIXME: Handle overflowed bbr +u64 BB_NumBitsRemaining(BB_Reader *bbr) { - return (br->base_len << 3) - br->cur_bit; + return (bbr->base_len << 3) - bbr->cur_bit; } // Returns the number of *full* bytes left until the bitbuff overflows -// FIXME: Handle overflowed br -u64 BB_NumBytesRemaining(BB_Reader *br) +// FIXME: Handle overflowed bbr +u64 BB_NumBytesRemaining(BB_Reader *bbr) { - return br->base_len - (br->cur_bit >> 3); + return bbr->base_len - (bbr->cur_bit >> 3); } -b32 BB_CheckReaderOverflowBits(BB_Reader *br, u64 num_bits) +b32 BB_CheckReaderOverflowBits(BB_Reader *bbr, u64 num_bits) { b32 result = 0; - if (br->overflowed) + if (bbr->overflowed) { result = 1; } else { - u64 bits_needed = br->cur_bit + num_bits; - u64 base_len_bits = br->base_len << 3; + u64 bits_needed = bbr->cur_bit + num_bits; + u64 base_len_bits = bbr->base_len << 3; if (bits_needed > base_len_bits) { // Tried to read past bitbuff memory @@ -453,8 +463,8 @@ b32 BB_CheckReaderOverflowBits(BB_Reader *br, u64 num_bits) Assert(0); #endif result = 1; - br->cur_bit = base_len_bits; - br->overflowed = 1; + bbr->cur_bit = base_len_bits; + bbr->overflowed = 1; } } return result; @@ -464,62 +474,62 @@ b32 BB_CheckReaderOverflowBits(BB_Reader *br, u64 num_bits) //~ Align reader // Align the pos to the next byte -void BB_ReadAlignToNextByte(BB_Reader *br) +void BB_ReadAlignToNextByte(BB_Reader *bbr) { #if BITBUFF_DEBUG - if ((br->cur_bit & 7) != 0) + if ((bbr->cur_bit & 7) != 0) { - BB_ReadDebugMagic(br, BB_DebugMagicKind_AlignNextByte, 0); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_AlignNextByte, 0); } #endif - br->cur_bit += (8 - (br->cur_bit & 7)) & 7; + bbr->cur_bit += (8 - (bbr->cur_bit & 7)) & 7; } -void BB_ReadAlignBytes(BB_Reader *br, u64 align) +void BB_ReadAlignBytes(BB_Reader *bbr, u64 align) { - BB_ReadAlignToNextByte(br); - BB_ReadDebugMagic(br, BB_DebugMagicKind_AlignBytes, align); + BB_ReadAlignToNextByte(bbr); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_AlignBytes, align); if (align > 0) { - u64 new_pos = (br->cur_bit >> 3); + u64 new_pos = (bbr->cur_bit >> 3); new_pos += (align - 1); new_pos -= new_pos % align; - if (BB_CheckReaderOverflowBits(br, (new_pos << 3) - br->cur_bit)) + if (BB_CheckReaderOverflowBits(bbr, (new_pos << 3) - bbr->cur_bit)) { return; } - br->cur_bit = new_pos << 3; + bbr->cur_bit = new_pos << 3; } } //////////////////////////////////////////////////////////// //~ Read bits -u64 BB_ReadUBitsNoMagic(BB_Reader *br, u8 num_bits) +u64 BB_ReadUBitsNoMagic(BB_Reader *bbr, u8 num_bits) { - if (BB_CheckReaderOverflowBits(br, num_bits)) + if (BB_CheckReaderOverflowBits(bbr, num_bits)) { return 0; } u64 result = 0; - u8 offset = br->cur_bit & 7; + u8 offset = bbr->cur_bit & 7; u8 num_trailing_bits = 0; if (offset) { - u8 *at = br->base + (br->cur_bit >> 3); + u8 *at = bbr->base + (bbr->cur_bit >> 3); num_trailing_bits = MinU8(8 - offset, num_bits); u8 mix_byte = *at; mix_byte >>= offset; mix_byte &= (1 << num_trailing_bits) - 1; result = mix_byte; num_bits -= num_trailing_bits; - br->cur_bit += num_trailing_bits; + bbr->cur_bit += num_trailing_bits; } // cur_bit is now aligned to byte - u8 *at = br->base + (br->cur_bit >> 3); + u8 *at = bbr->base + (bbr->cur_bit >> 3); u8 num_bytes = (num_bits + 7) >> 3; u64 tmp = 0; CopyBytes(&tmp, at, num_bytes); @@ -530,27 +540,27 @@ u64 BB_ReadUBitsNoMagic(BB_Reader *br, u8 num_bits) } tmp &= mask; result |= tmp << num_trailing_bits; - br->cur_bit += num_bits; + bbr->cur_bit += num_bits; return result; } -u64 BB_ReadUBits(BB_Reader *br, u8 num_bits) +u64 BB_ReadUBits(BB_Reader *bbr, u8 num_bits) { - BB_ReadDebugMagic(br, BB_DebugMagicKind_UBits, num_bits); - return BB_ReadUBitsNoMagic(br, num_bits); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_UBits, num_bits); + return BB_ReadUBitsNoMagic(bbr, num_bits); } -i64 BB_ReadIBits(BB_Reader *br, u8 num_bits) +i64 BB_ReadIBits(BB_Reader *bbr, u8 num_bits) { Assert(num_bits > 1); - BB_ReadDebugMagic(br, BB_DebugMagicKind_IBits, num_bits); - u64 tc = BB_ReadUBits(br, num_bits); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_IBits, num_bits); + u64 tc = BB_ReadUBits(bbr, num_bits); return BB_IntFromTwosCompliment(tc, num_bits); } -u8 BB_ReadBit(BB_Reader *br) +u8 BB_ReadBit(BB_Reader *bbr) { - return BB_ReadUBits(br, 1); + return BB_ReadUBits(bbr, 1); } //////////////////////////////////////////////////////////// @@ -558,14 +568,14 @@ u8 BB_ReadBit(BB_Reader *br) // Read a variable length unsigned integer. // See BB_WriteUV for details. -u64 BB_ReadUV(BB_Reader *br) +u64 BB_ReadUV(BB_Reader *bbr) { - BB_ReadDebugMagic(br, BB_DebugMagicKind_UV, 0); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_UV, 0); u64 result = 0; for (u64 i = 0; i <= 9; ++i) { - u64 part = BB_ReadUBits(br, 8); + u64 part = BB_ReadUBits(bbr, 8); u8 is_last_part = part <= 0x7F; result |= (part & 0x7F) << (i * 7); if (is_last_part) @@ -578,10 +588,10 @@ u64 BB_ReadUV(BB_Reader *br) // Read a variable length signed integer. // See BB_WriteIV for details. -i64 BB_ReadIV(BB_Reader *br) +i64 BB_ReadIV(BB_Reader *bbr) { - BB_ReadDebugMagic(br, BB_DebugMagicKind_IV, 0); - u8 first_byte = BB_ReadUBits(br, 8); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_IV, 0); + u8 first_byte = BB_ReadUBits(bbr, 8); u8 cont_bit = first_byte & 0x80; u8 sign_bit = first_byte & 0x40; @@ -591,7 +601,7 @@ i64 BB_ReadIV(BB_Reader *br) { for (u64 i = 0; i <= 9; ++i) { - u64 part = BB_ReadUBits(br, 8); + u64 part = BB_ReadUBits(bbr, 8); u8 is_last_part = part <= 0x7F; tc |= (part & 0x7F) << num_bits; num_bits += 7; @@ -620,40 +630,40 @@ i64 BB_ReadIV(BB_Reader *br) //////////////////////////////////////////////////////////// //~ Read floating point -f32 BB_ReadF32(BB_Reader *br) +f32 BB_ReadF32(BB_Reader *bbr) { - BB_ReadDebugMagic(br, BB_DebugMagicKind_F32, 0); - u32 ubits = BB_ReadUBits(br, 32); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_F32, 0); + u32 ubits = BB_ReadUBits(bbr, 32); return *(f32 *)&ubits; } -f64 BB_ReadF64(BB_Reader *br) +f64 BB_ReadF64(BB_Reader *bbr) { - BB_ReadDebugMagic(br, BB_DebugMagicKind_F64, 0); - u64 ubits = BB_ReadUBits(br, 64); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_F64, 0); + u64 ubits = BB_ReadUBits(bbr, 64); return *(f64 *)&ubits; } //////////////////////////////////////////////////////////// //~ Read Uid -Uid BB_ReadUid(BB_Reader *br) +Uid BB_ReadUid(BB_Reader *bbr) { - BB_ReadDebugMagic(br, BB_DebugMagicKind_Uid, 128); - u64 hi = BB_ReadUBits(br, 64); - u64 lo = BB_ReadUBits(br, 64); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_Uid, 128); + u64 hi = BB_ReadUBits(bbr, 64); + u64 lo = BB_ReadUBits(bbr, 64); return UID(hi, lo); } //////////////////////////////////////////////////////////// //~ Read raw data -String BB_ReadString(Arena *arena, BB_Reader *br) +String BB_ReadString(Arena *arena, BB_Reader *bbr) { - BB_ReadDebugMagic(br, BB_DebugMagicKind_String, 0); + BB_ReadDebugMagic(bbr, BB_DebugMagicKind_String, 0); String result = Zi; - u64 len = BB_ReadUV(br); - u8 *src = BB_ReadBytesRaw(br, len); + u64 len = BB_ReadUV(bbr); + u8 *src = BB_ReadBytesRaw(bbr, len); if (src != 0) { result.len = len; @@ -664,9 +674,9 @@ String BB_ReadString(Arena *arena, BB_Reader *br) } // Will fill dst with zeroes if bitbuff overflows -void BB_ReadBytes(BB_Reader *br, String out) +void BB_ReadBytes(BB_Reader *bbr, String out) { - u8 *src = BB_ReadBytesRaw(br, out.len); + u8 *src = BB_ReadBytesRaw(bbr, out.len); if (src) { CopyBytes(out.text, src, out.len); @@ -678,48 +688,48 @@ void BB_ReadBytes(BB_Reader *br, String out) } // Will return 0 on bitbuff overflow. Result should be checked. -u8 *BB_ReadBytesRaw(BB_Reader *br, u64 num_bytes) +u8 *BB_ReadBytesRaw(BB_Reader *bbr, u64 num_bytes) { - BB_ReadAlignToNextByte(br); + BB_ReadAlignToNextByte(bbr); u64 num_bits = num_bytes << 3; - if (BB_CheckReaderOverflowBits(br, num_bits)) + if (BB_CheckReaderOverflowBits(bbr, num_bits)) { return 0; } - u8 *raw = br->base + (br->cur_bit >> 3); - br->cur_bit += num_bits; + u8 *raw = bbr->base + (bbr->cur_bit >> 3); + bbr->cur_bit += num_bits; return raw; } -void BB_ReadSeekBytes(BB_Reader *br, u64 num_bytes) +void BB_ReadSeekBytes(BB_Reader *bbr, u64 num_bytes) { - BB_ReadAlignToNextByte(br); + BB_ReadAlignToNextByte(bbr); u64 num_bits = num_bytes << 3; - if (BB_CheckReaderOverflowBits(br, num_bits)) + if (BB_CheckReaderOverflowBits(bbr, num_bits)) { return; } - br->cur_bit += num_bits; + bbr->cur_bit += num_bits; } -void BB_ReadSeekToByte(BB_Reader *br, u64 pos) +void BB_ReadSeekToByte(BB_Reader *bbr, u64 pos) { - u64 cur_byte_pos = br->cur_bit >> 3; + u64 cur_byte_pos = bbr->cur_bit >> 3; if (pos >= cur_byte_pos) { - BB_ReadSeekBytes(br, pos - cur_byte_pos); + BB_ReadSeekBytes(bbr, pos - cur_byte_pos); } else { // Tried to seek byte backwards in reader Assert(0); - br->overflowed = 1; - br->cur_bit = (br->base_len << 3); + bbr->overflowed = 1; + bbr->cur_bit = (bbr->base_len << 3); } } @@ -728,15 +738,15 @@ void BB_ReadSeekToByte(BB_Reader *br, u64 pos) #if BITBUFF_DEBUG -void BB_ReadDebugMagic(BB_Reader *br, BB_DebugMagicKind expected_magic, u8 expected_num_bits) +void BB_ReadDebugMagic(BB_Reader *bbr, BB_DebugMagicKind expected_magic, u8 expected_num_bits) { - if (br->debug_enabled) + if (bbr->debug_enabled) { - if (BB_CheckReaderOverflowBits(br, 24)) + if (BB_CheckReaderOverflowBits(bbr, 24)) { return; } - u64 stored = BB_ReadUBitsNoMagic(br, 24); + u64 stored = BB_ReadUBitsNoMagic(bbr, 24); BB_DebugMagicKind stored_magic = stored & 0xFFFF; u8 stored_num_bits = (stored >> 16) & 0xFF; @@ -748,12 +758,12 @@ void BB_ReadDebugMagic(BB_Reader *br, BB_DebugMagicKind expected_magic, u8 expec } } -void BB_ReadDebugMarker(BB_Reader *br, String name) +void BB_ReadDebugMarker(BB_Reader *bbr, String name) { - br->cur_bit += (8 - (br->cur_bit & 7)) & 7; + bbr->cur_bit += (8 - (bbr->cur_bit & 7)) & 7; for (u64 i = 0; i < name.len; ++i) { - u8 c_stored = BB_ReadUBitsNoMagic(br, 8); + u8 c_stored = BB_ReadUBitsNoMagic(bbr, 8); u8 c_expected = name.text[i]; Assert(c_expected == c_stored); } @@ -858,72 +868,72 @@ void BB_Test(void) String encoded = Zi; { BB_Buff bb = BB_AcquireDynamicBuff(Gibi(64)); - BB_Writer bw = BB_WriterFromBuff(&bb); + BB_Writer bbw = BB_WriterFromBuff(&bb); for (u64 i = 0; i < countof(cases); ++i) { struct test_case c = cases[i]; if (c.kind == kind_ubits) { - BB_WriteUBits(&bw, c.ubits.v, c.ubits.num_bits); + BB_WriteUBits(&bbw, c.ubits.v, c.ubits.num_bits); } else if (c.kind == kind_ibits) { - BB_WriteIBits(&bw, c.ibits.v, c.ibits.num_bits); + BB_WriteIBits(&bbw, c.ibits.v, c.ibits.num_bits); } else if (c.kind == kind_uv) { - BB_WriteUV(&bw, c.uv.v); + BB_WriteUV(&bbw, c.uv.v); } else if (c.kind == kind_iv) { - BB_WriteIV(&bw, c.iv.v); + BB_WriteIV(&bbw, c.iv.v); } else if (c.kind == kind_string) { - BB_WriteString(&bw, c.s.v); + BB_WriteString(&bbw, c.s.v); } else { Assert(0); } } - encoded = BB_GetWritten(scratch.arena, &bw); + encoded = BB_GetWritten(scratch.arena, &bbw); } { BB_Buff bb = BB_BuffFromString(encoded); - BB_Reader br = BB_ReaderFromBuff(&bb); + BB_Reader bbr = BB_ReaderFromBuff(&bb); for (u64 i = 0; i < countof(cases); ++i) { struct test_case c = cases[i]; if (c.kind == kind_ubits) { u64 w = c.ubits.v; - u64 r = BB_ReadUBits(&br, c.ubits.num_bits); + u64 r = BB_ReadUBits(&bbr, c.ubits.num_bits); Assert(r == w); } else if (c.kind == kind_ibits) { i64 w = c.ibits.v; - i64 r = BB_ReadIBits(&br, c.ubits.num_bits); + i64 r = BB_ReadIBits(&bbr, c.ubits.num_bits); Assert(r == w); } else if (c.kind == kind_uv) { u64 w = c.uv.v; - u64 r = BB_ReadUV(&br); + u64 r = BB_ReadUV(&bbr); Assert(r == w); } else if (c.kind == kind_iv) { i64 w = c.iv.v; - i64 r = BB_ReadIV(&br); + i64 r = BB_ReadIV(&bbr); Assert(r == w); } else if (c.kind == kind_string) { String w = c.s.v; - String r = BB_ReadString(scratch.arena, &br); + String r = BB_ReadString(scratch.arena, &bbr); Assert(MatchString(r, w)); } else diff --git a/src/base/base_bitbuff.h b/src/base/base_bitbuff.h index a5db19a8..b476bef6 100644 --- a/src/base/base_bitbuff.h +++ b/src/base/base_bitbuff.h @@ -74,52 +74,54 @@ BB_Buff BB_BuffFromString(String s); BB_Writer BB_WriterFromBuff(BB_Buff *bb); BB_Writer BB_WriterFromBuffNoDebug(BB_Buff *bb); -u64 BB_GetNumBitsWritten(BB_Writer *bw); -u64 BB_GetNumBytesWritten(BB_Writer *bw); +void BB_ResetWriter(BB_Writer *bbw); -String BB_GetWritten(Arena *arena, BB_Writer *bw); -u8 *BB_GetWrittenRaw(BB_Writer *bw); +u64 BB_GetNumBitsWritten(BB_Writer *bbw); +u64 BB_GetNumBytesWritten(BB_Writer *bbw); -b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits); +String BB_GetWritten(Arena *arena, BB_Writer *bbw); +u8 *BB_GetWrittenRaw(BB_Writer *bbw); + +b32 BB_CheckWriterOverflowBits(BB_Writer *bbw, u64 num_bits); //////////////////////////////////////////////////////////// //~ Writer ops //- Align -void BB_WriteAlignToNextByte(BB_Writer *bw); -void BB_WriteAlignBytes(BB_Writer *bw, u64 align); +void BB_WriteAlignToNextByte(BB_Writer *bbw); +void BB_WriteAlignBytes(BB_Writer *bbw, u64 align); //- Bits -void BB_WriteUBitsNoMagic(BB_Writer *bw, u64 value, u8 num_bits); -void BB_WriteUBits(BB_Writer *bw, u64 value, u8 num_bits); -void BB_WriteIBits(BB_Writer *bw, i64 value, u8 num_bits); -b32 BB_WriteBit(BB_Writer *bw, u8 value); +void BB_WriteUBitsNoMagic(BB_Writer *bbw, u64 value, u8 num_bits); +void BB_WriteUBits(BB_Writer *bbw, u64 value, u8 num_bits); +void BB_WriteIBits(BB_Writer *bbw, i64 value, u8 num_bits); +b32 BB_WriteBit(BB_Writer *bbw, u8 value); //- Variable length integers -void BB_WriteUV(BB_Writer *bw, u64 value); -void BB_WriteIV(BB_Writer *bw, i64 value); +void BB_WriteUV(BB_Writer *bbw, u64 value); +void BB_WriteIV(BB_Writer *bbw, i64 value); //- Floating point -void BB_WriteF32(BB_Writer *bw, f32 value); -void BB_WriteF64(BB_Writer *bw, f64 value); +void BB_WriteF32(BB_Writer *bbw, f32 value); +void BB_WriteF64(BB_Writer *bbw, f64 value); //- Uid -void BB_WriteUid(BB_Writer *bw, Uid value); +void BB_WriteUid(BB_Writer *bbw, Uid value); //- Raw data -void BB_WriteString(BB_Writer *bw, String s); -void BB_WriteBytes(BB_Writer *bw, String bytes); -void BB_WriteSeekBytes(BB_Writer *bw, u64 num_bytes); +void BB_WriteString(BB_Writer *bbw, String s); +void BB_WriteBytes(BB_Writer *bbw, String bytes); +void BB_WriteSeekBytes(BB_Writer *bbw, u64 num_bytes); //////////////////////////////////////////////////////////// //~ Writer debug #if BITBUFF_DEBUG - void BB_WriteDebugMagic(BB_Writer *bw, BB_DebugMagicKind magic, u8 num_bits); - void BB_WriteDebugMarker(BB_Writer *bw, String name); + void BB_WriteDebugMagic(BB_Writer *bbw, BB_DebugMagicKind magic, u8 num_bits); + void BB_WriteDebugMarker(BB_Writer *bbw, String name); #else - #define BB_WriteDebugMagic(bw, magic, num_bits) - #define BB_WriteDebugMarker(bw, name) + #define BB_WriteDebugMagic(bbw, magic, num_bits) + #define BB_WriteDebugMarker(bbw, name) #endif //////////////////////////////////////////////////////////// @@ -128,54 +130,54 @@ void BB_WriteSeekBytes(BB_Writer *bw, u64 num_bytes); BB_Reader BB_ReaderFromBuff(BB_Buff *bb); BB_Reader BB_ReaderFromBuffNoDebug(BB_Buff *bb); -u64 BB_GetCurrentReaderBit(BB_Reader *br); -u64 BB_GetCurrentReaderByte(BB_Reader *br); +u64 BB_GetCurrentReaderBit(BB_Reader *bbr); +u64 BB_GetCurrentReaderByte(BB_Reader *bbr); -u64 BB_NumBitsRemaining(BB_Reader *br); -u64 BB_NumBytesRemaining(BB_Reader *br); +u64 BB_NumBitsRemaining(BB_Reader *bbr); +u64 BB_NumBytesRemaining(BB_Reader *bbr); -b32 BB_CheckReaderOverflowBits(BB_Reader *br, u64 num_bits); +b32 BB_CheckReaderOverflowBits(BB_Reader *bbr, u64 num_bits); //////////////////////////////////////////////////////////// //~ Reader ops //- Align -void BB_ReadAlignToNextByte(BB_Reader *br); -void BB_ReadAlignBytes(BB_Reader *br, u64 align); +void BB_ReadAlignToNextByte(BB_Reader *bbr); +void BB_ReadAlignBytes(BB_Reader *bbr, u64 align); //- Bits -u64 BB_ReadUBitsNoMagic(BB_Reader *br, u8 num_bits); -u64 BB_ReadUBits(BB_Reader *br, u8 num_bits); -i64 BB_ReadIBits(BB_Reader *br, u8 num_bits); -u8 BB_ReadBit(BB_Reader *br); +u64 BB_ReadUBitsNoMagic(BB_Reader *bbr, u8 num_bits); +u64 BB_ReadUBits(BB_Reader *bbr, u8 num_bits); +i64 BB_ReadIBits(BB_Reader *bbr, u8 num_bits); +u8 BB_ReadBit(BB_Reader *bbr); //- Variable length integers -u64 BB_ReadUV(BB_Reader *br); -i64 BB_ReadIV(BB_Reader *br); +u64 BB_ReadUV(BB_Reader *bbr); +i64 BB_ReadIV(BB_Reader *bbr); //- Floating point -f32 BB_ReadF32(BB_Reader *br); -f64 BB_ReadF64(BB_Reader *br); +f32 BB_ReadF32(BB_Reader *bbr); +f64 BB_ReadF64(BB_Reader *bbr); //- Uid -Uid BB_ReadUid(BB_Reader *br); +Uid BB_ReadUid(BB_Reader *bbr); //- Raw data -String BB_ReadString(Arena *arena, BB_Reader *br); -void BB_ReadBytes(BB_Reader *br, String dst); -u8 *BB_ReadBytesRaw(BB_Reader *br, u64 num_bytes); -void BB_ReadSeekBytes(BB_Reader *br, u64 num_bytes); -void BB_ReadSeekToByte(BB_Reader *br, u64 pos); +String BB_ReadString(Arena *arena, BB_Reader *bbr); +void BB_ReadBytes(BB_Reader *bbr, String dst); +u8 *BB_ReadBytesRaw(BB_Reader *bbr, u64 num_bytes); +void BB_ReadSeekBytes(BB_Reader *bbr, u64 num_bytes); +void BB_ReadSeekToByte(BB_Reader *bbr, u64 pos); //////////////////////////////////////////////////////////// //~ Reader debug #if BITBUFF_DEBUG -void BB_ReadDebugMagic(BB_Reader *br, BB_DebugMagicKind expected_magic, u8 expected_num_bits); -void BB_ReadDebugMarker(BB_Reader *br, String name); +void BB_ReadDebugMagic(BB_Reader *bbr, BB_DebugMagicKind expected_magic, u8 expected_num_bits); +void BB_ReadDebugMarker(BB_Reader *bbr, String name); #else -#define BB_ReadDebugMagic(br, expected_magic, expected_num_bits) -#define BB_ReadDebugMarker(br, name) +#define BB_ReadDebugMagic(bbr, expected_magic, expected_num_bits) +#define BB_ReadDebugMarker(bbr, name) #endif //////////////////////////////////////////////////////////// diff --git a/src/base/base_resource.c b/src/base/base_resource.c index c7e1ae07..f538c46a 100644 --- a/src/base/base_resource.c +++ b/src/base/base_resource.c @@ -10,20 +10,20 @@ void BootstrapResources(u64 archive_strings_count, String *archive_strings) if (archive.len > 0) { BB_Buff bb = BB_BuffFromString(archive); - BB_Reader br = BB_ReaderFromBuff(&bb); + BB_Reader bbr = BB_ReaderFromBuff(&bb); - u64 magic = BB_ReadUBits(&br, 64); + u64 magic = BB_ReadUBits(&bbr, 64); Assert(magic == ResourceEmbeddedMagic); // Create & insert entries - u64 num_entries = BB_ReadUBits(&br, 64); + u64 num_entries = BB_ReadUBits(&bbr, 64); for (u64 i = 0; i < num_entries; ++i) { - u64 store_hash = BB_ReadUBits(&br, 64); - u64 name_start = BB_ReadUBits(&br, 64); - u64 name_len = BB_ReadUBits(&br, 64); - u64 data_start = BB_ReadUBits(&br, 64); - u64 data_len = BB_ReadUBits(&br, 64); + u64 store_hash = BB_ReadUBits(&bbr, 64); + u64 name_start = BB_ReadUBits(&bbr, 64); + u64 name_len = BB_ReadUBits(&bbr, 64); + u64 data_start = BB_ReadUBits(&bbr, 64); + u64 data_len = BB_ReadUBits(&bbr, 64); ResourceEntry *entry = PushStruct(perm, ResourceEntry); entry->name = STRING(name_len, archive.text + name_start); diff --git a/src/meta/meta.c b/src/meta/meta.c index d4992155..80336c2c 100644 --- a/src/meta/meta.c +++ b/src/meta/meta.c @@ -155,13 +155,13 @@ EmbedObj Embed(String store_name, String dir_path) // TODO: Cache dynamic bitbuffs? BB_Buff bb = BB_AcquireDynamicBuff(Gibi(2)); - BB_Writer bw = BB_WriterFromBuff(&bb); + BB_Writer bbw = BB_WriterFromBuff(&bb); // Write magic - BB_WriteUBits(&bw, ResourceEmbeddedMagic, 64); + BB_WriteUBits(&bbw, ResourceEmbeddedMagic, 64); // Write header - BB_WriteUBits(&bw, entries_count, 64); + BB_WriteUBits(&bbw, entries_count, 64); // Reserve entries space u64 entry_size = 0 @@ -170,10 +170,10 @@ EmbedObj Embed(String store_name, String dir_path) + 8 // Name end + 8 // Data start + 8; // Data end - u8 *entries_start = BB_GetWrittenRaw(&bw) + BB_GetNumBytesWritten(&bw); + u8 *entries_start = BB_GetWrittenRaw(&bbw) + BB_GetNumBytesWritten(&bbw); u64 entries_size = entry_size * entries_count; String entries_str = STRING(entries_size, entries_start); - BB_WriteSeekBytes(&bw, entries_size); + BB_WriteSeekBytes(&bbw, entries_size); BB_Buff entries_bb = BB_BuffFromString(entries_str); BB_Writer entries_bw = BB_WriterFromBuff(&entries_bb); @@ -184,17 +184,17 @@ EmbedObj Embed(String store_name, String dir_path) String file_data = F_DataFromFile(perm, en->file_name); // Write name - BB_WriteAlignBytes(&bw, 64); - u64 name_start = BB_GetNumBytesWritten(&bw) + 1; - BB_WriteString(&bw, en->entry_name); - u64 name_len = BB_GetNumBytesWritten(&bw) - name_start; + BB_WriteAlignBytes(&bbw, 64); + u64 name_start = BB_GetNumBytesWritten(&bbw) + 1; + BB_WriteString(&bbw, en->entry_name); + u64 name_len = BB_GetNumBytesWritten(&bbw) - name_start; // Write data - BB_WriteAlignBytes(&bw, 64); + BB_WriteAlignBytes(&bbw, 64); // FIXME: Why no +1 here? - u64 data_start = BB_GetNumBytesWritten(&bw); - BB_WriteBytes(&bw, file_data); - u64 data_len = BB_GetNumBytesWritten(&bw) - data_start; + u64 data_start = BB_GetNumBytesWritten(&bbw); + BB_WriteBytes(&bbw, file_data); + u64 data_len = BB_GetNumBytesWritten(&bbw) - data_start; // Write entry BB_WriteUBits(&entries_bw, store_hash, 64); @@ -204,8 +204,8 @@ EmbedObj Embed(String store_name, String dir_path) BB_WriteUBits(&entries_bw, data_len, 64); } - arc_contents.len = BB_GetNumBytesWritten(&bw); - arc_contents.text = BB_GetWrittenRaw(&bw); + arc_contents.len = BB_GetNumBytesWritten(&bbw); + arc_contents.text = BB_GetWrittenRaw(&bbw); } // Write archive to file diff --git a/src/net/net.h b/src/net/net.h index a82b6c3b..ffdcaf3f 100644 --- a/src/net/net.h +++ b/src/net/net.h @@ -58,6 +58,9 @@ void NET_Bootstrap(void); //~ @hookdecl Net ops NET_Key NET_KeyFromString(String host, String port); +String NET_StringFromKey(Arena *arena, NET_Key key); +b32 NET_MatchKey(NET_Key a, NET_Key b); +u64 NET_HashFromKey(NET_Key key); NET_PipeHandle NET_AcquirePipe(void); diff --git a/src/net/net_win32/net_win32.c b/src/net/net_win32/net_win32.c index 992431bd..8e596b36 100644 --- a/src/net/net_win32/net_win32.c +++ b/src/net/net_win32/net_win32.c @@ -87,12 +87,6 @@ struct sockaddr_in6 NET_W32_AddressFromKey(NET_Key key) return result; } -u64 NET_W32_HashFromKey(NET_Key key) -{ - u64 result = HashString(StringFromStruct(&key)); - return result; -} - void NET_W32_SignalWorker(void) { i32 err = sendto( @@ -109,7 +103,7 @@ NET_W32_Peer *NET_W32_TouchPeerFromKey(NET_W32_Pipe *pipe, NET_Key key) { // TODO: Address challenge on first receive NET_W32_Peer *peer = 0; - u64 hash = NET_W32_HashFromKey(key); + u64 hash = NET_HashFromKey(key); NET_W32_PeerBin *bin = &pipe->peer_bins[hash % pipe->peer_bins_count]; peer = bin->first; for (; peer; peer = peer->next_in_bin) @@ -168,40 +162,71 @@ NET_Key NET_KeyFromString(String host, String port) NET_Key result = Zi; TempArena scratch = BeginScratchNoConflict(); { - struct addrinfo hints = Zi; - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_protocol = IPPROTO_UDP; - hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; - char *host_cstr = CstrFromString(scratch.arena, host); - char *port_cstr = CstrFromString(scratch.arena, port); + i64 port_i64 = CR_IntFromString(port); + if (port_i64 < 0 || port_i64 >= Kibi(64)) + { + port_i64 = 0; + } struct sockaddr_in6 addr = Zi; + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(port_i64); + + if (InetPtonA(AF_INET6, host_cstr, &addr.sin6_addr) != 1) { - struct addrinfo *first_ai = 0; - if (getaddrinfo(host_cstr, port_cstr, &hints, &first_ai) == 0) + IN_ADDR v4 = Zi; + if (InetPtonA(AF_INET, host_cstr, &v4) == 1) { - for (struct addrinfo *ai = first_ai; ai; ai = ai->ai_next) - { - if (ai->ai_family == AF_INET6 && ai->ai_addrlen >= sizeof(addr)) - { - CopyBytes(&addr, ai->ai_addr, sizeof(addr)); - break; - } - } - } - if (first_ai) - { - freeaddrinfo(first_ai); + ZeroStruct(&addr.sin6_addr); + addr.sin6_addr.u.Byte[10] = 0xFF; + addr.sin6_addr.u.Byte[11] = 0xFF; + CopyBytes(&addr.sin6_addr.u.Byte[12], &v4, 4); } } + result = NET_W32_KeyFromAddress(addr); } EndScratch(scratch); return result; } +String NET_StringFromKey(Arena *arena, NET_Key key) +{ + String result = Zi; + struct sockaddr_in6 sin6 = NET_W32_AddressFromKey(key); + char addr_chars[INET6_ADDRSTRLEN]; + u32 port = ntohs(sin6.sin6_port); + if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) + { + struct in_addr v4 = Zi; + CopyBytes(&v4, &sin6.sin6_addr.s6_addr[12], sizeof(v4)); + if (InetNtopA(AF_INET, &v4, addr_chars, (DWORD)sizeof(addr_chars))) + { + result = StringF(arena, "%F:%F", FmtString(StringFromCstr(addr_chars, countof(addr_chars))), FmtUint(port)); + } + } + else + { + if (InetNtopA(AF_INET6, &sin6.sin6_addr, addr_chars, (DWORD)sizeof(addr_chars))) + { + result = StringF(arena, "[%F]:%F", FmtString(StringFromCstr(addr_chars, countof(addr_chars))), FmtUint(port)); + } + } + return result; +} + +b32 NET_MatchKey(NET_Key a, NET_Key b) +{ + return MatchStruct(&a, &b); +} + +u64 NET_HashFromKey(NET_Key key) +{ + u64 result = HashString(StringFromStruct(&key)); + return result; +} + NET_PipeHandle NET_AcquirePipe(void) { Arena *perm = PermArena(); @@ -432,7 +457,7 @@ void NET_W32_TickForever(WaveLaneCtx *lane) hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol= IPPROTO_UDP; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; struct addrinfo *ai = 0; if (ok) { @@ -772,11 +797,11 @@ void NET_W32_TickForever(WaveLaneCtx *lane) msg_data.text = ArenaNext(msg_buff->arena, u8); msg_data.len = 0; - LogSuccessF( - "Assembled msg with msg seq: %F, data (%F bytes)", - FmtSint(packet->msg_seq), - FmtUint(msg->data.len) - ); + // LogSuccessF( + // "Assembled msg with msg seq: %F, data (%F bytes)", + // FmtSint(packet->msg_seq), + // FmtUint(msg->data.len) + // ); } } else diff --git a/src/net/net_win32/net_win32.h b/src/net/net_win32/net_win32.h index 7fe485af..d92de128 100644 --- a/src/net/net_win32/net_win32.h +++ b/src/net/net_win32/net_win32.h @@ -178,7 +178,6 @@ NET_W32_DummySocket NET_W32_CreateDummySocket(void); NET_W32_Pipe *NET_W32_PipeFromHandle(NET_PipeHandle pipe_handle); NET_Key NET_W32_KeyFromAddress(struct sockaddr_in6 addr); struct sockaddr_in6 NET_W32_AddressFromKey(NET_Key key); -u64 NET_W32_HashFromKey(NET_Key key); void NET_W32_SignalWorker(void); NET_W32_Peer *NET_W32_TouchPeerFromKey(NET_W32_Pipe *pipe, NET_Key key); u32 NET_W32_ChecksumFromString(String str); diff --git a/src/net_old/net_old.c b/src/net_old/net_old.c deleted file mode 100644 index 495814a5..00000000 --- a/src/net_old/net_old.c +++ /dev/null @@ -1,1075 +0,0 @@ -// TODO: -// -// Rate limiting. -// -// Resequence buffer to order incoming sequenced packets. -// -// Rolling window for message reassembly. -// This would remove the need for random access message buffers. -// -// Connection timeouts. -// -// Challenges to verify receiving address. - -//////////////////////////////////////////////////////////// -//~ Host - -N_Host *N_AcquireHost(u16 listen_port) -{ - Arena *arena = AcquireArena(Gibi(64)); - N_Host *host = PushStruct(arena, N_Host); - - host->arena = arena; - host->cmd_arena = AcquireArena(Gibi(64)); - host->channel_arena = AcquireArena(Gibi(64)); - host->rcv_buffer_read = PushStruct(host->arena, N_RcvBuffer); - host->rcv_buffer_write = PushStruct(host->arena, N_RcvBuffer); - host->rcv_buffer_read->arena = AcquireArena(Gibi(64)); - host->rcv_buffer_write->arena = AcquireArena(Gibi(64)); - host->buddy = AcquireBuddyCtx(Gibi(64)); - - host->channels = ArenaNext(host->channel_arena, N_Channel); - - host->num_channel_lookup_bins = N_NumChannelLookupBins; - host->channel_lookup_bins = PushStructs(host->arena, N_ChannelLookupBin, host->num_channel_lookup_bins); - - host->num_msg_assembler_lookup_bins = N_NumMsgAssemblerLookupBins; - host->msg_assembler_lookup_bins = PushStructs(host->arena, N_MsgAssemblerLookupBin, host->num_msg_assembler_lookup_bins); - - host->sock = PLT_AcquireSock(listen_port, Mebi(2), Mebi(2)); - - return host; -} - -void N_ReleaseHost(N_Host *host) -{ - PLT_ReleaseSock(host->sock); - - ReleaseBuddyCtx(host->buddy); - ReleaseArena(host->rcv_buffer_write->arena); - ReleaseArena(host->rcv_buffer_read->arena); - ReleaseArena(host->channel_arena); - ReleaseArena(host->cmd_arena); - ReleaseArena(host->arena); -} - -//////////////////////////////////////////////////////////// -//~ Channel - -u64 N_HashFromAddress(PLT_Address address) -{ - return HashString(StringFromStruct(&address)); -} - -N_Channel *N_ChannelFromAddress(N_Host *host, PLT_Address address) -{ - u64 hash = N_HashFromAddress(address); - N_ChannelLookupBin *bin = &host->channel_lookup_bins[hash % host->num_channel_lookup_bins]; - for (N_Channel *channel = bin->first; channel; channel = channel->next_address_hash) - { - if (channel->address_hash == hash && PLT_MatchAddress(channel->address, address)) - { - return channel; - } - } - return &N_nil_channel; -} - -// Returns nil channel if id = N_AllChannelsId -N_Channel *N_ChannelFromId(N_Host *host, N_ChannelId channel_id) -{ - if (channel_id.gen > 0 && channel_id.idx < host->num_channels_reserved) - { - N_Channel *channel = &host->channels[channel_id.idx]; - if (channel->id.gen == channel_id.gen) - { - return channel; - } - } - return &N_nil_channel; -} - -N_ChannelList N_ChannelsFromId(Arena *arena, N_Host *host, N_ChannelId channel_id) -{ - N_ChannelList result = ZI; - if (N_MatchChannelId(channel_id, N_AllChannelsId)) - { - for (u64 i = 0; i < host->num_channels_reserved; ++i) - { - N_Channel *channel = &host->channels[i]; - if (channel->valid) - { - N_ChannelNode *n = PushStruct(arena, N_ChannelNode); - n->channel = channel; - if (result.last) - { - result.last->next = n; - } - else - { - result.first = n; - } - result.last = n; - } - } - } - else - { - N_Channel *channel = N_ChannelFromId(host, channel_id); - if (channel->valid) - { - N_ChannelNode *n = PushStruct(arena, N_ChannelNode); - n->channel = channel; - result.first = n; - result.last = n; - } - } - return result; -} - -N_Channel *N_AcquireChannel(N_Host *host, PLT_Address address) -{ - N_ChannelId id = ZI; - N_Channel *channel; - if (host->first_free_channel) - { - channel = host->first_free_channel; - host->first_free_channel = channel->next_free; - id = channel->id; - ++id.gen; - } - else - { - channel = PushStructNoZero(host->channel_arena, N_Channel); - id.gen = 1; - id.idx = host->num_channels_reserved; - ++host->num_channels_reserved; - } - ZeroStruct(channel); - channel->valid = 1; - channel->id = id; - channel->host = host; - channel->address = address; - u64 address_hash = N_HashFromAddress(address); - channel->address_hash = address_hash; - - u64 bin_index = address_hash % host->num_channel_lookup_bins; - N_ChannelLookupBin *bin = &host->channel_lookup_bins[bin_index]; - if (bin->last) - { - channel->prev_address_hash = bin->last; - bin->last->next_address_hash = channel; - } - else - { - bin->first = channel; - } - bin->last = channel; - - return channel; -} - -void N_ReleaseChannel(N_Channel *channel) -{ - N_Host *host = channel->host; - - // Release from lookup table - { - N_ChannelLookupBin *bin = &host->channel_lookup_bins[channel->address_hash % host->num_channel_lookup_bins]; - N_Channel *prev = channel->prev_address_hash; - N_Channel *next = channel->next_address_hash; - if (prev) - { - prev->next_address_hash = next; - } - else - { - bin->first = next; - } - if (next) - { - next->prev_address_hash = prev; - } - else - { - bin->last = prev; - } - } - - // Release packets - { - if (channel->first_unreliable_packet) - { - host->first_free_packet = channel->first_unreliable_packet; - channel->last_unreliable_packet->next = host->first_free_packet; - } - if (channel->first_reliable_packet) - { - host->first_free_packet = channel->first_reliable_packet; - channel->last_reliable_packet->next = host->first_free_packet; - } - } - - // Release msg assemblers - for (N_MsgAssembler *ma = channel->least_recent_msg_assembler; ma; ma = ma->more_recent) - { - N_ReleaseMessageAssembler(ma); - } - - ++channel->id.gen; - channel->valid = 0; - channel->next_free = host->first_free_channel; - host->first_free_channel = channel; -} - -//////////////////////////////////////////////////////////// -//~ Message assembler - -u64 N_HashFromMsg(N_ChannelId channel_id, u64 msg_id) -{ - u64 result = 0; - result = HashStringEx(result, StringFromStruct(&channel_id)); - result = HashStringEx(result, StringFromStruct(&msg_id)); - return result; -} - -N_MsgAssembler *N_MsgAssemblerFromMsg(N_Host *host, N_ChannelId channel_id, u64 msg_id) -{ - u64 hash = N_HashFromMsg(channel_id, msg_id); - N_MsgAssemblerLookupBin *bin = &host->msg_assembler_lookup_bins[hash % host->num_msg_assembler_lookup_bins]; - for (N_MsgAssembler *ma = bin->first; ma; ma = ma->next_hash) - { - if (ma->hash == hash && N_MatchChannelId(ma->channel->id, channel_id) && ma->msg_id == msg_id) - { - return ma; - } - } - return 0; -} - -N_MsgAssembler *N_AcquireMsgAssembler(N_Channel *channel, u64 msg_id, u64 chunk_count, u64 now_ns, b32 is_reliable) -{ - N_Host *host = channel->host; - N_MsgAssembler *ma; - if (host->first_free_msg_assembler) - { - ma = host->first_free_msg_assembler; - host->first_free_msg_assembler = ma->next_free; - } - else - { - ma = PushStructNoZero(host->arena, N_MsgAssembler); - } - ZeroStruct(ma); - ma->channel = channel; - ma->msg_id = msg_id; - - ma->num_chunks_total = chunk_count; - - u64 chunk_bitmap_size = (chunk_count + 7) >> 3; - if ((chunk_bitmap_size % 16) != 0) - { - // Align chunk bitmap to 16 so msg data is aligned - chunk_bitmap_size += 16 - (chunk_bitmap_size % 16); - } - u64 chunk_data_size = chunk_count * N_MaxPacketChunkLen; - - // Acquire msg data using buddy allocator since the assembler has - // arbitrary lifetime and data needs to stay contiguous for random - // access as packets are received - ma->buddy_block = AcquireBuddyBlock(host->buddy, chunk_bitmap_size + chunk_data_size); - ma->chunk_bitmap = ma->buddy_block->memory; - ZeroBytes(ma->chunk_bitmap, chunk_bitmap_size); - ma->chunk_data = ma->chunk_bitmap + chunk_bitmap_size; - - // FIXME: Ensure chunk_count > 0 - ma->is_reliable = is_reliable; - - // Add to channel list - ma->touched_ns = now_ns; - if (channel->most_recent_msg_assembler) - { - channel->most_recent_msg_assembler->more_recent = ma; - ma->less_recent = channel->most_recent_msg_assembler; - } - else - { - channel->least_recent_msg_assembler = ma; - } - channel->most_recent_msg_assembler = ma; - - // Add to lookup table - u64 hash = N_HashFromMsg(channel->id, msg_id); - ma->hash = hash; - N_MsgAssemblerLookupBin *bin = &host->msg_assembler_lookup_bins[hash % host->num_msg_assembler_lookup_bins]; - if (bin->last) - { - bin->last->next_hash = ma; - ma->prev_hash = bin->last; - } - else - { - bin->first = ma; - } - bin->last = ma; - - return ma; -} - -void N_ReleaseMessageAssembler(N_MsgAssembler *ma) -{ - N_Channel *channel = ma->channel; - N_Host *host = channel->host; - ReleaseBuddyBlock(ma->buddy_block); - - // Release from channel list - { - N_MsgAssembler *prev = ma->less_recent; - N_MsgAssembler *next = ma->more_recent; - if (prev) - { - prev->more_recent = next; - } - else - { - channel->least_recent_msg_assembler = next; - } - if (next) - { - next->less_recent = prev; - } - else - { - channel->most_recent_msg_assembler = prev; - } - } - - // Release from lookup table - N_MsgAssemblerLookupBin *bin = &host->msg_assembler_lookup_bins[ma->hash % host->num_msg_assembler_lookup_bins]; - { - N_MsgAssembler *prev = ma->prev_hash; - N_MsgAssembler *next = ma->next_hash; - if (prev) - { - prev->next_hash = next; - } - else - { - bin->first = next; - } - if (next) - { - next->prev_hash = prev; - } - else - { - bin->last = prev; - } - } - - ma->next_free = host->first_free_msg_assembler; - host->first_free_msg_assembler = ma; -} - -void N_TouchMessageAssembler(N_MsgAssembler *ma, i64 now_ns) -{ - N_Channel *channel = ma->channel; - if (ma != channel->most_recent_msg_assembler) - { - // Remove from channel list - { - N_MsgAssembler *prev = ma->less_recent; - N_MsgAssembler *next = ma->more_recent; - if (prev) - { - prev->more_recent = next; - } - else - { - channel->least_recent_msg_assembler = next; - } - if (next) - { - next->less_recent = prev; - } - else - { - channel->most_recent_msg_assembler = prev; - } - } - - // Insert at end of channel list - { - if (channel->most_recent_msg_assembler) - { - channel->most_recent_msg_assembler->more_recent = ma; - ma->less_recent = channel->most_recent_msg_assembler; - } - else - { - channel->least_recent_msg_assembler = ma; - } - channel->most_recent_msg_assembler = ma; - } - } - ma->touched_ns = now_ns; -} - -b32 N_IsChunkFilled(N_MsgAssembler *ma, u64 chunk_id) -{ - if (chunk_id < ma->num_chunks_total) - { - return (ma->chunk_bitmap[chunk_id / 8] & (1 << (chunk_id % 8))) != 0; - } - return 0; -} - -void N_MarkChunkReceived(N_MsgAssembler *ma, u64 chunk_id) -{ - if (chunk_id < ma->num_chunks_total) - { - ma->chunk_bitmap[chunk_id / 8] |= (1 << (chunk_id % 8)); - } -} - -//////////////////////////////////////////////////////////// -//~ Packet - -N_SndPacket *N_PushSndPacket(N_Channel *channel, b32 is_reliable) -{ - N_Host *host = channel->host; - N_SndPacket *packet = 0; - if (host->first_free_packet) - { - packet = host->first_free_packet; - host->first_free_packet = packet->next; - } - else - { - packet = PushStructNoZero(host->arena, N_SndPacket); - } - ZeroStruct(packet); - - if (is_reliable) - { - if (channel->last_reliable_packet) - { - channel->last_reliable_packet->next = packet; - } - else - { - channel->first_reliable_packet = packet; - } - channel->last_reliable_packet = packet; - ++channel->num_reliable_packets; - packet->seq = ++channel->last_sent_seq; - } - else - { - if (channel->last_unreliable_packet) - { - channel->last_unreliable_packet->next = packet; - } - else - { - channel->first_unreliable_packet = packet; - } - channel->last_unreliable_packet = packet; - ++channel->num_unreliable_packets; - } - return packet; -} - -//////////////////////////////////////////////////////////// -//~ Host commands - -N_Cmd *N_PushCmd(N_Host *host) -{ - N_Cmd *cmd = PushStruct(host->cmd_arena, N_Cmd); - if (host->last_cmd) - { - host->last_cmd->next = cmd; - } - else - { - host->first_cmd = cmd; - } - host->last_cmd = cmd; - return cmd; -} - -void N_Connect(N_Host *host, PLT_Address connect_address) -{ - N_Channel *channel = N_ChannelFromAddress(host, connect_address); - if (!channel->valid) - { - channel = N_AcquireChannel(host, connect_address); - } -} - -void N_Disconnect(N_Host *host, N_ChannelId channel_id) -{ - N_Cmd *cmd = N_PushCmd(host); - cmd->kind = N_CmdKind_Disconnect; - cmd->channel_id = channel_id; -} - -void N_Write(N_Host *host, N_ChannelId channel_id, String msg, N_WriteFlag flags) -{ - N_Cmd *cmd = N_PushCmd(host); - cmd->kind = N_CmdKind_Write; - cmd->channel_id = channel_id; - cmd->write_msg = PushString(host->cmd_arena, msg); - cmd->write_reliable = flags & N_WriteFlag_Reliable; -} - -//////////////////////////////////////////////////////////// -//~ Channel info - -i64 N_GetChannelLastRttNs(N_Host *host, N_ChannelId channel_id) -{ - N_Channel *channel = N_ChannelFromId(host, channel_id); - return channel->last_heartbeat_rtt_ns; -} - -//////////////////////////////////////////////////////////// -//~ Update begin - -// Read incoming packets, update channels, and return events -N_EventList N_BeginUpdate(Arena *arena, N_Host *host) -{ - TempArena scratch = BeginScratch(arena); - - N_EventList events = ZI; - i64 now_ns = TimeNs(); - - ////////////////////////////// - //- Read socket - - { - N_RcvPacket *first_packet = 0; - N_RcvPacket *last_packet = 0; - { - PLT_Sock *sock = host->sock; - PLT_SockReadResult result = ZI; - while ((result = PLT_ReadSock(scratch.arena, sock)).valid) - { - PLT_Address address = result.address; - String data = result.data; - if (data.len > 0) - { - N_RcvPacket *packet = PushStruct(scratch.arena, N_RcvPacket); - packet->address = address; - packet->data = PushString(scratch.arena, data); - if (last_packet) - { - last_packet->next = packet; - } - else - { - first_packet = packet; - } - last_packet = packet; - } - } - } - - ////////////////////////////// - //- Process incoming packets - - { - for (N_RcvPacket *packet = first_packet; packet; packet = packet->next) - { - //struct sock *sock = packet->sock; - PLT_Address address = packet->address; - BB_Buff bb = BB_BuffFromString(packet->data); - BB_Reader br = BB_ReaderFromBuff(&bb); - u32 magic = BB_ReadUBits(&br, 32); // TODO: implicitly encode magic into crc32 - if (magic == N_PacketMagic) - { - // TODO: Combine kind byte with flags byte - N_Channel *channel = N_ChannelFromAddress(host, address); - N_PacketKind packet_kind = BB_ReadIBits(&br, 8); - u8 packet_flags = BB_ReadUBits(&br, 8); - - u64 their_acked_seq = BB_ReadUV(&br); - if (channel->valid) - { - channel->last_packet_received_ns = now_ns; - if (their_acked_seq > channel->their_acked_seq) - { - channel->their_acked_seq = their_acked_seq; - } - } - - b32 skip_packet = 0; - b32 is_reliable = packet_flags & N_PacketFlag_Reliable; - if (channel->valid) - { - if (is_reliable) - { - u64 packet_seq = BB_ReadUV(&br); - if (packet_seq == channel->our_acked_seq + 1) - { - channel->our_acked_seq = packet_seq; - } - else - { - skip_packet = 1; - } - } - } - - if (!skip_packet) - { - switch (packet_kind) - { - default: break; - - ////////////////////////////// - //- Read packet kind: TryConnect - - case N_PacketKind_TryConnect: - { - // A foreign host is trying to connect to us - if (!channel->valid) - { - LogInfoF("Host received conection attempt from %F", FmtString(PLT_StringFromAddress(scratch.arena, address))); - // TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? - channel = N_AcquireChannel(host, address); - } - N_Cmd *cmd = N_PushCmd(host); - cmd->kind = N_CmdKind_ConnectSuccess; - cmd->channel_id = channel->id; - } break; - - ////////////////////////////// - //- Read packet kind: ConnectSuccess - - case N_PacketKind_ConnectSuccess: - { - // We successfully connected to a foreign host and they are ready to receive messages - if (channel->valid && !channel->connected) - { - LogInfoF("Host received connection from %F", FmtString(PLT_StringFromAddress(scratch.arena, address))); - N_Event *event = N_PushEvent(arena, &events); - event->kind = N_EventKind_ChannelOpened; - event->channel_id = channel->id; - channel->connected = 1; - } - } break; - - ////////////////////////////// - //- Read packet kind: Disconnect - - case N_PacketKind_Disconnect: - { - // A foreign host disconnected from us - if (channel->valid) - { - LogInfoF("Host received disconnection from %F", FmtString(PLT_StringFromAddress(scratch.arena, address))); - N_Event *event = N_PushEvent(arena, &events); - event->kind = N_EventKind_ChannelClosed; - event->channel_id = channel->id; - N_ReleaseChannel(channel); - } - - } break; - - ////////////////////////////// - //- Read packet kind: Heartbeat - - case N_PacketKind_Heartbeat: - { - if (channel->valid) - { - u16 heartbeat_id = BB_ReadUBits(&br, 16); - u16 acked_heartbeat_id = BB_ReadUBits(&br, 16); - if (heartbeat_id > channel->last_heartbeat_received_id) - { - channel->last_heartbeat_received_id = heartbeat_id; - } - if (acked_heartbeat_id == channel->last_heartbeat_acked_id + 1) - { - channel->last_heartbeat_acked_id = acked_heartbeat_id; - if (channel->last_heartbeat_acked_ns > 0) - { - channel->last_heartbeat_rtt_ns = now_ns - channel->last_heartbeat_acked_ns; - } - channel->last_heartbeat_acked_ns = now_ns; - } - } - } break; - - ////////////////////////////// - //- Read packet kind: MsgChunk - - case N_PacketKind_MsgChunk: - { - if (channel->valid && channel->connected) - { - // Packet is chunk out of belonging to message - u64 msg_id = BB_ReadUV(&br); - u64 chunk_id = BB_ReadUV(&br); - u64 chunk_count = BB_ReadUV(&br); - b32 is_last_chunk = (chunk_id + 1) == chunk_count; - u64 chunk_len = is_last_chunk ? BB_ReadUV(&br) : N_MaxPacketChunkLen; - - N_MsgAssembler *ma = N_MsgAssemblerFromMsg(host, channel->id, msg_id); - if (!ma) - { - ma = N_AcquireMsgAssembler(channel, msg_id, chunk_count, now_ns, is_reliable); - } - - if (chunk_count == ma->num_chunks_total && chunk_id < chunk_count) - { - if (!N_IsChunkFilled(ma, chunk_id)) - { - u8 *src = BB_ReadBytesRaw(&br, chunk_len); - if (src) - { - u8 *dst = &ma->chunk_data[chunk_id * N_MaxPacketChunkLen]; - CopyBytes(dst, src, chunk_len); - if (is_last_chunk) - { - ma->last_chunk_len = chunk_len; - } - N_MarkChunkReceived(ma, chunk_id); - ++ma->num_chunks_received; - N_TouchMessageAssembler(ma, now_ns); - if (ma->num_chunks_received == chunk_count) - { - // All chunks filled, message has finished assembling - // TODO: Message ordering - N_Event *event = N_PushEvent(arena, &events); - String data = ZI; - data.len = ((chunk_count - 1) * N_MaxPacketChunkLen) + ma->last_chunk_len; - data.text = PushStructsNoZero(arena, u8, data.len); - CopyBytes(data.text, ma->chunk_data, data.len); - event->kind = N_EventKind_Msg; - event->msg = data; - event->channel_id = channel->id; - if (is_reliable) - { - // Release assembler if reliable - N_ReleaseMessageAssembler(ma); - } - } - } - else - { - // Overflow reading chunk - Assert(0); - } - } - } - else - { - // Chunk id/count mismatch - Assert(0); - } - } - } break; - } - } - host->bytes_received += packet->data.len; - } - } - } - } - - ////////////////////////////// - //- Update channels - - { - for (u64 i = 0; i < host->num_channels_reserved; ++i) - { - N_Channel *channel = &host->channels[i]; - if (channel->valid) - { - // Send / resend handshake if not connected - if (!channel->connected) - { - N_Cmd *cmd = N_PushCmd(host); - cmd->kind = N_CmdKind_TryConnect; - cmd->channel_id = channel->id; - } - // Send heartbeat - // TODO: Send this less frequently (once per second or half of timeout or something) - { - N_Cmd *cmd = N_PushCmd(host); - cmd->kind = N_CmdKind_Heartbeat; - cmd->heartbeat_id = channel->last_heartbeat_acked_id + 1; - cmd->heartbeat_ack_id = channel->last_heartbeat_received_id; - cmd->channel_id = channel->id; - } - // Release acked reliable packets - { - u64 acked_seq = channel->their_acked_seq; - N_SndPacket *packet = channel->first_reliable_packet; - while (packet) - { - N_SndPacket *next = packet->next; - u64 seq = packet->seq; - if (seq < acked_seq) - { - packet->next = host->first_free_packet; - host->first_free_packet = packet; - channel->first_reliable_packet = next; - --channel->num_reliable_packets; - } - else - { - break; - } - packet = next; - } - if (channel->first_reliable_packet == 0) - { - channel->last_reliable_packet = 0; - } - } - // Release timed out unreliable msg buffers - { - // TODO: Configurable timeout - i64 unreliable_msg_timeout_ns = NsFromSeconds(0.1); - N_MsgAssembler *ma = channel->least_recent_msg_assembler; - while (ma) - { - N_MsgAssembler *next = ma->more_recent; - if ((now_ns - ma->touched_ns) > unreliable_msg_timeout_ns) - { - if (!ma->is_reliable) - { - N_ReleaseMessageAssembler(ma); - } - } - else - { - break; - } - ma = next; - } - } - } - } - } - - EndScratch(scratch); - return events; -} - -//////////////////////////////////////////////////////////// -//~ Update end - -// Process host cmds & send outgoing packets -void N_EndUpdate(N_Host *host) -{ - TempArena scratch = BeginScratchNoConflict(); - - ////////////////////////////// - //- Process cmds - - // TODO: Unreliable packets don't need to be allocated into unreliable packet queue, should just send them and forget - { - for (N_Cmd *cmd = host->first_cmd; cmd; cmd = cmd->next) - { - N_CmdKind kind = cmd->kind; - N_ChannelId channel_id = cmd->channel_id; - N_ChannelList channels = N_ChannelsFromId(scratch.arena, host, channel_id); - for (N_ChannelNode *node = channels.first; node; node = node->next) - { - N_Channel *channel = node->channel; - switch (kind) - { - default: break; - - ////////////////////////////// - //- Process command: TryConnect - - case N_CmdKind_TryConnect: - { - u8 packet_flags = 0; - N_SndPacket *packet = N_PushSndPacket(channel, 0); - BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data)); - BB_Writer bw = BB_WriterFromBuff(&bb); - BB_WriteUBits(&bw, N_PacketMagic, 32); // TODO: implicitly encode magic into crc32 - BB_WriteIBits(&bw, N_PacketKind_TryConnect, 8); - BB_WriteUBits(&bw, packet_flags, 8); - BB_WriteUV(&bw, channel->our_acked_seq); - packet->data_len = BB_GetNumBytesWritten(&bw); - } break; - - ////////////////////////////// - //- Process command: ConnectSuccess - - case N_CmdKind_ConnectSuccess: - { - u8 packet_flags = 0; - N_SndPacket *packet = N_PushSndPacket(channel, 0); - BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data)); - BB_Writer bw = BB_WriterFromBuff(&bb); - BB_WriteUBits(&bw, N_PacketMagic, 32); // TODO: implicitly encode magic into crc32 - BB_WriteIBits(&bw, N_PacketKind_ConnectSuccess, 8); - BB_WriteUBits(&bw, packet_flags, 8); - BB_WriteUV(&bw, channel->our_acked_seq); - packet->data_len = BB_GetNumBytesWritten(&bw); - } break; - - ////////////////////////////// - //- Process command: Disconnect - - case N_CmdKind_Disconnect: - { - u8 packet_flags = 0; - N_SndPacket *packet = N_PushSndPacket(channel, 0); - BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data)); - BB_Writer bw = BB_WriterFromBuff(&bb); - BB_WriteUBits(&bw, N_PacketMagic, 32); // TODO: implicitly encode magic into crc32 - BB_WriteIBits(&bw, N_PacketKind_Disconnect, 8); - BB_WriteUBits(&bw, packet_flags, 8); - BB_WriteUV(&bw, channel->our_acked_seq); - packet->data_len = BB_GetNumBytesWritten(&bw); - } break; - - ////////////////////////////// - //- Process command: Heartbeat - - case N_CmdKind_Heartbeat: - { - u8 packet_flags = 0; - N_SndPacket *packet = N_PushSndPacket(channel, 0); - BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data)); - BB_Writer bw = BB_WriterFromBuff(&bb); - BB_WriteUBits(&bw, N_PacketMagic, 32); // TODO: implicitly encode magic into crc32 - BB_WriteIBits(&bw, N_PacketKind_Heartbeat, 8); - BB_WriteUBits(&bw, packet_flags, 8); - BB_WriteUV(&bw, channel->our_acked_seq); - BB_WriteUBits(&bw, cmd->heartbeat_id, 16); - BB_WriteUBits(&bw, cmd->heartbeat_ack_id, 16); - packet->data_len = BB_GetNumBytesWritten(&bw); - } break; - - ////////////////////////////// - //- Process command: Write - - case N_CmdKind_Write: - { - b32 is_reliable = cmd->write_reliable; - u8 packet_flags = (is_reliable * N_PacketFlag_Reliable); - String msg = cmd->write_msg; - - u64 chunk_count = 0; - if (msg.len > 0) - { - chunk_count = (msg.len - 1) / N_MaxPacketChunkLen; - } - chunk_count += 1; - - u64 msg_id = ++channel->last_sent_msg_id; - for (u64 i = 0; i < chunk_count; ++i) - { - u64 chunk_len = N_MaxPacketChunkLen; - b32 is_last_chunk = i + 1 == chunk_count; - if (is_last_chunk) - { - chunk_len = msg.len % N_MaxPacketChunkLen; - if (chunk_len == 0) - { - chunk_len = N_MaxPacketChunkLen; - } - } - N_SndPacket *packet = N_PushSndPacket(channel, is_reliable); - BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data)); - BB_Writer bw = BB_WriterFromBuff(&bb); - BB_WriteUBits(&bw, N_PacketMagic, 32); // TODO: implicitly encode magic into crc32 - BB_WriteIBits(&bw, N_PacketKind_MsgChunk, 8); - BB_WriteUBits(&bw, packet_flags, 8); - BB_WriteUV(&bw, channel->our_acked_seq); - if (is_reliable) - { - BB_WriteUV(&bw, packet->seq); - } - BB_WriteUV(&bw, msg_id); - BB_WriteUV(&bw, i); - BB_WriteUV(&bw, chunk_count); - if (is_last_chunk) - { - BB_WriteUV(&bw, chunk_len); - } - u8 *chunk_data = msg.text + (i * N_MaxPacketChunkLen); - BB_WriteBytes(&bw, STRING(chunk_len, chunk_data)); - packet->data_len = BB_GetNumBytesWritten(&bw); - } - } break; - } - } - } - } - - ////////////////////////////// - //- Send packets - - // TODO: Aggregate small packets - { - for (u64 i = 0; i < host->num_channels_reserved; ++i) - { - PLT_Sock *sock = host->sock; - N_Channel *channel = &host->channels[i]; - u64 total_sent = 0; - if (channel->valid) - { - PLT_Address address = channel->address; - // Send reliable packets to channel - for (N_SndPacket *packet = channel->first_reliable_packet; packet; packet = packet->next) - { - PLT_WriteSock(sock, address, STRING(packet->data_len, packet->data)); - total_sent += packet->data_len; - } - // Send unreliable packets to channel - for (N_SndPacket *packet = channel->first_unreliable_packet; packet; packet = packet->next) - { - PLT_WriteSock(sock, address, STRING(packet->data_len, packet->data)); - total_sent += packet->data_len; - } - // Release unreliable packets - if (channel->first_unreliable_packet) - { - channel->last_unreliable_packet->next = host->first_free_packet; - host->first_free_packet = channel->first_unreliable_packet; - channel->first_unreliable_packet = 0; - channel->last_unreliable_packet = 0; - channel->num_unreliable_packets = 0; - } - host->bytes_sent += total_sent; - } - } - } - - ////////////////////////////// - //- Reset command list - - host->first_cmd = 0; - host->last_cmd = 0; - ResetArena(host->cmd_arena); - - EndScratch(scratch); -} - -//////////////////////////////////////////////////////////// -//~ PushEvent - -N_Event *N_PushEvent(Arena *arena, N_EventList *list) -{ - N_Event *event = PushStruct(arena, N_Event); - if (list->last) - { - list->last->next = event; - } - else - { - list->first = event; - } - list->last = event; - return event; -} diff --git a/src/net_old/net_old.h b/src/net_old/net_old.h deleted file mode 100644 index 70c7d659..00000000 --- a/src/net_old/net_old.h +++ /dev/null @@ -1,318 +0,0 @@ -//////////////////////////////////////////////////////////// -//~ Channel ID - -Struct(N_ChannelId) -{ - u32 gen; - u32 idx; -}; - -//////////////////////////////////////////////////////////// -//~ Host command types - -Enum(N_CmdKind) -{ - N_CmdKind_None, - N_CmdKind_TryConnect, - N_CmdKind_ConnectSuccess, - N_CmdKind_Disconnect, - N_CmdKind_Heartbeat, - N_CmdKind_Write -}; - -Enum(N_WriteFlag) -{ - N_WriteFlag_None = 0, - N_WriteFlag_Reliable = (1 << 0) -}; - -Struct(N_Cmd) -{ - N_CmdKind kind; - N_ChannelId channel_id; - - u16 heartbeat_id; - u16 heartbeat_ack_id; - - b32 write_reliable; - String write_msg; - - N_Cmd *next; -}; - -//////////////////////////////////////////////////////////// -//~ Event types - -Enum(N_EventKind) -{ - N_EventKind_None, - N_EventKind_ChannelOpened, - N_EventKind_ChannelClosed, - N_EventKind_Msg -}; - -Struct(N_Event) -{ - N_EventKind kind; - N_ChannelId channel_id; - String msg; - - N_Event *next; -}; - -Struct(N_EventList) -{ - N_Event *first; - N_Event *last; -}; - -Struct(N_ChannelLookupBin) -{ - struct N_Channel *first; - struct N_Channel *last; -}; - -//////////////////////////////////////////////////////////// -//~ Packet types - -#define N_PacketMagic 0xd9e3b8b6 -#define N_MaxPacketChunkLen 1024 -#define N_MaxPacketLen 1280 // Give enough space for msg chunk + header - -Enum(N_PacketKind) -{ - N_PacketKind_None, - N_PacketKind_TryConnect, - N_PacketKind_ConnectSuccess, - N_PacketKind_Disconnect, - N_PacketKind_Heartbeat, - N_PacketKind_MsgChunk -}; - -Enum(N_PacketFlag) -{ - N_PacketFlag_None = 0, - N_PacketFlag_Reliable = (1 << 0) -}; - -Struct(N_SndPacket) -{ - N_SndPacket *next; - u64 seq; - - u64 data_len; - u8 data[N_MaxPacketLen]; -}; - -Struct(N_RcvPacket) -{ - PLT_Sock *sock; - PLT_Address address; - String data; - N_RcvPacket *next; -}; - -Struct(N_RcvBuffer) -{ - Arena *arena; - N_RcvPacket *first_packet; - N_RcvPacket *last_packet; -}; - -//////////////////////////////////////////////////////////// -//~ Channel types - -Struct(N_Channel) -{ - N_ChannelId id; - b32 valid; - b32 connected; - struct N_Host *host; - - N_Channel *next_free; - - PLT_Address address; - u64 address_hash; - N_Channel *next_address_hash; - N_Channel *prev_address_hash; - - // NOTE: Packets are allocated in host's `arena` - N_SndPacket *first_reliable_packet; - N_SndPacket *last_reliable_packet; - N_SndPacket *first_unreliable_packet; - N_SndPacket *last_unreliable_packet; - u64 num_reliable_packets; - u64 num_unreliable_packets; - - // NOTE: Msg assemblers are allocated in host's `arena` - struct N_MsgAssembler *least_recent_msg_assembler; - struct N_MsgAssembler *most_recent_msg_assembler; - - u16 last_heartbeat_received_id; - u16 last_heartbeat_acked_id; - i64 last_heartbeat_acked_ns; - i64 last_heartbeat_rtt_ns; - - u64 last_sent_msg_id; - u64 their_acked_seq; - u64 our_acked_seq; - u64 last_sent_seq; - - i64 last_packet_received_ns; -}; - -Struct(N_ChannelNode) -{ - N_Channel *channel; - N_ChannelNode *next; -}; - -Struct(N_ChannelList) -{ - N_ChannelNode *first; - N_ChannelNode *last; -}; - -//////////////////////////////////////////////////////////// -//~ Message asssembler types - -Struct(N_MsgAssembler) -{ - N_Channel *channel; - b32 is_reliable; - - // Free list - N_MsgAssembler *next_free; - - // Bucket list - N_MsgAssembler *next_hash; - N_MsgAssembler *prev_hash; - - // Channel list - N_MsgAssembler *less_recent; - N_MsgAssembler *more_recent; - - u64 msg_id; - u64 hash; - - u64 last_chunk_len; - u64 num_chunks_total; - u64 num_chunks_received; - - i64 touched_ns; - - BuddyBlock *buddy_block; - u8 *chunk_bitmap; - u8 *chunk_data; -}; - -Struct(N_MsgAssemblerLookupBin) -{ - N_MsgAssembler *first; - N_MsgAssembler *last; -}; - -//////////////////////////////////////////////////////////// -//~ Host types - -#define N_NumChannelLookupBins 512 -#define N_NumMsgAssemblerLookupBins 16384 - -Struct(N_Host) -{ - Arena *arena; - - PLT_Sock *sock; - - BuddyCtx *buddy; // For storing msg assembler data - - Arena *cmd_arena; - N_Cmd *first_cmd; - N_Cmd *last_cmd; - N_Cmd *first_free_cmd; - - Arena *channel_arena; - N_Channel *channels; - N_Channel *first_free_channel; - u64 num_channels_reserved; - - N_SndPacket *first_free_packet; // Acquired in `arena` - N_MsgAssembler *first_free_msg_assembler; // Acquired in `arena` - - N_ChannelLookupBin *channel_lookup_bins; // Acquired in `arena` - u64 num_channel_lookup_bins; - - N_MsgAssemblerLookupBin *msg_assembler_lookup_bins; // Acquired in `arena` - u64 num_msg_assembler_lookup_bins; - - // Double buffer for incoming data - Mutex rcv_buffer_write_mutex; - N_RcvBuffer *rcv_buffer_read; - N_RcvBuffer *rcv_buffer_write; - - u64 bytes_received; - u64 bytes_sent; -}; - -//////////////////////////////////////////////////////////// -//~ Nil constants - -Readonly Global N_Channel N_nil_channel = { .valid = 0 }; - -//////////////////////////////////////////////////////////// -//~ Host initialization - -N_Host *N_AcquireHost(u16 listen_port); -void N_ReleaseHost(N_Host *host); - -//////////////////////////////////////////////////////////// -//~ Channel - -#define N_NilChannelId (N_ChannelId) { .gen = 0, .idx = 0 } -#define N_AllChannelsId (N_ChannelId) { .gen = U32Max, .idx = U32Max } - -#define N_MatchChannelId(a, b) ((a).gen == (b).gen && (a).idx == (b).idx) -#define N_IsChannelIdNil(v) ((v).gen == 0 && (v).idx == 0) - -u64 N_HashFromAddress(PLT_Address address); -N_Channel *N_ChannelFromAddress(N_Host *host, PLT_Address address); -N_Channel *N_ChannelFromId(N_Host *host, N_ChannelId channel_id); -N_ChannelList N_ChannelsFromId(Arena *arena, N_Host *host, N_ChannelId channel_id); -N_Channel *N_AcquireChannel(N_Host *host, PLT_Address address); -void N_ReleaseChannel(N_Channel *channel); - -//////////////////////////////////////////////////////////// -//~ Message assembler - -u64 N_HashFromMsg(N_ChannelId channel_id, u64 msg_id); -N_MsgAssembler *N_MsgAssemblerFromMsg(N_Host *host, N_ChannelId channel_id, u64 msg_id); -N_MsgAssembler *N_AcquireMsgAssembler(N_Channel *channel, u64 msg_id, u64 chunk_count, u64 now_ns, b32 is_reliable); -void N_ReleaseMessageAssembler(N_MsgAssembler *ma); -void N_TouchMessageAssembler(N_MsgAssembler *ma, i64 now_ns); -b32 N_IsChunkFilled(N_MsgAssembler *ma, u64 chunk_id); -void N_MarkChunkReceived(N_MsgAssembler *ma, u64 chunk_id); - -//////////////////////////////////////////////////////////// -//~ Packet - -N_SndPacket *N_PushSndPacket(N_Channel *channel, b32 is_reliable); - -//////////////////////////////////////////////////////////// -//~ Host command - -N_Cmd *N_PushCmd(N_Host *host); -void N_Connect(N_Host *host, PLT_Address connect_address); -void N_Disconnect(N_Host *host, N_ChannelId channel_id); -void N_Write(N_Host *host, N_ChannelId channel_id, String msg, N_WriteFlag flags); - -//////////////////////////////////////////////////////////// -//~ Channel info - -i64 N_GetChannelLastRttNs(N_Host *host, N_ChannelId channel_id); - -//////////////////////////////////////////////////////////// -//~ Update - -N_Event *N_PushEvent(Arena *arena, N_EventList *list); -N_EventList N_BeginUpdate(Arena *arena, N_Host *host); -void N_EndUpdate(N_Host *host); diff --git a/src/net_old/net_old.lay b/src/net_old/net_old.lay deleted file mode 100644 index 82c9d661..00000000 --- a/src/net_old/net_old.lay +++ /dev/null @@ -1,16 +0,0 @@ -@Layer net_old - -////////////////////////////// -//- Dependencies - -@Dep platform - -////////////////////////////// -//- Api - -@IncludeC net.h - -////////////////////////////// -//- Impl - -@IncludeC net.c diff --git a/src/pp/pp.h b/src/pp/pp.h index f16d65ec..51c6916b 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -307,34 +307,24 @@ Enum(P_MsgKind) P_MsgKind_None, // User -> sim - P_MsgKind_UserSnapshot, + // P_MsgKind_UserSnapshot, P_MsgKind_SaveWorld, P_MsgKind_ResetWorld, P_MsgKind_TileEdit, P_MsgKind_EntEdit, // Sim -> user - P_MsgKind_SimSnapshot, + // P_MsgKind_SimSnapshot, P_MsgKind_Tiles, }; Struct(P_Msg) { - //- In - - P_Key dst_user; // If dst is 0, then cmd is meant to be broadcast - b32 burst; - - //- Out - - P_Key src_user; - - //- In / Out - P_MsgKind kind; + NET_Key dst; - P_UserSnapshot user_snapshot; - P_SimSnapshot sim_snapshot; + // P_UserSnapshot user_snapshot; + // P_SimSnapshot sim_snapshot; P_TileKind tile_kind; Rng2I32 tile_range; diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 62b4124d..f32ccd5f 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -1,10 +1,20 @@ S_Ctx S = Zi; +Readonly S_Client S_NilClient = { + .next = &S_NilClient, + .prev = &S_NilClient, +}; + //////////////////////////////////////////////////////////// //~ Bootstrap void S_Bootstrap(void) { + Arena *perm = PermArena(); + + S.client_bins_count = Kibi(4); + S.client_bins = PushStructsNoZero(perm, S_ClientBin, S.client_bins_count); + DispatchWave(Lit("Sim"), 1, S_TickForever, 0); OnExit(S_Shutdown); } @@ -15,6 +25,30 @@ void S_Shutdown(void) YieldOnFence(&S.shutdown_fence, 1); } +//////////////////////////////////////////////////////////// +//~ Helpers + +b32 S_IsClientNil(S_Client *client) +{ + return client == 0 || client == &S_NilClient; +} + +S_Client *S_ClientFromNetKey(NET_Key key) +{ + S_Client *result = &S_NilClient; + u64 hash = NET_HashFromKey(key); + S_ClientBin *bin = &S.client_bins[hash % S.client_bins_count]; + for (S_Client *client = bin->first; client; client = client->next_in_bin) + { + if (client->hash == hash) + { + result = client; + break; + } + } + return result; +} + //////////////////////////////////////////////////////////// //~ Sim tick @@ -31,9 +65,8 @@ void S_TickForever(WaveLaneCtx *lane) b32 has_sent_initial_tick = 0; NET_PipeHandle net_pipe = NET_AcquirePipe(); - - - + BB_Buff packer_bb = BB_AcquireDynamicBuff(Gibi(64)); + BB_Writer packer_bbw = BB_WriterFromBuff(&packer_bb); @@ -128,33 +161,110 @@ void S_TickForever(WaveLaneCtx *lane) u64 port = 22121; NET_Bind(net_pipe, port); + + + + + + P_MsgList in_msgs = Zi; { NET_MsgList net_msgs = NET_Swap(frame_arena, net_pipe); for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) { + NET_Key net_key = net_msg->sender; + String address_str = NET_StringFromKey(frame_arena, net_key); + LogDebugF("Received message from client \"%F\"", FmtString(address_str)); + + + + // Create client + S_Client *client = S_ClientFromNetKey(net_key); + if (S_IsClientNil(client)) + { + u64 hash = NET_HashFromKey(net_key); + S_ClientBin *bin = &S.client_bins[hash % S.client_bins_count]; + + // FIXME: Freelist client + client = PushStruct(perm, S_Client); + client->hash = hash; + client->net_key = net_key; + DllQueuePushNPZ(&S_NilClient, S.first_client, S.last_client, client, next, prev); + DllQueuePushNP(bin->first, bin->last, client, next_in_bin, prev_in_bin); + } + + + + + + String packed = net_msg->data; - P_MsgNode *dst_msg_node = PushStruct(frame_arena, P_MsgNode); - P_Msg *dst_msg = &dst_msg_node->msg; - *dst_msg = P_UnpackMsg(frame_arena, packed); - // FIXME: Set src user here based on net key - // dst_msg->src_user = - DllQueuePush(in_msgs.first, in_msgs.last, dst_msg_node); - ++in_msgs.count; + P_MsgList client_msgs = P_UnpackMessages(frame_arena, packed); + // FIXME: Set src user here based on net key (or maybe just attach net key to msg instead of user) - // { - // LogDebugF( - // "Server received msg (%F bytes): \"%F\"", - // FmtUint(packed.len), - // FmtString(packed) - // ); - // } - + if (client_msgs.first) + { + if (in_msgs.last) + { + in_msgs.last->next = client_msgs.first; + } + else + { + in_msgs.first = client_msgs.first; + } + client_msgs.first->prev = in_msgs.last; + in_msgs.last = client_msgs.last; + in_msgs.count += client_msgs.count; + } } } + + + + + + + + + // P_MsgList in_msgs = Zi; + // { + // NET_MsgList net_msgs = NET_Swap(frame_arena, net_pipe); + // for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) + // { + // NET_Key net_key = net_msg->sender; + // String address_str = NET_StringFromKey(frame_arena, net_key); + // LogDebugF("Received message from client \"%F\"", FmtString(address_str)); + + // NET_Push(net_pipe, net_key, Lit("HIII"), 0); + + // String packed = net_msg->data; + // P_MsgNode *dst_msg_node = PushStruct(frame_arena, P_MsgNode); + // P_Msg *dst_msg = &dst_msg_node->msg; + // *dst_msg = P_UnpackMsg(frame_arena, packed); + // // FIXME: Set src user here based on net key + // // dst_msg->src_user = + // DllQueuePush(in_msgs.first, in_msgs.last, dst_msg_node); + // ++in_msgs.count; + + + + // // { + // // LogDebugF( + // // "Server received msg (%F bytes): \"%F\"", + // // FmtUint(packed.len), + // // FmtString(packed) + // // ); + // // } + + // } + // } + + + + ////////////////////////////// //- Process connection messages @@ -238,17 +348,6 @@ void S_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Apply user snapshots - for (P_MsgNode *msg_node = in_msgs.first; msg_node; msg_node = msg_node->next) - { - P_Msg *msg = &msg_node->msg; - - if (msg->kind == P_MsgKind_UserSnapshot) - { - - } - } - - // P_MsgList user_msgs = Zi; // { // i64 user_msgs_min_tick = world_frame->tick + user_msg_tick_range.min; @@ -323,63 +422,63 @@ void S_TickForever(WaveLaneCtx *lane) // FIXME: Only accept edits from privileged users - // { - // b32 should_save = 0; - // for (P_MsgNode *msg_node = user_msgs.first; msg_node; msg_node = msg_node->next) - // { - // P_Msg *msg = &msg_node->msg; - // b32 allow = 0; - // if (msg->kind == P_MsgKind_SaveWorld) - // { - // // FIXME: Only accept save from local user - // should_save = 1; - // } - // if (msg->kind == P_MsgKind_ResetWorld) - // { - // // TODO: Real reset - // for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) - // { - // ent->exists = 0; - // } - // } - // if (msg->kind == P_MsgKind_EntEdit) - // { - // P_EntList ents = Zi; - // P_Ent *dst = P_PushTempEnt(frame_arena, &ents); - // *dst = msg->ent; - // P_SpawnEntsFromList(world_frame, ents); - // } - // if (msg->kind == P_MsgKind_TileEdit) - // { - // P_TileKind tile = msg->tile_kind; - // Rng2I32 range = msg->tile_range; - // for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) - // { - // for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) - // { - // Vec2 tile_pos = VEC2(tile_x, tile_y); - // i32 tile_idx = P_TileIdxFromTilePos(tile_pos); - // world->tiles[tile_idx] = (u8)tile; - // } - // } - // // Hash tiles - // { - // u64 old_tiles_hash = world->tiles_hash; - // world->tiles_hash = HashString(STRING(P_TilesCount, world->tiles)); - // if (world->tiles_hash != old_tiles_hash) - // { - // tiles_dirty = 1; - // } - // } - // } - // } - // // Save world - // if (should_save) - // { - // String path = Lit("..."); - // LogInfoF("Saving world to %F", FmtString(path)); - // } - // } + { + b32 should_save = 0; + for (P_MsgNode *msg_node = in_msgs.first; msg_node; msg_node = msg_node->next) + { + P_Msg *msg = &msg_node->msg; + b32 allow = 0; + if (msg->kind == P_MsgKind_SaveWorld) + { + // FIXME: Only accept save from local user + should_save = 1; + } + if (msg->kind == P_MsgKind_ResetWorld) + { + // TODO: Real reset + for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + { + ent->exists = 0; + } + } + if (msg->kind == P_MsgKind_EntEdit) + { + P_EntList ents = Zi; + P_Ent *dst = P_PushTempEnt(frame_arena, &ents); + *dst = msg->ent; + P_SpawnEntsFromList(world_frame, ents); + } + if (msg->kind == P_MsgKind_TileEdit) + { + P_TileKind tile = msg->tile_kind; + Rng2I32 range = msg->tile_range; + for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y) + { + for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) + { + Vec2 tile_pos = VEC2(tile_x, tile_y); + i32 tile_idx = P_TileIdxFromTilePos(tile_pos); + world->tiles[tile_idx] = (u8)tile; + } + } + // Hash tiles + { + u64 old_tiles_hash = world->tiles_hash; + world->tiles_hash = HashString(STRING(P_TilesCount, world->tiles)); + if (world->tiles_hash != old_tiles_hash) + { + tiles_dirty = 1; + } + } + } + } + // Save world + if (should_save) + { + String path = Lit("..."); + LogInfoF("Saving world to %F", FmtString(path)); + } + } ////////////////////////////// //- Update ent controls @@ -414,22 +513,22 @@ void S_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Push tile messages - // if (tiles_dirty) - // { - // P_Msg *msg = 0; - // { - // P_MsgNode *msg_node = PushStruct(frame_arena, P_MsgNode); - // DllQueuePush(output->msgs.first, output->msgs.last, msg_node); - // ++output->msgs.count; - // msg = &msg_node->msg; - // } - // msg->kind = P_MsgKind_Tiles; - // msg->tiles_hash = world->tiles_hash; - // msg->raw_tiles = PushStructsNoZero(frame_arena, u8, P_TilesCount); - // msg->tile_range = RNG2I32(VEC2I32(0, 0), VEC2I32(P_TilesPitch, P_TilesPitch)); - // CopyBytes(msg->raw_tiles, world->tiles, P_TilesCount); - // has_sent_initial_tick = 1; - // } + { + // TODO: Receive remote tile hashes via user snapshots + for (S_Client *client = S.first_client; !S_IsClientNil(client); client = client->next) + { + if (tiles_dirty || client->remote_tiles_hash != world->tiles_hash) + { + P_Msg *msg = P_PushMsg(P_MsgKind_Tiles, Zstr); + msg->kind = P_MsgKind_Tiles; + msg->tiles_hash = world->tiles_hash; + msg->tile_range = RNG2I32(VEC2I32(0, 0), VEC2I32(P_TilesPitch, P_TilesPitch)); + msg->dst = client->net_key; + msg->data = STRING(P_TilesCount, world->tiles); + client->remote_tiles_hash = world->tiles_hash; + } + } + } ////////////////////////////// //- Push snapshot messages @@ -486,35 +585,151 @@ void S_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Send messages - for (P_MsgNode *msg_node = P_tl.out_msgs.first; msg_node; msg_node = msg_node->next) { - P_Msg *msg = &msg_node->msg; - if (P_IsKeyNil(msg->dst_user)) + // Group messages by client + for (P_MsgNode *msg_node = P_tl.out_msgs.first; msg_node; msg_node = msg_node->next) { - // Broadcast - String packed = P_PackMessage(frame_arena, msg); - for (P_Ent *user = P_FirstEnt(world_frame); !P_IsEntNil(user); user = P_NextEnt(user)) + P_Msg *msg = &msg_node->msg; + if (NET_IsKeyNil(msg->dst)) { - if (user->is_user) + // Broadcast msg + for (S_Client *client = S.first_client; !S_IsClientNil(client); client = client->next) { - NET_Push(net_pipe, user->net, packed, msg->burst); + P_MsgNode *dst_msg_node = PushStruct(frame_arena, P_MsgNode); + *dst_msg_node = *msg_node; + DllQueuePush(client->out_msgs.first, client->out_msgs.last, dst_msg_node); + ++client->out_msgs.count; + } + } + else + { + // Targeted msg + S_Client *client = S_ClientFromNetKey(msg->dst); + if (!S_IsClientNil(client)) + { + P_MsgNode *dst_msg_node = PushStruct(frame_arena, P_MsgNode); + *dst_msg_node = *msg_node; + DllQueuePush(client->out_msgs.first, client->out_msgs.last, dst_msg_node); + ++client->out_msgs.count; } } } - else + + // Send messages to clients + for (S_Client *client = S.first_client; !S_IsClientNil(client); client = client->next) { - P_Ent *user = P_EntFromKey(world_frame, msg->dst_user); - if (!NET_IsKeyNil(user->net)) + P_MsgList msgs = client->out_msgs; + if (msgs.count > 0) { - String packed = P_PackMessage(frame_arena, msg); - NET_Push(net_pipe, user->net, packed, msg->burst); + String packed = P_PackMessages(&packer_bbw, msgs); + NET_Push(net_pipe, client->net_key, packed, 0); + ZeroStruct(&client->out_msgs); } } + + ResetArena(P_tl.out_msgs_arena); + ZeroStruct(&P_tl.out_msgs); } + + // { + // // Group messages by client + // for (P_MsgNode *msg_node = P_tl.out_msgs.first; msg_node; msg_node = msg_node->next) + // { + // P_Msg *msg = &msg_node->msg; + // if (NET_IsKeyNil(msg->dst)) + // { + // // Broadcast msg + // for (S_Client *client = S.first_client; client; client = client->next) + // { + // P_MsgNode *dst_msg_node = PushStruct(frame_arena, P_MsgNode); + // *dst_msg_node = *msg_node; + // DllQueuePush(client->out_msgs.first, client->out_msgs.last, dst_msg_node); + // ++client->out_msgs.count; + // } + // } + // else + // { + // // Targeted msg + // S_Client client = S_ClientFromNetKey(msg->dst); + // if (!S_IsClientNil(client)) + // { + + // } + // } + // } + + // for (S_Client *client = first_client; client; client = client->next) + // { + // } + // } + + + // for (P_MsgNode *msg_node = P_tl.out_msgs.first; msg_node; msg_node = msg_node->next) + // { + // P_Msg *msg = &msg_node->msg; + // if (P_IsKeyNil(msg->dst_user)) + // { + // // Broadcast + // String packed = P_PackMessage(frame_arena, msg); + // for (P_Ent *user = P_FirstEnt(world_frame); !P_IsEntNil(user); user = P_NextEnt(user)) + // { + // if (user->is_user) + // { + // NET_Push(net_pipe, user->net, packed, msg->burst); + // } + // } + // } + // else + // { + // P_Ent *user = P_EntFromKey(world_frame, msg->dst_user); + // if (!NET_IsKeyNil(user->net)) + // { + // String packed = P_PackMessage(frame_arena, msg); + // NET_Push(net_pipe, user->net, packed, msg->burst); + // } + // } + // } + + + + + + + + + // for (P_MsgNode *msg_node = P_tl.out_msgs.first; msg_node; msg_node = msg_node->next) + // { + // P_Msg *msg = &msg_node->msg; + // if (P_IsKeyNil(msg->dst_user)) + // { + // // Broadcast + // String packed = P_PackMessage(frame_arena, msg); + // for (P_Ent *user = P_FirstEnt(world_frame); !P_IsEntNil(user); user = P_NextEnt(user)) + // { + // if (user->is_user) + // { + // NET_Push(net_pipe, user->net, packed, msg->burst); + // } + // } + // } + // else + // { + // P_Ent *user = P_EntFromKey(world_frame, msg->dst_user); + // if (!NET_IsKeyNil(user->net)) + // { + // String packed = P_PackMessage(frame_arena, msg); + // NET_Push(net_pipe, user->net, packed, msg->burst); + // } + // } + // } + + + + // // TODO: Only copy active entities // LockTicketMutex(&P.sim_output_back_tm); // { diff --git a/src/pp/pp_sim/pp_sim_core.h b/src/pp/pp_sim/pp_sim_core.h index 21c97a65..ecd8d390 100644 --- a/src/pp/pp_sim/pp_sim_core.h +++ b/src/pp/pp_sim/pp_sim_core.h @@ -1,3 +1,26 @@ +//////////////////////////////////////////////////////////// +//~ Client types + +Struct(S_Client) +{ + S_Client *next; + S_Client *prev; + S_Client *next_in_bin; + S_Client *prev_in_bin; + + u64 hash; + NET_Key net_key; + P_MsgList out_msgs; + + u64 remote_tiles_hash; +}; + +Struct(S_ClientBin) +{ + S_Client *first; + S_Client *last; +}; + //////////////////////////////////////////////////////////// //~ State types @@ -5,9 +28,16 @@ Struct(S_Ctx) { Atomic32 shutdown; Fence shutdown_fence; + + S_Client *first_client; + S_Client *last_client; + + i64 client_bins_count; + S_ClientBin *client_bins; }; extern S_Ctx S; +extern Readonly S_Client S_NilClient; //////////////////////////////////////////////////////////// //~ Bootstrap @@ -15,6 +45,13 @@ extern S_Ctx S; void S_Bootstrap(void); void S_Shutdown(void); +//////////////////////////////////////////////////////////// +//~ Helpers + + +b32 S_IsClientNil(S_Client *client); +S_Client *S_ClientFromNetKey(NET_Key key); + //////////////////////////////////////////////////////////// //~ Sim tick diff --git a/src/pp/pp_transcode.c b/src/pp/pp_transcode.c index 50bd4ca4..6d3cd353 100644 --- a/src/pp/pp_transcode.c +++ b/src/pp/pp_transcode.c @@ -198,16 +198,49 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed) //////////////////////////////////////////////////////////// //~ Message -String P_PackMessage(Arena *arena, P_Msg *msg) +String P_PackMessages(BB_Writer *bbw, P_MsgList msgs) { + u64 pos_start = BB_GetNumBytesWritten(bbw); + { + for (P_MsgNode *msg_node = msgs.first; msg_node; msg_node = msg_node->next) + { + // TODO: Compress + P_Msg *msg = &msg_node->msg; + BB_WriteBytes(bbw, StringFromStruct(msg)); + BB_WriteString(bbw, msg->data); + } + } + u64 pos_end = BB_GetNumBytesWritten(bbw); String result = Zi; - // TODO + result.text = BB_GetWrittenRaw(bbw) + pos_start; + result.len = pos_end - pos_start; return result; } -P_Msg P_UnpackMsg(Arena *arena, String packed) +P_MsgList P_UnpackMessages(Arena *arena, String packed) { - P_Msg result = Zi; - // TODO + P_MsgList result = Zi; + BB_Buff bb = BB_BuffFromString(packed); + BB_Reader bbr = BB_ReaderFromBuff(&bb); + b32 done = 0; + while (!done) + { + u8 *msg_raw = BB_ReadBytesRaw(&bbr, sizeof(P_Msg)); + if (msg_raw != 0) + { + // Read msg header + P_MsgNode *dst_msg_node = PushStruct(arena, P_MsgNode); + CopyStruct(&dst_msg_node->msg, msg_raw); + DllQueuePush(result.first, result.last, dst_msg_node); + result.count += 1; + // Read msg data string + String data_str = BB_ReadString(arena, &bbr); + dst_msg_node->msg.data = data_str; + } + else + { + done = 1; + } + } return result; } diff --git a/src/pp/pp_transcode.h b/src/pp/pp_transcode.h index 2bc744fe..8825d095 100644 --- a/src/pp/pp_transcode.h +++ b/src/pp/pp_transcode.h @@ -32,5 +32,5 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed); //////////////////////////////////////////////////////////// //~ Message -String P_PackMessage(Arena *arena, P_Msg *msg); -P_Msg P_UnpackMsg(Arena *arena, String packed); +String P_PackMessages(BB_Writer *bbw, P_MsgList msgs); +P_MsgList P_UnpackMessages(Arena *arena, String packed); diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index b70fd7a0..f79af252 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -346,6 +346,8 @@ void V_TickForever(WaveLaneCtx *lane) const f32 meters_per_draw_width = 18; NET_PipeHandle net_pipe = NET_AcquirePipe(); + BB_Buff packer_bb = BB_AcquireDynamicBuff(Gibi(64)); + BB_Writer packer_bbw = BB_WriterFromBuff(&packer_bb); ////////////////////////////// //- Init vis state @@ -563,46 +565,46 @@ void V_TickForever(WaveLaneCtx *lane) { //- Init bitbuff BB_Buff bb = Zi; - BB_Writer bw = Zi; - BB_Reader br = Zi; + BB_Writer bbw = Zi; + BB_Reader bbr = Zi; if (swapout) { u64 max_size = Mebi(64); u8 *bytes = PushStructsNoZero(frame->arena, u8, max_size); bb = BB_BuffFromString(STRING(max_size, bytes)); - bw = BB_WriterFromBuff(&bb); + bbw = BB_WriterFromBuff(&bb); } else { String swap_encoded = SwappedStateFromName(frame->arena, Lit("pp_vis.swp")); bb = BB_BuffFromString(swap_encoded); - br = BB_ReaderFromBuff(&bb); + bbr = BB_ReaderFromBuff(&bb); } //- Transcode swap state if (swapout) { - BB_WriteUBits(&bw, V.user_key.v, 64); - BB_WriteBit(&bw, prev_frame->is_editing); - BB_WriteF32(&bw, prev_frame->edit_camera_pos.x); - BB_WriteF32(&bw, prev_frame->edit_camera_pos.y); - BB_WriteF32(&bw, prev_frame->edit_camera_zoom); - BB_WriteString(&bw, prev_frame->window_restore); + BB_WriteUBits(&bbw, V.user_key.v, 64); + BB_WriteBit(&bbw, prev_frame->is_editing); + BB_WriteF32(&bbw, prev_frame->edit_camera_pos.x); + BB_WriteF32(&bbw, prev_frame->edit_camera_pos.y); + BB_WriteF32(&bbw, prev_frame->edit_camera_zoom); + BB_WriteString(&bbw, prev_frame->window_restore); } else { - V.user_key.v = BB_ReadUBits(&br, 64); - frame->is_editing = BB_ReadBit(&br); - frame->edit_camera_pos.x = BB_ReadF32(&br); - frame->edit_camera_pos.y = BB_ReadF32(&br); - frame->edit_camera_zoom = BB_ReadF32(&br); - frame->window_restore = BB_ReadString(frame->arena, &br); + V.user_key.v = BB_ReadUBits(&bbr, 64); + frame->is_editing = BB_ReadBit(&bbr); + frame->edit_camera_pos.x = BB_ReadF32(&bbr); + frame->edit_camera_pos.y = BB_ReadF32(&bbr); + frame->edit_camera_zoom = BB_ReadF32(&bbr); + frame->window_restore = BB_ReadString(frame->arena, &bbr); } //- Write swapout if (swapout) { - WriteSwappedState(Lit("pp_vis.swp"), STRING(BB_GetNumBytesWritten(&bw), BB_GetWrittenRaw(&bw))); + WriteSwappedState(Lit("pp_vis.swp"), STRING(BB_GetNumBytesWritten(&bbw), BB_GetWrittenRaw(&bbw))); } } } @@ -2655,25 +2657,84 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Pop messages from sim + + + + // FIXME: Reject messages if not from currently connected sim + + + + P_MsgList in_msgs = Zi; { NET_Bind(net_pipe, 0); NET_MsgList net_msgs = NET_Swap(frame->arena, net_pipe); for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) { + NET_Key net_key = net_msg->sender; + String address_str = NET_StringFromKey(frame->arena, net_key); + LogDebugF("Received message from server \"%F\"", FmtString(address_str)); + String packed = net_msg->data; - P_MsgNode *dst_msg_node = PushStruct(frame->arena, P_MsgNode); - P_Msg *dst_msg = &dst_msg_node->msg; - *dst_msg = P_UnpackMsg(frame->arena, packed); - // FIXME: Set src user here based on net key - // dst_msg->src_user = - DllQueuePush(in_msgs.first, in_msgs.last, dst_msg_node); - ++in_msgs.count; + + P_MsgList server_msgs = P_UnpackMessages(frame->arena, packed); + if (server_msgs.first) + { + if (in_msgs.last) + { + in_msgs.last->next = server_msgs.first; + } + else + { + in_msgs.first = server_msgs.first; + } + server_msgs.first->prev = in_msgs.last; + in_msgs.last = server_msgs.last; + in_msgs.count += server_msgs.count; + } } } + + + + + + + + + + + // P_MsgList in_msgs = Zi; + // { + // NET_Bind(net_pipe, 0); + // NET_MsgList net_msgs = NET_Swap(frame->arena, net_pipe); + // for (NET_Msg *net_msg = net_msgs.first; net_msg; net_msg = net_msg->next) + // { + // NET_Key net_key = net_msg->sender; + // String address_str = NET_StringFromKey(frame->arena, net_key); + // LogDebugF("Received message from server \"%F\"", FmtString(address_str)); + + + + + // String packed = net_msg->data; + // P_MsgNode *dst_msg_node = PushStruct(frame->arena, P_MsgNode); + // P_Msg *dst_msg = &dst_msg_node->msg; + // *dst_msg = P_UnpackMsg(frame->arena, packed); + // // FIXME: Set src user here based on net key + // // dst_msg->src_user = + // DllQueuePush(in_msgs.first, in_msgs.last, dst_msg_node); + // ++in_msgs.count; + // } + // } + + + + + // { // LockTicketMutex(&P.s2u_snapshot_mutex); // P_SimSnapshot *src_snapshot = &P.s2u_snapshot; @@ -2724,13 +2785,13 @@ void V_TickForever(WaveLaneCtx *lane) { P_Msg *msg = &msg_node->msg; - if (msg->kind == P_MsgKind_SimSnapshot && msg->sim_snapshot.tick > sim_world->last_frame->tick) - { - if (!newest_snapshot_msg || msg->sim_snapshot.tick > newest_snapshot_msg->sim_snapshot.tick) - { - newest_snapshot_msg = msg; - } - } + // if (msg->kind == P_MsgKind_SimSnapshot && msg->sim_snapshot.tick > sim_world->last_frame->tick) + // { + // if (!newest_snapshot_msg || msg->sim_snapshot.tick > newest_snapshot_msg->sim_snapshot.tick) + // { + // newest_snapshot_msg = msg; + // } + // } //- Chat // if (msg->kind == P_MsgKind_Chat) @@ -2769,50 +2830,50 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Apply sim snapshot - if (newest_snapshot_msg) - { - P_SimSnapshot *snapshot = &newest_snapshot_msg->sim_snapshot; + // if (newest_snapshot_msg) + // { + // P_SimSnapshot *snapshot = &newest_snapshot_msg->sim_snapshot; - P_Frame *src_frame = P_FrameFromTick(sim_world, snapshot->src_tick); - P_Frame *dst_frame = P_PushFrame(sim_world, src_frame, snapshot->tick); - sim_world->seed = snapshot->world_seed; - dst_frame->time_ns = snapshot->time_ns; + // P_Frame *src_frame = P_FrameFromTick(sim_world, snapshot->src_tick); + // P_Frame *dst_frame = P_PushFrame(sim_world, src_frame, snapshot->tick); + // sim_world->seed = snapshot->world_seed; + // dst_frame->time_ns = snapshot->time_ns; - //- Apply deltas - for (P_SimDeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) - { - P_SimDelta *delta = &dn->delta; - //- Raw ent - if (delta->kind == P_SimDeltaKind_RawEnt) - { - P_Ent tmp_ent = delta->ent; - P_EntListNode tmp_ent_node = Zi; - tmp_ent_node.ent = tmp_ent; - P_EntList ent_list = Zi; - ent_list.first = &tmp_ent_node; - ent_list.last = &tmp_ent_node; - P_SpawnEntsFromList(dst_frame, ent_list); - } - } + // //- Apply deltas + // for (P_SimDeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) + // { + // P_SimDelta *delta = &dn->delta; + // //- Raw ent + // if (delta->kind == P_SimDeltaKind_RawEnt) + // { + // P_Ent tmp_ent = delta->ent; + // P_EntListNode tmp_ent_node = Zi; + // tmp_ent_node.ent = tmp_ent; + // P_EntList ent_list = Zi; + // ent_list.first = &tmp_ent_node; + // ent_list.last = &tmp_ent_node; + // P_SpawnEntsFromList(dst_frame, ent_list); + // } + // } - //- Update sim debug info - // { - // ResetArena(sim_debug_arena); - // first_sim_debug_draw_node = 0; - // last_sim_debug_draw_node = 0; - // { - // i64 dst_idx = 0; - // P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, snapshot->debug_draw_nodes_count); - // for (P_DebugDrawNode *src = snapshot->first_debug_draw_node; src; src = src->next) - // { - // P_DebugDrawNode *dst = &dst_nodes[dst_idx]; - // *dst = *src; - // dst_idx += 1; - // SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst); - // } - // } - // } - } + // //- Update sim debug info + // // { + // // ResetArena(sim_debug_arena); + // // first_sim_debug_draw_node = 0; + // // last_sim_debug_draw_node = 0; + // // { + // // i64 dst_idx = 0; + // // P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, snapshot->debug_draw_nodes_count); + // // for (P_DebugDrawNode *src = snapshot->first_debug_draw_node; src; src = src->next) + // // { + // // P_DebugDrawNode *dst = &dst_nodes[dst_idx]; + // // *dst = *src; + // // dst_idx += 1; + // // SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst); + // // } + // // } + // // } + // } // TODO: Remove this P_ClearFrames(sim_world, I64Min, sim_world->last_frame->tick - 1); @@ -3790,12 +3851,23 @@ void V_TickForever(WaveLaneCtx *lane) - for (P_MsgNode *msg_node = P_tl.out_msgs.first; msg_node; msg_node = msg_node->next) + // for (P_MsgNode *msg_node = P_tl.out_msgs.first; msg_node; msg_node = msg_node->next) + // { + // P_Msg *msg = &msg_node->msg; + // String packed = P_PackMessage(frame->arena, msg); + // NET_Push(net_pipe, server_key, packed, msg->burst); + // } + { - P_Msg *msg = &msg_node->msg; - String packed = P_PackMessage(frame->arena, msg); - NET_Push(net_pipe, server_key, packed, msg->burst); + if (P_tl.out_msgs.count > 0) + { + BB_ResetWriter(&packer_bbw); + String packed = P_PackMessages(&packer_bbw, P_tl.out_msgs); + NET_Push(net_pipe, server_key, packed, 0); + + } } + ResetArena(P_tl.out_msgs_arena); ZeroStruct(&P_tl.out_msgs); diff --git a/src/tar/tar.c b/src/tar/tar.c deleted file mode 100644 index 0224089a..00000000 --- a/src/tar/tar.c +++ /dev/null @@ -1,139 +0,0 @@ -Readonly TAR_Entry TAR_nil_entry = Zi; - -//////////////////////////////////////////////////////////// -//~ Helpers - -u64 TAR_U64FromOctString(String str) -{ - u64 n = 0; - for (u64 i = 0; i < str.len; ++i) - { - n *= 8; - n += (u64)(str.text[i]) - '0'; - } - return n; -} - -//////////////////////////////////////////////////////////// -//~ Archive - -// `prefix` will be prepended to all file names in the archive -// -// NOTE: The resulting archive merely points into the supplied tar data, no -// copying is done. Accessing the archive assumes that the data string is still valid. -TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix) -{ - TAR_Archive archive = ZI; - BB_Buff bb = BitbuffFromString(data); - BB_Reader br = BB_ReaderFromBuffNoDebug(&bb); - - u64 num_files = 0; - while (BB_NumBytesRemaining(&br) > 1024) - { - - TAR_Header header = ZI; - BB_ReadBytes(&br, StringFromStruct(&header)); - - if (!MatchString(StringFromFixedArray(header.ustar_indicator), Lit("ustar\0"))) - { - // Invalid header - Assert(0); - continue; - } - - if (header.file_name_prefix[0] != 0) - { - // Header file name prefix not supported - Assert(0); - continue; - } - - String file_size_oct_str = { .len = 11, .text = header.file_size }; - - u64 file_size = TAR_U64FromOctString(file_size_oct_str); - u8 *file_data_ptr = BB_ReadBytesRaw(&br, file_size); - if (!file_data_ptr) - { - file_size = 0; - } - String file_data = STRING(file_size, file_data_ptr); - - // Skip sector padding - u64 remaining = (512 - (file_size % 512)) % 512; - BB_SeekBytes(&br, remaining); - - b32 is_dir = header.file_type == TAR_FileKind_Directory; - if (!is_dir && header.file_type != TAR_FileKind_File) - { - // Unsupported type - Assert(header.file_type == TAR_FileKind_PaxHeaderX || header.file_type == TAR_FileKind_PaxHeaderG); - continue; - } - - String file_name_cstr = StringFromCstrNoLimit((char *)header.file_name); - if (file_name_cstr.len >= 2) - { - // Chop off './' prefix - file_name_cstr.len -= 2; - file_name_cstr.text += 2; - } - String file_name = CatString(arena, prefix, file_name_cstr); - - TAR_Entry *entry = PushStruct(arena, TAR_Entry); - entry->valid = 1; - entry->is_dir = is_dir; - entry->file_name = file_name; - entry->data = file_data; - - entry->next = archive.head; - archive.head = entry; - ++num_files; - } - - // Build lookup table - archive.lookup = InitDict(arena, (u64)((f64)num_files * TAR_ArchiveLookupTableCapacityFactor)); - for (TAR_Entry *entry = archive.head; entry; entry = entry->next) - { - u64 hash = HashString(entry->file_name); - SetDictValue(arena, archive.lookup, hash, (u64)entry); - } - - // Build hierarchy - // - // NOTE: This is a separate pass because tar entry order is not guaranteed - // (IE file entries may be encountered before their parent directory entry) - for (TAR_Entry *entry = archive.head; entry; entry = entry->next) - { - // Enter into hierarchy - if (!entry->is_dir) - { - // Find parent entry - TAR_Entry *parent_entry = 0; - for (String parent_dir_name = entry->file_name; parent_dir_name.len > 0; --parent_dir_name.len) - { - if (parent_dir_name.text[parent_dir_name.len - 1] == '/') - { - u64 hash = HashString(parent_dir_name); - parent_entry = (TAR_Entry *)DictValueFromHash(archive.lookup, hash); - break; - } - } - // Insert child into parent's list - if (parent_entry) - { - entry->next_child = parent_entry->next_child; - parent_entry->next_child = entry; - } - } - } - - return archive; -} - -Readonly Global TAR_Entry g_nil_tar_entry = ZI; -TAR_Entry *TAR_EntryFromName(TAR_Archive *archive, String name) -{ - u64 hash = HashString(name); - TAR_Entry *lookup = (TAR_Entry *)DictValueFromHash(archive->lookup, hash); - return lookup ? lookup : &g_nil_tar_entry; -} diff --git a/src/tar/tar.h b/src/tar/tar.h deleted file mode 100644 index 0dcee73e..00000000 --- a/src/tar/tar.h +++ /dev/null @@ -1,80 +0,0 @@ -//////////////////////////////////////////////////////////// -//~ Archive types - -#define TAR_ArchiveLookupTableCapacityFactor 2.0 - -Struct(TAR_Entry) -{ - b32 valid; - String file_name; - String data; - - b32 is_dir; - TAR_Entry *next; - TAR_Entry *next_child; // If entry is dir, points to first child. Otherwise points to next sibling. -}; - -Struct(TAR_Archive) -{ - Dict *lookup; - TAR_Entry *head; -}; - -//////////////////////////////////////////////////////////// -//~ Header types - -Enum(TAR_FileKind) -{ - TAR_FileKind_File = '0', - TAR_FileKind_HardLink = '1', - TAR_FileKind_SymLink = '2', - TAR_FileKind_CharacterSpecial = '3', - TAR_FileKind_BlockSpecial = '4', - TAR_FileKind_Directory = '5', - TAR_FileKind_Fifo = '6', - TAR_FileKind_ContiguousFile = '7', - TAR_FileKind_PaxHeaderG = 'g', - TAR_FileKind_PaxHeaderX = 'x' -}; - -Packed(Struct(TAR_Header) -{ - // Pre-posix - u8 file_name[100]; - u8 file_mode[8]; - u8 owner_id[8]; - u8 group_id[8]; - u8 file_size[12]; - u8 last_modified[12]; - u8 checksum[8]; - - // Both - u8 file_type; - u8 linked_file_name[100]; - - // UStar - u8 ustar_indicator[6]; - u8 ustar_version[2]; - u8 owner_user_name[32]; - u8 owner_group_name[32]; - u8 device_major_number[8]; - u8 device_minor_number[8]; - u8 file_name_prefix[155]; - u8 padding[12]; -}); - -//////////////////////////////////////////////////////////// -//~ State types - -extern Readonly TAR_nil_entry; - -//////////////////////////////////////////////////////////// -//~ Helpers - -u64 TAR_U64FromOctString(String str); - -//////////////////////////////////////////////////////////// -//~ Archive - -TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix); -TAR_Entry *TAR_EntryFromName(TAR_Archive *archive, String name); diff --git a/src/tar/tar.lay b/src/tar/tar.lay deleted file mode 100644 index 1f4f899b..00000000 --- a/src/tar/tar.lay +++ /dev/null @@ -1,17 +0,0 @@ -@Layer tar - -////////////////////////////// -//- Dependencies - -@Dep platform -@Dep bitbuff - -////////////////////////////// -//- Api - -@IncludeC tar.h - -////////////////////////////// -//- Impl - -@IncludeC tar.c