Wt examples  3.2.3
/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,
00016                                        TextFormat format) const
00017 {
00018   switch (type_) {
00019   case Login:
00020     return WString::fromUTF8("<span class='chat-info'>")
00021       + WWebWidget::escapeText(user_) + " joined.</span>";
00022   case Logout:
00023     return WString::fromUTF8("<span class='chat-info'>")
00024       + ((user == user_) ?
00025          WString::fromUTF8("You") :
00026          WWebWidget::escapeText(user_))
00027       + " logged out.</span>";
00028   case Rename:
00029     return "<span class='chat-info'>"
00030       + ((user == data_ || user == user_) ?
00031          "You are" :
00032          (WWebWidget::escapeText(user_) + " is")) 
00033       + " now known as " + WWebWidget::escapeText(data_) + ".</span>";
00034   case Message:{
00035     WString result;
00036 
00037     result = WString("<span class='")
00038       + ((user == user_) ?
00039          "chat-self" :
00040          "chat-user")
00041       + "'>" + WWebWidget::escapeText(user_) + ":</span>";
00042 
00043     WString msg
00044       = (format == XHTMLText ? message_ : WWebWidget::escapeText(message_));
00045 
00046     if (message_.toUTF8().find(user.toUTF8()) != std::string::npos)
00047       return result + "<span class='chat-highlight'>" + msg + "</span>";
00048     else
00049       return result + msg;
00050   }
00051   default:
00052     return "";
00053   }
00054 }
00055 
00056 
00057 SimpleChatServer::SimpleChatServer(WServer& server)
00058   : server_(server)
00059 { }
00060 
00061 bool SimpleChatServer::connect(Client *client,
00062                                const ChatEventCallback& handleEvent)
00063 {
00064   boost::recursive_mutex::scoped_lock lock(mutex_);
00065 
00066   if (clients_.count(client) == 0) {
00067     ClientInfo clientInfo;
00068   
00069     clientInfo.sessionId = WApplication::instance()->sessionId();
00070     clientInfo.eventCallback = handleEvent;
00071 
00072     clients_[client] = clientInfo;
00073 
00074     return true;
00075   } else
00076     return false;
00077 }
00078 
00079 bool SimpleChatServer::disconnect(Client *client)
00080 {
00081   boost::recursive_mutex::scoped_lock lock(mutex_);
00082 
00083   return clients_.erase(client) == 1;
00084 }
00085 
00086 bool SimpleChatServer::login(const WString& user)
00087 {
00088   boost::recursive_mutex::scoped_lock lock(mutex_);
00089   
00090   if (users_.find(user) == users_.end()) {
00091     users_.insert(user);
00092 
00093     postChatEvent(ChatEvent(ChatEvent::Login, user));
00094 
00095     return true;
00096   } else
00097     return false;
00098 }
00099 
00100 void SimpleChatServer::logout(const WString& user)
00101 {
00102   boost::recursive_mutex::scoped_lock lock(mutex_);
00103 
00104   UserSet::iterator i = users_.find(user);
00105 
00106   if (i != users_.end()) {
00107     users_.erase(i);
00108 
00109     postChatEvent(ChatEvent(ChatEvent::Logout, user));
00110   }
00111 }
00112 
00113 bool SimpleChatServer::changeName(const WString& user, const WString& newUser)
00114 {
00115   if (user == newUser)
00116     return true;
00117 
00118   boost::recursive_mutex::scoped_lock lock(mutex_);
00119   
00120   UserSet::iterator i = users_.find(user);
00121 
00122   if (i != users_.end()) {
00123     if (users_.count(newUser) == 0) {
00124       users_.erase(i);
00125       users_.insert(newUser);
00126 
00127       postChatEvent(ChatEvent(ChatEvent::Rename, user, newUser));
00128 
00129       return true;
00130     } else
00131       return false;
00132   } else
00133     return false;
00134 }
00135 
00136 WString SimpleChatServer::suggestGuest()
00137 {
00138   boost::recursive_mutex::scoped_lock lock(mutex_);
00139 
00140   for (int i = 1;; ++i) {
00141     std::string s = "guest " + boost::lexical_cast<std::string>(i);
00142     WString ss = s;
00143 
00144     if (users_.find(ss) == users_.end())
00145       return ss;
00146   }
00147 }
00148 
00149 void SimpleChatServer::sendMessage(const WString& user, const WString& message)
00150 {
00151   postChatEvent(ChatEvent(user, message));
00152 }
00153 
00154 void SimpleChatServer::postChatEvent(const ChatEvent& event)
00155 {
00156   boost::recursive_mutex::scoped_lock lock(mutex_);
00157 
00158   WApplication *app = WApplication::instance();
00159 
00160   for (ClientMap::const_iterator i = clients_.begin(); i != clients_.end();
00161        ++i) {
00162     /*
00163      * If the user corresponds to the current application, we directly
00164      * call the call back method. This avoids an unnecessary delay for
00165      * the update to the user causing the event.
00166      *
00167      * For other uses, we post it to their session. By posting the
00168      * event, we avoid dead-lock scenarios, race conditions, and
00169      * delivering the event to a session that is just about to be
00170      * terminated.
00171      */
00172     if (app && app->sessionId() == i->second.sessionId)
00173       i->second.eventCallback(event);
00174     else
00175       server_.post(i->second.sessionId,
00176                    boost::bind(i->second.eventCallback, event));
00177   }
00178 }
00179 
00180 SimpleChatServer::UserSet SimpleChatServer::users()
00181 {
00182   boost::recursive_mutex::scoped_lock lock(mutex_);
00183 
00184   UserSet result = users_;
00185 
00186   return result;
00187 }
00188 

Generated on Thu Nov 1 2012 for the C++ Web Toolkit (Wt) by doxygen 1.7.5.1