HDLC-Daemon
HdlcdPacketEndpoint.h
Go to the documentation of this file.
1 
37 #ifndef HDLCD_PACKET_ENDPOINT_H
38 #define HDLCD_PACKET_ENDPOINT_H
39 
40 #include <iostream>
41 #include <memory>
42 #include <utility>
43 #include <boost/asio.hpp>
44 #include "FrameEndpoint.h"
45 #include "HdlcdPacketData.h"
46 #include "HdlcdPacketCtrl.h"
47 #include <assert.h>
48 
49 class HdlcdPacketEndpoint: public std::enable_shared_from_this<HdlcdPacketEndpoint> {
50 public:
51  HdlcdPacketEndpoint(boost::asio::io_service& a_IOService, std::shared_ptr<FrameEndpoint> a_FrameEndpoint): m_IOService(a_IOService), m_FrameEndpoint(a_FrameEndpoint), m_KeepAliveTimer(a_IOService) {
52  // Checks
53  assert(m_FrameEndpoint);
54 
55  // Initialize remaining components
56  m_bStarted = false;
57  m_bStopped = false;
58  m_FrameEndpoint->ResetFrameFactories(0xF0); // 0xF0 = type byte filter regarding the HLDCd access protocol specification
59  m_FrameEndpoint->RegisterFrameFactory(HDLCD_PACKET_DATA, []()->std::shared_ptr<Frame>{ return HdlcdPacketData::CreateDeserializedPacket(); });
60  m_FrameEndpoint->RegisterFrameFactory(HDLCD_PACKET_CTRL, []()->std::shared_ptr<Frame>{ return HdlcdPacketCtrl::CreateDeserializedPacket(); });
61  m_FrameEndpoint->SetOnFrameCallback([this](std::shared_ptr<Frame> a_Frame)->bool{ return OnFrame(a_Frame); });
62  m_FrameEndpoint->SetOnClosedCallback ([this](){ OnClosed(); });
63  }
64 
66  m_OnDataCallback = nullptr;
67  m_OnCtrlCallback = nullptr;
68  m_OnClosedCallback = nullptr;
69  Close();
70  }
71 
72  // Callback methods
73  void SetOnDataCallback(std::function<bool(std::shared_ptr<const HdlcdPacketData> a_PacketData)> a_OnDataCallback) {
74  m_OnDataCallback = a_OnDataCallback;
75  }
76 
77  void SetOnCtrlCallback(std::function<void(const HdlcdPacketCtrl& a_PacketCtrl)> a_OnCtrlCallback) {
78  m_OnCtrlCallback = a_OnCtrlCallback;
79  }
80 
81  void SetOnClosedCallback(std::function<void()> a_OnClosedCallback) {
82  m_OnClosedCallback = a_OnClosedCallback;
83  }
84 
85  bool Send(const Frame& a_Frame, std::function<void()> a_OnSendDoneCallback = nullptr) {
86  return (m_FrameEndpoint->SendFrame(a_Frame, a_OnSendDoneCallback));
87  }
88 
89  void Start() {
90  assert(m_bStarted == false);
91  assert(m_bStopped == false);
92  m_bStarted = true;
93  auto self(shared_from_this());
94  if (m_FrameEndpoint->GetWasStarted()) {
95  m_IOService.post([this, self](){ m_FrameEndpoint->TriggerNextFrame(); });
96  } else {
97  m_IOService.post([this, self](){ m_FrameEndpoint->Start(); });
98  } // else
99 
100  StartKeepAliveTimer();
101  }
102 
103  void Shutdown() {
104  m_FrameEndpoint->Shutdown();
105  m_KeepAliveTimer.cancel();
106  }
107 
108  void Close() {
109  if (m_bStarted && (!m_bStopped)) {
110  m_bStopped = true;
111  m_KeepAliveTimer.cancel();
112  m_FrameEndpoint->Close();
113  if (m_OnClosedCallback) {
114  m_OnClosedCallback();
115  } // if
116  } // if
117  }
118 
120  m_FrameEndpoint->TriggerNextFrame();
121  }
122 
123 private:
124  void StartKeepAliveTimer() {
125  auto self(shared_from_this());
126  m_KeepAliveTimer.expires_from_now(boost::posix_time::minutes(1));
127  m_KeepAliveTimer.async_wait([this, self](const boost::system::error_code& a_ErrorCode) {
128  if (!a_ErrorCode) {
129  // Periodically send keep alive packets
130  m_FrameEndpoint->SendFrame(HdlcdPacketCtrl::CreateKeepAliveRequest());
131  StartKeepAliveTimer();
132  } // if
133  }); // async_wait
134  }
135 
136 private:
137  // Members
138  void OnClosed() {
139  Close();
140  }
141 
142  bool OnFrame(std::shared_ptr<Frame> a_Frame) {
143  // Reception completed, deliver the packet
144  bool l_bReceiving = true;
145  auto l_PacketData = std::dynamic_pointer_cast<HdlcdPacketData>(a_Frame);
146  if (l_PacketData) {
147  if (m_OnDataCallback) {
148  // Deliver the data packet but stall the receiver
149  l_bReceiving = m_OnDataCallback(l_PacketData);
150  } // if
151  } else {
152  auto l_PacketCtrl = std::dynamic_pointer_cast<HdlcdPacketCtrl>(a_Frame);
153  if (l_PacketCtrl) {
154  bool l_bDeliver = true;
155  if (l_PacketCtrl->GetPacketType() == HdlcdPacketCtrl::CTRL_TYPE_KEEP_ALIVE) {
156  // This is a keep alive packet, simply drop it.
157  l_bDeliver = false;
158  } // if
159 
160  if ((l_bDeliver) && (m_OnCtrlCallback)) {
161  m_OnCtrlCallback(*(l_PacketCtrl.get()));
162  } // if
163  } else {
164  assert(false);
165  } // else
166  } // else
167 
168  return l_bReceiving;
169  }
170 
171  boost::asio::io_service& m_IOService;
172  std::shared_ptr<FrameEndpoint> m_FrameEndpoint;
173 
174 
175  // All possible callbacks for a user of this class
176  std::function<bool(std::shared_ptr<const HdlcdPacketData> a_PacketData)> m_OnDataCallback;
177  std::function<void(const HdlcdPacketCtrl& a_PacketCtrl)> m_OnCtrlCallback;
178  std::function<void()> m_OnClosedCallback;
179 
180  bool m_bStarted;
181  bool m_bStopped;
182 
183  // The keep alive timer
184  boost::asio::deadline_timer m_KeepAliveTimer;
185 };
186 
187 #endif // HDLCD_PACKET_ENDPOINT_H
This file contains the header declaration of class FrameEndpoint.
static std::shared_ptr< HdlcdPacketData > CreateDeserializedPacket()
Copyright (c) 2016, Florian Evers, florian-evers@gmx.de All rights reserved.
A control packet of the HDLCd access protocol.
Definition: HdlcdPacket.h:52
static std::shared_ptr< HdlcdPacketCtrl > CreateDeserializedPacket()
bool Send(const Frame &a_Frame, std::function< void()> a_OnSendDoneCallback=nullptr)
void SetOnDataCallback(std::function< bool(std::shared_ptr< const HdlcdPacketData > a_PacketData)> a_OnDataCallback)
HdlcdPacketEndpoint(boost::asio::io_service &a_IOService, std::shared_ptr< FrameEndpoint > a_FrameEndpoint)
A data packet of the HDLCd access protocol.
Definition: HdlcdPacket.h:51
void SetOnClosedCallback(std::function< void()> a_OnClosedCallback)
static HdlcdPacketCtrl CreateKeepAliveRequest()
Class Frame.
Definition: Frame.h:59
void SetOnCtrlCallback(std::function< void(const HdlcdPacketCtrl &a_PacketCtrl)> a_OnCtrlCallback)
Copyright (c) 2016, Florian Evers, florian-evers@gmx.de All rights reserved.