Line data Source code
1 : /*
2 : * Copyright (c) 2014 CodiLime, Inc. All rights reserved.
3 : */
4 :
5 : #include <boost/asio.hpp>
6 : #include <boost/scoped_ptr.hpp>
7 : #include <boost/random.hpp>
8 :
9 : #include "bfd/bfd_udp_connection.h"
10 : #include "bfd/bfd_connection.h"
11 : #include "bfd/bfd_control_packet.h"
12 : #include "bfd/bfd_common.h"
13 : #include "bfd/bfd_server.h"
14 :
15 : #include "base/logging.h"
16 :
17 : namespace BFD {
18 :
19 2 : UDPConnectionManager::UDPRecvServer::UDPRecvServer(UDPConnectionManager *parent,
20 : EventManager *evm,
21 2 : int recvPort)
22 2 : : UdpServer(evm), parent_(parent) {
23 2 : Initialize(recvPort);
24 2 : }
25 :
26 1 : void UDPConnectionManager::UDPRecvServer::RegisterCallback(
27 : RecvCallback callback) {
28 1 : this->callback_ = callback;
29 1 : }
30 :
31 1 : void UDPConnectionManager::UDPRecvServer::HandleReceive(
32 : const boost::asio::const_buffer &recv_buffer,
33 : boost::asio::ip::udp::endpoint remote_endpoint,
34 : std::size_t bytes_transferred,
35 : const boost::system::error_code &error) {
36 2 : if (callback_) {
37 1 : callback_.get()(remote_endpoint, recv_buffer, bytes_transferred, error);
38 1 : return;
39 : }
40 :
41 0 : boost::system::error_code err;
42 0 : parent_->HandleReceive(recv_buffer, GetLocalEndpoint(&err),
43 0 : remote_endpoint, SessionIndex(), bytes_transferred,
44 : error);
45 : }
46 :
47 2 : UDPConnectionManager::UDPCommunicator::UDPCommunicator(EventManager *evm,
48 2 : int remotePort)
49 2 : : UdpServer(evm), remotePort_(remotePort) {
50 2 : boost::random::uniform_int_distribution<> dist(kSendPortMin, kSendPortMax);
51 4 : for (int i = 0; i < 100 && GetServerState() != OK; ++i) {
52 2 : int localPort = dist(randomGen);
53 2 : LOG(DEBUG, "Bind UDPCommunicator to localport: " << localPort);
54 2 : Initialize(localPort);
55 2 : if (GetServerState() != OK) {
56 0 : Shutdown();
57 : }
58 : }
59 :
60 2 : if (GetServerState() != OK) {
61 0 : LOG(ERROR, "Unable to bind to port in range: " << kSendPortMin
62 : << "-" << kSendPortMax);
63 : }
64 2 : }
65 :
66 2 : UDPConnectionManager::UDPConnectionManager(EventManager *evm, int recvPort,
67 2 : int remotePort)
68 2 : : udpRecv_(new BFD::UDPConnectionManager::UDPRecvServer(this, evm,
69 2 : recvPort)),
70 2 : udpSend_(new BFD::UDPConnectionManager::UDPCommunicator(evm,
71 4 : remotePort)), server_(NULL) {
72 2 : if (udpRecv_->GetServerState() != UDPRecvServer::OK)
73 0 : LOG(ERROR, "Unable to listen on port " << recvPort);
74 : else
75 2 : udpRecv_->StartReceive();
76 2 : }
77 :
78 0 : Server *UDPConnectionManager::GetServer() const {
79 0 : return server_;
80 : }
81 :
82 2 : void UDPConnectionManager::SetServer(Server *server) {
83 2 : server_ = server;
84 2 : }
85 :
86 1 : void UDPConnectionManager::RegisterCallback(RecvCallback callback) {
87 1 : udpRecv_->RegisterCallback(callback);
88 1 : }
89 :
90 1 : void UDPConnectionManager::SendPacket(boost::asio::ip::address remoteHost,
91 : const ControlPacket *packet) {
92 : boost::asio::mutable_buffer send =
93 : boost::asio::mutable_buffer(new uint8_t[kMinimalPacketLength],
94 1 : kMinimalPacketLength);
95 1 : int pktSize = EncodeControlPacket(packet,
96 : boost::asio::buffer_cast<uint8_t *>(send),
97 : kMinimalPacketLength);
98 1 : if (pktSize != kMinimalPacketLength) {
99 0 : LOG(ERROR, "Unable to encode packet");
100 0 : const uint8_t *p = boost::asio::buffer_cast<const uint8_t *>(send);
101 0 : delete[] p;
102 0 : return;
103 : }
104 : boost::asio::ip::udp::endpoint remote_endpoint(remoteHost,
105 1 : udpSend_->remotePort());
106 1 : SendPacket(boost::asio::ip::udp::endpoint(), remote_endpoint, 0, send,
107 : pktSize);
108 : }
109 :
110 1 : void UDPConnectionManager::SendPacket(
111 : const boost::asio::ip::udp::endpoint &local_endpoint,
112 : const boost::asio::ip::udp::endpoint &remote_endpoint,
113 : const SessionIndex &index, const boost::asio::mutable_buffer &send,
114 : int pktSize) {
115 1 : udpSend_->StartSend(remote_endpoint, pktSize, send);
116 1 : }
117 :
118 2 : UDPConnectionManager::~UDPConnectionManager() {
119 2 : udpRecv_->Shutdown();
120 2 : udpSend_->Shutdown();
121 2 : UdpServerManager::DeleteServer(udpRecv_);
122 2 : UdpServerManager::DeleteServer(udpSend_);
123 2 : }
124 :
125 0 : void UDPConnectionManager::NotifyStateChange(const SessionKey &key,
126 : const bool &up) {
127 0 : }
128 :
129 : } // namespace BFD
|