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'>" + user_ + " joined.</span>"; 00021 case Logout: 00022 return "<span class='chat-info'>" 00023 + ((user == user_) ? "You" : user_) 00024 + " logged out.</span>"; 00025 case Rename: 00026 return "<span class='chat-info'>" 00027 + ((user == data_ || user == user_) ? 00028 "You are" : (user_ + " is")) + " now known as " 00029 + data_ + ".</span>"; 00030 case Message:{ 00031 WString result; 00032 00033 result = WString("<span class='") 00034 + ((user == user_) ? "chat-self" : "chat-user") 00035 + "'>" + user_ + ":</span>"; 00036 00037 if (message_.toUTF8().find(user.toUTF8()) != std::string::npos) 00038 return result + "<span class='chat-highlight'>" + message_ + "</span>"; 00039 else 00040 return result + message_; 00041 } 00042 default: 00043 return ""; 00044 } 00045 } 00046 00047 00048 SimpleChatServer::SimpleChatServer() 00049 : chatEvent_(this) 00050 { } 00051 00052 bool SimpleChatServer::login(const WString& user) 00053 { 00054 // In every application path that holds a lock to a mutex while also 00055 // trying to update another application (as is in this method the 00056 // case during chatEvent_.emit()) we need to use Wt::SyncLock to 00057 // avoid dead-locks. 00058 00059 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00060 00061 if (users_.find(user) == users_.end()) { 00062 users_.insert(user); 00063 00064 chatEvent_.emit(ChatEvent(ChatEvent::Login, user)); 00065 00066 return true; 00067 } else 00068 return false; 00069 } 00070 00071 void SimpleChatServer::logout(const WString& user) 00072 { 00073 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00074 00075 UserSet::iterator i = users_.find(user); 00076 00077 if (i != users_.end()) { 00078 users_.erase(i); 00079 00080 chatEvent_.emit(ChatEvent(ChatEvent::Logout, user)); 00081 } 00082 } 00083 00084 bool SimpleChatServer::changeName(const WString& user, const WString& newUser) 00085 { 00086 if (user == newUser) 00087 return true; 00088 00089 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00090 00091 UserSet::iterator i = users_.find(user); 00092 00093 if (i != users_.end()) { 00094 if (users_.find(newUser) == users_.end()) { 00095 users_.erase(i); 00096 users_.insert(newUser); 00097 00098 chatEvent_.emit(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 SyncLock<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 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00123 00124 chatEvent_.emit(ChatEvent(user, message)); 00125 } 00126 00127 SimpleChatServer::UserSet SimpleChatServer::users() 00128 { 00129 SyncLock<boost::recursive_mutex::scoped_lock> lock(mutex_); 00130 00131 return users_; 00132 }