Line data Source code
1 : /* 2 : * NexthopDBServer maintains two primary data structures: 3 : * (1) nexthop_table: a std::map DB of nexthop entries (NexthopDBEntry) 4 : * keyed through a string representation of the nexthop address. 5 : * (2) client_table: a std::map DB of client entries (NexthopDBClient) 6 : * keyed through the session_id of the underlying session 7 : * (UnixDomainSocketSession). 8 : */ 9 : #include <base/logging.h> 10 : #include "nexthop_client.h" 11 : #include "nexthop_server.h" 12 : #include <pthread.h> 13 : #include "rapidjson/document.h" 14 : #include "rapidjson/stringbuffer.h" 15 : #include "rapidjson/writer.h" 16 : 17 0 : NexthopDBServer::NexthopDBServer(boost::asio::io_context &io, 18 0 : const std::string &path) 19 0 : : io_service_(io), endpoint_path_(path), nexthop_table_(), client_table_() 20 : { 21 0 : std::remove(endpoint_path_.c_str()); 22 0 : io_server_.reset(new UnixDomainSocketServer(&io_service_, endpoint_path_)); 23 0 : io_server_->set_observer(boost::bind(&NexthopDBServer::EventHandler, this, 24 : _1, _2, _3)); 25 0 : } 26 : 27 : void 28 0 : NexthopDBServer::Run() 29 : { 30 0 : io_service_.run(); 31 0 : } 32 : 33 : void 34 0 : NexthopDBServer::EventHandler(UnixDomainSocketServer * server, 35 : UnixDomainSocketSession * session, 36 : UnixDomainSocketServer::Event event) 37 : { 38 0 : std::scoped_lock lock(mutex_); 39 0 : if (event == UnixDomainSocketServer::NEW_SESSION) { 40 0 : NexthopDBClient::ClientPtr cl(new NexthopDBClient(session, this)); 41 0 : AddClient(cl); 42 0 : } else if (event == UnixDomainSocketServer::DELETE_SESSION) { 43 0 : NexthopDBClient::ClientPtr cl = client_table_[session->session_id()]; 44 0 : if (cl) { 45 0 : RemoveClient(session->session_id()); 46 : } 47 0 : } 48 0 : } 49 : 50 : void 51 0 : NexthopDBServer::AddClient(NexthopDBClient::ClientPtr cl) 52 : { 53 : /* Add client to the client table */ 54 0 : assert (client_table_[cl->session_->session_id()] == NULL); 55 0 : client_table_[cl->session_->session_id()] = cl; 56 : 57 : /* Build the client's nexthop list */ 58 0 : for (NexthopIterator iter = nexthop_table_.begin(); 59 0 : iter != nexthop_table_.end(); ++iter) { 60 0 : if (iter->second) { 61 0 : cl->AddNexthop(iter->second); 62 : } 63 : } 64 : 65 0 : cl->WriteMessage(); 66 0 : LOG (DEBUG, "[NexthopServer] New client: " << cl->session_->session_id()); 67 0 : } 68 : 69 : void 70 0 : NexthopDBServer::RemoveClient(uint64_t session_id) 71 : { 72 0 : LOG (DEBUG, "[NexthopServer] Remove client " << session_id); 73 0 : client_table_.erase(session_id); 74 0 : } 75 : 76 : void 77 0 : NexthopDBServer::TriggerClients() 78 : { 79 0 : for (ClientIterator iter = client_table_.begin(); 80 0 : iter != client_table_.end(); ++iter) { 81 0 : iter->second->WriteMessage(); 82 : } 83 0 : } 84 : 85 : void 86 0 : NexthopDBServer::AddNexthop(NexthopDBEntry::NexthopPtr nh) 87 : { 88 0 : for (ClientIterator iter = client_table_.begin(); 89 0 : iter != client_table_.end(); ++iter) { 90 0 : iter->second->AddNexthop(nh); 91 : } 92 0 : } 93 : 94 : NexthopDBEntry::NexthopPtr 95 0 : NexthopDBServer::FindOrCreateNexthop(const std::string &nh_str) 96 : { 97 0 : std::scoped_lock lock (mutex_); 98 : 99 : /* 100 : * Does the nexthop exist? If so, return. 101 : */ 102 0 : if (nexthop_table_[nh_str] != NULL) { 103 0 : return nexthop_table_[nh_str]; 104 : } 105 : 106 0 : NexthopDBEntry::NexthopPtr nh(new NexthopDBEntry(nh_str)); 107 0 : nexthop_table_[nh_str] = nh; 108 : 109 : /* 110 : * Add the nexthop to the tail of each client's announce list and trigger 111 : * clients so they are notified of the new nexthop. 112 : */ 113 0 : AddNexthop(nh); 114 0 : TriggerClients(); 115 0 : return nh; 116 0 : } 117 : 118 : void 119 0 : NexthopDBServer::FindAndRemoveNexthop(const std::string &str) 120 : { 121 0 : std::scoped_lock lock(mutex_); 122 : 123 0 : if (nexthop_table_[str] == NULL) { 124 0 : return; 125 : } 126 0 : NexthopDBEntry::NexthopPtr nh = nexthop_table_[str]; 127 0 : RemoveNexthop(nh); 128 0 : nexthop_table_.erase(str); 129 0 : TriggerClients(); 130 0 : } 131 : 132 : void 133 0 : NexthopDBServer::RemoveNexthop(NexthopDBEntry::NexthopPtr nh) 134 : { 135 0 : nh->set_state(NexthopDBEntry::NEXTHOP_STATE_DELETED); 136 0 : for (ClientIterator iter = client_table_.begin(); 137 0 : iter != client_table_.end(); ++iter) { 138 0 : if (!iter->second->FindNexthop(nh)) { 139 0 : iter->second->AddNexthop(nh); 140 : } 141 : } 142 0 : }