Wt examples 3.1.10
/build/buildd/witty-3.1.10/examples/simplechat/SimpleChatServer.C
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Emweb bvba, Heverlee, Belgium.
00003  *
00004  * See the LICENSE file for terms of use.
00005  */
00006 
00007 #include "SimpleChatServer.h"
00008 #include <Wt/WServer>
00009 
00010 #include <iostream>
00011 #include <boost/lexical_cast.hpp>
00012 
00013 using namespace Wt;
00014 
00015 const WString ChatEvent::formattedHTML(const WString& user) const
00016 {
00017   switch (type_) {
00018   case Login:
00019     return "<span class='chat-info'>" + user_ + " joined.</span>";
00020   case Logout:
00021     return "<span class='chat-info'>"
00022       + ((user == user_) ? "You" : user_)
00023       + " logged out.</span>";
00024   case Rename:
00025     return "<span class='chat-info'>"
00026       + ((user == data_ || user == user_) ?
00027          "You are" : (user_ + " is")) + " now known as "
00028       + data_ + ".</span>";
00029   case Message:{
00030     WString result;
00031 
00032     result = WString("<span class='")
00033       + ((user == user_) ? "chat-self" : "chat-user")
00034       + "'>" + user_ + ":</span>";
00035 
00036     if (message_.toUTF8().find(user.toUTF8()) != std::string::npos)
00037       return result + "<span class='chat-highlight'>" + message_ + "</span>";
00038     else
00039       return result + message_;
00040   }
00041   default:
00042     return "";
00043   }
00044 }
00045 
00046 
00047 SimpleChatServer::SimpleChatServer(WServer& server)
00048   : server_(server)
00049 { }
00050 
00051 bool SimpleChatServer::login(const WString& user,
00052                              const ChatEventCallback& handleEvent)
00053 {
00054   boost::recursive_mutex::scoped_lock lock(mutex_);
00055   
00056   if (users_.find(user) == users_.end()) {
00057     UserInfo userInfo;
00058     userInfo.sessionId = WApplication::instance()->sessionId();
00059     userInfo.eventCallback = handleEvent;
00060 
00061     users_[user] = userInfo;
00062 
00063     postChatEvent(ChatEvent(ChatEvent::Login, user));
00064 
00065     return true;
00066   } else
00067     return false;
00068 }
00069 
00070 void SimpleChatServer::logout(const WString& user)
00071 {
00072   boost::recursive_mutex::scoped_lock lock(mutex_);
00073 
00074   UserMap::iterator i = users_.find(user);
00075 
00076   if (i != users_.end()) {
00077     users_.erase(i);
00078 
00079     postChatEvent(ChatEvent(ChatEvent::Logout, user));
00080   }
00081 }
00082 
00083 bool SimpleChatServer::changeName(const WString& user, const WString& newUser)
00084 {
00085   if (user == newUser)
00086     return true;
00087 
00088   boost::recursive_mutex::scoped_lock lock(mutex_);
00089   
00090   UserMap::iterator i = users_.find(user);
00091 
00092   if (i != users_.end()) {
00093     if (users_.find(newUser) == users_.end()) {
00094       UserInfo info = i->second;
00095       users_.erase(i);
00096       users_[newUser] = info;
00097 
00098       postChatEvent(ChatEvent(ChatEvent::Rename, user, newUser));
00099 
00100       return true;
00101     } else
00102       return false;
00103   } else
00104     return false;
00105 }
00106 
00107 WString SimpleChatServer::suggestGuest()
00108 {
00109   boost::recursive_mutex::scoped_lock lock(mutex_);
00110 
00111   for (int i = 1;; ++i) {
00112     std::string s = "guest " + boost::lexical_cast<std::string>(i);
00113     WString ss = s;
00114 
00115     if (users_.find(ss) == users_.end())
00116       return ss;
00117   }
00118 }
00119 
00120 void SimpleChatServer::sendMessage(const WString& user, const WString& message)
00121 {
00122   postChatEvent(ChatEvent(user, message));
00123 }
00124 
00125 void SimpleChatServer::postChatEvent(const ChatEvent& event)
00126 {
00127   boost::recursive_mutex::scoped_lock lock(mutex_);
00128 
00129   WApplication *app = WApplication::instance();
00130 
00131   for (UserMap::const_iterator i = users_.begin(); i != users_.end(); ++i) {
00132     /*
00133      * If the user corresponds to the current application, we directly
00134      * call the call back method. This avoids an unnecessary delay for
00135      * the update to the user causing the event.
00136      *
00137      * For other uses, we post it to their session. By posting the
00138      * event, we avoid dead-lock scenarios, race conditions, and
00139      * delivering the event to a session that is just about to be
00140      * terminated.
00141      */
00142     if (app && app->sessionId() == i->second.sessionId)
00143       i->second.eventCallback(event);
00144     else
00145       server_.post(i->second.sessionId,
00146                    boost::bind(i->second.eventCallback, event));
00147   }
00148 }
00149 
00150 SimpleChatServer::UserSet SimpleChatServer::users()
00151 {
00152   boost::recursive_mutex::scoped_lock lock(mutex_);
00153 
00154   UserSet result;
00155   for (UserMap::const_iterator i = users_.begin(); i != users_.end(); ++i)
00156     result.insert(i->first);
00157 
00158   return result;
00159 }
00160 

Generated on Mon Nov 14 2011 for the C++ Web Toolkit (Wt) by doxygen 1.7.4