Bridges-C++  3.1.1
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 
21  public:
22  virtual void keyup(std::string JSONmessage) = 0;
23  virtual void keydown(std::string JSONmessage) = 0;
24  };
25 
27  bool debug = false;
28  sio::client client;
29  sio::socket::ptr current_socket;
30 
32 
33  std::mutex _lock;
34 
35  std::condition_variable_any _cond; //condition used to wait on connection to be established
36  bool connect_finish = false;
37 
38  std::list<KeypressListener*> key_listeners;
39 
40  private:
43  std::string getJSON( sio::message::ptr msg ) {
44  //This function is from SocketIO's issues.
45  static sio::packet_manager manager;
46  static std::mutex packetLock;
47  std::lock_guard< std::mutex > guard( packetLock );
48 
49 
50  std::stringstream ss;
51  sio::packet packet( "/", msg );
52  manager.encode( packet, [&](bool isBinary, std::shared_ptr<const std::string> const & json) {
53  ss << *json;
54  assert( !isBinary );
55  });
56  manager.reset();
57 
58  // Need to strip off the message type flags (typically '42',
59  // but there are other possible combinations).
60  std::string result = ss.str();
61  std::size_t indexList = result.find( '[' );
62  std::size_t indexObject = result.find( '{' );
63  std::size_t indexString = result.find( '"' );
64  std::size_t index = indexList;
65  if ( indexObject != std::string::npos && indexObject < index )
66  index = indexObject;
67  if ( indexString != std::string::npos && indexString < index )
68  index = indexString;
69 
70  if ( index == std::string::npos ) {
71  std::cerr << "Error decoding json object" << std::endl << " Body: " << result << std::endl;
72  return "";
73  }
74  return result.substr(index);
75  }
76 
77  public:
78 
79  //Bridges object should have been initialized with correct
80  //credentials and server at this point.
82  : bridges(b) {
83  client.set_open_listener(std::bind(&SocketConnection::on_connected, this));
84  client.set_close_listener(std::bind(&SocketConnection::on_close, this, std::placeholders::_1));
85  client.set_fail_listener(std::bind(&SocketConnection::on_fail, this));
86 
87  std::string serverURL = bridges.getServerURL();
88 
89  if (debug)
90  std::cerr << "connecting SocketIO with " << serverURL << "\n";
91 
92  client.connect(serverURL); //get from bridges object
93 
94  wait_on_connection();
95 
96  usleep(100000);
97 
98  current_socket = client.socket();
99 
100  current_socket->on("keyup", std::bind(&SocketConnection::forwardKeyUp, this, std::placeholders::_1));
101  current_socket->on("keydown", std::bind(&SocketConnection::forwardKeyDown, this, std::placeholders::_1));
102  current_socket->on("announcement", std::bind(&SocketConnection::on_announcement, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
103 
104  sendCredentials();
105  }
106 
108  std::lock_guard< std::mutex > guard( _lock );
109 
110  key_listeners.push_back(p);
111  }
112 
113  void forwardKeyUp(sio::event & e) {
114  std::lock_guard< std::mutex > guard( _lock );
115 
116  std::string jsonmsg = getJSON(e.get_message());
117 
118  if (debug)
119  std::cerr << "forwardKeyUp:" << e.get_nsp() << " " << e.get_name() << " : " << jsonmsg << "\n";
120 
121  for (auto& ptr : key_listeners)
122  ptr->keyup(jsonmsg);
123  }
124 
125  void forwardKeyDown(sio::event & e) {
126  std::lock_guard< std::mutex > guard( _lock );
127 
128  std::string jsonmsg = getJSON(e.get_message());
129 
130  if (debug)
131  std::cerr << "forwardKeyDown:" << e.get_nsp() << " " << e.get_name() << " : " << jsonmsg << "\n";
132 
133  for (auto& ptr : key_listeners)
134  ptr->keydown(jsonmsg);
135  }
136 
137 
139  client.sync_close();
140  client.clear_con_listeners();
141  }
142 
144  std::lock_guard< std::mutex > guard( _lock );
145  if (debug)
146  std::cerr << "Sending credentials\n";
147 
148  std::string user = bridges.getUserName();
149  std::string apikey = bridges.getApiKey();
150 
151  auto assID = bridges.getAssignment();
152 
153  current_socket->emit("credentials",
154  "{\"user\":\"" + user
155  + "\",\"apikey\":\"" + apikey
156  + "\",\"assignment\":\"" + std::to_string(assID)
157  + "\"}");
158  if (debug)
159  std::cerr << "Credentials sent\n";
160  }
161 
162  void on_connected() {
163  std::lock_guard< std::mutex > guard( _lock );
164  if (debug)
165  std::cout << "connected!!\n";
166 
167  _cond.notify_all();
168  connect_finish = true;
169  }
170  void on_close(sio::client::close_reason const& reason) {
171  std::cout << "sio closed\n";
172  exit(0);
173  }
174 
175  void on_fail() {
176  std::cout << "sio failed\n";
177  exit(0);
178  }
179 
180  void on_announcement (std::string const& name, sio::message::ptr const& data, bool isAck, sio::message::list &ack_resp) {
181  if (debug)
182  std::cerr << "announcement something\n";
183  }
184 
186  //can't use lock guard since we need to wait on a condition
187  _lock.lock();
188  if (!connect_finish) {
189  _cond.wait(_lock);
190  }
191  _lock.unlock();
192 
193  }
194 
195  void sendGameGrid(const GameGrid& gg) {
196  if (debug)
197  std::cerr << "Sending GameGrid\n";
198  std::string gridjson = "{" + gg.getDataStructureRepresentation();
199 
200  current_socket->emit("gamegrid:recv", gridjson);
201  }
202  };
203  }
204 }
205 
206 #endif
void on_connected()
Definition: SocketConnection.h:162
Definition: GameGrid.h:365
void forwardKeyUp(sio::event &e)
Definition: SocketConnection.h:113
virtual void keydown(std::string JSONmessage)=0
void sendCredentials()
Definition: SocketConnection.h:143
void forwardKeyDown(sio::event &e)
Definition: SocketConnection.h:125
virtual const string getDataStructureRepresentation() const override
Definition: GameGrid.h:490
Definition: SocketConnection.h:26
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
void registerKeyListener(KeypressListener *p)
Definition: SocketConnection.h:107
void wait_on_connection()
Definition: SocketConnection.h:185
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:81
void on_announcement(std::string const &name, sio::message::ptr const &data, bool isAck, sio::message::list &ack_resp)
Definition: SocketConnection.h:180
void sendGameGrid(const GameGrid &gg)
Definition: SocketConnection.h:195
void on_fail()
Definition: SocketConnection.h:175
void on_close(sio::client::close_reason const &reason)
Definition: SocketConnection.h:170
Definition: SocketConnection.h:20
unsigned int getAssignment() const
Definition: Bridges.h:211
~SocketConnection()
Definition: SocketConnection.h:138