# # # patch "README" # from [dfd06ce97cbe36c3af669ff2ec827a5e42d6bb76] # to [ac0ae174796b5559a1550aa7ca5f95060dce5fa2] # # patch "administrator.cc" # from [9be891285d9532a69276b02a5541e959abdc4be0] # to [e6271c8806d89446734f9c93ce08a24a63dfb4a3] # # patch "channel.cc" # from [41640f1281a983d3f304545ad95a3fcb3d5eb9b6] # to [c640472ee1249d74eeffcc952e779b2980d555dc] # # patch "channel.hh" # from [e7c35bd545765f9aa0908a1b955132bb3ba69802] # to [0416de1474ad63b22f1e662a752e93129e3cf9f2] # # patch "server.cc" # from [1c2fc2c81be790bbfa83850380ffbfe9872886da] # to [495a7153e9c9d2d314624c99d8edc5dec5c059db] # # patch "server.hh" # from [3b06fa45604b1a9aea829006c630a5595e7dff96] # to [11f759e526dd912e587ab12079cc60752efad741] # # patch "server_manager.cc" # from [36910e7007c355bd549ebd61555afde8e440b59c] # to [444fdd0e31957863451d6ca36706879dfce87c9f] # # patch "server_manager.hh" # from [5dfcfa92583c640562517653691199f91250969c] # to [1152c59274ff86e1192341696acfe57a15a146a2] # ============================================================ --- README dfd06ce97cbe36c3af669ff2ec827a5e42d6bb76 +++ README ac0ae174796b5559a1550aa7ca5f95060dce5fa2 @@ -172,6 +172,12 @@ WAITING, or ACTIVE (with n being the total number of open connections, across all servers). +LISTCONNECTIONS [servername] + Returns a space-separated list of all clients connected to the given server, + or connected to any server is the servername is not provided. + "(servername)123.123.123.123:12345 (servername)127.0.2.4:1025" + Returns "none" if there are no connections to list. + STOP servername Prevent the given local server from receiving further connections, and stop it once all connections are closed. The result will be the new status of ============================================================ --- administrator.cc 9be891285d9532a69276b02a5541e959abdc4be0 +++ administrator.cc e6271c8806d89446734f9c93ce08a24a63dfb4a3 @@ -108,6 +108,43 @@ administrator::process(cstate & cs) } } cs.buf = oss.str(); + } else if (cmd == "LISTCONNECTIONS") { + string srv; + iss>>srv; + std::ostringstream oss; + if (srv.empty()) + { + set servers = manager.list_servers(string()); + for (set::iterator s = servers.begin(); + s != servers.end(); ++s) + { + srv = *s; + + set clients = manager.list_connections(srv); + for (set::iterator c = clients.begin(); + c != clients.end(); ++c) + { + if (!oss.str().empty()) + oss<<" "; + oss<<"("< clients = manager.list_connections(srv); + for (set::iterator c = clients.begin(); + c != clients.end(); ++c) + { + if (!oss.str().empty()) + oss<<" "; + oss<<"("<>srv; ============================================================ --- channel.cc 41640f1281a983d3f304545ad95a3fcb3d5eb9b6 +++ channel.cc c640472ee1249d74eeffcc952e779b2980d555dc @@ -10,13 +10,37 @@ using std::max; #include #include +#include +#include +using boost::lexical_cast; + +string sockname(sock & s) +{ + struct sockaddr_in sai; + socklen_t len = sizeof(sai); + if (getpeername(s, (sockaddr*)&sai, &len) == -1) + return "(error)"; + string out; + char *ip = (char*)&sai.sin_addr.s_addr; + for (int i = 0; i < 4; ++i, ++ip) + { + out += lexical_cast(*ip); + if (i < 3) + out += "."; + } + out += ":"; + out += lexical_cast(ntohs(sai.sin_port)); + return out; +} + channel::channel(sock & c, server_manager &sm) : num(++counter), cli(c), srv(-1), have_routed(false), no_server(false), manager(sm) { + name = sockname(cli); char * dat; int size; make_packet(greeting, dat, size); @@ -34,7 +58,7 @@ channel::~channel() channel::~channel() { if (srv && !no_server) - manager.disconnect_from_server(srv); + manager.disconnect_from_server(srv, name); } bool @@ -99,7 +123,8 @@ channel::process_selected(fd_set & rd, f string reply_srv, reply_pat; if (extract_reply(cbuf, reply_srv, reply_pat)) { try { - serversock ss = manager.connect_to_server(reply_srv, reply_pat); + serversock ss = manager.connect_to_server(reply_srv, reply_pat, + name); srv = ss; have_routed = true; s = srv; ============================================================ --- channel.hh e7c35bd545765f9aa0908a1b955132bb3ba69802 +++ channel.hh 0416de1474ad63b22f1e662a752e93129e3cf9f2 @@ -23,6 +23,7 @@ struct channel buffer cbuf; buffer sbuf; server_manager &manager; + string name; channel(sock & c, server_manager &sm); ~channel(); bool is_finished(); ============================================================ --- server.cc 1c2fc2c81be790bbfa83850380ffbfe9872886da +++ server.cc 495a7153e9c9d2d314624c99d8edc5dec5c059db @@ -195,7 +195,7 @@ sock } sock -server::connect() +server::connect(string const &name) { if (!enabled) throw errstr("This server is disabled."); @@ -230,12 +230,16 @@ server::connect() throw errstr("Cannot fork server."); sock s = make_outgoing(port, addr); ++connection_count; + clients.insert(name); return s; } void -server::disconnect() +server::disconnect(string const &name) { + set::iterator i = clients.find(name); + if (i != clients.end()) + clients.erase(i); if (--connection_count || !local) return; last_conn_time = time(0); ============================================================ --- server.hh 3b06fa45604b1a9aea829006c630a5595e7dff96 +++ server.hh 11f759e526dd912e587ab12079cc60752efad741 @@ -7,6 +7,8 @@ using std::vector; using std::string; #include using std::vector; +#include +using std::set; #include using boost::shared_ptr; @@ -36,14 +38,15 @@ struct server string addr; int port; int connection_count; + set clients; int last_conn_time; server_manager &manager; weak_ptr me; server(server_manager &sm); ~server(); serverstate get_state(); - sock connect(); - void disconnect(); + sock connect(string const &name); + void disconnect(string const &name); void maybekill(); void yeskill(); shared_ptr self(); ============================================================ --- server_manager.cc 36910e7007c355bd549ebd61555afde8e440b59c +++ server_manager.cc 444fdd0e31957863451d6ca36706879dfce87c9f @@ -182,7 +182,8 @@ server_manager::connect_to_server(string serversock server_manager::connect_to_server(string const &host, - string const &pattern) + string const &pattern, + string const &name) { if (!connections_allowed) throw errstr("All servers are disabled."); @@ -202,7 +203,7 @@ server_manager::connect_to_server(string } if (srv) { - sock s = srv->connect(); + sock s = srv->connect(name); serversock ss(s); map, serverdata>::iterator i = servers.find(srv); if (i == servers.end()) @@ -220,12 +221,13 @@ void } } void -server_manager::disconnect_from_server(serversock const &s) +server_manager::disconnect_from_server(serversock const &s, + string const &name) { map >::iterator i = by_name.find(s.srv); if (i == by_name.end()) return; - i->second->disconnect(); + i->second->disconnect(name); if (i->second->local && i->second->pid == -1) live.erase(i->second); --total_connections; @@ -252,6 +254,18 @@ server_manager::list_servers(string cons return out; } +set +server_manager::list_connections(string const &name) +{ + set out; + map >::iterator i = by_name.find(name); + if (i != by_name.end()) + { + out = i->second->clients; + } + return out; +} + void server_manager::allow_connections(bool allow) { ============================================================ --- server_manager.hh 5dfcfa92583c640562517653691199f91250969c +++ server_manager.hh 1152c59274ff86e1192341696acfe57a15a146a2 @@ -70,10 +70,13 @@ public: void allow_connections(bool allow=true); string start_stop_server(string const &srv, bool start); void reload_servers(); - serversock connect_to_server(string const &host, string const &pattern); - void disconnect_from_server(serversock const &s); + serversock connect_to_server(string const &host, string const &pattern, + string const &name); + void disconnect_from_server(serversock const &s, + string const &name); string get_server_state(string const &name); set list_servers(string const &state); + set list_connections(string const &name); void kill_old_servers(); };