/* Copyright (C) 2012-2015 Carl Hetherington This file is part of DCP-o-matic. DCP-o-matic 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. DCP-o-matic 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 DCP-o-matic. If not, see . */ #include "dcpomatic_socket.h" #include "compose.hpp" #include "exceptions.h" #include #include #include #include "i18n.h" /** @param timeout Timeout in seconds */ Socket::Socket (int timeout) : _deadline (_io_service) , _socket (_io_service) , _timeout (timeout) { _deadline.expires_at (boost::posix_time::pos_infin); check (); } void Socket::check () { if (_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now ()) { _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")); } } /** 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 (&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 (&v), 4); return ntohl (v); }