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 00009 #include <Wt/SyncLock> 00010 00011 #include <iostream> 00012 #include <boost/lexical_cast.hpp> 00013 00014 using namespace Wt; 00015 00016 const WString ChatEvent::formattedHTML(const WString& user) const 00017 { 00018 switch (type_) { 00019 case Login: 00020 return "<span class='chat-info'>" 00021 + user_ + " joined the conversation.</span>"; 00022 case Logout: 00023 return "<span class='chat-info'>" 00024 + ((user == user_) ? "You" : user_) 00025 + " logged out.</span>"; 00026 case Message:{ 00027 WString result; 00028 00029 result = WString("<span class='") 00030 + ((user == user_) ? "chat-self" : "chat-user") 00031 + "'>" + user_ + ":</span>"; 00032 00033 if (message_.toUTF8().find(user.toUTF8()) != std::string::npos) 00034 return result + "<span class='chat-highlight'>" + message_ + "</span>"; 00035 else 00036 return result + message_; 00037 } 00038 default: 00039 return ""; 00040 } 00041 } 00042 00043 00044 SimpleChatServer::SimpleChatServer() 00045 : chatEvent_(this) 00046 { } 00047 00048 bool SimpleChatServer::login(const WString& user) 00049 { 00050 // In every application path that holds a lock to a mutex while also 00051 // trying to update another application (as is in this method the 00052 // case during chatEvent_.emit()) we need to use Wt::SyncLock to 00053 // avoid dead-locks. 00054 00055 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00056 00057 if (users_.find(user) == users_.end()) { 00058 users_.insert(user); 00059 00060 chatEvent_.emit(ChatEvent(ChatEvent::Login, user)); 00061 00062 return true; 00063 } else 00064 return false; 00065 } 00066 00067 void SimpleChatServer::logout(const WString& user) 00068 { 00069 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00070 00071 UserSet::iterator i = users_.find(user); 00072 00073 if (i != users_.end()) { 00074 users_.erase(i); 00075 00076 chatEvent_.emit(ChatEvent(ChatEvent::Logout, user)); 00077 } 00078 } 00079 00080 WString SimpleChatServer::suggestGuest() 00081 { 00082 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00083 00084 for (int i = 1;; ++i) { 00085 std::string s = "guest " + boost::lexical_cast<std::string>(i); 00086 WString ss = s; 00087 00088 if (users_.find(ss) == users_.end()) 00089 return ss; 00090 } 00091 } 00092 00093 void SimpleChatServer::sendMessage(const WString& user, const WString& message) 00094 { 00095 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00096 00097 chatEvent_.emit(ChatEvent(user, message)); 00098 } 00099 00100 SimpleChatServer::UserSet SimpleChatServer::users() 00101 { 00102 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00103 00104 return users_; 00105 }