terom@185: terom@185: #include terom@185: #include terom@185: terom@186: #include "Packet.hh" terom@400: #include "Platform.hh" terom@185: terom@425: #include terom@391: #include terom@391: terom@365: // XXX: assumes that sizeof(float32) == sizeof(int32); terom@365: terom@200: /* terom@200: * NetworkPacketInput terom@200: */ terom@200: template T NetworkPacketInput::read_val (void) { terom@185: T val; terom@185: terom@185: // read terom@185: read(&val, sizeof(T)); terom@185: terom@185: // return terom@185: return val; terom@185: } terom@185: terom@200: uint32_t NetworkPacketInput::read_uint32 (void) { terom@185: return ntohl(read_val()); terom@185: } terom@185: terom@200: uint16_t NetworkPacketInput::read_uint16 (void) { terom@185: return ntohs(read_val()); terom@185: } terom@185: terom@200: uint8_t NetworkPacketInput::read_uint8 (void) { terom@185: return read_val(); terom@185: } terom@185: terom@200: int32_t NetworkPacketInput::read_int32 (void) { terom@185: return ntohl(read_val()); terom@185: } terom@185: terom@200: int16_t NetworkPacketInput::read_int16 (void) { terom@185: return ntohs(read_val()); terom@185: } terom@185: terom@200: int8_t NetworkPacketInput::read_int8 (void) { terom@185: return read_val(); terom@185: } terom@185: terom@200: float NetworkPacketInput::read_float32 (void) { terom@185: int32_t ival = read_int32(); terom@365: float fval; terom@365: terom@365: assert(sizeof(ival) == sizeof(fval)); terom@185: terom@365: memcpy(&fval, &ival, sizeof(float)); terom@365: terom@365: return fval; terom@185: } terom@185: terom@200: Vector NetworkPacketInput::read_vector (void) { terom@185: float fx = read_float32(); terom@185: float fy = read_float32(); terom@185: terom@185: return Vector(fx, fy); terom@185: } terom@391: terom@391: size_t NetworkPacketInput::read_uncompressed (void *buf, size_t len) { terom@391: // given len terom@391: unsigned long inflate_size = len; terom@391: terom@391: // read deflate size terom@391: unsigned long deflate_size = read_uint32(); terom@391: terom@391: // pointer to packet data terom@391: const void *deflate_ptr = read_ptr(deflate_size); terom@391: terom@391: // uncompress the rest of the packet data terom@391: if (uncompress((uint8_t *) buf, &inflate_size, (const uint8_t *) deflate_ptr, deflate_size) != Z_OK) terom@391: throw Error("uncompress"); terom@391: terom@391: // return inflated size terom@391: return inflate_size; terom@391: } terom@185: terom@200: /* terom@200: * NetworkPacketOutput terom@200: */ terom@200: template void NetworkPacketOutput::write_val (const T &val) { terom@200: // write terom@200: write(&val, sizeof(T)); terom@200: } terom@200: terom@200: terom@200: void NetworkPacketOutput::write_uint32 (uint32_t val) { terom@185: write_val(htonl(val)); terom@185: } terom@185: terom@200: void NetworkPacketOutput::write_uint16 (uint16_t val) { terom@185: write_val(htons(val)); terom@185: } terom@185: terom@200: void NetworkPacketOutput::write_uint8 (uint8_t val) { terom@185: write_val(val); terom@185: } terom@185: terom@200: void NetworkPacketOutput::write_int32 (int32_t val) { terom@185: write_val(htonl(val)); terom@185: } terom@185: terom@200: void NetworkPacketOutput::write_int16 (int16_t val) { terom@185: write_val(htons(val)); terom@185: } terom@185: terom@200: void NetworkPacketOutput::write_int8 (int8_t val) { terom@185: write_val(val); terom@185: } terom@185: terom@365: void NetworkPacketOutput::write_float32 (float fval) { terom@365: int32_t ival; terom@365: terom@365: assert(sizeof(ival) == sizeof(fval)); terom@365: terom@365: memcpy(&ival, &fval, sizeof(int32_t)); terom@365: terom@365: write_int32(ival); terom@185: } terom@185: terom@200: void NetworkPacketOutput::write_vector (const Vector &vec) { terom@185: write_float32(vec.x); terom@185: write_float32(vec.y); terom@185: } terom@185: terom@200: void NetworkPacketOutput::write_packet (const NetworkPacketBuffer &pkt) { terom@200: // just write() it terom@200: write(pkt.get_buf(), pkt.get_data_size()); terom@185: } terom@391: terom@391: void NetworkPacketOutput::write_compressed (const void *ptr, uint32_t len) { terom@391: // full compression buffer size, including header terom@391: unsigned long deflate_buf_size = write_compressed_size(len); terom@391: terom@391: // size of compressed data area after header terom@391: unsigned long deflate_size = deflate_buf_size - sizeof(uint32_t); terom@391: terom@391: // packet buffer terom@391: void *deflate_buf = write_ptr(deflate_buf_size); terom@391: terom@391: // compress terom@391: if (compress((uint8_t *) deflate_buf + sizeof(uint32_t), &deflate_size, (const uint8_t *) ptr, len) != Z_OK) terom@391: throw Error("compress failed"); terom@391: terom@391: // write data size terom@391: *((uint32_t *) deflate_buf) = htonl(deflate_size); terom@391: terom@391: // adjust final area terom@391: write_ptr_adjust(deflate_buf_size, sizeof(uint32_t) + deflate_size); terom@391: } terom@391: terom@391: size_t NetworkPacketOutput::write_compressed_size (uint32_t len) { terom@391: return sizeof(uint32_t) + compressBound(len); terom@391: } terom@185: terom@200: /* terom@200: * NetworkPacketBuffer terom@200: */ terom@200: NetworkPacketBuffer::NetworkPacketBuffer (char *buf_ptr, size_t buf_size, size_t data_size) : terom@200: buf_ptr(buf_ptr), buf_size(buf_size), data_size(data_size), offset(0) { terom@200: terom@200: // nothing terom@200: if (buf_ptr == NULL) terom@200: throw NetworkPacketError("buf_ptr may not be NULL"); terom@200: } terom@200: terom@200: void NetworkPacketBuffer::check_write_size (size_t item_size) { terom@200: if (offset + item_size > buf_size) terom@200: throw NetworkPacketError("not enough space to write"); terom@200: terom@200: } terom@200: terom@200: void NetworkPacketBuffer::check_read_size (size_t item_size) { terom@200: if (offset + item_size > data_size) terom@200: throw NetworkPacketError("not enough data to read"); terom@200: } terom@387: terom@387: const void* NetworkPacketBuffer::read_ptr (size_t len) { terom@200: // check buffer overflow terom@391: check_read_size(len); terom@200: terom@387: // pointer value... terom@387: const void *ptr = buf_ptr + offset; terom@387: terom@387: // update offset terom@387: offset += len; terom@387: terom@387: // return pointer terom@387: return ptr; terom@387: } terom@387: terom@387: void* NetworkPacketBuffer::write_ptr (size_t len) { terom@387: // check buffer overflow terom@387: check_write_size(len); terom@387: terom@387: // pointer value... terom@387: void *ptr = buf_ptr + offset; terom@200: terom@200: // update offset and size terom@200: offset += len; terom@200: data_size += len; terom@387: terom@387: // return pointer terom@387: return ptr; terom@200: } terom@200: terom@200: void NetworkPacketBuffer::read (void *ptr, size_t len) { terom@387: // get input pointer... terom@387: const void *input_ptr = read_ptr(len); terom@200: terom@387: // copy value out terom@387: memcpy(ptr, input_ptr, len); terom@387: } terom@387: terom@387: void NetworkPacketBuffer::write (const void *ptr, size_t len) { terom@387: // get output pointer... terom@387: void *output_ptr = write_ptr(len); terom@200: terom@387: // copy value in terom@387: memcpy(output_ptr, ptr, len); terom@387: } terom@387: terom@391: void NetworkPacketBuffer::write_ptr_adjust (size_t buf_len, size_t data_len) { terom@391: assert(data_len <= buf_len); terom@391: terom@391: // adjust offset backwards terom@391: offset -= (buf_len - data_len); terom@391: data_size -= (buf_len - data_len); terom@391: } terom@391: terom@387: size_t NetworkPacketBuffer::tell_remaining (void) { terom@387: // number of bytes in total - number of bytes read terom@387: return data_size - offset; terom@200: } terom@200: terom@200: /* terom@200: * NetworkPacket terom@200: */ terom@200: NetworkPacket::NetworkPacket (void) : terom@200: NetworkPacketBuffer(_buf, NETWORK_PACKET_SIZE, 0) terom@200: { terom@200: terom@200: } terom@200: terom@200: /* terom@200: * BigNetworkPacket terom@200: */ terom@200: BigNetworkPacket::BigNetworkPacket (size_t size) : terom@200: NetworkPacketBuffer((char *) malloc(size), size, 0) terom@200: { terom@200: terom@200: } terom@200: terom@202: BigNetworkPacket::~BigNetworkPacket (void) { terom@202: free(buf_ptr); terom@202: } terom@202: