summaryrefslogtreecommitdiff
path: root/src/lib/dcpomatic_socket.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-01-29 00:37:06 +0000
committerCarl Hetherington <cth@carlh.net>2015-01-29 00:37:06 +0000
commitf213fd833a840fc97e3875979ae7dc7cbbc883b1 (patch)
treebf585e448f263668ebaf39d37a8b90757c1dea91 /src/lib/dcpomatic_socket.cc
parentc58b1a4a478201b76a4f8491fa075cbe476af484 (diff)
Move Socket to dcpomatic_socket.{cc,h}.
Diffstat (limited to 'src/lib/dcpomatic_socket.cc')
-rw-r--r--src/lib/dcpomatic_socket.cc156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/lib/dcpomatic_socket.cc b/src/lib/dcpomatic_socket.cc
new file mode 100644
index 000000000..bc8f596a7
--- /dev/null
+++ b/src/lib/dcpomatic_socket.cc
@@ -0,0 +1,156 @@
+/*
+ Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "dcpomatic_socket.h"
+#include "compose.hpp"
+#include "exceptions.h"
+#include <boost/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+
+#include "i18n.h"
+
+Socket::Socket (int timeout)
+ : _deadline (_io_service)
+ , _socket (_io_service)
+ , _acceptor (0)
+ , _timeout (timeout)
+{
+ _deadline.expires_at (boost::posix_time::pos_infin);
+ check ();
+}
+
+Socket::~Socket ()
+{
+ delete _acceptor;
+}
+
+void
+Socket::check ()
+{
+ if (_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now ()) {
+ if (_acceptor) {
+ _acceptor->cancel ();
+ } else {
+ _socket.close ();
+ }
+ _deadline.expires_at (boost::posix_time::pos_infin);
+ }
+
+ _deadline.async_wait (boost::bind (&Socket::check, this));
+}
+
+/** Blocking connect.
+ * @param endpoint End-point to connect to.
+ */
+void
+Socket::connect (boost::asio::ip::tcp::endpoint endpoint)
+{
+ _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
+ boost::system::error_code ec = boost::asio::error::would_block;
+ _socket.async_connect (endpoint, boost::lambda::var(ec) = boost::lambda::_1);
+ do {
+ _io_service.run_one();
+ } while (ec == boost::asio::error::would_block);
+
+ if (ec) {
+ throw NetworkError (String::compose (_("error during async_connect (%1)"), ec.value ()));
+ }
+
+ if (!_socket.is_open ()) {
+ throw NetworkError (_("connect timed out"));
+ }
+}
+
+void
+Socket::accept (int port)
+{
+ _acceptor = new boost::asio::ip::tcp::acceptor (_io_service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port));
+
+ _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
+ boost::system::error_code ec = boost::asio::error::would_block;
+ _acceptor->async_accept (_socket, boost::lambda::var(ec) = boost::lambda::_1);
+ do {
+ _io_service.run_one ();
+ } while (ec == boost::asio::error::would_block);
+
+ delete _acceptor;
+ _acceptor = 0;
+
+ if (ec) {
+ throw NetworkError (String::compose (_("error during async_accept (%1)"), ec.value ()));
+ }
+}
+
+/** Blocking write.
+ * @param data Buffer to write.
+ * @param size Number of bytes to write.
+ */
+void
+Socket::write (uint8_t const * data, int size)
+{
+ _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
+ boost::system::error_code ec = boost::asio::error::would_block;
+
+ boost::asio::async_write (_socket, boost::asio::buffer (data, size), boost::lambda::var(ec) = boost::lambda::_1);
+
+ do {
+ _io_service.run_one ();
+ } while (ec == boost::asio::error::would_block);
+
+ if (ec) {
+ throw NetworkError (String::compose (_("error during async_write (%1)"), ec.value ()));
+ }
+}
+
+void
+Socket::write (uint32_t v)
+{
+ v = htonl (v);
+ write (reinterpret_cast<uint8_t*> (&v), 4);
+}
+
+/** Blocking read.
+ * @param data Buffer to read to.
+ * @param size Number of bytes to read.
+ */
+void
+Socket::read (uint8_t* data, int size)
+{
+ _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
+ boost::system::error_code ec = boost::asio::error::would_block;
+
+ boost::asio::async_read (_socket, boost::asio::buffer (data, size), boost::lambda::var(ec) = boost::lambda::_1);
+
+ do {
+ _io_service.run_one ();
+ } while (ec == boost::asio::error::would_block);
+
+ if (ec) {
+ throw NetworkError (String::compose (_("error during async_read (%1)"), ec.value ()));
+ }
+}
+
+uint32_t
+Socket::read_uint32 ()
+{
+ uint32_t v;
+ read (reinterpret_cast<uint8_t *> (&v), 4);
+ return ntohl (v);
+}
+