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