Wt examples: /home/koen/project/wt/public-git/wt/examples/simplechat/SimpleChatServer.C Source File

Wt examples 3.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

/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