Wt examples: simplechat/SimpleChatServer.C Source File

Wt examples 4.10.4

Loading...
Searching...
No Matches
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
13 const Wt::WString ChatEvent::formattedHTML(const Wt::WString& user,
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
55SimpleChatServer::SimpleChatServer(Wt::WServer& server)
56 : server_(server)
57{ }
58
59 bool SimpleChatServer::connect(Client *client,
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
67 clientInfo.sessionId = Wt::WApplication::instance()->sessionId();
68 clientInfo.eventCallback = handleEvent;
69
70 clients_[client] = clientInfo;
71
72 return true;
73 } else
74 return false;
75}
76
77 bool SimpleChatServer::disconnect(Client *client)
78{
79 std::unique_lock<std::recursive_mutex> lock(mutex_);
80
81 return clients_.erase(client) == 1;
82}
83
84 bool SimpleChatServer::login(const Wt::WString& user)
85{
86 std::unique_lock<std::recursive_mutex> lock(mutex_);
87
88 if (users_.find(user) == users_.end()) {
89 users_.insert(user);
90
91 postChatEvent(ChatEvent(ChatEvent::Login, user));
92
93 return true;
94 } else
95 return false;
96}
97
98 void SimpleChatServer::logout(const Wt::WString& user)
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
107 postChatEvent(ChatEvent(ChatEvent::Logout, user));
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
134Wt::WString SimpleChatServer::suggestGuest()
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
152 void SimpleChatServer::postChatEvent(const ChatEvent& event)
153{
154 std::unique_lock<std::recursive_mutex> lock(mutex_);
155
156 Wt::WApplication *app = Wt::WApplication::instance();
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
178 SimpleChatServer::UserSet SimpleChatServer::users()
179{
180 std::unique_lock<std::recursive_mutex> lock(mutex_);
181
182 UserSet result = users_;
183
184 return result;
185}
186
SimpleChatServer.h
ChatEventCallback
std::function< void(const ChatEvent &)> ChatEventCallback
Definition SimpleChatServer.h:80
ChatEvent
Encapsulate a chat event.
Definition SimpleChatServer.h:30
ChatEvent::user_
Wt::WString user_
Definition SimpleChatServer.h:61
ChatEvent::type_
Type type_
Definition SimpleChatServer.h:60
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
ChatEvent::message_
Wt::WString message_
Definition SimpleChatServer.h:63
ChatEvent::user
const Wt::WString & user() const
Get the user who caused the event.
Definition SimpleChatServer.h:42
ChatEvent::data_
Wt::WString data_
Definition SimpleChatServer.h:62
ChatEvent::Login
@ Login
Definition SimpleChatServer.h:34
ChatEvent::Logout
@ Logout
Definition SimpleChatServer.h:34
ChatEvent::Rename
@ Rename
Definition SimpleChatServer.h:34
ChatEvent::Message
@ Message
Definition SimpleChatServer.h:34
SimpleChatServer::Client
Definition SimpleChatServer.h:91
SimpleChatServer::changeName
bool changeName(const Wt::WString &user, const Wt::WString &newUser)
Changes the name.
Definition SimpleChatServer.C:111
SimpleChatServer::disconnect
bool disconnect(Client *client)
Disconnect from the chat server.
Definition SimpleChatServer.C:77
SimpleChatServer::SimpleChatServer
SimpleChatServer(Wt::WServer &server)
Create a new chat server.
Definition SimpleChatServer.C:55
SimpleChatServer::users
UserSet users()
Get the users currently logged in.
Definition SimpleChatServer.C:178
SimpleChatServer::postChatEvent
void postChatEvent(const ChatEvent &event)
Definition SimpleChatServer.C:152
SimpleChatServer::logout
void logout(const Wt::WString &user)
Logout from the server.
Definition SimpleChatServer.C:98
SimpleChatServer::connect
bool connect(Client *client, const ChatEventCallback &handleEvent)
Connects to the chat server.
Definition SimpleChatServer.C:59
SimpleChatServer::UserSet
std::set< Wt::WString > UserSet
Typedef for a collection of user names.
Definition SimpleChatServer.h:142
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::mutex_
std::recursive_mutex mutex_
Definition SimpleChatServer.h:157
SimpleChatServer::server_
Wt::WServer & server_
Definition SimpleChatServer.h:156
SimpleChatServer::suggestGuest
Wt::WString suggestGuest()
Get a suggestion for a guest user name.
Definition SimpleChatServer.C:134
SimpleChatServer::login
bool login(const Wt::WString &user)
Try to login with given user name.
Definition SimpleChatServer.C:84
SimpleChatServer::clients_
ClientMap clients_
Definition SimpleChatServer.h:158
SimpleChatServer::users_
UserSet users_
Definition SimpleChatServer.h:159
SimpleChatServer::ClientInfo
Definition SimpleChatServer.h:149
SimpleChatServer::ClientInfo::sessionId
std::string sessionId
Definition SimpleChatServer.h:150
SimpleChatServer::ClientInfo::eventCallback
ChatEventCallback eventCallback
Definition SimpleChatServer.h:151