Wt examples  3.2.0
/home/koen/project/wt/public-git/wt/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::connect(Client *client,
00052                                const ChatEventCallback& handleEvent)
00053 {
00054   boost::recursive_mutex::scoped_lock lock(mutex_);
00055 
00056   if (clients_.count(client) == 0) {
00057     ClientInfo clientInfo;
00058   
00059     clientInfo.sessionId = WApplication::instance()->sessionId();
00060     clientInfo.eventCallback = handleEvent;
00061 
00062     clients_[client] = clientInfo;
00063 
00064     return true;
00065   } else
00066     return false;
00067 }
00068 
00069 bool SimpleChatServer::disconnect(Client *client)
00070 {
00071   boost::recursive_mutex::scoped_lock lock(mutex_);
00072 
00073   return clients_.erase(client) == 1;
00074 }
00075 
00076 bool SimpleChatServer::login(const WString& user)
00077 {
00078   boost::recursive_mutex::scoped_lock lock(mutex_);
00079   
00080   if (users_.find(user) == users_.end()) {
00081     users_.insert(user);
00082 
00083     postChatEvent(ChatEvent(ChatEvent::Login, user));
00084 
00085     return true;
00086   } else
00087     return false;
00088 }
00089 
00090 void SimpleChatServer::logout(const WString& user)
00091 {
00092   boost::recursive_mutex::scoped_lock lock(mutex_);
00093 
00094   UserSet::iterator i = users_.find(user);
00095 
00096   if (i != users_.end()) {
00097     users_.erase(i);
00098 
00099     postChatEvent(ChatEvent(ChatEvent::Logout, user));
00100   }
00101 }
00102 
00103 bool SimpleChatServer::changeName(const WString& user, const WString& newUser)
00104 {
00105   if (user == newUser)
00106     return true;
00107 
00108   boost::recursive_mutex::scoped_lock lock(mutex_);
00109   
00110   UserSet::iterator i = users_.find(user);
00111 
00112   if (i != users_.end()) {
00113     if (users_.count(newUser) == 0) {
00114       users_.erase(i);
00115       users_.insert(newUser);
00116 
00117       postChatEvent(ChatEvent(ChatEvent::Rename, user, newUser));
00118 
00119       return true;
00120     } else
00121       return false;
00122   } else
00123     return false;
00124 }
00125 
00126 WString SimpleChatServer::suggestGuest()
00127 {
00128   boost::recursive_mutex::scoped_lock lock(mutex_);
00129 
00130   for (int i = 1;; ++i) {
00131     std::string s = "guest " + boost::lexical_cast<std::string>(i);
00132     WString ss = s;
00133 
00134     if (users_.find(ss) == users_.end())
00135       return ss;
00136   }
00137 }
00138 
00139 void SimpleChatServer::sendMessage(const WString& user, const WString& message)
00140 {
00141   postChatEvent(ChatEvent(user, message));
00142 }
00143 
00144 void SimpleChatServer::postChatEvent(const ChatEvent& event)
00145 {
00146   boost::recursive_mutex::scoped_lock lock(mutex_);
00147 
00148   WApplication *app = WApplication::instance();
00149 
00150   for (ClientMap::const_iterator i = clients_.begin(); i != clients_.end();
00151        ++i) {
00152     /*
00153      * If the user corresponds to the current application, we directly
00154      * call the call back method. This avoids an unnecessary delay for
00155      * the update to the user causing the event.
00156      *
00157      * For other uses, we post it to their session. By posting the
00158      * event, we avoid dead-lock scenarios, race conditions, and
00159      * delivering the event to a session that is just about to be
00160      * terminated.
00161      */
00162     if (app && app->sessionId() == i->second.sessionId)
00163       i->second.eventCallback(event);
00164     else
00165       server_.post(i->second.sessionId,
00166                    boost::bind(i->second.eventCallback, event));
00167   }
00168 }
00169 
00170 SimpleChatServer::UserSet SimpleChatServer::users()
00171 {
00172   boost::recursive_mutex::scoped_lock lock(mutex_);
00173 
00174   UserSet result = users_;
00175 
00176   return result;
00177 }
00178 

Generated on Tue Nov 29 2011 for the C++ Web Toolkit (Wt) by doxygen 1.7.5.1