Wt examples  4.10.3
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
13const 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
56 : server_(server)
57{ }
58
61{
62 std::unique_lock<std::recursive_mutex> lock(mutex_);
63
64 if (clients_.count(client) == 0) {
66
67 clientInfo.sessionId = Wt::WApplication::instance()->sessionId();
68 clientInfo.eventCallback = handleEvent;
69
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
84bool 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
92
93 return true;
94 } else
95 return false;
96}
97
98void 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
108 }
109}
110
111bool 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
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
147void 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
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
179{
180 std::unique_lock<std::recursive_mutex> lock(mutex_);
181
183
184 return result;
185}
186
Wt::Auth::Dbo::UserDatabase< AuthInfo > UserDatabase
Definition Session.h:22
std::function< void(const ChatEvent &)> ChatEventCallback
Encapsulate a chat event.
Wt::WString user_
const Wt::WString formattedHTML(const Wt::WString &user, Wt::TextFormat format) const
Get the message formatted as HTML, rendered for the given user.
Wt::WString message_
const Wt::WString & user() const
Get the user who caused the event.
Wt::WString data_
bool changeName(const Wt::WString &user, const Wt::WString &newUser)
Changes the name.
bool disconnect(Client *client)
Disconnect from the chat server.
SimpleChatServer(Wt::WServer &server)
Create a new chat server.
UserSet users()
Get the users currently logged in.
void postChatEvent(const ChatEvent &event)
void logout(const Wt::WString &user)
Logout from the server.
std::set< Wt::WString > UserSet
Typedef for a collection of user names.
bool connect(Client *client, const ChatEventCallback &handleEvent)
Connects to the chat server.
void sendMessage(const Wt::WString &user, const Wt::WString &message)
Send a message on behalve of a user.
std::recursive_mutex mutex_
Wt::WServer & server_
Wt::WString suggestGuest()
Get a suggestion for a guest user name.
bool login(const Wt::WString &user)
Try to login with given user name.