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
This commit is contained in:
@@ -96,7 +96,7 @@ public:
|
||||
int sendPacket(Packet* packet);
|
||||
void receivePacket(const boost::asio::error& error, std::size_t length, char* receiveBuffer);
|
||||
|
||||
std::list<Packet*> inbox() { return _inbox; };
|
||||
std::list<Packet*>* inbox() { return &_inbox; };
|
||||
|
||||
LLUUID agent_id() { return _agent_id; };
|
||||
void agent_id(LLUUID agent_id) { _agent_id = agent_id; };
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
@@ -94,9 +94,9 @@ void Network::login(std::string firstName, std::string lastName, std::string pas
|
||||
"<member><name>passwd</name><value><string>" + passwordDigest + "</string></value></member>"
|
||||
"<member><name>start</name><value><string>last</string></value></member>"
|
||||
"<member><name>major</name><value><string>1</string></value></member>"
|
||||
"<member><name>minor</name><value><string>9</string></value></member>"
|
||||
"<member><name>minor</name><value><string>10</string></value></member>"
|
||||
"<member><name>patch</name><value><string>0</string></value></member>"
|
||||
"<member><name>build</name><value><string>21</string></value></member>"
|
||||
"<member><name>build</name><value><string>32</string></value></member>"
|
||||
"<member><name>platform</name><value><string>" + platform + "</string></value></member>"
|
||||
"<member><name>mac</name><value><string>" + mac + "</string></value></member>"
|
||||
"<member><name>viewer_digest</name><value><string>" + viewerDigest + "</string></value></member>"
|
||||
@@ -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()),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<Packet*>* 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<std::string, callback>::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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user