AC_HEADER_STDBOOL
AC_HEADER_STDC
-AC_CHECK_HEADERS([stddef.h stdint.h stdlib.h string.h unistd.h])
+AC_CHECK_HEADERS([byteswap.h stddef.h stdint.h stdlib.h string.h unistd.h])
BOOST_SMART_PTR
BOOST_STRING_ALGO
AC_TYPE_UINT8_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
AC_TYPE_SIZE_T
-AC_TYPE_SSIZE_T
####
}
+#include <Moof/Socket.hh>
+
int main(int argc, char* argv[])
{
+ Mf::ResolverTask task("compy", "4950", SOCK_DGRAM);
+ task.run();
+
+ int i = task.wait();
+ Mf::logWarning << "task ended with code: " << i << std::endl;
+
+ std::vector<Mf::SocketAddress>::const_iterator it;
+ for (it = task.addresses().begin(); it != task.addresses().end(); ++it)
+ {
+ Mf::SocketAddress addr = *it;
+
+ Mf::logInfo << "address: " << addr.name() << ":" << addr.port()
+ << " (" << addr.type() << ")" << std::endl;
+ }
+
+ Mf::SocketAddress addr("www.apple.com", "80", SOCK_DGRAM);
+
+ Mf::logInfo << "address: " << addr.name() << ":" << addr.port()
+ << " (" << addr.type() << ")" << std::endl;
+
+ Mf::Packet packet(1000000);
+ packet << (uint16_t)45;
+ Mf::logInfo << "packet size: " << packet.size() << std::endl;
+ packet << (int64_t)-1234567890123456789;
+ Mf::logInfo << "packet size: " << packet.size() << std::endl;
+
+ packet << true << false << false << true << false << true << true;
+ Mf::logInfo << "packet size: " << packet.size() << std::endl;
+
+ std::vector<char> hi;
+ hi.push_back(34);
+ hi.push_back(-12345);
+ hi.push_back(7734);
+
+ for (int a = 0; a < 15900; a++)
+ {
+ hi.push_back(a);
+ }
+
+ packet << hi;
+ Mf::logInfo << "packet size: " << packet.size() << std::endl;
+
+ packet << "hello world";
+ Mf::logInfo << "packet size: " << packet.size() << std::endl;
+
+ packet << false << false << false << true << false;
+ Mf::logInfo << "packet size: " << packet.size() << std::endl;
+
+
+ for (it = task.addresses().begin(); it != task.addresses().end(); ++it)
+ {
+ Mf::SocketAddress addr = *it;
+ Mf::Socket sock(addr);
+ sock.write(packet);
+ }
+
+
+ return 0;
+
+
if (argc > 1)
{
std::string arg(argv[1]);
Moof/Manager.hh \
Moof/Math.hh \
Moof/ModalDialog.hh \
+ Moof/Network.hh \
Moof/Octree.hh \
Moof/OpenGL.hh \
+ Moof/Packet.cc \
+ Moof/Packet.hh \
Moof/Plane.cc \
Moof/Plane.hh \
Moof/Ray.hh \
Moof/Resource.hh \
Moof/RigidBody.hh \
Moof/Script.hh \
+ Moof/Service.hh \
Moof/Settings.cc \
Moof/Settings.hh \
Moof/Shape.hh \
+ Moof/Socket.hh \
Moof/Sound.cc \
Moof/Sound.hh \
Moof/Sphere.hh \
{
}
-
-} // namespace Mf
+} // namepsace Mf
--- /dev/null
+
+/*] 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.
+*
+**************************************************************************/
+
+#ifndef _MOOF_NETWORK_HH_
+#define _MOOF_NETWORK_HH_
+
+#include <string>
+#include <vector>
+
+
+namespace Mf {
+
+
+class NetworkGamer
+{
+};
+
+
+class NetworkSession
+{
+public:
+
+ const std::vector<NetworkGamer>& gamers();
+};
+
+
+} // namespace Mf
+
+#endif // _MOOF_NETWORK_HH_
+
--- /dev/null
+
+/*] 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 <arpa/inet.h>
+
+#include <SDL/SDL.h>
+
+#include "Packet.hh"
+
+
+#ifndef bswap_64
+#define bswap_64(x) (((uint64_t)(x) << 56) | \
+ (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \
+ (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \
+ (((uint64_t)(x) << 8) & 0xff00000000ULL) | \
+ (((uint64_t)(x) >> 8) & 0xff000000ULL) | \
+ (((uint64_t)(x) >> 24) & 0xff0000ULL) | \
+ (((uint64_t)(x) >> 40) & 0xff00ULL) | \
+ ((uint64_t)(x) >> 56))
+#endif
+
+static uint64_t htonll(uint64_t x)
+{
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+ return bswap_64(x);
+#endif
+}
+
+static uint64_t ntohll(uint64_t x)
+{
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+ return bswap_64(x);
+#endif
+}
+
+
+namespace Mf {
+
+
+Packet::Packet(size_t size) :
+ mR(0),
+ mW(0),
+ mBoolR(0),
+ mBoolW(0),
+ mBoolNumR(0),
+ mBoolNumW(0)
+{
+ mBuffer = boost::shared_array<char>(new char[size]);
+ mSize = size;
+}
+
+Packet::Packet(const char* data, size_t size) :
+ mR(0),
+ mBoolR(0),
+ mBoolW(0),
+ mBoolNumR(0),
+ mBoolNumW(0)
+{
+ mBuffer = boost::shared_array<char>(new char[size]);
+ mSize = size;
+ mW = size;
+ memcpy(mBuffer.get(), data, mSize);
+}
+
+
+Packet& Packet::operator<<(bool value)
+{
+ int bit = mBoolNumW % 8;
+ if (bit == 0)
+ {
+ mBoolW = mW;
+
+ unsigned char byte = 0;
+ if (write(&byte, 1) == 0) return *this;
+ }
+
+ if (value) mBuffer[mBoolW] |= (1 << bit);
+ ++mBoolNumW;
+
+ return *this;
+}
+
+
+Packet& Packet::operator<<(int8_t value)
+{
+ return *this << (uint8_t)value;
+}
+
+Packet& Packet::operator<<(int16_t value)
+{
+ return *this << (uint16_t)value;
+}
+
+Packet& Packet::operator<<(int32_t value)
+{
+ return *this << (uint32_t)value;
+}
+
+Packet& Packet::operator<<(int64_t value)
+{
+ return *this << (uint64_t)value;
+}
+
+
+Packet& Packet::operator<<(uint8_t value)
+{
+ write(&value, sizeof(value));
+ return *this;
+}
+
+Packet& Packet::operator<<(uint16_t value)
+{
+ value = htons(value);
+ write(&value, sizeof(value));
+ return *this;
+}
+
+Packet& Packet::operator<<(uint32_t value)
+{
+ value = htonl(value);
+ write(&value, sizeof(value));
+ return *this;
+}
+
+Packet& Packet::operator<<(uint64_t value)
+{
+ value = htonll(value);
+ write(&value, sizeof(value));
+ return *this;
+}
+
+//Packet& Packet::operator<<(float value)
+//{
+//}
+
+//Packet& Packet::operator<<(double value)
+//{
+//}
+
+//Packet& Packet::operator<<(long double value)
+//{
+//}
+
+
+size_t Packet::write(const void* bytes, size_t size)
+{
+ size_t nBytes = std::min(size, mSize - mW);
+ memcpy(&mBuffer[mW], bytes, nBytes);
+ mW += nBytes;
+ return nBytes;
+}
+
+
+Packet& Packet::operator>>(bool& value)
+{
+ int bit = mBoolNumR % 8;
+ if (bit == 0)
+ {
+ mBoolR = mR;
+
+ unsigned char byte = 0;
+ if (read(&byte, 1) == 0) return *this;
+ }
+
+ value = 1 & (mBuffer[mBoolR] >> bit);
+ ++mBoolNumR;
+
+ return *this;
+}
+
+Packet& Packet::operator>>(int8_t& value)
+{
+ return *this >> (uint8_t&)value;
+}
+
+Packet& Packet::operator>>(int16_t& value)
+{
+ return *this >> (uint16_t&)value;
+}
+
+Packet& Packet::operator>>(int32_t& value)
+{
+ return *this >> (uint32_t&)value;
+}
+
+Packet& Packet::operator>>(int64_t& value)
+{
+ return *this >> (uint64_t&)value;
+}
+
+Packet& Packet::operator>>(uint8_t& value)
+{
+ read(&value, sizeof(value));
+ return *this;
+}
+
+Packet& Packet::operator>>(uint16_t& value)
+{
+ read(&value, sizeof(value));
+ value = ntohs(value);
+ return *this;
+}
+
+Packet& Packet::operator>>(uint32_t& value)
+{
+ read(&value, sizeof(value));
+ value = ntohl(value);
+ return *this;
+}
+
+Packet& Packet::operator>>(uint64_t& value)
+{
+ read(&value, sizeof(value));
+ value = ntohll(value);
+ return *this;
+}
+
+
+size_t Packet::read(void* bytes, size_t size)
+{
+ size_t nBytes = std::min(size, mW - mR);
+ memcpy(bytes, &mBuffer[mR], nBytes);
+ mR += nBytes;
+ return nBytes;
+}
+
+
+} // namespace Mf
+
--- /dev/null
+
+/*] 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.
+*
+**************************************************************************/
+
+#ifndef _MOOF_PACKET_HH_
+#define _MOOF_PACKET_HH_
+
+#include <cstring>
+#include <string>
+#include <vector>
+
+#include <boost/shared_array.hpp>
+
+
+namespace Mf {
+
+
+class Packet
+{
+public:
+
+ Packet(size_t size = 1024);
+ Packet(const char* data, size_t size);
+
+ Packet& operator<<(bool value);
+ Packet& operator<<(int8_t value);
+ Packet& operator<<(int16_t value);
+ Packet& operator<<(int32_t value);
+ Packet& operator<<(int64_t value);
+ Packet& operator<<(uint8_t value);
+ Packet& operator<<(uint16_t value);
+ Packet& operator<<(uint32_t value);
+ Packet& operator<<(uint64_t value);
+ //Packet& operator<<(float value);
+ //Packet& operator<<(double value);
+ //Packet& operator<<(long double value);
+
+ size_t write(const void* bytes, size_t size);
+
+ Packet& operator>>(bool& value);
+ Packet& operator>>(int8_t& value);
+ Packet& operator>>(int16_t& value);
+ Packet& operator>>(int32_t& value);
+ Packet& operator>>(int64_t& value);
+ Packet& operator>>(uint8_t& value);
+ Packet& operator>>(uint16_t& value);
+ Packet& operator>>(uint32_t& value);
+ Packet& operator>>(uint64_t& value);
+
+ size_t read(void* bytes, size_t size);
+
+
+ const char* bytes() const
+ {
+ return &mBuffer.get()[mR];
+ }
+
+ size_t size() const
+ {
+ return mW - mR;
+ }
+
+
+private:
+
+ boost::shared_array<char> mBuffer;
+ size_t mSize;
+
+ size_t mR;
+ size_t mW;
+
+ size_t mBoolR;
+ size_t mBoolW;
+ size_t mBoolNumR;
+ size_t mBoolNumW;
+};
+
+
+inline Packet& operator<<(Packet& packet, const char* value)
+{
+ uint8_t length = strnlen(value, 255);
+ packet << length;
+ packet.write(value, length);
+ return packet;
+}
+
+inline Packet& operator<<(Packet& packet, const std::string& value)
+{
+ packet << (uint8_t)value.length();
+ packet.write(value.c_str(), value.length());
+ return packet;
+}
+
+template <class T>
+inline Packet& operator<<(Packet& packet, const std::vector<T>& value)
+{
+ packet << (uint8_t)value.size();
+ typename std::vector<T>::const_iterator it;
+ for (it = value.begin(); it != value.end(); ++it)
+ {
+ packet << *it;
+ }
+ return packet;
+}
+
+
+inline Packet& operator>>(Packet& packet, std::string& value)
+{
+ uint8_t length = 0;
+ packet >> length;
+
+ char str[256];
+ size_t charsRead = packet.read(str, length);
+ value.assign(str, charsRead);
+ return packet;
+}
+
+template <class T>
+inline Packet& operator>>(Packet& packet, std::vector<T>& value)
+{
+ uint8_t size = 0;
+ packet >> size;
+
+ value.clear();
+ for (uint8_t i = 0; i < size; ++i)
+ {
+ T item;
+ packet >> item;
+ value.push_back(item);
+ }
+ return packet;
+}
+
+
+
+} // namespace Mf
+
+#endif // _MOOF_PACKET_HH_
+
--- /dev/null
+
+/*] 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.
+*
+**************************************************************************/
+
+#ifndef _MOOF_SERVICE_HH_
+#define _MOOF_SERVICE_HH_
+
+#include <Moof/Math.hh>
+
+
+namespace Mf {
+
+
+class ServiceBroadcaster
+{
+public:
+
+ ServiceBroadcaster(const std::string& name);
+
+ void update(Scalar t, Scalar dt);
+};
+
+
+class ServiceLocator
+{
+public:
+
+ ServiceLocator(const std::string& name);
+
+ void update(Scalar t, Scalar dt);
+};
+
+
+} // namespace Mf
+
+#endif // _MOOF_SERVICE_HH_
+
--- /dev/null
+
+/*] 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.
+*
+**************************************************************************/
+
+#ifndef _MOOF_SOCKET_HH_
+#define _MOOF_SOCKET_HH_
+
+#include <cstring>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <Moof/Log.hh>
+#include <Moof/Packet.hh>
+#include <Moof/Thread.hh>
+
+
+namespace Mf {
+
+
+class SocketAddress
+{
+public:
+
+ SocketAddress(int type = SOCK_STREAM)
+ {
+ mType = type;
+ memset(&mAddress.in4, 0, sizeof(mAddress.in4));
+ mAddress.in4.sin_family = AF_INET;
+ mAddress.in4.sin_port = 0;
+ mAddress.in4.sin_addr.s_addr = INADDR_ANY;
+ mName = "[any]";
+ mSize = sizeof(mAddress.in4);
+ }
+
+ SocketAddress(const std::string& name, const std::string& service,
+ int type = SOCK_STREAM, int family = AF_INET)
+ {
+ ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
+ ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
+
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = type;
+ hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
+
+ struct addrinfo* addr;
+ int status = getaddrinfo(name.length() > 0 ? name.c_str() : 0,
+ service.length() > 0 ? service.c_str() : 0, &hints, &addr);
+ if (status != 0)
+ {
+ Mf::logError("uh oh, that didn't work!");
+ return;
+ }
+
+ mType = addr->ai_socktype;
+ memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
+ mName = addr->ai_canonname;
+ mSize = addr->ai_addrlen;
+
+ freeaddrinfo(addr);
+ }
+
+ SocketAddress(const std::string& name, const struct addrinfo* addr)
+ {
+ mType = addr->ai_socktype;
+ memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
+ mName = name;
+ mSize = addr->ai_addrlen;
+ }
+
+ SocketAddress(const struct sockaddr* addr, size_t size,
+ int type = SOCK_STREAM)
+ {
+ mType = type;
+ memcpy(&mAddress.sa, addr, size);
+ mSize = size;
+
+ char name[128] = {'\0'};
+ inet_ntop(addr->sa_family, (struct sockaddr_in*)addr,
+ name, sizeof(name));
+ mName = name;
+ }
+
+
+ const std::string& name() const
+ {
+ return mName;
+ }
+
+ unsigned short port() const
+ {
+ return ntohs(mAddress.in4.sin_port);
+ }
+
+ int type() const
+ {
+ return mType;
+ }
+
+ int family() const
+ {
+ return mAddress.sa.sa_family;
+ }
+
+
+ const struct sockaddr* address() const
+ {
+ return &mAddress.sa;
+ }
+
+ size_t size() const
+ {
+ return mSize;
+ }
+
+
+ static int resolve(const std::string& name, const std::string& service,
+ int type, int family, std::vector<SocketAddress>& resolved)
+ {
+ ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
+ ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
+
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = type;
+ hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
+
+ struct addrinfo* list;
+ int status = getaddrinfo(name.length() > 0 ? name.c_str() : 0,
+ service.length() > 0 ? service.c_str() : 0, &hints, &list);
+ if (status != 0) return -1;
+
+ resolved.clear();
+
+ const char* canonicalName = list->ai_canonname;
+ struct addrinfo* addr = list;
+ while (addr != 0)
+ {
+ resolved.push_back(SocketAddress(canonicalName, addr));
+ addr = addr->ai_next;
+ }
+
+ freeaddrinfo(list);
+ return 0;
+ }
+
+
+private:
+
+ union
+ {
+ sockaddr sa;
+ sockaddr_in in4;
+ sockaddr_in6 in6;
+ } mAddress;
+ size_t mSize;
+ std::string mName;
+ int mType;
+};
+
+
+class Socket
+{
+public:
+
+ Socket(const SocketAddress& address) :
+ mAddress(address)
+ {
+ mFd = socket(address.family(), address.type(), 0);
+ }
+
+ ~Socket()
+ {
+ close(mFd);
+ }
+
+
+ bool isConnected() const
+ {
+ return false;
+ }
+
+ const SocketAddress& address() const
+ {
+ return mAddress;
+ }
+
+
+ void write(const Packet& packet)
+ {
+ write(mAddress, packet);
+ }
+
+ void write(const SocketAddress& address, const Packet& packet)
+ {
+ sendto(mFd, packet.bytes(), packet.size(), 0,
+ address.address(), address.size());
+ }
+
+ Packet read()
+ {
+ char buffer[1024];
+ int size = recv(mFd, buffer, sizeof(buffer), 0);
+
+ return Packet(buffer, size);
+ }
+
+ Packet read(SocketAddress& address)
+ {
+ union
+ {
+ sockaddr sa;
+ sockaddr_storage storage;
+ } addr;
+ socklen_t length = sizeof(addr);
+
+ char buffer[1024];
+ int size = recvfrom(mFd, buffer, sizeof(buffer), 0,
+ &addr.sa, &length);
+
+ address = SocketAddress(&addr.sa, length, SOCK_DGRAM);
+ return Packet(buffer, size);
+ }
+
+
+private:
+
+ int mFd;
+ SocketAddress mAddress;
+};
+
+
+class ResolverTask : public ThreadedTask
+{
+public:
+
+ ResolverTask(const std::string& name, const std::string& service,
+ int type = SOCK_STREAM, int family = AF_UNSPEC) :
+ mIsDone(false)
+ {
+ mFunction = boost::bind(&ResolverTask::resolve,
+ this, name, service, type, family);
+ }
+
+
+ bool isDone() const
+ {
+ return mIsDone;
+ }
+
+ void run()
+ {
+ if (!mThread) mThread = Mf::detachFunction(mFunction);
+ }
+
+
+ const std::vector<SocketAddress>& addresses() const
+ {
+ return mAddressList;
+ }
+
+
+private:
+
+ int resolve(const std::string& name, const std::string& service,
+ int type, int family)
+ {
+ int status = SocketAddress::resolve(name, service,
+ type, family, mAddressList);
+ mIsDone = true;
+ return status;
+ }
+
+
+ std::vector<SocketAddress> mAddressList;
+ bool mIsDone;
+ Function mFunction;
+};
+
+
+} // namespace Mf
+
+#endif // _MOOF_SOCKET_HH_
+
namespace Mf {
+
//
// The detach function detaches a separate thread by calling 'func' with
// the 'arg' parameter.
}
+class AsyncTask
+{
+public:
+
+ virtual ~AsyncTask() {}
+
+ virtual bool isDone() const = 0;
+
+ virtual void run() = 0;
+ virtual int wait() = 0;
+};
+
+class ThreadedTask
+{
+public:
+
+ ThreadedTask() :
+ mThread(0) {}
+
+ Thread thread() const { return mThread; }
+
+ int wait()
+ {
+ int code = waitOnThread(mThread);
+ mThread = 0;
+ return code;
+ }
+
+
+protected:
+
+ Thread mThread;
+};
+
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Mutex