From 026ebea1115080d908a4a5042ce186bfbcb64f37 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 18 May 2006 14:18:13 +0000 Subject: [PATCH] Added the beginnings of Boost.Function and Boost.Threads for callback handling and threaded network handling git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@6 52acb1d6-8a22-11de-b505-999d5b087335 --- include/Decoder.h | 8 +- include/Network.h | 2 + include/Packet.h | 80 ++++++++++--------- include/ProtocolManager.h | 10 ++- include/SecondLife.h | 19 ++++- include/SimConnection.h | 3 + include/includes.h | 45 ++++++----- src/Decoder.cpp | 19 ++++- src/Network.cpp | 26 +++--- src/Packet.cpp | 164 ++++++++++++++++++++++++++------------ src/ProtocolManager.cpp | 12 ++- src/SecondLife.cpp | 52 ++++++++++-- src/SimConnection.cpp | 4 +- 13 files changed, 303 insertions(+), 141 deletions(-) diff --git a/include/Decoder.h b/include/Decoder.h index 72f198ea..e5ad41fe 100644 --- a/include/Decoder.h +++ b/include/Decoder.h @@ -30,15 +30,19 @@ #ifndef _SL_DECODER_ #define _SL_DECODER_ -#include "includes.h" +#include "includes.h" +#include "Network.h" class Decoder { protected: - + Network* _network; public: Decoder(); + Decoder(Network* network); virtual ~Decoder(); + + int decodePackets(); }; #endif //_SL_DECODER_ diff --git a/include/Network.h b/include/Network.h index fb8cf8eb..cfd43aab 100644 --- a/include/Network.h +++ b/include/Network.h @@ -54,6 +54,8 @@ public: Network(ProtocolManager* protocol); virtual ~Network(); + std::list inbox() { return _inbox; }; + int connectSim(boost::asio::ipv4::address ip, unsigned short port, U32 code, bool setCurrent = false); int sendPacket(boost::asio::ipv4::address ip, unsigned short port, Packet* packet); void receivePacket(const boost::asio::error& error, std::size_t length, char* receiveBuffer); diff --git a/include/Packet.h b/include/Packet.h index 242f2e3a..5bc6059f 100644 --- a/include/Packet.h +++ b/include/Packet.h @@ -27,42 +27,50 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _SL_PACKET_ -#define _SL_PACKET_ - -#include "includes.h" -#include "ProtocolManager.h" - -// Higher value will mean less realloc()s, more wasted memory. Lower value is -// vice versa. -#define DEFAULT_PACKET_SIZE 128 - -class LIBSECONDLIFE_CLASS_DECL Packet -{ -protected: - packetDiagram* _layout; - byte* _buffer; - size_t _length; - boost::asio::ipv4::udp::endpoint _remoteHost; - ProtocolManager* _protocol; - -public: - Packet(); - Packet(ProtocolManager* protocol, size_t length = 0); - virtual ~Packet(); +#ifndef _SL_PACKET_ +#define _SL_PACKET_ - bool setCommand(std::string command); - ll::llType getFieldType(std::string block, std::string field); - void* getField(std::string block, size_t blockNumber, std::string field); - int setField(std::string block, size_t blockNumber, std::string field, void* value); - - size_t getLength() { return _length; }; - int getRawData(byte* buffer, size_t length); - byte* getRawDataPtr(); - void setRawData(byte* buffer, size_t length); +#include "includes.h" +#include "ProtocolManager.h" + +// Higher value will mean less realloc()s, more wasted memory. Lower value is +// vice versa. +#define DEFAULT_PACKET_SIZE 128 + +class LIBSECONDLIFE_CLASS_DECL Packet +{ +protected: + packetDiagram* _layout; + byte* _buffer; + size_t _length; + boost::asio::ipv4::udp::endpoint _remoteHost; + ProtocolManager* _protocol; + +public: + Packet(std::string command = "TestMessage", ProtocolManager* protocol = NULL, size_t length = 0); + virtual ~Packet(); + + std::string command(); + bool command(std::string command); + + ll::llType getFieldType(std::string block, std::string field); + void* getField(std::string block, size_t blockNumber, std::string field); + int setField(std::string block, size_t blockNumber, std::string field, void* value); + + size_t length() { return _length; }; + byte* rawData(); + void rawData(byte* buffer, size_t length); + + ll::frequency frequency(); + + unsigned short flags(); + void flags(unsigned short flags); + + unsigned short sequence(); + void sequence(unsigned short sequence); boost::asio::ipv4::udp::endpoint getRemoteHost(); - void setRemoteHost(boost::asio::ipv4::udp::endpoint remoteHost); -}; - -#endif //_SL_PACKET_ + void setRemoteHost(boost::asio::ipv4::udp::endpoint remoteHost); +}; + +#endif //_SL_PACKET_ diff --git a/include/ProtocolManager.h b/include/ProtocolManager.h index 8bc0afa3..9008cf5c 100644 --- a/include/ProtocolManager.h +++ b/include/ProtocolManager.h @@ -60,6 +60,13 @@ namespace ll Single, Multiple }; + + enum frequency { + Invalid, + Low, + Medium, + High + }; }; typedef struct llVector3 { @@ -114,7 +121,8 @@ namespace std }; typedef struct packetDiagram { - std::string name; + std::string name; + ll::frequency frequency; bool trusted; bool encoded; std::list blocks; diff --git a/include/SecondLife.h b/include/SecondLife.h index 3d6337b1..7ecfaee0 100644 --- a/include/SecondLife.h +++ b/include/SecondLife.h @@ -30,10 +30,15 @@ #ifndef _SL_SECONDLIFE_ #define _SL_SECONDLIFE_ -#include "includes.h" +#include "includes.h" #include "ProtocolManager.h" +#include "SimConnection.h" #include "Network.h" -#include "Decoder.h" +#include "Decoder.h" + +// Model for the callbacks: +// bool functionname(std::string command, Packet*) +typedef boost::function2 callback; class LIBSECONDLIFE_CLASS_DECL SecondLife { @@ -42,14 +47,24 @@ public: ProtocolManager* _protocol; Network* _network; Decoder* _decoder; + bool _running; + // Later on we'll want internal callbacks and client callbacks, so the client doesn't overwrite + // for example the stream building functions + std::map _callbacks; + //public: SecondLife(); virtual ~SecondLife(); + void registerCallback(std::string command, callback handler) { _callbacks[command] = handler; }; + // Pass-through functions to make life easier on the client int loadKeywords(std::string filename) { return _protocol->loadKeywords(filename); }; int decryptCommFile(std::string source, std::string destination) { return _protocol->decryptCommFile(source, destination); }; int buildProtocolMap(std::string filename) { return _protocol->buildProtocolMap(filename); }; + + void connectSim(boost::asio::ipv4::address ip, unsigned short port, U32 code, bool setCurrent = false); + void tick(); }; #endif //_SL_SECONDLIFE_ diff --git a/include/SimConnection.h b/include/SimConnection.h index d9884310..2b1b7674 100644 --- a/include/SimConnection.h +++ b/include/SimConnection.h @@ -41,6 +41,7 @@ protected: boost::asio::datagram_socket* _socket; bool _running; char* _buffer; + unsigned short _sequence; public: SimConnection(); @@ -65,6 +66,8 @@ public: char* buffer() { return _buffer; }; size_t bufferSize() { return SL_BUFFER_SIZE; }; + unsigned short sequence() { return _sequence++; }; + bool operator==(SimConnection &p); bool operator!=(SimConnection &p); }; diff --git a/include/includes.h b/include/includes.h index 62ee8873..15428765 100644 --- a/include/includes.h +++ b/include/includes.h @@ -27,14 +27,14 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _SL_INCLUDES_ -#define _SL_INCLUDES_ - +#ifndef _SL_INCLUDES_ +#define _SL_INCLUDES_ + #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -46,13 +46,16 @@ #include #include #include -#include +#include +#include + +#include int httoi(const char* value); #define SL_BUFFER_SIZE 8192 -// Data types +// Data types #define byte unsigned char struct LLUUID { @@ -61,19 +64,19 @@ struct LLUUID { // This needs to loop through the string and convert each letter to a byte using (byte)httoi() //LLUUID operator=(const std::string p) { memcpy(data, p.c_str(), 16); return *this; }; }; - + typedef unsigned int U32; // - -#ifdef WIN32 -#pragma warning (disable : 4996 4251) -#ifdef LIBSECONDLIFE_EXPORTS - #define LIBSECONDLIFE_CLASS_DECL __declspec(dllexport) -#else - #define LIBSECONDLIFE_CLASS_DECL __declspec(dllimport) + +#ifdef WIN32 +#pragma warning (disable : 4996 4251) +#ifdef LIBSECONDLIFE_EXPORTS + #define LIBSECONDLIFE_CLASS_DECL __declspec(dllexport) +#else + #define LIBSECONDLIFE_CLASS_DECL __declspec(dllimport) #endif #else -#define LIBSECONDLIFE_CLASS_DECL -#endif - -#endif //_SL_INCLUDES_ +#define LIBSECONDLIFE_CLASS_DECL +#endif + +#endif //_SL_INCLUDES_ diff --git a/src/Decoder.cpp b/src/Decoder.cpp index 6ecf9bd6..e9109e51 100644 --- a/src/Decoder.cpp +++ b/src/Decoder.cpp @@ -2,10 +2,27 @@ Decoder::Decoder() { - ; + _network = NULL; } + +Decoder::Decoder(Network* network) +{ + _network = network; +} Decoder::~Decoder() { ; } + +int Decoder::decodePackets() +{ + if (!_network || !_network->inbox().size()) { + //FIXME: Log + return -1; + } + + + + return 0; +} diff --git a/src/Network.cpp b/src/Network.cpp index f397fb6c..0ecf1e3b 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -1,18 +1,18 @@ #include "Network.h" -Network::Network(ProtocolManager* protocol) -{ +Network::Network(ProtocolManager* protocol) +{ _protocol = protocol; _currentSim = NULL; _avatar_id = 0; _session_id = 0; - _secure_session_id = 0; -} - -Network::~Network() -{ + _secure_session_id = 0; +} + +Network::~Network() +{ //FIXME: Close and free all the sockets - // Delete all remaining packets + // Delete all remaining packets } void Network::receivePacket(const boost::asio::error& error, std::size_t length, char* receiveBuffer) @@ -26,7 +26,7 @@ void Network::receivePacket(const boost::asio::error& error, std::size_t length, // Build a Packet object and fill it with the incoming data Packet* packet = new Packet(); - packet->setRawData((byte*)receiveBuffer, length); + packet->rawData((byte*)receiveBuffer, length); // Push it on to the list boost::mutex::scoped_lock lock(_inboxMutex); @@ -45,8 +45,7 @@ int Network::connectSim(boost::asio::ipv4::address ip, unsigned short port, U32 } // Build a connection packet - Packet* packet = new Packet(_protocol, 36); - packet->setCommand("UseCircuitCode"); + Packet* packet = new Packet("UseCircuitCode", _protocol, 36); packet->setField("CircuitCode", 1, "ID", &_session_id); packet->setField("CircuitCode", 1, "SessionID", &_session_id); packet->setField("CircuitCode", 1, "Code", &code); @@ -60,7 +59,7 @@ int Network::connectSim(boost::asio::ipv4::address ip, unsigned short port, U32 // Send the packet try { - size_t bytesSent = socket->send_to(boost::asio::buffer(packet->getRawDataPtr(), packet->getLength()), 0, sim->endpoint()); + size_t bytesSent = socket->send_to(boost::asio::buffer(packet->rawData(), packet->length()), 0, sim->endpoint()); // Debug printf("Sent %i byte connection packet\n", bytesSent); @@ -110,7 +109,8 @@ int Network::sendPacket(boost::asio::ipv4::address ip, unsigned short port, Pack } try { - size_t bytesSent = _connections[i]->socket()->send_to(boost::asio::buffer(packet->getRawDataPtr(), packet->getLength()), 0, _connections[i]->endpoint()); + size_t bytesSent = _connections[i]->socket()->send_to(boost::asio::buffer(packet->rawData(), packet->length()), + 0, _connections[i]->endpoint()); // Debug printf("Sent %i bytes\n", bytesSent); diff --git a/src/Packet.cpp b/src/Packet.cpp index 479fae90..c9048278 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -1,41 +1,108 @@ #include "Packet.h" -Packet::Packet() +Packet::Packet(std::string command, ProtocolManager* protocol, size_t length) { - _buffer = (byte*)malloc(DEFAULT_PACKET_SIZE); - if (!_buffer) { - //FIXME: Log memory error - } + _length = length; + _protocol = protocol; - _length = 0; - _protocol = NULL; -} - -Packet::Packet(ProtocolManager* protocol, size_t length) -{ - _buffer = (byte*)malloc(length ? length : DEFAULT_PACKET_SIZE); - if (!_buffer) { - //FIXME: Log memory error + _layout = _protocol->getCommand(command); + if (!_layout) { + //FIXME: Log invalid packet name + _buffer = NULL; _length = 0; } else { - _length = length; - } + _buffer = (byte*)malloc(_length ? _length : DEFAULT_PACKET_SIZE); - _protocol = protocol; + if (!_buffer) { + //FIXME: Log memory error + _length = 0; + } + + // Setup the flags and the frequency right now + ; + } } Packet::~Packet() { free(_buffer); -} - -bool Packet::setCommand(std::string command) -{ - packetDiagram* layout = _protocol->getCommand(command); - if (!layout) return false; - - _layout = layout; - return true; +} + +ll::frequency Packet::frequency() +{ + if (!_layout) { + return ll::Invalid; + } + + return _layout->frequency; +} + +unsigned short Packet::flags() +{ + if (_length < 2) { + return 0; + } + + return (unsigned short)*_buffer; +} + +void Packet::flags(unsigned short flags) +{ + if (_length < 2) { + // Make room, assume the default packet size + _buffer = (byte*)realloc(_buffer, DEFAULT_PACKET_SIZE); + _length = 2; + } + + if (!_buffer) { + //FIXME: Log memory error + _length = 0; + return; + } + + memcpy(_buffer, &flags, sizeof(flags)); +} + +unsigned short Packet::sequence() +{ + if (_length < 4) { + return 0; + } + + return ntohs((unsigned short)*(_buffer + 2)); +} + +void Packet::sequence(unsigned short sequence) +{ + unsigned short hostSequence = htons(sequence); + + if (_length < 4) { + // Make room, assume the default packet size + _buffer = (byte*)realloc(_buffer, DEFAULT_PACKET_SIZE); + _length = 4; + } + + if (!_buffer) { + //FIXME: Log memory error + _length = 0; + return; + } + + memcpy(_buffer + 2, &hostSequence, sizeof(sequence)); +} + +std::string Packet::command() +{ + return _layout->name; +} + +bool Packet::command(std::string command) +{ + packetDiagram* layout = _protocol->getCommand(command); + if (!layout) return false; + + _layout = layout; + return true; } ll::llType Packet::getFieldType(std::string block, std::string field) @@ -91,11 +158,11 @@ void* Packet::getField(std::string block, size_t blockNumber, std::string field) } int Packet::setField(std::string block, size_t blockNumber, std::string field, void* value) -{ - if (!_layout) { - //FIXME: Log - return -1; - } +{ + if (!_layout) { + //FIXME: Log + return -1; + } // Find out what type of field this is ll::llType type = getFieldType(block, field); @@ -125,14 +192,14 @@ int Packet::setField(std::string block, size_t blockNumber, std::string field, v size_t offset = blockSize * (blockNumber - 1) + fieldOffset; // Reallocate memory if necessary - if ((offset + fieldSize) > _length) { + if ((offset + fieldSize) > _length) { if ((offset + fieldSize) > DEFAULT_PACKET_SIZE) { _buffer = (byte*)realloc(_buffer, offset + fieldSize); if (!_buffer) { //FIXME: Log memory error _length = 0; return -5; - } + } } _length = offset + fieldSize; @@ -144,17 +211,12 @@ int Packet::setField(std::string block, size_t blockNumber, std::string field, v return 0; } -int Packet::getRawData(byte* buffer, size_t length) +byte* Packet::rawData() { - return (memcpy((void*)buffer, _buffer, length) != NULL); -} - -byte* Packet::getRawDataPtr() -{ - return _buffer; + return _buffer; } -void Packet::setRawData(byte* buffer, size_t length) +void Packet::rawData(byte* buffer, size_t length) { if (length > _length) { _buffer = (byte*)realloc(_buffer, length); @@ -168,13 +230,13 @@ void Packet::setRawData(byte* buffer, size_t length) memcpy(_buffer, buffer, length); _length = length; } - -boost::asio::ipv4::udp::endpoint Packet::getRemoteHost() -{ - return _remoteHost; -} - -void Packet::setRemoteHost(boost::asio::ipv4::udp::endpoint remoteHost) -{ - _remoteHost = remoteHost; -} + +boost::asio::ipv4::udp::endpoint Packet::getRemoteHost() +{ + return _remoteHost; +} + +void Packet::setRemoteHost(boost::asio::ipv4::udp::endpoint remoteHost) +{ + _remoteHost = remoteHost; +} diff --git a/src/ProtocolManager.cpp b/src/ProtocolManager.cpp index 45329ba8..9907e015 100644 --- a/src/ProtocolManager.cpp +++ b/src/ProtocolManager.cpp @@ -326,13 +326,17 @@ int ProtocolManager::buildProtocolMap(std::string filename) temp = header_tokens.at(2); // Truncate it to a short int fixed = httoi((char*)temp.c_str()) ^ 0xffff0000; - packet = &_lowPackets[fixed]; + packet = &_lowPackets[fixed]; + packet->frequency = ll::Low; } else if (temp == "Low") { - packet = &_lowPackets[low++]; + packet = &_lowPackets[low++]; + packet->frequency = ll::Low; } else if (temp == "Medium") { - packet = &_mediumPackets[medium++]; + packet = &_mediumPackets[medium++]; + packet->frequency = ll::Medium; } else if (temp == "High") { - packet = &_highPackets[high++]; + packet = &_highPackets[high++]; + packet->frequency = ll::High; } else { //FIXME: Debug log return -2; diff --git a/src/SecondLife.cpp b/src/SecondLife.cpp index 34944244..3584336f 100644 --- a/src/SecondLife.cpp +++ b/src/SecondLife.cpp @@ -1,16 +1,52 @@ #include "SecondLife.h" -SecondLife::SecondLife() +SecondLife::SecondLife() { - boost::thread _placeHolder; _protocol = new ProtocolManager(); _network = new Network(_protocol); - _decoder = new Decoder(); -} - -SecondLife::~SecondLife() -{ + _decoder = new Decoder(); + _running = true; +} + +SecondLife::~SecondLife() +{ delete _protocol; delete _network; - delete _decoder; + delete _decoder; +} + +void SecondLife::connectSim(boost::asio::ipv4::address ip, unsigned short port, U32 code, bool setCurrent) +{ + if (!_network) { + //FIXME: Log + return; + } + + boost::thread thread; + //FIXME: Run the below function in the above thread + _network->connectSim(ip, port, code, setCurrent); +} + +void SecondLife::tick() +{ + Packet* packet; + // When we get to stream handling, this function will build data stream + // classes and append new data, for sounds/images/animations/etc + + // tick() will process all of the outstanding packets, building classes and + // firing callbacks as it goes + if (_network) { + while (_network->inbox().size() > 0) { + packet = _network->inbox().front(); + _network->inbox().pop_front(); + std::string command = packet->command(); + + callback handler = _callbacks[command]; + bool returnValue = handler(command, packet); + + if (returnValue) { + ; + } + } + } } diff --git a/src/SimConnection.cpp b/src/SimConnection.cpp index 734a159f..01967dc1 100644 --- a/src/SimConnection.cpp +++ b/src/SimConnection.cpp @@ -5,8 +5,8 @@ SimConnection::SimConnection() _code = 0; _socket = NULL; _running = true; - _buffer = (char*)malloc(SL_BUFFER_SIZE); + _sequence = 1; } SimConnection::SimConnection(boost::asio::ipv4::address ip, unsigned short port, U32 code) @@ -15,8 +15,8 @@ SimConnection::SimConnection(boost::asio::ipv4::address ip, unsigned short port, _code = code; _socket = NULL; _running = true; - _buffer = (char*)malloc(SL_BUFFER_SIZE); + _sequence = 1; } SimConnection::~SimConnection()