From 2f239b9ba2a556a5ca810cfffc60552a56a4fe86 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Fri, 21 May 2010 03:41:17 -0600 Subject: [PATCH] tcp socket disconnecting by remote --- src/Moof/Service.cc | 18 +- src/Moof/Service.hh | 70 +++++++- src/Moof/Socket.hh | 27 ++- src/Moof/old/Packet.cc | 376 +++++++++++++++++++++++++++++++++++++++++ src/Moof/old/Packet.hh | 260 ++++++++++++++++++++++++++++ 5 files changed, 727 insertions(+), 24 deletions(-) create mode 100644 src/Moof/old/Packet.cc create mode 100644 src/Moof/old/Packet.hh diff --git a/src/Moof/Service.cc b/src/Moof/Service.cc index 400006b..3432ae6 100644 --- a/src/Moof/Service.cc +++ b/src/Moof/Service.cc @@ -38,7 +38,7 @@ int Service::handlePacket(SocketMultiplexer& sock, if (magic == SOLICIT) { Packet out; - out << RESPONSE << mAddress.service() << mText; + out << RESPONSE << mType << mName << mText; sock.socket().write(out); return 0; } @@ -55,13 +55,15 @@ int ServiceFinder::handlePacket(SocketMultiplexer& sock, packet >> magic; if (magic == RESPONSE) { - std::string service; - std::string text; - - packet >> service >> text; - if (service == mService) + std::string type; + packet >> type; + if (type == mType) { - mServices.push_back(Service(address, text)); + std::string name; + std::string text; + packet >> name >> text; + mServices.insert(std::make_pair(name, + Service(address, name, text))); return 0; } } @@ -73,7 +75,7 @@ int ServiceFinder::handlePacket(SocketMultiplexer& sock, return -1; } -ServiceFinder::ServiceFinder(const std::string& service, int type) +ServiceFinder::ServiceFinder(const std::string& type, int sockType) { } diff --git a/src/Moof/Service.hh b/src/Moof/Service.hh index 77cee18..b26f4cf 100644 --- a/src/Moof/Service.hh +++ b/src/Moof/Service.hh @@ -17,7 +17,7 @@ #ifndef _MOOF_SERVICE_HH_ #define _MOOF_SERVICE_HH_ -#include +#include #include #include @@ -34,18 +34,37 @@ class Service public: /** - * Construct a network service. + * Construct a network service. The type of service will be inferred + * from the address. * \param address The address of the host. + * \param name The service name. * \param text The service information. */ - Service(const SocketAddress& address, const std::string& text); + Service(const SocketAddress& address, + const std::string& name, + const std::string& text); + + /** + * Construct a network service with an explicit type. + * \param address The address of the host. + * \param type The type of service. + * \param name The service name. + * \param text The service information. + */ + Service(const SocketAddress& address, + const std::string& type, + const std::string& name, + const std::string& text); /** - * Publish the service on the local network. + * Publish the service on the network. */ void publish(); + /** + * Stop publishing the service on the network. + */ void stop(); @@ -58,6 +77,24 @@ public: return mAddress; } + /** + * Get the type of the service. + * \return The service type. + */ + const std::string& type() const + { + return mType; + } + + /** + * Get the service name. + * \return The service name. + */ + const std::string& name() const + { + return mName; + } + /** * Get the service information. * \return The service information as a string. @@ -68,6 +105,9 @@ public: } + ~Service(); + + private: int handlePacket(SocketMultiplexer& sock, @@ -75,6 +115,8 @@ private: const SocketAddress& address); SocketAddress mAddress; + std::string mType; + std::string mName; std::string mText; }; @@ -83,10 +125,22 @@ class ServiceFinder { public: - ServiceFinder(const std::string& service, int type = SOCK_STREAM); + /** + * Construct a service finder to find services of the same type as an + * address. + * \address The address. + */ + ServiceFinder(const SocketAddress& address); + + /** + * Construct a service finder to find services of a certain type. + * \param type The type of the service. + * \param sockType The type of socket. + */ + ServiceFinder(const std::string& type, int sockType = SOCK_STREAM); - const std::vector& services() const + const std::map& services() const { return mServices; } @@ -98,8 +152,8 @@ private: Packet& packet, const SocketAddress& address); - std::string mService; - std::vector mServices; + std::string mType; + std::map mServices; }; diff --git a/src/Moof/Socket.hh b/src/Moof/Socket.hh index a4cb310..17e841c 100644 --- a/src/Moof/Socket.hh +++ b/src/Moof/Socket.hh @@ -729,11 +729,13 @@ public: * \param flags The send options. * \return The number of bytes written. */ - ssize_t write(const void* bytes, size_t size, - const SocketAddress& address, int flags = 0) + ssize_t write(const void* bytes, + size_t size, + const SocketAddress& address, + int flags = 0) { return sendto(mImpl.fd, bytes, size, flags, - address.address(), address.size()); + address.address(), address.size()); } /** @@ -755,8 +757,9 @@ public: * \param flags The send options. * \return The number of bytes written. */ - ssize_t write(const Packet& packet, const SocketAddress& address, - int flags = 0) + ssize_t write(const Packet& packet, + const SocketAddress& address, + int flags = 0) { return write(packet.bytes(), packet.size(), address, flags); } @@ -771,7 +774,9 @@ public: */ ssize_t read(void* bytes, size_t size, int flags = 0) { - return recv(mImpl.fd, bytes, size, flags); + ssize_t result = recv(mImpl.fd, bytes, size, flags); + if (result == 0) mImpl.isConnected = false; + return result; } /** @@ -783,8 +788,10 @@ public: * \param flags The recv options. * \return The number of bytes read. */ - ssize_t read(void* bytes, size_t size, SocketAddress& address, - int flags = 0) + ssize_t read(void* bytes, + size_t size, + SocketAddress& address, + int flags = 0) { union { @@ -799,6 +806,10 @@ public: { address = SocketAddress(&addr.sa, length, mImpl.address.type()); } + else if (result == 0) + { + mImpl.isConnected = false; + } return result; } diff --git a/src/Moof/old/Packet.cc b/src/Moof/old/Packet.cc new file mode 100644 index 0000000..2bbceb5 --- /dev/null +++ b/src/Moof/old/Packet.cc @@ -0,0 +1,376 @@ + +/*] 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 Mf { + + +Packet::Packet(size_t capacity) : + mBuffer((char*)malloc(capacity)), + mSize(capacity), + mR(0), + mW(0), + mOriginalW(0), + mBoolR(0), + mBoolW(0), + mBoolNumR(0), + mBoolNumW(0) {} + +Packet::Packet(const char* data, size_t size) : + mBuffer((char*)malloc(size)), + mSize(size), + mR(0), + mW(size), + mOriginalW(size), + mBoolR(0), + mBoolW(0), + mBoolNumR(0), + mBoolNumW(0) +{ + if (mBuffer) memcpy(mBuffer, data, size); +} + + +Packet::Packet(const Packet& copy) : + mBuffer((char*)malloc(copy.mSize)), + mSize(copy.mSize), + mR(copy.mR), + mW(copy.mW), + mOriginalW(copy.mOriginalW), + mBoolR(copy.mBoolR), + mBoolW(copy.mBoolW), + mBoolNumR(copy.mBoolNumR), + mBoolNumW(copy.mBoolNumW) +{ + if (mBuffer) memcpy(mBuffer, copy.mBuffer, mSize); +} + +Packet& Packet::operator=(const Packet& copy) +{ + free(mBuffer); + + mBuffer = (char*)malloc(copy.mSize); + mSize = copy.mSize; + mR = copy.mR; + mW = copy.mW; + mOriginalW = copy.mOriginalW; + mBoolR = copy.mBoolR; + mBoolW = copy.mBoolW; + mBoolNumR = copy.mBoolNumR; + mBoolNumW = copy.mBoolNumW; + if (mBuffer) memcpy(mBuffer, copy.mBuffer, mSize); + return *this; +} + + +Packet::~Packet() +{ + free(mBuffer); +} + + +bool Packet::put(bool value) +{ + int bit = mBoolNumW % 8; + if (bit == 0) + { + mBoolW = mW; + + unsigned char byte = 0; + if (write(&byte, 1) == 0) return false; + } + + if (value) mBuffer[mBoolW] |= (1 << bit); + ++mBoolNumW; + return true; +} + + +bool Packet::put(int8_t value) +{ + return put(uint8_t(value)); +} + +bool Packet::put(int16_t value) +{ + return put(uint16_t(value)); +} + +bool Packet::put(int32_t value) +{ + return put(uint32_t(value)); +} + +bool Packet::put(int64_t value) +{ + return put(uint64_t(value)); +} + + +bool Packet::put(uint8_t value) +{ + return write(&value, sizeof(value)) == sizeof(value); +} + +bool Packet::put(uint16_t value) +{ + value = htons(value); + return write(&value, sizeof(value)) == sizeof(value); +} + +bool Packet::put(uint32_t value) +{ + value = htonl(value); + return write(&value, sizeof(value)) == sizeof(value); +} + +bool Packet::put(uint64_t value) +{ + value = htonll(value); + return write(&value, sizeof(value)) == sizeof(value); +} + +bool Packet::put(float value) +{ + // XXX: assumes the ieee-754 + uint32_t* integer = reinterpret_cast(&value); + *integer = htonl(*integer); + return write(integer, sizeof(value)) == sizeof(value); +} + +bool Packet::put(double value) +{ + // XXX: assumes the ieee-754 + uint64_t* integer = reinterpret_cast(&value); + *integer = htonll(*integer); + return write(integer, sizeof(value)) == sizeof(value); +} + + +size_t Packet::write(const void* bytes, size_t size) +{ + size_t nBytes = std::min(size, mSize - mW); + if (!mBuffer || nBytes < size) + { + int nPages = 1 + size / PAGE_SIZE; + int newSize = mSize + nPages * PAGE_SIZE; + char* newBuffer = (char*)realloc(mBuffer, newSize); + if (newBuffer) + { + mBuffer = newBuffer; + mSize = newSize; + nBytes = size; + } + if (!mBuffer) return 0; + } + memcpy(mBuffer + mW, bytes, nBytes); + mW += nBytes; + return nBytes; +} + + +bool Packet::get(bool& value, int flags) +{ + int bit = mBoolNumR % 8; + if (bit == 0) + { + mBoolR = mR; + + unsigned char byte = 0; + if (read(&byte, 1, flags) == 0) return false; + } + + value = 1 & (mBuffer[mBoolR] >> bit); + if (!(flags & PEEK)) ++mBoolNumR; + return true; +} + +bool Packet::get(int8_t& value, int flags) +{ + return get((uint8_t&)value, flags); +} + +bool Packet::get(int16_t& value, int flags) +{ + return get((uint16_t&)value, flags); +} + +bool Packet::get(int32_t& value, int flags) +{ + return get((uint32_t&)value, flags); +} + +bool Packet::get(int64_t& value, int flags) +{ + return get((uint64_t&)value, flags); +} + +bool Packet::get(uint8_t& value, int flags) +{ + size_t numBytes = read(&value, sizeof(value), flags); + return numBytes == sizeof(value); +} + +bool Packet::get(uint16_t& value, int flags) +{ + size_t numBytes = read(&value, sizeof(value), flags); + value = ntohs(value); + return numBytes == sizeof(value); +} + +bool Packet::get(uint32_t& value, int flags) +{ + size_t numBytes = read(&value, sizeof(value), flags); + value = ntohl(value); + return numBytes == sizeof(value); +} + +bool Packet::get(uint64_t& value, int flags) +{ + size_t numBytes = read(&value, sizeof(value), flags); + value = ntohll(value); + return numBytes == sizeof(value); +} + +bool Packet::get(float& value, int flags) +{ + // XXX: assumes the ieee-754 + uint32_t* integer = reinterpret_cast(&value); + size_t numBytes = read(integer, sizeof(value)); + *integer = htonl(*integer); + return numBytes == sizeof(value); +} + +bool Packet::get(double& value, int flags) +{ + // XXX: assumes the ieee-754 + uint64_t* integer = reinterpret_cast(&value); + size_t numBytes = read(integer, sizeof(value)); + *integer = htonll(*integer); + return numBytes == sizeof(value); +} + + +size_t Packet::read(void* bytes, size_t size, int flags) +{ + size_t nBytes = std::min(size, mW - mR); + memcpy(bytes, mBuffer + mR, nBytes); + if (!(flags & PEEK)) mR += nBytes; + return nBytes; +} + + +void Packet::clear() +{ + mR = 0; + mW = 0; + mBoolR = 0; + mBoolW = 0; + mBoolNumR = 0; + mBoolNumW = 0; +} + + +void Packet::reset() +{ + mR = 0; + mW = mOriginalW; + mBoolR = 0; + mBoolW = 0; + mBoolNumR = 0; + mBoolNumW = 0; +} + + +} // namespace Mf + diff --git a/src/Moof/old/Packet.hh b/src/Moof/old/Packet.hh new file mode 100644 index 0000000..c6cf4bf --- /dev/null +++ b/src/Moof/old/Packet.hh @@ -0,0 +1,260 @@ + +/*] 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. +* +**************************************************************************/ + +/** + * \file Packet.hh + * Classes for building and interpreting datagram packets. + */ + +#ifndef _MOOF_PACKET_HH_ +#define _MOOF_PACKET_HH_ + +#include +#include +#include + + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + + +namespace Mf { + + +/** + * Represents a packet of serialized variables ready for transfer over the + * network. This method is most suitable for representing datagram + * packets, but it may also be useful for seralizing data for persistent + * state storage. The semantics are similar to that of a FIFO queue or + * stream where packets are written and read by inserting and extracting + * variables to and from the packet, although the actual order of the + * variables in the buffer may be different. At any time, a pointer to a + * buffer and the size of the buffer can be retrieved. This class also + * handles endian differences by serializing variables in network byte + * order (big endian). + */ +class Packet +{ +public: + + /** + * Packet flags. + */ + enum Flags + { + PEEK = 0x01 /// Do not actually remove anything. + }; + + + /** + * Construct a packet with an initial capacity. + * \param capacity Initial capacity of the packet. + */ + Packet(size_t capacity = PAGE_SIZE); + + /** + * Construct a packet with some bytes from a buffer. The bytes will be + * copied into the packet, so you don't need to keep the original + * buffer. + * \param data The bytes. + * \param size The number of bytes. + */ + Packet(const char* data, size_t size); + + + /** + * Insert a variable into the packet, serializing it. This usually + * increases the size of the packet by the size of the data type. + * \param value The value to insert. + * \return This. + */ + bool put(bool value); + bool put(int8_t value); + bool put(int16_t value); + bool put(int32_t value); + bool put(int64_t value); + bool put(uint8_t value); + bool put(uint16_t value); + bool put(uint32_t value); + bool put(uint64_t value); + bool put(float value); + bool put(double value); + + bool put(const char* value) + { + uint16_t length = strlen(value); + if (put(length)) + { + size_t numBytes = write(value, length); + return numBytes == length; + } + return false; + } + + template + bool put(const std::basic_string& value) + { + if (put(uint16_t(value.length()))) + { + size_t byteLength = value.length() * sizeof(T); + size_t numBytes = write(value.data(), byteLength); + return numBytes == byteLength; + } + return false; + } + + template + bool put(const std::vector& value) + { + if (put(uint16_t(value.size()))) + { + typename std::vector::const_iterator it; + for (it = value.begin(); it != value.end(); ++it) + { + if (!put(*it)) return false; + } + return true; + } + return false; + } + + + /** + * Write some bytes to the packet. + * \param bytes The bytes. + * \param size The number of bytes. + * return The number of bytes actually written. + */ + size_t write(const void* bytes, size_t size); + + + /** + * Extract a variable from the packet. This usually decreases the size + * of the packet by the size of the data type. + * \param value Reference to the variable to extract. + * \return This. + */ + bool get(bool& value, int flags = 0); + bool get(int8_t& value, int flags = 0); + bool get(int16_t& value, int flags = 0); + bool get(int32_t& value, int flags = 0); + bool get(int64_t& value, int flags = 0); + bool get(uint8_t& value, int flags = 0); + bool get(uint16_t& value, int flags = 0); + bool get(uint32_t& value, int flags = 0); + bool get(uint64_t& value, int flags = 0); + bool get(float& value, int flags = 0); + bool get(double& value, int flags = 0); + + template + bool get(std::basic_string& value, int flags = 0) + { + uint16_t length = 0; + if (get(length, flags)) + { + size_t byteLength = length * sizeof(T); + T str[length]; + size_t numBytes = read(str, byteLength, flags); + value.assign(str, numBytes); + return numBytes == byteLength; + } + return false; + } + + template + bool get(std::vector& value, int flags = 0) + { + uint16_t size = 0; + if (get(size, flags)) + { + value.clear(); + for (uint16_t i = 0; i < size; ++i) + { + T item; + if (get(item, flags)) value.push_back(item); + else return false; + } + return true; + } + return false; + } + + /** + * Read some bytes from the packet. + * \param bytes The buffer to hold the bytes read. + * \param size The size of the read buffer. + * \return The number of bytes actually read. + */ + size_t read(void* bytes, size_t size, int flags = 0); + + + /** + * Clear the contents of the packet, setting the size of the packet to + * zero. + */ + void clear(); + + + /** + * Reset the read/write markers to their initial positions, putting the + * packet in the state it was at right after construction. + */ + void reset(); + + + /** + * Get a pointer to an internal structure holding the serialized bytes + * of the packet. + * return The pointer. + */ + const char* bytes() const + { + return mBuffer + mR; + } + + /** + * Get the size of the buffer holding the serialized bytes of the + * packet. + * \return The number of bytes. + */ + size_t size() const + { + return mW - mR; + } + + // The rest of this stuff is just to implement correct copy semantics. + + Packet(const Packet& copy); + Packet& operator=(const Packet& copy); + ~Packet(); + + +private: + + char* mBuffer; + size_t mSize; + + size_t mR; + size_t mW; + size_t mOriginalW; + + size_t mBoolR; + size_t mBoolW; + size_t mBoolNumR; + size_t mBoolNumW; +}; + + +} // namespace Mf + +#endif // _MOOF_PACKET_HH_ + -- 2.45.2