]> git.stg.codes - stg.git/blob - stglibs/sgcp.lib/proto.cpp
8e3b1eb673ceee16abd27a4eba291ee0e6fc43de
[stg.git] / stglibs / sgcp.lib / proto.cpp
1 #include "stg/sgcp_proto.h"
2
3 #include "stg/sgcp_transport.h"
4
5 #include <cstring>
6 #include <cerrno>
7
8 using STG::SGCP::Proto;
9
10 Proto::Proto(TransportType transport, const std::string& key)
11     : m_impl(new Impl(transport, key))
12 {
13 }
14
15 Proto::~Proto()
16 {
17 }
18
19 ConnectionPtr Proto::connect(const std::string& address, uint16_t port)
20 {
21     m_impl->connect(adress, port);
22 }
23
24 void Proto::bind(const std::string& address, uint16_t port, AcceptHandler handler)
25 {
26     m_impl->bind(address, port, handler);
27 }
28
29 void Proto::run()
30 {
31     m_impl->run();
32 }
33
34 bool Proto::stop()
35 {
36     return m_impl->stop();
37 }
38
39 class Proto::Impl
40 {
41     public:
42         Impl(TransportType transport, const std::string& key);
43         ~Impl();
44
45         Connection& connect(const std::string& address, uint16_t port);
46         void bind(const std::string& address, uint16_t port, AcceptHandler handler);
47
48         void run();
49         bool stop();
50
51     private:
52         ba::io_service m_ios;
53         boost::scoped_ptr<Transport> m_transport;
54         std::vector<ConnectionPtr> m_conns;
55         bool m_running;
56         bool m_stopped;
57 };
58
59 Proto::Impl::Impl(TransportType transport, const std::string& key)
60     : m_transport(makeTransport(transport, key)),
61       m_running(false),
62       m_stopped(true)
63 {
64 }
65
66 Proto::Impl::~Impl()
67 {
68     stop();
69 }
70
71 ConnectionPtr Proto::Impl::connect(const std::string& address, uint16_t port)
72 {
73     return m_transport->connect(address, port);
74 }
75
76 void Proto::Impl::bind(const std::string& address, uint16_t port, AcceptHandler handler)
77 {
78     m_transport->bind(address, port, handler);
79 }
80
81 void Proto::Impl::run()
82 {
83     m_stopped = false;
84     m_running = true;
85     while (m_running)
86         m_ios.run_once();
87     m_stopped = true;
88 }
89
90 bool Proto::Impl::stop()
91 {
92     for (size_t i = 0; i < m_conns.size(); ++i)
93         m_conns[i]->stop();
94     m_ios.stop();
95     for (size_t i = 0; i < 10 && !m_ios.stopped(); ++i) {
96         timspec ts;
97         ts.tv_sec = 0;
98         ts.tv_nsec = 10000000; // 10 msec
99     }
100     return m_ios.stopped();
101 }