Use Vlinder::Atomics
[Arachnida.git] / lib / Spin / Listener.cpp
blobdbba9a91b52b3b99feb9068aafbe9ed46004ecc3
1 #include "Listener.h"
2 #include <cassert>
3 #include <boost/format.hpp>
4 #include <boost/bind.hpp>
5 #include <boost/filesystem/path.hpp>
6 #include <loki/ScopeGuard.h>
7 #include <Scorpion/BIO.h>
8 extern "C" {
9 #include <openssl/bio.h>
10 #include <openssl/ssl.h>
12 #include "Connection.h"
13 #include "Private/ConnectionHandler.h"
14 #include "Handlers/NewConnectionHandler.h"
15 #include "Exceptions/Connection/UnusableListener.h"
17 namespace Spin
19 Listener::Listener(Details::Address local_address, boost::uint16_t local_port)
20 : bio_(createBIO_(constructLocalAddress_(local_address, local_port))),
21 new_connection_handler_(0)
22 { /* no-op */ }
24 Listener::Listener(const Scorpion::Context & security_context, Details::Address local_address, boost::uint16_t local_port)
25 : security_context_(security_context),
26 bio_(createSSLBIO_(constructLocalAddress_(local_address, local_port))),
27 new_connection_handler_(0)
28 { /* no-op */ }
30 Listener::~Listener()
32 clearNewConnectionHandler();
35 boost::shared_ptr< Connection > Listener::accept()
37 if (!bio_)
38 throw Exceptions::Connection::UnusableListener();
39 else
40 { /* all is well */ }
41 return boost::shared_ptr< Connection >(new Connection(bio_->accept()));
44 void Listener::abort()
46 if (!bio_)
47 throw Exceptions::Connection::UnusableListener();
48 else
49 { /* all is well */ }
50 bio_->reset();
53 void Listener::setNewConnectionHandler(Handlers::NewConnectionHandler & handler)
55 new_connection_handler_ = &handler;
56 if (!bio_)
57 throw Exceptions::Connection::UnusableListener();
58 else
59 { /* all is well */ }
60 Private::ConnectionHandler::getInstance().attach(bio_->getFD(), boost::bind(&Listener::onNewConnection_, this));
63 void Listener::clearNewConnectionHandler()
65 if (new_connection_handler_)
67 if (!bio_)
68 throw Exceptions::Connection::UnusableListener();
69 else
70 { /* all is well */ }
71 Private::ConnectionHandler::getInstance().detach(bio_->getFD());
72 new_connection_handler_ = 0;
74 else
75 { /* nothing to clear */ }
78 std::string Listener::constructLocalAddress_(Details::Address local_address, boost::uint16_t local_port)
80 std::string local_address_s;
81 if (local_address.u_.u32_ == 0)
82 local_address_s = "*";
83 else
85 boost::format fmt("%1%.%2%.%3%.%4%");
86 fmt % (unsigned int)local_address.u_.u8_[0]
87 % (unsigned int)local_address.u_.u8_[1]
88 % (unsigned int)local_address.u_.u8_[2]
89 % (unsigned int)local_address.u_.u8_[3]
91 local_address_s = fmt.str();
93 boost::format fmt("%1%:%2%");
94 fmt % local_address_s;
95 if (local_port == 0)
96 fmt % "*";
97 else
98 fmt % local_port;
100 return fmt.str();
103 Scorpion::BIO * Listener::createBIO_(const std::string & local_address)
105 return Scorpion::createAcceptBIO(local_address, Scorpion::BIO::non_blocking__);
108 Scorpion::BIO * Listener::createSSLBIO_(const std::string & local_address)
110 return Scorpion::createSSLAcceptBIO(local_address, security_context_, Scorpion::BIO::auto_retry__ | Scorpion::BIO::non_blocking__);
113 void Listener::onNewConnection_()
115 if (new_connection_handler_)
116 (*new_connection_handler_)(accept());
117 else
118 { /* no new connection handler set */ }