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