00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #include <QUANTA/QUANTAnet_datapack_c.hxx>
00033 #include <QUANTA/QUANTAnet_tcpReflector_c.hxx>
00034 #include <QUANTA/QUANTAnet_udp_c.hxx>
00035
00036 #include <QAvatarManager.h>
00037 #include <QAvatarFactory.h>
00038 #include <QAvatarListener.h>
00039
00040 #include <assert.h>
00041 #include <string.h>
00042
00043 #ifdef USE_STL_NAMESPACE
00044 #include <iostream>
00045 using std::cerr;
00046 using std::cout;
00047 using std::endl;
00048 #else
00049 #include <iostream.h>
00050 #endif
00051
00052 const char QAvatarManager::AUX_MSG = 'a';
00053 const char QAvatarManager::BYE_MSG = 'b';
00054 const char QAvatarManager::HELLO_MSG = 'h';
00055 const char QAvatarManager::TRACKER_MSG = 't';
00056
00057 QAvatarManager::QAvatarManager(QAvatarFactory* factory)
00058 : m_avatarDB(NULL), m_selfAvatar(NULL),
00059 m_avatarFactory(factory),
00060 m_hailingTCP(NULL),
00061 m_trackerUDP(NULL),
00062 m_hailingBuffer(NULL), m_trackerBuffer(NULL),
00063 m_noNetworking(false), m_trackerDelay(0.25),
00064 m_tempBuffer(NULL)
00065 {
00066 m_hailingTCP = new QUANTAnet_tcpReflectorClient_c;
00067 m_trackerUDP = new QUANTAnet_udp_c;
00068
00069 double theTime = QUANTAnet_socketbase_c::getTimeInSecs();
00070 char idStr[256];
00071 sprintf(idStr,"%lf", theTime);
00072
00073
00074 QUANTAmisc_hashWord_t hashVal = QUANTAmisc_hash(idStr, strlen(idStr)+1);
00075 long selfAvatarID = hashVal;
00076 m_selfAvatar = m_avatarFactory->createAvatar(selfAvatarID);
00077 assert(m_selfAvatar != NULL);
00078 m_avatarDB = new QUANTAmisc_hashDict<QAvatar*, long>;
00079
00080 m_selfAvatar->lock();
00081 if ((m_selfAvatar->getHelloDataSize() == 0)
00082 || (m_selfAvatar->getTrackerDataSize() == 0)) {
00083 cerr << "WARNING: QAvatarManager detected uninitialized avatar "
00084 << "hello or tracker data size." << endl;
00085 }
00086
00087
00088 m_hailingBufSize = QUANTAnet_datapack_c::sizeof_char()
00089 + QUANTAnet_datapack_c::sizeof_long()
00090 + (m_selfAvatar->getHelloDataSize() > m_selfAvatar->getAuxDataSize()
00091 ? m_selfAvatar->getHelloDataSize() : m_selfAvatar->getAuxDataSize());
00092 cout << "AVATAR hailing size: " << m_hailingBufSize << endl;
00093 m_hailingBuffer = new char[m_hailingBufSize];
00094 m_trackerBufSize = QUANTAnet_datapack_c::sizeof_char()
00095 + QUANTAnet_datapack_c::sizeof_long()
00096 + m_selfAvatar->getTrackerDataSize();
00097 cout << "AVATAR tracker size: " << m_trackerBufSize << endl;
00098 m_trackerBuffer = new char[m_trackerBufSize];
00099 m_tempBuffer = new char[m_selfAvatar->getHelloDataSize()];
00100 m_selfAvatar->unlock();
00101 }
00102
00103 QAvatarManager::~QAvatarManager()
00104 {
00105
00106 m_hailingTCP->close();
00107 m_trackerUDP->close();
00108
00109 delete m_selfAvatar;
00110 delete m_avatarDB;
00111 delete m_hailingTCP;
00112 delete m_trackerUDP;
00113 delete[] m_hailingBuffer;
00114 delete[] m_trackerBuffer;
00115 delete[] m_tempBuffer;
00116 }
00117
00118 void
00119 QAvatarManager::checkForTimeouts()
00120 {
00121
00122 m_avatarDB->lock();
00123 int numItems;
00124 QAvatar** avatarList = m_avatarDB->buildListOfEntries(&numItems);
00125 QAvatar* theAvatar;
00126 if (numItems) {
00127 for (int i = 0; i < numItems; i++) {
00128 theAvatar = avatarList[i];
00129
00130
00131 if ((QUANTAnet_socketbase_c::getTimeInSecs()
00132 - theAvatar->getLastUpdateTime()) > 120) {
00133 m_avatarDB->remove(theAvatar->getID());
00134 cout << "AVATAR " << avatarList[i]->getID() << " timed out" << endl;
00135
00136 this->notifyBye(theAvatar);
00137 delete theAvatar;
00138 }
00139 }
00140 }
00141 m_avatarDB->unlock();
00142
00143 if (numItems)
00144 delete[] avatarList;
00145 }
00146
00147 bool
00148 QAvatarManager::connect(const char* server, const unsigned short& hailingPort,
00149 const unsigned short& trackerPort)
00150 {
00151
00152 if (m_hailingTCP->connectToServer(server, hailingPort)
00153 == QUANTAnet_tcpReflectorClient_c::OK) {
00154 cout << "AVATAR hailing channel connected to "
00155 << server << ':'<< hailingPort << endl;
00156 } else {
00157 m_noNetworking = true;
00158 cerr << "AVATAR TCP CONNECT FAILED" << endl;
00159 return false;
00160 }
00161
00162
00163 m_trackerUDP->setSendAddress(server, trackerPort);
00164 if (m_trackerUDP->init() == QUANTAnet_udp_c::OK) {
00165 cout << "AVATAR tracker channel connected to "
00166 << server << ':'<< trackerPort << endl;
00167 } else {
00168 m_noNetworking = true;
00169 cerr << "AVATAR UDP CONNECT FAILED" << endl;
00170 return false;
00171 }
00172 return true;
00173 }
00174
00175 QAvatar*
00176 QAvatarManager::getSelfAvatar()
00177 {
00178 assert(m_selfAvatar != NULL);
00179 return m_selfAvatar;
00180 }
00181
00182 void
00183 QAvatarManager::attach(QAvatarListener* listener)
00184 {
00185 if (listener != NULL)
00186 m_listeners.push_back(listener);
00187 }
00188
00189 void
00190 QAvatarManager::detach(QAvatarListener* listener)
00191 {
00192 if (listener != NULL)
00193 m_listeners.remove(listener);
00194 }
00195
00196 void
00197 QAvatarManager::process()
00198 {
00199 if (m_noNetworking)
00200 return;
00201
00202 char* hailData = NULL;
00203 int dataSize;
00204 int udpBytesRead;
00205
00206 int status = m_hailingTCP->read(&hailData, &dataSize,
00207 QUANTAnet_tcpReflectorClient_c::NON_BLOCKING);
00208 if (hailData) {
00209 this->handleHailingData(hailData, dataSize);
00210 delete[] hailData;
00211 }
00212
00213 char* buf = new char[m_trackerBufSize];
00214
00215 udpBytesRead = m_trackerUDP->receive(buf, m_trackerBufSize,
00216 QUANTAnet_udp_c::NON_BLOCKING);
00217 if (udpBytesRead > 0)
00218 this->handleTrackerData(buf, udpBytesRead);
00219 delete[] buf;
00220
00221 this->checkForTimeouts();
00222 }
00223
00224 bool
00225 QAvatarManager::sendAux()
00226 {
00227 if (m_noNetworking)
00228 return false;
00229
00230 QUANTAnet_datapack_c datapack;
00231 datapack.initPack(m_hailingBuffer, m_hailingBufSize);
00232 datapack.packChar(QAvatarManager::AUX_MSG);
00233 datapack.packLong(m_selfAvatar->getID());
00234 m_selfAvatar->lock();
00235 datapack.pack(m_selfAvatar->getAuxData(), m_selfAvatar->getAuxDataSize());
00236 m_selfAvatar->unlock();
00237
00238 int bufSize = datapack.getBufferFilledSize();
00239 if (m_hailingTCP->write(m_hailingBuffer, &bufSize)
00240 == QUANTAnet_tcpReflectorClient_c::OK)
00241 return true;
00242
00243 return false;
00244 }
00245
00246 bool
00247 QAvatarManager::sendBye()
00248 {
00249 if (m_noNetworking)
00250 return false;
00251
00252 QUANTAnet_datapack_c datapack;
00253 datapack.initPack(m_hailingBuffer, m_hailingBufSize);
00254 datapack.packChar(QAvatarManager::BYE_MSG);
00255 datapack.packLong(m_selfAvatar->getID());
00256
00257 int bufSize = datapack.getBufferFilledSize();
00258 if (m_hailingTCP->write(m_hailingBuffer, &bufSize)
00259 == QUANTAnet_tcpReflectorClient_c::OK)
00260 return true;
00261
00262 return false;
00263 }
00264
00265 bool
00266 QAvatarManager::sendHello()
00267 {
00268 if (m_noNetworking)
00269 return false;
00270
00271 QUANTAnet_datapack_c datapack;
00272 datapack.initPack(m_hailingBuffer, m_hailingBufSize);
00273 datapack.packChar(QAvatarManager::HELLO_MSG);
00274 datapack.packLong(m_selfAvatar->getID());
00275 m_selfAvatar->lock();
00276 datapack.pack(m_selfAvatar->getHelloData(),
00277 m_selfAvatar->getHelloDataSize());
00278 m_selfAvatar->unlock();
00279
00280 int bufSize = datapack.getBufferFilledSize();
00281
00282 if (m_hailingTCP->write(m_hailingBuffer, &bufSize)
00283 == QUANTAnet_tcpReflectorClient_c::OK)
00284 return true;
00285
00286 return false;
00287 }
00288
00289 bool
00290 QAvatarManager::sendTracker()
00291 {
00292 if (m_noNetworking)
00293 return false;
00294
00295 double currentTime = QUANTAnet_socketbase_c::getTimeInSecs();
00296 if ((currentTime - m_lastTimeTrackerSent) < m_trackerDelay) {
00297 return true;
00298 }
00299
00300 QUANTAnet_datapack_c datapack;
00301 datapack.initPack(m_trackerBuffer, m_trackerBufSize);
00302 datapack.packChar(QAvatarManager::TRACKER_MSG);
00303 datapack.packLong(m_selfAvatar->getID());
00304 m_selfAvatar->lock();
00305 datapack.pack(m_selfAvatar->getTrackerData(),
00306 m_selfAvatar->getTrackerDataSize());
00307 m_selfAvatar->unlock();
00308
00309 int bufSize = datapack.getBufferFilledSize();
00310
00311 if (m_trackerUDP->send(m_trackerBuffer, bufSize, QUANTAnet_udp_c::NON_BLOCKING)
00312 != -1) {
00313 m_lastTimeTrackerSent = currentTime;
00314 return true;
00315 } else {
00316 cerr << "AVATAR tracker data was not sent!" << endl;
00317 }
00318
00319 return false;
00320 }
00321
00322 void
00323 QAvatarManager::setTrackerUpdateDelay(const double& delay)
00324 {
00325 assert(delay >= 0.0);
00326 m_trackerDelay = delay;
00327 }
00328
00329 void
00330 QAvatarManager::handleHailingData(char* dataBuf, const size_t& dataSize)
00331 {
00332 if (dataSize == 0)
00333 return;
00334
00335 cout << "AVATAR: HailingCB" << endl;
00336 m_avatarDB->lock();
00337
00338 QUANTAnet_datapack_c datapack;
00339
00340
00341 datapack.initUnpack(dataBuf, dataSize);
00342 char command;
00343 datapack.unpackChar(&command);
00344 long avatarID;
00345 datapack.unpackLong(&avatarID);
00346
00347
00348 QAvatar* theQAvatar;
00349 m_avatarDB->find(avatarID, theQAvatar);
00350
00351 if (command == QAvatarManager::HELLO_MSG) {
00352 if (!theQAvatar) {
00353
00354
00355
00356 theQAvatar = m_avatarFactory->createAvatar(avatarID);
00357
00358
00359 if (!theQAvatar) {
00360 cerr << "AVATAR: Unable to allocate new entry for avatar." << endl;
00361 }
00362
00363
00364 theQAvatar->markUpdateTime();
00365
00366
00367 m_avatarDB->enter(avatarID, theQAvatar);
00368
00369
00370 datapack.unpack(m_tempBuffer, m_selfAvatar->getHelloDataSize());
00371 theQAvatar->setHelloData(m_tempBuffer, m_selfAvatar->getHelloDataSize());
00372
00373 cout << "AVATAR: new avatar "<< avatarID << " arrived" << endl;
00374
00375
00376 this->notifyArrive(theQAvatar);
00377
00378
00379 if (command == QAvatarManager::HELLO_MSG) {
00380 this->sendHello();
00381 }
00382
00383 } else {
00384
00385
00386 theQAvatar->markUpdateTime();
00387
00388
00389 datapack.unpack(m_tempBuffer, m_selfAvatar->getHelloDataSize());
00390
00391
00392 if (memcmp(m_tempBuffer, theQAvatar->getHelloData(), m_selfAvatar->getHelloDataSize())) {
00393
00394
00395 theQAvatar->setHelloData(m_tempBuffer, m_selfAvatar->getHelloDataSize());
00396
00397
00398 this->notifyHello(theQAvatar);
00399 }
00400 }
00401
00402 } else if (command == QAvatarManager::BYE_MSG) {
00403
00404 if (!theQAvatar) {
00405 m_avatarDB->unlock();
00406 return;
00407 }
00408
00409
00410
00411 m_avatarDB->remove(avatarID);
00412 this->notifyBye(theQAvatar);
00413 delete theQAvatar;
00414
00415 } else if (command == QAvatarManager::AUX_MSG) {
00416
00417 if (!theQAvatar) {
00418 m_avatarDB->unlock();
00419 return;
00420 }
00421
00422
00423 theQAvatar->markUpdateTime();
00424
00425 datapack.unpack(m_tempBuffer, m_selfAvatar->getAuxDataSize());
00426 theQAvatar->setAuxData(m_tempBuffer, m_selfAvatar->getAuxDataSize());
00427
00428
00429 this->notifyAux(theQAvatar);
00430 }
00431
00432 m_avatarDB->unlock();
00433 }
00434
00435 void
00436 QAvatarManager::handleTrackerData(char* dataBuf, const size_t& dataSize)
00437 {
00438
00439
00440
00441
00442
00443
00444
00445 QUANTAnet_datapack_c datapack;
00446
00447 datapack.initUnpack(dataBuf, dataSize);
00448 char command;
00449 datapack.unpackChar(&command);
00450 long avatarID;
00451 datapack.unpackLong(&avatarID);
00452
00453
00454 QAvatar* theQAvatar;
00455 m_avatarDB->lock();
00456 m_avatarDB->find(avatarID, theQAvatar);
00457 m_avatarDB->unlock();
00458
00459
00460 if (!theQAvatar) {
00461 return;
00462 }
00463
00464
00465 if (command == QAvatarManager::TRACKER_MSG) {
00466 theQAvatar->markUpdateTime();
00467
00468 datapack.unpack(m_tempBuffer, m_selfAvatar->getTrackerDataSize());
00469 theQAvatar->setTrackerData(m_tempBuffer, m_selfAvatar->getTrackerDataSize());
00470
00471 this->notifyTracker(theQAvatar);
00472 }
00473 }
00474
00475 void
00476 QAvatarManager::notifyArrive(QAvatar* theQAvatar)
00477 {
00478 for (ListenerList::iterator i = m_listeners.begin();
00479 i != m_listeners.end(); i++) {
00480 (*i)->avatarArrive(theQAvatar);
00481 }
00482 }
00483
00484 void
00485 QAvatarManager::notifyAux(QAvatar* theQAvatar)
00486 {
00487 for (ListenerList::iterator i = m_listeners.begin();
00488 i != m_listeners.end(); i++) {
00489 (*i)->avatarAux(theQAvatar);
00490 }
00491 }
00492
00493 void
00494 QAvatarManager::notifyBye(QAvatar* theQAvatar)
00495 {
00496 for (ListenerList::iterator i = m_listeners.begin();
00497 i != m_listeners.end(); i++) {
00498 (*i)->avatarBye(theQAvatar);
00499 }
00500 }
00501
00502 void
00503 QAvatarManager::notifyHello(QAvatar* theQAvatar)
00504 {
00505 for (ListenerList::iterator i = m_listeners.begin();
00506 i != m_listeners.end(); i++) {
00507 (*i)->avatarHello(theQAvatar);
00508 }
00509 }
00510
00511 void
00512 QAvatarManager::notifyTracker(QAvatar* theQAvatar)
00513 {
00514 for (ListenerList::iterator i = m_listeners.begin();
00515 i != m_listeners.end(); i++) {
00516 (*i)->avatarTracker(theQAvatar);
00517 }
00518 }