Bridges-C++  3.2.0
Bridges(C++API)
SocketConnection.h
Go to the documentation of this file.
1 #ifndef SOCKET_CONNECTION_H
2 #define SOCKET_CONNECTION_H
3 
4 #include "sio_client.h"
5 #include "internal/sio_packet.h"
6 #include <Bridges.h>
7 #include <GameGrid.h>
8 #include <list>
9 #include <thread>
10 #include <mutex>
11 #include <condition_variable>
12 #include <functional>
13 
14 #include <unistd.h>
15 
16 
17 namespace bridges {
18  namespace game {
19 
24  public:
25  virtual void keyup(std::string JSONmessage) = 0;
26  virtual void keydown(std::string JSONmessage) = 0;
27  };
28 
38  bool debug = false;
39  sio::client client;
40  sio::socket::ptr current_socket;
41 
43 
44  std::mutex _lock;
45 
46  std::condition_variable_any _cond; //condition used to wait on connection to be established
47  bool connect_finish = false;
48 
49  std::list<KeypressListener*> key_listeners;
50 
51  private:
54  std::string getJSON( sio::message::ptr msg ) {
55  //This function is from SocketIO's issues.
56  static sio::packet_manager manager;
57  static std::mutex packetLock;
58  std::lock_guard< std::mutex > guard( packetLock );
59 
60 
61  std::stringstream ss;
62  sio::packet packet( "/", msg );
63  manager.encode( packet, [&](bool isBinary, std::shared_ptr<const std::string> const & json) {
64  ss << *json;
65  assert( !isBinary );
66  });
67  manager.reset();
68 
69  // Need to strip off the message type flags (typically '42',
70  // but there are other possible combinations).
71  std::string result = ss.str();
72  std::size_t indexList = result.find( '[' );
73  std::size_t indexObject = result.find( '{' );
74  std::size_t indexString = result.find( '"' );
75  std::size_t index = indexList;
76  if ( indexObject != std::string::npos && indexObject < index )
77  index = indexObject;
78  if ( indexString != std::string::npos && indexString < index )
79  index = indexString;
80 
81  if ( index == std::string::npos ) {
82  std::cerr << "Error decoding json object" << std::endl << " Body: " << result << std::endl;
83  return "";
84  }
85  return result.substr(index);
86  }
87 
88  public:
89 
90  //Bridges object should have been initialized with correct
91  //credentials and server at this point.
93  : bridges(b) {
94  client.set_open_listener(std::bind(&SocketConnection::on_connected, this));
95  client.set_close_listener(std::bind(&SocketConnection::on_close, this, std::placeholders::_1));
96  client.set_fail_listener(std::bind(&SocketConnection::on_fail, this));
97 
98  std::string serverURL = bridges.getServerURL();
99 
100  if (debug)
101  std::cerr << "connecting SocketIO with " << serverURL << "\n";
102 
103  client.connect(serverURL); //get from bridges object
104 
105  wait_on_connection();
106 
107  usleep(100000);
108 
109  current_socket = client.socket();
110 
111  current_socket->on("keyup", std::bind(&SocketConnection::forwardKeyUp, this, std::placeholders::_1));
112  current_socket->on("keydown", std::bind(&SocketConnection::forwardKeyDown, this, std::placeholders::_1));
113  current_socket->on("announcement", std::bind(&SocketConnection::on_announcement, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
114 
115  sendCredentials();
116  }
117 
119  std::lock_guard< std::mutex > guard( _lock );
120 
121  key_listeners.push_back(p);
122  }
123 
125  std::lock_guard< std::mutex > guard( _lock );
126 
127  std::string jsonmsg = getJSON(e.get_message());
128 
129  if (debug)
130  std::cerr << "forwardKeyUp:" << e.get_nsp() << " " << e.get_name() << " : " << jsonmsg << "\n";
131 
132  for (auto& ptr : key_listeners)
133  ptr->keyup(jsonmsg);
134  }
135 
137  std::lock_guard< std::mutex > guard( _lock );
138 
139  std::string jsonmsg = getJSON(e.get_message());
140 
141  if (debug)
142  std::cerr << "forwardKeyDown:" << e.get_nsp() << " " << e.get_name() << " : " << jsonmsg << "\n";
143 
144  for (auto& ptr : key_listeners)
145  ptr->keydown(jsonmsg);
146  }
147 
148 
150  client.sync_close();
151  client.clear_con_listeners();
152  }
153 
155  std::lock_guard< std::mutex > guard( _lock );
156  if (debug)
157  std::cerr << "Sending credentials\n";
158 
159  std::string user = bridges.getUserName();
160  std::string apikey = bridges.getApiKey();
161 
162  auto assID = bridges.getAssignment();
163 
164  current_socket->emit("credentials",
165  "{\"user\":\"" + user
166  + "\",\"apikey\":\"" + apikey
167  + "\",\"assignment\":\"" + std::to_string(assID)
168  + "\"}");
169  if (debug)
170  std::cerr << "Credentials sent\n";
171  }
172 
173  void on_connected() {
174  std::lock_guard< std::mutex > guard( _lock );
175  if (debug)
176  std::cout << "connected!!\n";
177 
178  _cond.notify_all();
179  connect_finish = true;
180  }
181  void on_close(sio::client::close_reason const& reason) {
182  std::cout << "sio closed\n";
183  exit(0);
184  }
185 
186  void on_fail() {
187  std::cout << "sio failed\n";
188  exit(0);
189  }
190 
191  void on_announcement (std::string const& name, sio::message::ptr const& data, bool isAck, sio::message::list &ack_resp) {
192  if (debug)
193  std::cerr << "announcement something\n";
194  }
195 
197  //can't use lock guard since we need to wait on a condition
198  _lock.lock();
199  if (!connect_finish) {
200  _cond.wait(_lock);
201  }
202  _lock.unlock();
203 
204  }
205 
206  void sendGameGrid(const GameGrid& gg) {
207  if (debug)
208  std::cerr << "Sending GameGrid\n";
209  std::string gridjson = "{" + gg.getDataStructureRepresentation();
210 
211  current_socket->emit("gamegrid:recv", gridjson);
212  }
213  };
214  }
215 }
216 
217 #endif
void set_close_listener(close_listener const &l)
std::shared_ptr< message > ptr
Definition: sio_message.h:37
void on_connected()
Definition: SocketConnection.h:173
This is a class in BRIDGES for representing an (n x n)game grid.
Definition: GameGrid.h:400
Definition: sio_client.h:17
Definition: sio_socket.h:8
std::shared_ptr< socket > ptr
Definition: sio_socket.h:52
void clear_con_listeners()
sio::socket::ptr const & socket(const std::string &nsp="")
const std::string & get_name() const
const message::ptr & get_message() const
void forwardKeyUp(sio::event &e)
Definition: SocketConnection.h:124
virtual void keydown(std::string JSONmessage)=0
void sendCredentials()
Definition: SocketConnection.h:154
const std::string & get_nsp() const
void forwardKeyDown(sio::event &e)
Definition: SocketConnection.h:136
void connect(const std::string &uri)
virtual const string getDataStructureRepresentation() const override
Definition: GameGrid.h:525
This is meant to be an internal class, not something that the library user will use.
Definition: SocketConnection.h:37
close_reason
Definition: sio_client.h:19
This class contains methods to connect and transmit a user&#39;s data structure representation to the Bri...
Definition: Bridges.h:39
these methods convert byte arrays in to base64 codes and are used in BRIDGES to represent the color a...
Definition: alltypes.h:4
Definition: sio_message.h:344
void registerKeyListener(KeypressListener *p)
Definition: SocketConnection.h:118
void wait_on_connection()
Definition: SocketConnection.h:196
virtual void keyup(std::string JSONmessage)=0
const string & getApiKey() const
Definition: Bridges.h:185
const string & getUserName() const
Definition: Bridges.h:160
SocketConnection(bridges::Bridges &b)
Definition: SocketConnection.h:92
void sync_close()
void on_announcement(std::string const &name, sio::message::ptr const &data, bool isAck, sio::message::list &ack_resp)
Definition: SocketConnection.h:191
void sendGameGrid(const GameGrid &gg)
Definition: SocketConnection.h:206
void on_fail()
Definition: SocketConnection.h:186
void on_close(sio::client::close_reason const &reason)
Definition: SocketConnection.h:181
void set_fail_listener(con_listener const &l)
void set_open_listener(con_listener const &l)
This is meant to be an internal class, not something that the library user will use. Provides support for input handling for the Game API.
Definition: SocketConnection.h:23
unsigned int getAssignment() const
Definition: Bridges.h:211
~SocketConnection()
Definition: SocketConnection.h:149