Skip to content
Newer
Older
100644 279 lines (247 sloc) 7.14 KB
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
1 #include "libf2f/router.h"
2 #include "libf2f/connection.h"
3 #include "libf2f/protocol.h"
4
5 #include <boost/date_time/posix_time/posix_time.hpp>
6 #include <boost/thread.hpp>
7 #include <boost/foreach.hpp>
8
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
9 namespace libf2f {
10
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
11 using namespace std;
12
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
13 Router::Router( boost::shared_ptr<boost::asio::ip::tcp::acceptor> accp,
71ae0bb @RJ now the demo app works properly again
authored Jun 4, 2009
14 Protocol * p, boost::function<std::string()> uuidf )
15 : m_acceptor( accp ),
16 m_protocol( p ),
17 seen_connections(0),
18 m_uuidgen( uuidf )
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
19 {
71ae0bb @RJ now the demo app works properly again
authored Jun 4, 2009
20 cout << "Testing uuid generator... " << flush;
21 string uuid = m_uuidgen();
22 if( uuid.length() != 36 )
23 {
24 cout << "ERROR length must be 36." << endl;
25 throw;
26 }
27 cout << "OK" << endl;
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
28 p->set_router( this );
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
29 // Start an accept operation for a new connection.
a665733 @RJ no need for a newconn macro anymore. make messages responsible for ca…
authored Jun 7, 2009
30 connection_ptr new_conn = new_connection();
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
31
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
32 m_acceptor->async_accept(new_conn->socket(),
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
33 boost::bind(&Router::handle_accept, this,
34 boost::asio::placeholders::error, new_conn));
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
35
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
36 }
37
a665733 @RJ no need for a newconn macro anymore. make messages responsible for ca…
authored Jun 7, 2009
38 connection_ptr
39 Router::new_connection()
40 {
41 return connection_ptr( new Connection( m_acceptor->io_service(), this ) );
42 }
43
71ae0bb @RJ now the demo app works properly again
authored Jun 4, 2009
44 std::string
45 Router::gen_uuid()
46 {
47 return m_uuidgen();
48 }
49
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
50 void
51 Router::stop()
52 {
9f96f23 @RJ get/set state per connection
authored Jul 8, 2009
53 while( m_connections.size() )
54 {
80d4be5 @RJ more defensive when a connection is shutting down
authored Jul 18, 2009
55 // this removes the connection from m_connections:
9f96f23 @RJ get/set state per connection
authored Jul 8, 2009
56 m_connections.front()->fin();
57 }
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
58 }
59
60 void
61 Router::connection_terminated( connection_ptr conn )
62 {
63 unregister_connection( conn );
64 m_protocol->connection_terminated( conn );
65 }
66
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
67 /// Handle completion of a accept operation.
68 void
69 Router::handle_accept(const boost::system::error_code& e, connection_ptr conn)
70 {
71 if(e)
72 {
73 // Log it and return. Since we are not starting a new
74 // accept operation the io_service will run out of work to do and the
75 // Servent will exit.
76 std::cerr << e.message() << std::endl;
77 return;
78 }
79 if( !m_protocol->new_incoming_connection(conn) )
80 {
188fe1f @RJ fix crash in connection::str when remote end disconnected
authored Jul 15, 2009
81 // cout << "Rejecting connection " << conn->str() << endl;
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
82 // don't register it (so it autodestructs)
83 }
84 else
85 {
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
86 register_connection( conn );
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
87 conn->async_read();
88 }
89
90 // Start an accept operation for a new connection.
a665733 @RJ no need for a newconn macro anymore. make messages responsible for ca…
authored Jun 7, 2009
91 connection_ptr new_conn = new_connection();
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
92
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
93 m_acceptor->async_accept(new_conn->socket(),
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
94 boost::bind(&Router::handle_accept, this,
95 boost::asio::placeholders::error, new_conn));
96 }
97
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
98 void
99 Router::register_connection( connection_ptr conn )
100 {
101 boost::mutex::scoped_lock lk(m_connections_mutex);
102 vector<connection_ptr>::iterator it;
103 for( it=m_connections.begin() ; it < m_connections.end() ; ++it )
104 {
105 if( *it == conn )
106 {
107 // already registered, wtf?
108 cout << "ERROR connection already registered!" << endl;
109 assert(false);
110 return;
111 }
112 }
113 m_connections.push_back( conn );
80d4be5 @RJ more defensive when a connection is shutting down
authored Jul 18, 2009
114 //cout << connections_str() << endl;
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
115 }
116
117 void
118 Router::unregister_connection( connection_ptr conn )
119 {
120 boost::mutex::scoped_lock lk(m_connections_mutex);
121 vector<connection_ptr>::iterator it;
122 for( it=m_connections.begin() ; it < m_connections.end() ; ++it )
123 {
124 if( *it == conn )
125 {
126 m_connections.erase( it );
188fe1f @RJ fix crash in connection::str when remote end disconnected
authored Jul 15, 2009
127 //cout << "Router::unregistered " << conn->str() << endl;
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
128 }
129 }
80d4be5 @RJ more defensive when a connection is shutting down
authored Jul 18, 2009
130 //cout << connections_str() << endl;
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
131 }
132
71ae0bb @RJ now the demo app works properly again
authored Jun 4, 2009
133 connection_ptr
134 Router::get_connection_by_name( const std::string &name )
135 {
136 vector<connection_ptr>::iterator it;
d975378 @RJ error msg
authored Jul 20, 2009
137 boost::mutex::scoped_lock lk(m_connections_mutex);
71ae0bb @RJ now the demo app works properly again
authored Jun 4, 2009
138 for( it=m_connections.begin() ; it < m_connections.end() ; ++it )
139 {
140 if( (*it)->name() == name )
141 {
142 return *it;
143 }
144 }
145 return connection_ptr();
146 }
147
9f96f23 @RJ get/set state per connection
authored Jul 8, 2009
148 /// debug usage - get list of connections
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
149 string
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
150 Router::connections_str()
151 {
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
152 ostringstream os;
153 os << "<connections>" << endl;
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
154 BOOST_FOREACH( connection_ptr conn, m_connections )
155 {
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
156 os << conn->str() << endl;
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
157 }
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
158 os << "</connections>" << endl;
159 return os.str();
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
160 }
161
9f96f23 @RJ get/set state per connection
authored Jul 8, 2009
162 vector<string>
163 Router::get_connected_names()
164 {
165 vector<string> v;
d975378 @RJ error msg
authored Jul 20, 2009
166 boost::mutex::scoped_lock lk(m_connections_mutex);
9f96f23 @RJ get/set state per connection
authored Jul 8, 2009
167 BOOST_FOREACH( connection_ptr conn, m_connections )
168 {
169 v.push_back( conn->name() );
170 }
171 return v;
172 }
173
174 /// this is the default msg recvd callback passed to new connections
175 /// it does some basic sanity checks, then fires the callback
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
176 void
177 Router::message_received( message_ptr msgp, connection_ptr conn )
178 {
188fe1f @RJ fix crash in connection::str when remote end disconnected
authored Jul 15, 2009
179 //cout << "router::message_received from " << conn->str()
180 // << " " << msgp->str() << endl;
181
182 /* // Not relevant for darknet configurations:
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
183 if( msgp->hops() > 3 )
184 {
185 cout << "Dropping, hop count: " << msgp->hops() << endl;
186 return;
187 }
188fe1f @RJ fix crash in connection::str when remote end disconnected
authored Jul 15, 2009
188 */
71ae0bb @RJ now the demo app works properly again
authored Jun 4, 2009
189 if( msgp->length() > 16384 ) // hard limit
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
190 {
188fe1f @RJ fix crash in connection::str when remote end disconnected
authored Jul 15, 2009
191 cout << "f2f router: Dropping, msg length: " << msgp->length() << endl;
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
192 return;
193 }
194 m_protocol->message_received( msgp, conn );
195 }
196
197 /// Connect out to a remote Servent at endpoint
198 void
199 Router::connect_to_remote(boost::asio::ip::tcp::endpoint &endpoint)
200 {
9f96f23 @RJ get/set state per connection
authored Jul 8, 2009
201 map<string,string> props;
202 connect_to_remote( endpoint, props );
203 }
204
205 void
206 Router::connect_to_remote(boost::asio::ip::tcp::endpoint &endpoint, const map<string,string>& props)
207 {
188fe1f @RJ fix crash in connection::str when remote end disconnected
authored Jul 15, 2009
208 cout << "router::connect_to_remote(" << endpoint.address().to_string()<<":"
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
209 << endpoint.port()<<")" << endl;
a665733 @RJ no need for a newconn macro anymore. make messages responsible for ca…
authored Jun 7, 2009
210 connection_ptr new_conn = new_connection();
9f96f23 @RJ get/set state per connection
authored Jul 8, 2009
211 typedef pair<string,string> pair_t;
212 BOOST_FOREACH( pair_t p, props )
213 {
214 new_conn->set( p.first, p.second );
215 }
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
216 // Start an asynchronous connect operation.
217 new_conn->socket().async_connect(endpoint,
218 boost::bind(&Router::handle_connect, this,
219 boost::asio::placeholders::error, endpoint, new_conn));
220 }
221
222 /// Handle completion of a connect operation.
223 void
224 Router::handle_connect( const boost::system::error_code& e,
225 boost::asio::ip::tcp::endpoint &endpoint,
226 connection_ptr conn )
227 {
228 if (e)
229 {
230 std::cerr << "Failed to connect out to remote Servent: "
231 << e.message() << std::endl;
232 return;
233 }
234 /// Successfully established connection.
235 m_protocol->new_outgoing_connection( conn );
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
236 register_connection( conn );
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
237 conn->async_read(); // start read loop for this connection
238 }
239
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
240 /// apply fun to all connections
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
241 void
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
242 Router::foreach_conns( boost::function<void(connection_ptr)> fun )
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
243 {
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
244 boost::mutex::scoped_lock lk(m_connections_mutex);
245 BOOST_FOREACH( connection_ptr conn, m_connections )
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
246 {
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
247 fun( conn );
0a0b1b3 @RJ initial commit, f2f library
authored May 27, 2009
248 }
249 }
250
251
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
252
253 void
254 Router::foreach_conns_except( boost::function<void(connection_ptr)> fun, connection_ptr conn )
255 {
256 boost::mutex::scoped_lock lk(m_connections_mutex);
257 BOOST_FOREACH( connection_ptr c, m_connections )
258 {
259 if( c == conn ) continue;
260 fun( c );
261 }
262 }
263
264 void
265 Router::send_all( message_ptr msgp )
266 {
71ae0bb @RJ now the demo app works properly again
authored Jun 4, 2009
267 //foreach_conns( boost::bind(&Connection::async_write, _1, msgp) );
268 boost::mutex::scoped_lock lk(m_connections_mutex);
269 BOOST_FOREACH( connection_ptr conn, m_connections )
270 {
188fe1f @RJ fix crash in connection::str when remote end disconnected
authored Jul 15, 2009
271 //cout << "Sending " << msgp->str() << " to " << conn->str() << endl;
71ae0bb @RJ now the demo app works properly again
authored Jun 4, 2009
272 conn->async_write( msgp );
273 }
162ed96 @RJ foreach_conns_except because i can't make boost lambda behave..
authored May 29, 2009
274 }
275
276
277
74ed16b @RJ chained sending for connections, ping/pong, namespaced
authored May 28, 2009
278 } //ns
Something went wrong with that request. Please try again.