Wt examples  4.2.2
SimpleChatServer.C
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 
7 #include "SimpleChatServer.h"
8 #include <Wt/WServer.h>
9 
10 #include <iostream>
11 
12 
14  Wt::TextFormat format) const
15 {
16  switch (type_) {
17  case Login:
18  return Wt::WString("<span class='chat-info'>")
19  + Wt::WWebWidget::escapeText(user_) + " joined.</span>";
20  case Logout:
21  return Wt::WString("<span class='chat-info'>")
22  + ((user == user_) ?
23  Wt::WString("You") :
24  Wt::WWebWidget::escapeText(user_))
25  + " logged out.</span>";
26  case Rename:
27  return "<span class='chat-info'>"
28  + ((user == data_ || user == user_) ?
29  "You are" :
30  (Wt::WWebWidget::escapeText(user_) + " is"))
31  + " now known as " + Wt::WWebWidget::escapeText(data_) + ".</span>";
32  case Message:{
33  Wt::WString result;
34 
35  result = Wt::WString("<span class='")
36  + ((user == user_) ?
37  "chat-self" :
38  "chat-user")
39  + "'>" + Wt::WWebWidget::escapeText(user_) + ":</span>";
40 
41  Wt::WString msg
42  = (format == Wt::TextFormat::XHTML ? message_ : Wt::WWebWidget::escapeText(message_));
43 
44  if (message_.toUTF8().find(user.toUTF8()) != std::string::npos)
45  return result + "<span class='chat-highlight'>" + msg + "</span>";
46  else
47  return result + msg;
48  }
49  default:
50  return "";
51  }
52 }
53 
54 
56  : server_(server)
57 { }
58 
60  const ChatEventCallback& handleEvent)
61 {
62  std::unique_lock<std::recursive_mutex> lock(mutex_);
63 
64  if (clients_.count(client) == 0) {
65  ClientInfo clientInfo;
66 
68  clientInfo.eventCallback = handleEvent;
69 
70  clients_[client] = clientInfo;
71 
72  return true;
73  } else
74  return false;
75 }
76 
78 {
79  std::unique_lock<std::recursive_mutex> lock(mutex_);
80 
81  return clients_.erase(client) == 1;
82 }
83 
85 {
86  std::unique_lock<std::recursive_mutex> lock(mutex_);
87 
88  if (users_.find(user) == users_.end()) {
89  users_.insert(user);
90 
92 
93  return true;
94  } else
95  return false;
96 }
97 
99 {
100  std::unique_lock<std::recursive_mutex> lock(mutex_);
101 
102  UserSet::iterator i = users_.find(user);
103 
104  if (i != users_.end()) {
105  users_.erase(i);
106 
108  }
109 }
110 
111 bool SimpleChatServer::changeName(const Wt::WString& user, const Wt::WString& newUser)
112 {
113  if (user == newUser)
114  return true;
115 
116  std::unique_lock<std::recursive_mutex> lock(mutex_);
117 
118  UserSet::iterator i = users_.find(user);
119 
120  if (i != users_.end()) {
121  if (users_.count(newUser) == 0) {
122  users_.erase(i);
123  users_.insert(newUser);
124 
125  postChatEvent(ChatEvent(ChatEvent::Rename, user, newUser));
126 
127  return true;
128  } else
129  return false;
130  } else
131  return false;
132 }
133 
135 {
136  std::unique_lock<std::recursive_mutex> lock(mutex_);
137 
138  for (int i = 1;; ++i) {
139  std::string s = "guest " + std::to_string(i);
140  Wt::WString ss = s;
141 
142  if (users_.find(ss) == users_.end())
143  return ss;
144  }
145 }
146 
147 void SimpleChatServer::sendMessage(const Wt::WString& user, const Wt::WString& message)
148 {
149  postChatEvent(ChatEvent(user, message));
150 }
151 
153 {
154  std::unique_lock<std::recursive_mutex> lock(mutex_);
155 
157 
158  for (ClientMap::const_iterator i = clients_.begin(); i != clients_.end();
159  ++i) {
160  /*
161  * If the user corresponds to the current application, we directly
162  * call the call back method. This avoids an unnecessary delay for
163  * the update to the user causing the event.
164  *
165  * For other uses, we post it to their session. By posting the
166  * event, we avoid dead-lock scenarios, race conditions, and
167  * delivering the event to a session that is just about to be
168  * terminated.
169  */
170  if (app && app->sessionId() == i->second.sessionId)
171  i->second.eventCallback(event);
172  else
173  server_.post(i->second.sessionId,
174  std::bind(i->second.eventCallback, event));
175  }
176 }
177 
179 {
180  std::unique_lock<std::recursive_mutex> lock(mutex_);
181 
182  UserSet result = users_;
183 
184  return result;
185 }
186 
SimpleChatServer::clients_
ClientMap clients_
Definition: SimpleChatServer.h:158
Wt::WApplication::instance
static WApplication * instance()
ChatEvent::message_
Wt::WString message_
Definition: SimpleChatServer.h:63
Wt::WApplication
ChatEvent::formattedHTML
const Wt::WString formattedHTML(const Wt::WString &user, Wt::TextFormat format) const
Get the message formatted as HTML, rendered for the given user.
Definition: SimpleChatServer.C:13
SimpleChatServer::server_
Wt::WServer & server_
Definition: SimpleChatServer.h:156
Wt::WApplication::sessionId
std::string sessionId() const
SimpleChatServer::disconnect
bool disconnect(Client *client)
Disconnect from the chat server.
Definition: SimpleChatServer.C:77
SimpleChatServer::ClientInfo::sessionId
std::string sessionId
Definition: SimpleChatServer.h:150
SimpleChatServer::ClientInfo::eventCallback
ChatEventCallback eventCallback
Definition: SimpleChatServer.h:151
Wt::WServer::post
WT_API void post(const std::string &sessionId, const std::function< void()> &function, const std::function< void()> &fallBackFunction=std::function< void()>())
SimpleChatServer::Client
Definition: SimpleChatServer.h:90
ChatEvent::Rename
@ Rename
Definition: SimpleChatServer.h:34
ChatEvent::user_
Wt::WString user_
Definition: SimpleChatServer.h:61
ChatEvent
Encapsulate a chat event.
Definition: SimpleChatServer.h:29
ChatEvent::type_
Type type_
Definition: SimpleChatServer.h:60
SimpleChatServer.h
ChatEvent::Logout
@ Logout
Definition: SimpleChatServer.h:34
Wt::WString
SimpleChatServer::users_
UserSet users_
Definition: SimpleChatServer.h:159
SimpleChatServer::ClientInfo
Definition: SimpleChatServer.h:149
Wt::TextFormat
TextFormat
ChatEvent::Message
@ Message
Definition: SimpleChatServer.h:34
Wt::WServer
SimpleChatServer::SimpleChatServer
SimpleChatServer(Wt::WServer &server)
Create a new chat server.
Definition: SimpleChatServer.C:55
Wt::WString::toUTF8
std::string toUTF8() const
SimpleChatServer::sendMessage
void sendMessage(const Wt::WString &user, const Wt::WString &message)
Send a message on behalve of a user.
Definition: SimpleChatServer.C:147
SimpleChatServer::users
UserSet users()
Get the users currently logged in.
Definition: SimpleChatServer.C:178
ChatEventCallback
std::function< void(const ChatEvent &)> ChatEventCallback
Definition: SimpleChatServer.h:80
Wt::TextFormat::XHTML
@ XHTML
SimpleChatServer::login
bool login(const Wt::WString &user)
Try to login with given user name.
Definition: SimpleChatServer.C:84
SimpleChatServer::connect
bool connect(Client *client, const ChatEventCallback &handleEvent)
Connects to the chat server.
Definition: SimpleChatServer.C:59
SimpleChatServer::suggestGuest
Wt::WString suggestGuest()
Get a suggestion for a guest user name.
Definition: SimpleChatServer.C:134
SimpleChatServer::changeName
bool changeName(const Wt::WString &user, const Wt::WString &newUser)
Changes the name.
Definition: SimpleChatServer.C:111
ChatEvent::data_
Wt::WString data_
Definition: SimpleChatServer.h:62
SimpleChatServer::UserSet
std::set< Wt::WString > UserSet
Typedef for a collection of user names.
Definition: SimpleChatServer.h:142
SimpleChatServer::postChatEvent
void postChatEvent(const ChatEvent &event)
Definition: SimpleChatServer.C:152
ChatEvent::Login
@ Login
Definition: SimpleChatServer.h:34
ChatEvent::user
const Wt::WString & user() const
Get the user who caused the event.
Definition: SimpleChatServer.h:42
SimpleChatServer::logout
void logout(const Wt::WString &user)
Logout from the server.
Definition: SimpleChatServer.C:98
SimpleChatServer::mutex_
std::recursive_mutex mutex_
Definition: SimpleChatServer.h:157

Generated on Fri Mar 20 2020 for the C++ Web Toolkit (Wt) by doxygen 1.8.17