tcp socket disconnecting by remote
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Fri, 21 May 2010 09:41:17 +0000 (03:41 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Fri, 21 May 2010 09:41:17 +0000 (03:41 -0600)
src/Moof/Service.cc
src/Moof/Service.hh
src/Moof/Socket.hh
src/Moof/old/Packet.cc [new file with mode: 0644]
src/Moof/old/Packet.hh [new file with mode: 0644]

index 400006ba2eb6ee59a4e4dad2391b90dd3a55240a..3432ae6ac12c763857fe25d558442a18f192f66f 100644 (file)
@@ -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)
 {
 }
 
index 77cee183f9b3346c8563dbafff75105b00e9ee76..b26f4cfb375a01433eb9f1c3c5c59a371f0f4028 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef _MOOF_SERVICE_HH_
 #define _MOOF_SERVICE_HH_
 
-#include <vector>
+#include <map>
 
 #include <Moof/Math.hh>
 #include <Moof/Socket.hh>
@@ -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<Service>& services() const
+       const std::map<std::string,Service>& services() const
        {
                return mServices;
        }
@@ -98,8 +152,8 @@ private:
                                         Packet& packet,
                                         const SocketAddress& address);
 
-       std::string                             mService;
-       std::vector<Service>    mServices;
+       std::string                                             mType;
+       std::map<std::string,Service>   mServices;
 };
 
 
index a4cb310b3403b4183562354dedbc54d56ab24738..17e841cca87ba4170b82637fe0dd53aecb349581 100644 (file)
@@ -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 (file)
index 0000000..2bbceb5
--- /dev/null
@@ -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 <algorithm>
+#if HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+#include <cstdlib>
+
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <SDL/SDL.h>
+
+#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<uint32_t*>(&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<uint64_t*>(&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<uint32_t*>(&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<uint64_t*>(&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 (file)
index 0000000..c6cf4bf
--- /dev/null
@@ -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 <cstring>
+#include <string>
+#include <vector>
+
+
+#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 <class T>
+       bool put(const std::basic_string<T>& 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 <class T>
+       bool put(const std::vector<T>& value)
+       {
+               if (put(uint16_t(value.size())))
+               {
+                       typename std::vector<T>::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 <class T>
+       bool get(std::basic_string<T>& 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 <class T>
+       bool get(std::vector<T>& 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_
+
This page took 0.037739 seconds and 4 git commands to generate.