X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmoof%2Fpacket.cc;fp=src%2Fmoof%2Fpacket.cc;h=0440b7df5749760861dfdfc4a5c913220258a450;hb=831f04d4bc19a390415ac0bbac4331c7a65509bc;hp=0000000000000000000000000000000000000000;hpb=299af4f2047e767e5d79501c26444473bda64c64;p=chaz%2Fyoink diff --git a/src/moof/packet.cc b/src/moof/packet.cc new file mode 100644 index 0000000..0440b7d --- /dev/null +++ b/src/moof/packet.cc @@ -0,0 +1,398 @@ + +/*] Copyright (c) 2009-2010, Charles McGarvey [************************** +**] All rights reserved. +* +* vi:ts=4 sw=4 tw=75 +* +* Distributable under the terms and conditions of the 2-clause BSD license; +* see the file COPYING for a complete text of the license. +* +**************************************************************************/ + +#include "../config.h" + +#include +#if HAVE_BYTESWAP_H +#include +#endif +#include + +#if HAVE_ARPA_INET_H +#include +#endif + +#include + +#include "packet.hh" + + +#ifndef bswap_16 +#define bswap_16(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) +#endif + +#ifndef bswap_32 +#define bswap_32(x) ((((x) & 0xff000000) >> 24) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x000000ff) << 24)) +#endif + +#ifndef bswap_64 +#define bswap_64(x) (((x) << 56) | \ + (((x) << 40) & 0xff000000000000ULL) | \ + (((x) << 24) & 0xff0000000000ULL) | \ + (((x) << 8) & 0xff00000000ULL) | \ + (((x) >> 8) & 0xff000000ULL) | \ + (((x) >> 24) & 0xff0000ULL) | \ + (((x) >> 40) & 0xff00ULL) | \ + ((x) >> 56)) +#endif + + +#if !HAVE_ARPA_INET_H +static uint16_t htons(uint16_t x) +{ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + return bswap_16(x); +#else + return x; +#endif +} +static uint16_t ntohs(uint16_t x) +{ + return htons(x); +} + +static uint32_t htonl(uint32_t x) +{ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + return bswap_32(x); +#else + return x; +#endif +} +static uint32_t ntohl(uint32_t x) +{ + return htonl(x); +} +#endif + + +static uint64_t htonll(uint64_t x) +{ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + return bswap_64(x); +#else + return x; +#endif +} +static uint64_t ntohll(uint64_t x) +{ + return htonll(x); +} + + +namespace moof { + + +packet::packet(size_t size) : + buffer_((char*)malloc(size)), + size_(size) {} + +packet::packet(const char* data, size_t size) : + buffer_((char*)malloc(size)), + size_(size), + state_(size), + saved_(size) +{ + if (buffer_) memcpy(buffer_, data, size); + else throw std::length_error("out of memory"); +} + + +packet::packet(const packet& copy) : + buffer_((char*)malloc(copy.size_)), + size_(copy.size_), + state_(copy.state_), + saved_(copy.saved_) +{ + if (buffer_) memcpy(buffer_, copy.buffer_, size_); + else throw std::length_error("out of memory"); +} + +packet& packet::operator = (const packet& copy) +{ + free(buffer_); + buffer_ = (char*)malloc(copy.size_); + size_ = copy.size_; + if (buffer_) memcpy(buffer_, copy.buffer_, size_); + else throw std::length_error("out of memory"); + + state_ = copy.state_; + saved_ = copy.saved_; + return *this; +} + + +packet::~packet() +{ + free(buffer_); +} + + +packet& packet::operator << (bool value) +{ + int bit = state_.write_bool_num % 8; + if (bit == 0) + { + state_.write_bool_mark = state_.write_mark; + + unsigned char byte = 0; + if (write(&byte, 1) == 0) throw std::length_error("out of memory"); + } + + if (value) buffer_[state_.write_bool_mark] |= (1 << bit); + ++state_.write_bool_num; + + return *this; +} + + +packet& packet::operator << (int8_t value) +{ + return *this << reinterpret_cast(value); +} + +packet& packet::operator << (int16_t value) +{ + return *this << reinterpret_cast(value); +} + +packet& packet::operator << (int32_t value) +{ + return *this << reinterpret_cast(value); +} + +packet& packet::operator << (int64_t value) +{ + return *this << reinterpret_cast(value); +} + + +packet& packet::operator << (uint8_t value) +{ + if (write(&value, sizeof(value)) != sizeof(value)) + { + throw std::length_error("out of memory"); + } + return *this; +} + +packet& packet::operator << (uint16_t value) +{ + value = htons(value); + if (write(&value, sizeof(value)) != sizeof(value)) + { + throw std::length_error("out of memory"); + } + return *this; +} + +packet& packet::operator << (uint32_t value) +{ + value = htonl(value); + if (write(&value, sizeof(value)) != sizeof(value)) + { + throw std::length_error("out of memory"); + } + return *this; +} + +packet& packet::operator << (uint64_t value) +{ + value = htonll(value); + if (write(&value, sizeof(value)) != sizeof(value)) + { + throw std::length_error("out of memory"); + } + return *this; +} + +packet& packet::operator << (float value) +{ + // XXX: assumes the ieee-754 + uint32_t* integer = reinterpret_cast(&value); + *integer = htonl(*integer); + if (write(integer, sizeof(value)) != sizeof(value)) + { + throw std::length_error("out of memory"); + } + return *this; +} + +packet& packet::operator << (double value) +{ + // XXX: assumes the ieee-754 + uint64_t* integer = reinterpret_cast(&value); + *integer = htonll(*integer); + if (write(integer, sizeof(value)) != sizeof(value)) + { + throw std::length_error("out of memory"); + } + return *this; +} + +size_t packet::write(const void* bytes, size_t size) +{ + size_t num_bytes = std::min(size, size_ - state_.write_mark); + if (!buffer_ || num_bytes < size) + { + int num_pages = 1 + size / PAGE_SIZE; + int new_size = size_ + num_pages * PAGE_SIZE; + char* new_buffer = (char*)realloc(buffer_, new_size); + if (new_buffer) + { + buffer_ = new_buffer; + size_ = new_size; + num_bytes = size; + } + if (!buffer_) return 0; + } + memcpy(buffer_ + state_.write_mark, bytes, num_bytes); + state_.write_mark += num_bytes; + return num_bytes; +} + + +packet& packet::operator >> (bool& value) +{ + int bit = state_.read_bool_num % 8; + if (bit == 0) + { + state_.read_bool_mark = state_.read_mark; + + unsigned char byte = 0; + if (read(&byte, 1) == 0) throw std::out_of_range("end of packet"); + } + + value = 1 & (buffer_[state_.read_bool_mark] >> bit); + ++state_.read_bool_num; + + return *this; +} + +packet& packet::operator >> (int8_t& value) +{ + return *this >> reinterpret_cast(value); +} + +packet& packet::operator >> (int16_t& value) +{ + return *this >> reinterpret_cast(value); +} + +packet& packet::operator >> (int32_t& value) +{ + return *this >> reinterpret_cast(value); +} + +packet& packet::operator >> (int64_t& value) +{ + return *this >> reinterpret_cast(value); +} + +packet& packet::operator >> (uint8_t& value) +{ + if (read(&value, sizeof(value)) != sizeof(value)) + { + throw std::out_of_range("end of packet"); + } + return *this; +} + +packet& packet::operator >> (uint16_t& value) +{ + if (read(&value, sizeof(value)) != sizeof(value)) + { + throw std::out_of_range("end of packet"); + } + value = ntohs(value); + return *this; +} + +packet& packet::operator >> (uint32_t& value) +{ + if (read(&value, sizeof(value)) != sizeof(value)) + { + throw std::out_of_range("end of packet"); + } + value = ntohl(value); + return *this; +} + +packet& packet::operator >> (uint64_t& value) +{ + if (read(&value, sizeof(value)) != sizeof(value)) + { + throw std::out_of_range("end of packet"); + } + value = ntohll(value); + return *this; +} + +packet& packet::operator >> (float& value) +{ + // XXX: assumes the ieee-754 + uint32_t* integer = reinterpret_cast(&value); + if (read(integer, sizeof(value)) != sizeof(value)) + { + throw std::out_of_range("end of packet"); + } + *integer = htonl(*integer); + return *this; +} + +packet& packet::operator >> (double& value) +{ + // XXX: assumes the ieee-754 + uint64_t* integer = reinterpret_cast(&value); + if (read(integer, sizeof(value)) != sizeof(value)) + { + throw std::out_of_range("end of packet"); + } + *integer = htonll(*integer); + return *this; +} + +size_t packet::read(void* bytes, size_t size) +{ + size_t num_bytes = std::min(size, state_.write_mark - state_.read_mark); + memcpy(bytes, buffer_ + state_.read_mark, num_bytes); + state_.read_mark += num_bytes; + return num_bytes; +} + + +void packet::clear() +{ + state_.read_mark = state_.write_mark; + state_.read_bool_mark = 0; + state_.read_bool_num = 0; + state_.write_bool_mark = 0; + state_.write_bool_num = 0; +} + + +void packet::save() +{ + saved_ = state_; +} + +void packet::revert() +{ + state_ = saved_; +} + + +} // namespace moof +