Bridges-C++ 3.5.0-dev2-1-ge3e57bf
Bridges(C++ API)
SocketConnection.h
Go to the documentation of this file.
1#ifndef SOCKET_CONNECTION_H
2#define SOCKET_CONNECTION_H
3
5//technically these are defined necessarry for socketio.
6//but they only get included from here
7//so this is simpler than mocking with build chains for each compiler
8#define BOOST_DATE_TIME_NO_LIB
9#define BOOST_REGEX_NO_LIB
10#define ASIO_STANDALONE
11#define _WEBSOCKETPP_CPP11_STL_
12#define _WEBSOCKETPP_CPP11_FUNCTIONAL_
14
15#include "sio_client.h"
16#include "internal/sio_packet.h"
17#include <Bridges.h>
18#include <GameGrid.h>
19#include <Scene.h>
20#include <list>
21#include <thread>
22#include <mutex>
23#include <condition_variable>
24#include <functional>
25
26#include <unistd.h>
27
28namespace bridges {
29 namespace game {
30
35 public:
36 virtual void keyup(std::string JSONmessage) = 0;
37 virtual void keydown(std::string JSONmessage) = 0;
38 };
39
49 bool debug = false;
50 bool debugVerbose = false;
51 sio::client client;
52 sio::socket::ptr current_socket;
53
55
56 std::mutex _lock;
57
58 std::condition_variable_any _cond; //condition used to wait on connection to be established
59 bool connect_finish = false;
60
61 std::list<KeypressListener*> key_listeners;
62
63 private:
66 std::string getJSON( sio::message::ptr msg ) {
67 //This function is from SocketIO's issues.
68 static sio::packet_manager manager;
69 static std::mutex packetLock;
70 std::lock_guard< std::mutex > guard( packetLock );
71
72 std::stringstream ss;
73 sio::packet packet( "/", msg );
74 manager.encode( packet, [&](bool isBinary, std::shared_ptr<const std::string> const & json) {
75 ss << *json;
76 assert( !isBinary );
77 });
78 manager.reset();
79
80 // Need to strip off the message type flags (typically '42',
81 // but there are other possible combinations).
82 std::string result = ss.str();
83 std::size_t indexList = result.find( '[' );
84 std::size_t indexObject = result.find( '{' );
85 std::size_t indexString = result.find( '"' );
86 std::size_t index = indexList;
87 if ( indexObject != std::string::npos && indexObject < index )
88 index = indexObject;
89 if ( indexString != std::string::npos && indexString < index )
90 index = indexString;
91
92 if ( index == std::string::npos ) {
93 std::cerr << "Error decoding json object" << std::endl << " Body: " << result << std::endl;
94 return "";
95 }
96 return result.substr(index);
97 }
98
99 public:
100
101 //Bridges object should have been initialized with correct
102 //credentials and server at this point.
104 : bridges(b) {
105 client.set_open_listener(std::bind(&SocketConnection::on_connected, this));
106 client.set_close_listener(std::bind(&SocketConnection::on_close, this, std::placeholders::_1));
107 client.set_fail_listener(std::bind(&SocketConnection::on_fail, this));
108 client.set_reconnect_listener(std::bind(&SocketConnection::on_reconnect, this, std::placeholders::_1, std::placeholders::_2));
109 client.set_socket_open_listener(std::bind(&SocketConnection::on_socketopen, this, std::placeholders::_1));
110
111 //client.set_logs_verbose();
112
113 std::string serverURL = bridges.getServerURL();
114
115 if (debug)
116 std::cerr << "connecting SocketIO with " << serverURL << "\n";
117
118 client.connect(serverURL); //get from bridges object
119
121
122 usleep(100000);
123
125
126 }
127
129 std::lock_guard< std::mutex > guard( _lock );
130
131 key_listeners.push_back(p);
132 }
133
134 void forwardKeyUp(sio::event & e) {
135 std::lock_guard< std::mutex > guard( _lock );
136
137 std::string jsonmsg = getJSON(e.get_message());
138
139 if (debug)
140 std::cerr << "forwardKeyUp:" << e.get_nsp() << " " << e.get_name() << " : " << jsonmsg << "\n";
141
142 for (auto& ptr : key_listeners)
143 ptr->keyup(jsonmsg);
144 }
145
146 void forwardKeyDown(sio::event & e) {
147 std::lock_guard< std::mutex > guard( _lock );
148
149 std::string jsonmsg = getJSON(e.get_message());
150
151 if (debug)
152 std::cerr << "forwardKeyDown:" << e.get_nsp() << " " << e.get_name() << " : " << jsonmsg << "\n";
153
154 for (auto& ptr : key_listeners)
155 ptr->keydown(jsonmsg);
156 }
157
159 client.clear_con_listeners();
160 client.sync_close();
161 }
162
164 if (debug && debugVerbose) {
165 std::cout<<"Reconfiguring socket\n";
166 }
167
168 current_socket = client.socket();
169
170 current_socket->on("keyup", std::bind(&SocketConnection::forwardKeyUp, this, std::placeholders::_1));
171 current_socket->on("keydown", std::bind(&SocketConnection::forwardKeyDown, this, std::placeholders::_1));
172 current_socket->on("announcement", std::bind(&SocketConnection::on_announcement, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
173 current_socket->on_error(std::bind(&SocketConnection::on_socketerror, this, std::placeholders::_1));
175
176 }
177
179 if (debug)
180 std::cerr << "Sending credentials\n";
181
182 std::string user = bridges.getUserName();
183 std::string apikey = bridges.getApiKey();
184
185 auto assID = bridges.getAssignment();
186
187 current_socket->emit("credentials",
188 "{\"user\":\"" + user
189 + "\",\"apikey\":\"" + apikey
190 + "\",\"assignment\":\"" + std::to_string(assID)
191 + "\"}");
192 if (debug)
193 std::cerr << "Credentials sent\n";
194 }
195
196 void on_reconnect(unsigned, unsigned) {
197 std::cout << "reconnect..." << std::endl;
198 //reconfigure_socket();
199 }
200
201 void on_socketopen(const std::string & nsp) {
202 std::lock_guard< std::mutex > guard( _lock );
203 if (debug)
204 std::cout << "sockopen on namespace " << nsp << std::endl;
205
207 }
208
210 std::lock_guard< std::mutex > guard( _lock );
211 if (debug)
212 std::cout << "connected!!\n";
213
214 _cond.notify_all();
215 connect_finish = true;
216 }
217
218 void on_close(sio::client::close_reason const& reason) {
219 std::cout << "sio closed\n";
220 exit(0);
221 }
222
223 void on_socketerror(sio::message::ptr const& message) {
224 std::cout << "socket errror\n";
225
226 }
227
228 void on_fail() {
229 std::cout << "sio failed\n";
230 exit(0);
231 }
232
233 void on_announcement (std::string const& name, sio::message::ptr const& data, bool isAck, sio::message::list &ack_resp) {
234 if (debug)
235 std::cerr << "announcement something\n";
236 }
237
239 if (debug && debugVerbose) {
240 std::cout<<"Waiting on connection\n";
241 }
242
243 //can't use lock guard since we need to wait on a condition
244 _lock.lock();
245 if (!connect_finish) {
246 _cond.wait(_lock);
247 }
248 _lock.unlock();
249 if (debug && debugVerbose) {
250 std::cout<<"Waiting is over\n";
251 }
252
253 }
254
255 void sendDataToServer(const GameGrid& gg) {
256 if (debug && debugVerbose)
257 std::cerr << "Sending GameGrid\n";
258 std::string gridjson = "{" + gg.getDataStructureRepresentation();
259
260 current_socket->emit("gamegrid:recv", gridjson);
261 }
262
264 if (debug && debugVerbose)
265 std::cerr << "Sending Scene\n";
266 std::string scenejson = "{" + s.getDataStructureRepresentation();
267
268 current_socket->emit("scene:recv", scenejson);
269 }
270 };
271 }
272}
273
274#endif
This class contains methods to connect and transmit a user's data structure representation to the Bri...
Definition: Bridges.h:51
Definition: Scene.h:14
This is a class in BRIDGES for representing an (n x n)game grid.
Definition: GameGrid.h:398
virtual const string getDataStructureRepresentation() const override
Definition: GameGrid.h:522
This is meant to be an internal class, not something that the library user will use....
Definition: SocketConnection.h:34
virtual void keyup(std::string JSONmessage)=0
virtual void keydown(std::string JSONmessage)=0
This is meant to be an internal class, not something that the library user will use.
Definition: SocketConnection.h:48
void sendSceneDataToServer(const Scene &s)
Definition: SocketConnection.h:263
void reconfigure_socket()
Definition: SocketConnection.h:163
void sendCredentials()
Definition: SocketConnection.h:178
void forwardKeyDown(sio::event &e)
Definition: SocketConnection.h:146
void on_fail()
Definition: SocketConnection.h:228
void on_connected()
Definition: SocketConnection.h:209
SocketConnection(bridges::Bridges &b)
Definition: SocketConnection.h:103
void registerKeyListener(KeypressListener *p)
Definition: SocketConnection.h:128
void on_announcement(std::string const &name, sio::message::ptr const &data, bool isAck, sio::message::list &ack_resp)
Definition: SocketConnection.h:233
void on_socketopen(const std::string &nsp)
Definition: SocketConnection.h:201
void wait_on_connection()
Definition: SocketConnection.h:238
void on_close(sio::client::close_reason const &reason)
Definition: SocketConnection.h:218
void on_reconnect(unsigned, unsigned)
Definition: SocketConnection.h:196
void sendDataToServer(const GameGrid &gg)
Definition: SocketConnection.h:255
~SocketConnection()
Definition: SocketConnection.h:158
void on_socketerror(sio::message::ptr const &message)
Definition: SocketConnection.h:223
void forwardKeyUp(sio::event &e)
Definition: SocketConnection.h:134
these methods convert byte arrays in to base64 codes and are used in BRIDGES to represent the color a...
Definition: alltypes.h:4