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

Generated on Fri May 17 2024 for the C++ Web Toolkit (Wt) by doxygen 1.9.8