1 /* Copyrignt (C) 2014 Codership Oy <info@codership.com> */
2 
3 #include "gcomm/protonet.hpp"
4 #include "gcomm/util.hpp"
5 #include "gcomm/conf.hpp"
6 
7 #include <map>
8 #include <stdexcept>
9 
10 static gu::Config conf;
11 
12 class Client : public gcomm::Toplay
13 {
14 public:
Client(gcomm::Protonet & pnet,const std::string & uri)15     Client(gcomm::Protonet& pnet, const std::string& uri)
16         :
17         gcomm::Toplay(conf),
18         uri_   (uri),
19         pnet_  (pnet),
20         pstack_(),
21         socket_(pnet_.socket(uri)),
22         msg_   ()
23     {
24         pstack_.push_proto(this);
25         pnet_.insert(&pstack_);
26     }
27 
~Client()28     ~Client()
29     {
30         pnet_.erase(&pstack_);
31         pstack_.pop_proto(this);
32         socket_->close();
33     }
34 
connect(bool f=false)35     void connect(bool f = false)
36     {
37         socket_->connect(uri_);
38     }
39 
msg() const40     std::string msg() const
41     {
42         return std::string(msg_.begin(), msg_.end());
43     }
44 
handle_up(const void * id,const gcomm::Datagram & dg,const gcomm::ProtoUpMeta & um)45     void handle_up(const void* id, const gcomm::Datagram& dg,
46                    const gcomm::ProtoUpMeta& um)
47     {
48         if (um.err_no() != 0)
49         {
50             log_error << "socket failed: " << um.err_no();
51             socket_->close();
52             throw std::exception();
53         }
54         else
55         {
56             assert(id == socket_->id());
57             msg_.insert(msg_.begin(), gcomm::begin(dg),
58                         gcomm::begin(dg) + gcomm::available(dg));
59         }
60     }
61 private:
62     gu::URI           uri_;
63     gcomm::Protonet&  pnet_;
64     gcomm::Protostack pstack_;
65     gcomm::SocketPtr  socket_;
66     gu::Buffer        msg_;
67 };
68 
69 
70 class Server : public gcomm::Toplay
71 {
72 public:
Server(gcomm::Protonet & pnet,const std::string & uri)73     Server(gcomm::Protonet& pnet, const std::string& uri)
74         :
75         gcomm::Toplay(conf),
76         uri_(uri),
77         pnet_(pnet),
78         pstack_(),
79         listener_(),
80         smap_(),
81         msg_("hello ssl")
82     {
83         pstack_.push_proto(this);
84         pnet_.insert(&pstack_);
85         listener_ = pnet_.acceptor(uri_);
86     }
87 
~Server()88     ~Server()
89     {
90         pnet_.erase(&pstack_);
91         pstack_.pop_proto(this);
92     }
93 
listen()94     void listen()
95     {
96         listener_->listen(uri_);
97     }
98 
handle_up(const void * id,const gcomm::Datagram & dg,const gcomm::ProtoUpMeta & um)99     void handle_up(const void* id, const gcomm::Datagram& dg,
100                    const gcomm::ProtoUpMeta& um)
101     {
102         if (id == listener_->id())
103         {
104             gcomm::SocketPtr socket(listener_->accept());
105             if (smap_.insert(
106                     std::make_pair(socket->id(), socket)).second == false)
107             {
108                 throw std::logic_error("duplicate socket entry");
109             }
110             return;
111         }
112 
113         std::map<const void*, gcomm::SocketPtr>::iterator si(smap_.find(id));
114         if (si == smap_.end())
115         {
116             throw std::logic_error("could not find socket from map");
117         }
118 
119         gcomm::SocketPtr socket(si->second);
120         if (socket->state() == gcomm::Socket::S_CONNECTED)
121         {
122             gcomm::Datagram msg;
123             msg.payload().resize(msg_.size());
124             std::copy(msg_.begin(), msg_.end(), msg.payload().begin());
125             socket->send(0, msg);
126         }
127         else if (socket->state() == gcomm::Socket::S_CLOSED ||
128                  socket->state() == gcomm::Socket::S_FAILED)
129         {
130             std::cerr << "socket " << id << " failed" << std::endl;
131             socket->close();
132             smap_.erase(id);
133         }
134         else
135         {
136             std::cerr << "socket state: " << socket->state() << std::endl;
137         }
138     }
139 
140 private:
141     Server(const Server&);
142     void operator=(const Server&);
143     gu::URI                           uri_;
144     gcomm::Protonet&                  pnet_;
145     gcomm::Protostack                 pstack_;
146     std::shared_ptr<gcomm::Acceptor>  listener_;
147     std::map<const void*, gcomm::SocketPtr> smap_;
148     const std::string                 msg_;
149 };
150 
151 
152 
main(int argc,char * argv[])153 int main(int argc, char* argv[])
154 {
155     if (argc != 4)
156     {
157         std::cerr << "usage: " << argv[0] << " <-s|-c> <conf> <uri>"
158                   << std::endl;
159         return 1;
160     }
161 
162     gu::Config conf;
163     gcomm::Conf::register_params(conf);
164     conf.parse(argv[2]);
165     std::unique_ptr<gcomm::Protonet> pnet(gcomm::Protonet::create(conf));
166 
167     if (std::string("-s") == argv[1])
168     {
169         Server server(*pnet, argv[3]);
170         server.listen();
171         while (true)
172         {
173             pnet->event_loop(gu::datetime::Period(1 * gu::datetime::Sec));
174         }
175     }
176     else if (std::string("-c") == argv[1])
177     {
178         Client client(*pnet, argv[3]);
179         client.connect();
180         while (true)
181         {
182             pnet->event_loop(gu::datetime::Period(1*gu::datetime::MSec));
183             std::string msg(client.msg());
184             if (msg != "")
185             {
186                 std::cout << "read message from server: '" << msg << "'" << std::endl;
187                 break;
188             }
189         }
190     }
191     return 0;
192 }
193