Logo Search packages:      
Sourcecode: dc-qt version File versions  Download package

Session.cpp

#include "Session.h"
#include "ClientNotifier.h"
#include "SessionManager.h"
#include <iostream>
#include "CommonTypes.h"
#include <boost/thread/recursive_mutex.hpp>

using namespace std;

namespace dcqt_backend {

Session::Session(int aId,Client* aClient,string aUrl) : id(aId), client(aClient), url(aUrl) {
    client->addListener(this);
    client->setNick("Arnold");
      
    // Make sure we get search results.
    SearchManager::getInstance()->addListener( this );
    TimerManager::getInstance()->addListener( this );
}

Session::~Session()
{
  //cerr << "Session dtor" << endl;
  SearchManager::getInstance()->removeListener( this );
  TimerManager::getInstance()->removeListener( this );
}

void Session::connect() {
    client->connect();
}

void Session::sendChat(const string& msg) {
    client->hubMessage(msg);
}

void Session::search(int sizeMode, int64_t size, int typeMode, const string& searchString, const string& token) {
  SearchManager::SizeModes dcppSizeMode;
  SearchManager::TypeModes dcppTypeMode;

  //cout <<"Searching for '"<<searchString<<"'  sz:"<<size<<" szMode: "<<(int)sizeMode<<" typeMode"<<(int)typeMode<<endl;

  // This silly-looking switch-style mapping is here in case TypeModes
  // and/or SizeModes enums in dc++ SearchManager should change in the
  // future releases and become different from corresponding enums in
  // the backend namespace.  I see no point in making a proper map for
  // this, yet.

  switch (sizeMode) {
  case backend::SIZE_DONTCARE:   dcppSizeMode = SearchManager::SIZE_DONTCARE; break;
  case backend::SIZE_ATLEAST:    dcppSizeMode = SearchManager::SIZE_ATLEAST; break;
  case backend::SIZE_ATMOST:     dcppSizeMode = SearchManager::SIZE_ATMOST; break;
  default:
    dcppSizeMode = SearchManager::SIZE_DONTCARE; break;
  };

  switch (typeMode) {
  case backend::TYPE_ANY:        dcppTypeMode = SearchManager::TYPE_ANY; break;
  case backend::TYPE_AUDIO:      dcppTypeMode = SearchManager::TYPE_AUDIO; break;
  case backend::TYPE_COMPRESSED: dcppTypeMode = SearchManager::TYPE_COMPRESSED; break;
  case backend::TYPE_DOCUMENT:   dcppTypeMode = SearchManager::TYPE_DOCUMENT; break;
  case backend::TYPE_EXECUTABLE: dcppTypeMode = SearchManager::TYPE_EXECUTABLE; break;
  case backend::TYPE_PICTURE:    dcppTypeMode = SearchManager::TYPE_PICTURE; break;
  case backend::TYPE_VIDEO:      dcppTypeMode = SearchManager::TYPE_VIDEO; break;
  case backend::TYPE_DIRECTORY:  dcppTypeMode = SearchManager::TYPE_DIRECTORY; break;
  case backend::TYPE_TTH:        dcppTypeMode = SearchManager::TYPE_TTH; break;
  default:
    dcppTypeMode = SearchManager::TYPE_ANY; break;
  };

  SearchManager::getInstance()->search(searchString, size, dcppTypeMode, dcppSizeMode, "");

  //client->search(SearchManager::SIZE_DONTCARE, 0, SearchManager::TYPE_ANY, searchString, token);
}

////////////////////////////////////////
// TODO userRemoved
////////////////////////////////////////

void Session::updateUser(const ::User::Ptr& user) {
    dcqt_backend::User u = SessionManager::instance()->getUserPtrMap()[user];
    if(u.id==0) {
        // This user does not have an ID, get one.
        u.id = SessionManager::instance()->generateUserId();
    }

    u.flags = 0;
    // Stupid dc++ does not provide a getflags()
    if(user->isSet(::User::OP))
        u.flags|=::User::OP;
    if(user->isSet(::User::ONLINE))
        u.flags|=::User::ONLINE;
    if(user->isSet(::User::DCPLUSPLUS))
        u.flags|=::User::DCPLUSPLUS;
    if(user->isSet(::User::PASSIVE))
        u.flags|=::User::PASSIVE;
    if(user->isSet(::User::QUIT_HUB))
        u.flags|=::User::QUIT_HUB;
    if(user->isSet(::User::HIDDEN))
        u.flags|=::User::HIDDEN;
    if(user->isSet(::User::HUB))
        u.flags|=::User::HUB;
    if(user->isSet(::User::BOT))
        u.flags|=::User::BOT;
    u.nick = user->getNick();
    u.email = user->getEmail();
    u.desc = user->getDescription();
    u.connection = user->getConnection();
    u.tag = user->getTag();
    u.shared = user->getBytesShared();
    u.slots = user->getSlots();
    SessionManager::instance()->getUserPtrMap()[user] = u;
    SessionManager::instance()->getUserIdMap()[u.id] = user;
    userIdSet.insert(u.id);
    userUpdateCache.push_back(u.id);
}

void Session::on(ClientListener::Connecting, Client *aClient) throw() {
   // cout << "Session::on Connecting" << endl;
}

void Session::on(ClientListener::Connected, Client *aClient) throw() {
    //cout << "Session::on Connected" << endl;
    if(aClient==client) {

        ClientNotifier::instance()->connected(id);
    }
}

void Session::on(ClientListener::BadPassword, Client *client) throw() {
    //cout << "Session::on badpass" << endl;
}

void Session::on(ClientListener::UserUpdated, Client *aClient, const ::User::Ptr& user) throw() 
{
  if(aClient==client) {
    // cout << "Session::on userupdated" << endl;
      boost::recursive_mutex::scoped_lock sl(SessionManager::instance()->sessionLock);
      //SessionManager::instance()->aquireLock();
    updateUser(user);
    //SessionManager::instance()->releaseLock();

    // On large hubs, this function really gets spammed. Therefore, we delay the notification
    // until we feel we're ready to send.
    // ClientNotifier::instance()->userUpdated(id,user);
  }
}

void Session::on(ClientListener::UsersUpdated, Client *aClient, const ::User::List &list) throw() {
    //cout << "Session::on usersupdated" << endl;

    if(aClient==client) {
//        SessionManager::instance()->aquireLock();
            boost::recursive_mutex::scoped_lock sl(SessionManager::instance()->sessionLock);
        ::User::List::const_iterator it;
        for (it = list.begin (); it != list.begin (); it++) {
            updateUser(*it);
        }
//        SessionManager::instance()->releaseLock();
      //   ClientNotifier::instance()->usersUpdated(id,list);
    }
}

void Session::on(ClientListener::UserRemoved, Client *aClient, const ::User::Ptr &user) throw() {
    //cout << "Session::on userremoved" << endl;

    if(aClient==client) {
//        SessionManager::instance()->aquireLock();
            boost::recursive_mutex::scoped_lock sl(SessionManager::instance()->sessionLock);
        // Find the user
        int userid = SessionManager::instance()->getUserPtrMap()[user].id;
        userIdSet.erase ( userIdSet.find(userid) );
        SessionManager::instance()->getUserPtrMap().erase( SessionManager::instance()->getUserPtrMap().find(user) );
        SessionManager::instance()->getUserIdMap().erase(  SessionManager::instance()->getUserIdMap().find(userid) );
//        SessionManager::instance()->releaseLock();
        ClientNotifier::instance()->userRemoved(id,userid);
    }
}

void Session::on(ClientListener::Redirect,
                 Client *aClient, const string &address) throw() {
  if(client==aClient) {
    //cout << "Session::on redirect: " << address << endl;
    if(!address.empty()) {
      
            client->removeListener(this);
      ClientManager::getInstance()->putClient(client);
      client = ClientManager::getInstance()->getClient(Text::fromT(address));
      client->addListener(this);
      client->connect();



    }
  }
    
}

void Session::on(ClientListener::Failed,
                 Client *aClient, const string &reason) throw() {
   // cout << "Session::on failed" << endl;

    if( client == aClient ) {

      ClientNotifier::instance()->connectionFailed(id,reason);

    }

}

void Session::on(ClientListener::GetPassword, Client *aClient) throw() {
    //cout << "Session::on getpassword" << endl;
    if(client==aClient)
      ClientNotifier::instance()->getPassword(id);
}

void Session::on(ClientListener::HubUpdated, Client *aClient) throw() {
    //cout << "Session::on hubupdated" << endl;
    if(aClient==client) {
        //SessionManager::instance()->aquireLock();
            boost::recursive_mutex::scoped_lock sl(SessionManager::instance()->sessionLock);
        if (client->getName().empty())
            hubName = client->getAddress() + ":" + client->getAddressPort();
        else
            hubName = client->getName();
        //SessionManager::instance()->releaseLock();
        ClientNotifier::instance()->hubUpdated(id,hubName);
    }
}

void Session::on(ClientListener::Message, Client *aClient, const string &msg) throw() {
 // cout << "Session::on message: " << msg << endl;
    if(aClient==client) {

      if( Text::isAscii(msg) )
      cout << "Chat message is ascii\n";
      else
      cout << "Chat message is utf8!\n";

        ClientNotifier::instance()->message(id,msg);
    }
}

void Session::on(ClientListener::PrivateMessage,
                 Client *aClient, const ::User::Ptr &user, const string &msg) throw() {
   // cout << "Session::on privmsg" << endl;

    if(aClient==client) {
        ClientNotifier::instance()->privateMessage(id,user,msg);
    }

}
      

void Session::on(ClientListener::UserCommand, Client *client,
                 int, int, const string&, const string&) throw() {
    //cout << "Session::on usercommand" << endl;
}

void Session::on(ClientListener::HubFull, Client *client) throw() {
    //cout << "Session::on hubfull" << endl;
}

void Session::on(ClientListener::NickTaken, Client *client) throw() {
    //cout << "Session::on nicktaken" << endl;
}

void Session::on(ClientListener::SearchFlood, Client *client, const string &msg) throw() {
   // cout << "Session::on searchflood" << endl;
}

void Session::on(ClientListener::NmdcSearch, Client *client, const string&, int, int64_t, int, const string&) throw() {
    //cout << "Session::on nmcdsearch" << endl;
}

void Session::on(SearchManagerListener::SR, SearchResult* result) throw() {
    //cout << "Session::on SearchResult" << endl;
  // Check if the user the result corresponds to belongs to our hub
  if( result->getUser()->isClient( client ) ) {
    
    //  cout << "Session::on SearchResult with correct client" << endl;
    
    // if( Text::isAscii(result->getFileName())) cout << "Search result is ASCII\n";
    //else cout << "Search result is UTF8\n";
    //cout << "SearchResult utf8 flag: " << result->getUtf8();

    // Send the result to the client notifier so clients get the result
    // ClientNotifier::instance()->searchResult( id, result );

    //TTHValue* tth = result->getTTH();
    //[printf("TTH: ");
    //[for(int i=0;i < TTHValue::SIZE;i++)
    //  printf("%x ",tth->data[i]);


    result->incRef();
    searchCS.enter();
    searchResultCache.push_back(result);
    searchCS.leave();
  }
}

void Session::on(TimerManagerListener::Second, u_int32_t s) throw()
{
 
  // Take care of our userUpdated cache
  if( (s % 2) && userUpdateCache.size() ) {
    //SessionManager::instance()->aquireLock();
      boost::recursive_mutex::scoped_lock sl(SessionManager::instance()->sessionLock);
      ClientNotifier::instance()->usersUpdated(id,userUpdateCache);
    userUpdateCache.clear();
    //SessionManager::instance()->releaseLock();
  }

  // Flush the search result cache
   if( (s%2==0) && searchResultCache.size() ) {
     // assert(0);

     // Lock
    searchCS.enter();

    // Send
    ClientNotifier::instance()->searchResults(id,searchResultCache);

    // Release & clear
    for(int i=0;i < searchResultCache.size();i++)
      searchResultCache[i]->decRef();

    searchResultCache.clear();
    // Unlock
    searchCS.leave();
    

    }

      // Send total share size each 10 seconds
      if( s%10==0 ) {
            ClientNotifier::instance()->hubStats(id,client->getAvailable());
      }
      
  }
}

Generated by  Doxygen 1.6.0   Back to index