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:
John Hurliman
2006-05-25 22:20:56 +00:00
parent dd31af5032
commit 4e6f82d6bf
8 changed files with 129 additions and 48 deletions

View File

@@ -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; };

View File

@@ -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_

View File

@@ -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);

View File

@@ -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>

View File

@@ -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()),

View File

@@ -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;
}

View File

@@ -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",

View File

@@ -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);
}