From 4e6f82d6bf5ed9f9d7d2b425ef315de028e4ed1b Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 25 May 2006 22:20:56 +0000 Subject: [PATCH] First alpha release * Fixed several nasty malloc/memcpy/realloc bugs * Added sleeps to the threads * Hack to make the packet flags correct (for now) * Added a default callback and fixed the callback handler * Misc. fixes git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@9 52acb1d6-8a22-11de-b505-999d5b087335 --- include/Network.h | 2 +- include/Packet.h | 6 ++-- include/ProtocolManager.h | 1 + include/includes.h | 1 + src/Network.cpp | 65 +++++++++++++++++++++++++++++---------- src/Packet.cpp | 50 ++++++++++++++++++------------ src/ProtocolManager.cpp | 18 +++++++++++ src/SecondLife.cpp | 34 +++++++++++++++----- 8 files changed, 129 insertions(+), 48 deletions(-) diff --git a/include/Network.h b/include/Network.h index 5977c63a..4cce1b62 100644 --- a/include/Network.h +++ b/include/Network.h @@ -96,7 +96,7 @@ public: int sendPacket(Packet* packet); void receivePacket(const boost::asio::error& error, std::size_t length, char* receiveBuffer); - std::list inbox() { return _inbox; }; + std::list* inbox() { return &_inbox; }; LLUUID agent_id() { return _agent_id; }; void agent_id(LLUUID agent_id) { _agent_id = agent_id; }; diff --git a/include/Packet.h b/include/Packet.h index eedb3370..478c9da4 100644 --- a/include/Packet.h +++ b/include/Packet.h @@ -43,12 +43,13 @@ protected: packetDiagram* _layout; byte* _buffer; size_t _length; - boost::asio::ipv4::udp::endpoint _remoteHost; ProtocolManager* _protocol; byte _headerLength; public: Packet(std::string command = "TestMessage", ProtocolManager* protocol = NULL, size_t length = 0); + Packet(unsigned short command, ProtocolManager* protocol, byte* buffer, size_t length, byte headerLength, + ll::frequency frequency); virtual ~Packet(); std::string command(); @@ -69,9 +70,6 @@ public: 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_ diff --git a/include/ProtocolManager.h b/include/ProtocolManager.h index 9792824f..bd3693d7 100644 --- a/include/ProtocolManager.h +++ b/include/ProtocolManager.h @@ -155,6 +155,7 @@ public: int getKeywordPosition(std::string keyword); packetDiagram* getCommand(std::string command); + packetDiagram* getCommand(unsigned short command, ll::frequency frequency); ll::llType getFieldType(std::string type); static int getTypeSize(ll::llType type); std::string getTypeName(ll::llType type); diff --git a/include/includes.h b/include/includes.h index d30eeb78..66ee5c7d 100644 --- a/include/includes.h +++ b/include/includes.h @@ -43,6 +43,7 @@ #include #include +#include #include #include #include diff --git a/src/Network.cpp b/src/Network.cpp index 99200995..8f645a33 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -94,9 +94,9 @@ void Network::login(std::string firstName, std::string lastName, std::string pas "passwd" + passwordDigest + "" "startlast" "major1" - "minor9" + "minor10" "patch0" - "build21" + "build32" "platform" + platform + "" "mac" + mac + "" "viewer_digest" + viewerDigest + "" @@ -146,6 +146,12 @@ void Network::listen(SimConnection* sim) // simultaneously _demuxer.run(); _demuxer.reset(); + + // Sleep for 1000 nanoseconds + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC); + xt.nsec += 1000; + boost::thread::sleep(xt); } // Debug @@ -178,6 +184,9 @@ int Network::connectSim(boost::asio::ipv4::address ip, unsigned short port, U32 boost::asio::datagram_socket* socket = new boost::asio::datagram_socket(_demuxer, boost::asio::ipv4::udp::endpoint(0)); sim->socket(socket); + // Push this connection on to the list + _connections.push_back(sim); + // Send the packet try { size_t bytesSent = socket->send_to(boost::asio::buffer(packet->rawData(), packet->length()), 0, sim->endpoint()); @@ -202,23 +211,44 @@ int Network::connectSim(boost::asio::ipv4::address ip, unsigned short port, U32 void Network::receivePacket(const boost::asio::error& error, std::size_t length, char* receiveBuffer) { - // Debug - printf("Received datagram, length: %u\n", length); - for (size_t i = 0; i < length; i++) { - printf("%02x ", receiveBuffer[i]); + if (length < 8) { + //FIXME: Log + return; } - printf("\n"); - - //FIXME: Decode the command name from the packet so we can call the Packet constructor properly - - // Build a Packet object and fill it with the incoming data - //FIXME: Something in here is segfaulting, fix it - /*Packet* packet = new Packet(); - packet->rawData((byte*)receiveBuffer, length); - + + Packet* packet; + unsigned short command; + + if (!receiveBuffer[0]) { + // We don't need to push this packet in to the inbox, it can be handled at the network layer + //TODO: Do something with this + + //Debug: + printf("Received network-level datagram, length: %u\n", length); + + return; + } + + if (receiveBuffer[4] & 0xFF) { + if (receiveBuffer[5] & 0xFF) { + // Low frequency packet + memcpy(&command, &receiveBuffer[6], 2); + command = ntohs(command); + packet = new Packet(command, _protocol, (byte*)receiveBuffer, length, 8, ll::Low); + } else { + // Medium frequency packet + command = (unsigned short)receiveBuffer[5]; + packet = new Packet(command, _protocol, (byte*)receiveBuffer, length, 6, ll::Medium); + } + } else { + // High frequency packet + command = (unsigned short)receiveBuffer[4]; + packet = new Packet(command, _protocol, (byte*)receiveBuffer, length, 5, ll::High); + } + // Push it on to the list boost::mutex::scoped_lock lock(_inboxMutex); - _inbox.push_back(packet);*/ + _inbox.push_back(packet); } int Network::sendPacket(boost::asio::ipv4::address ip, unsigned short port, Packet* packet) @@ -238,6 +268,9 @@ int Network::sendPacket(boost::asio::ipv4::address ip, unsigned short port, Pack //FIXME: Log return -1; } + + // Set the packet sequence number + packet->sequence(_connections[i]->sequence()); try { size_t sent = _connections[i]->socket()->send_to(boost::asio::buffer(packet->rawData(), packet->length()), diff --git a/src/Packet.cpp b/src/Packet.cpp index 56ab54f3..105e8816 100644 --- a/src/Packet.cpp +++ b/src/Packet.cpp @@ -3,7 +3,7 @@ Packet::Packet(std::string command, ProtocolManager* protocol, size_t length) { // Make the minimum length sane to avoid excessive bounds checking - _length = (length >= 8) ? length : 8; + _length = (length > 8) ? length : 8; _protocol = protocol; unsigned short flags; @@ -26,7 +26,12 @@ Packet::Packet(std::string command, ProtocolManager* protocol, size_t length) // snowcrash wrong? Why are virtually all packets (except acks) sent with // 0x4000 when lots of commands are untrusted? trusted != reliable? flags = (_layout->trusted & MSG_RELIABLE) + (_layout->encoded & MSG_ZEROCODED); - flags = htons(flags); + + //FIXME: Serious hack to temporarily work around the aforementioned problem + if (!flags) { + flags = 0x40; + } + //flags = htons(flags); memcpy(_buffer, &flags, 2); // Setup the frequency/id bytes @@ -54,6 +59,25 @@ Packet::Packet(std::string command, ProtocolManager* protocol, size_t length) } } +Packet::Packet(unsigned short command, ProtocolManager* protocol, byte* buffer, size_t length, byte headerLength, + ll::frequency frequency) +{ + _length = length; + _protocol = protocol; + _layout = _protocol->getCommand(command, frequency); + + _buffer = (byte*)malloc(length); + if (!_buffer) { + //FIXME: Log memory error + _length = 0; + return; + } + + memcpy(_buffer, buffer, length); + + _headerLength = headerLength; +} + Packet::~Packet() { free(_buffer); @@ -211,13 +235,11 @@ int Packet::setField(std::string block, size_t blockNumber, std::string field, v // Reallocate memory if necessary 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; - } + _buffer = (byte*)realloc(_buffer, offset + fieldSize); + if (!_buffer) { + //FIXME: Log memory error + _length = 0; + return -5; } _length = offset + fieldSize; @@ -248,13 +270,3 @@ void Packet::rawData(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; -} diff --git a/src/ProtocolManager.cpp b/src/ProtocolManager.cpp index 635c9cc6..a61521af 100644 --- a/src/ProtocolManager.cpp +++ b/src/ProtocolManager.cpp @@ -390,6 +390,24 @@ packetDiagram* ProtocolManager::getCommand(std::string command) return NULL; } +packetDiagram* ProtocolManager::getCommand(unsigned short command, ll::frequency frequency) +{ + switch (frequency) + { + case ll::Low: + return &_lowPackets[command]; + case ll::Medium: + return &_mediumPackets[command]; + case ll::High: + return &_highPackets[command]; + case ll::Invalid: + //FIXME: Log + break; + } + + return NULL; +} + ll::llType ProtocolManager::getFieldType(std::string type) { const std::string llTypes[] = {"U8", "U16", "U32", "U64", "S8", "S16", "S32", "S64", diff --git a/src/SecondLife.cpp b/src/SecondLife.cpp index e4065914..24512854 100644 --- a/src/SecondLife.cpp +++ b/src/SecondLife.cpp @@ -21,23 +21,41 @@ void SecondLife::connectSim(boost::asio::ipv4::address ip, unsigned short port, void SecondLife::tick() { Packet* packet; - // When we get to stream handling, this function will build data stream + bool returnValue; + std::list* inbox = _network->inbox(); + + // 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 + // 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(); + while (inbox->size() > 0) { + packet = inbox->front(); + inbox->pop_front(); std::string command = packet->command(); - callback handler = _callbacks[command]; - bool returnValue = handler(command, packet); + std::map::iterator handler = _callbacks.find(command); + + if (handler == _callbacks.end()) { + handler = _callbacks.find("Default"); + + if (handler != _callbacks.end()) { + returnValue = (handler->second)(command, packet); + } + } else { + returnValue = (handler->second)(command, packet); + } if (returnValue) { - ; + //FIXME: What is the purpose of the return value? } } } + + // Sleep for 1000 nanoseconds + boost::xtime xt; + boost::xtime_get(&xt, boost::TIME_UTC); + xt.nsec += 1000; + boost::thread::sleep(xt); }