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