diff options
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/network.cpp | 33 | ||||
-rw-r--r-- | src/network.h | 3 | ||||
-rw-r--r-- | src/network/protocol.cpp | 69 | ||||
-rw-r--r-- | src/network/protocol.h | 33 |
5 files changed, 116 insertions, 23 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6676a9c..478fc50 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(erebos merge.cpp message.cpp network.cpp + network/protocol.cpp pairing.cpp pubkey.cpp service.cpp diff --git a/src/network.cpp b/src/network.cpp index cd13bc4..b5dfd68 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -1,6 +1,7 @@ #include "network.h" #include "identity.h" +#include "network/protocol.h" #include "service.h" #include <algorithm> @@ -313,10 +314,12 @@ Server::Priv::Priv(const Head<LocalState> & local, const Identity & self): } } - sock = socket(AF_INET6, SOCK_DGRAM, 0); + int sock = socket(AF_INET6, SOCK_DGRAM, 0); if (sock < 0) throw std::system_error(errno, std::generic_category()); + protocol = NetworkProtocol(sock); + int disable = 0; // Should be disabled by default, but try to make sure. On platforms // where the calls fails, IPv4 might not work. @@ -349,15 +352,11 @@ Server::Priv::~Priv() finish = true; } - if (sock >= 0) - shutdown(sock, SHUT_RDWR); + protocol.shutdown(); announceCondvar.notify_all(); threadListen.join(); threadAnnounce.join(); - - if (sock >= 0) - close(sock); } shared_ptr<Server::Priv> Server::Priv::getptr() @@ -372,18 +371,11 @@ void Server::Priv::doListen() unique_lock lock(dataMutex); for (; !finish; lock.lock()) { - sockaddr_in6 paddr; - lock.unlock(); - socklen_t addrlen = sizeof(paddr); - buf.resize(4096); - ssize_t ret = recvfrom(sock, buf.data(), buf.size(), 0, - (sockaddr *) &paddr, &addrlen); - if (ret < 0) - throw std::system_error(errno, std::generic_category()); - if (ret == 0) + + sockaddr_in6 paddr; + if (not protocol.recvfrom(buf, paddr)) break; - buf.resize(ret); if (isSelfAddress(paddr)) continue; @@ -456,7 +448,7 @@ void Server::Priv::doAnnounce() sin.sin_family = AF_INET; sin.sin_addr = in; sin.sin_port = htons(discoveryPort); - sendto(sock, bytes.data(), bytes.size(), 0, (sockaddr *) &sin, sizeof(sin)); + protocol.sendto(bytes, sin); } lastAnnounce += announceInterval * ((now - lastAnnounce) / announceInterval); @@ -703,8 +695,7 @@ void Server::Peer::send(const TransportHeader & header, const vector<Object> & o out = std::move(data); if (!out.empty()) - sendto(server.sock, out.data(), out.size(), 0, - (sockaddr *) &addr, sizeof(addr)); + server.protocol.sendto(out, addr); } void Server::Peer::updateIdentity(ReplyBuilder &) @@ -840,9 +831,7 @@ void Server::Peer::trySendOutQueue() for (const auto & data : secureOutQueue) { auto out = std::get<unique_ptr<Channel>>(channel)->encrypt(data); - - sendto(server.sock, out.data(), out.size(), 0, - (sockaddr *) &addr, sizeof(addr)); + server.protocol.sendto(out, addr); } secureOutQueue.clear(); diff --git a/src/network.h b/src/network.h index 1c1bb57..c242ac5 100644 --- a/src/network.h +++ b/src/network.h @@ -3,6 +3,7 @@ #include <erebos/network.h> #include "channel.h" +#include "network/protocol.h" #include <condition_variable> #include <mutex> @@ -181,7 +182,7 @@ struct Server::Priv vector<struct TransportHeader> outgoing; vector<weak_ptr<WaitingRef>> waiting; - int sock; + NetworkProtocol protocol; vector<in_addr> localAddresses; vector<in_addr> bcastAddresses; diff --git a/src/network/protocol.cpp b/src/network/protocol.cpp new file mode 100644 index 0000000..63cfde5 --- /dev/null +++ b/src/network/protocol.cpp @@ -0,0 +1,69 @@ +#include "protocol.h" + +#include <sys/socket.h> +#include <unistd.h> + +#include <system_error> + +namespace erebos { + +NetworkProtocol::NetworkProtocol(): + sock(-1) +{} + +NetworkProtocol::NetworkProtocol(int s): + sock(s) +{} + +NetworkProtocol::NetworkProtocol(NetworkProtocol && other): + sock(other.sock) +{ + other.sock = -1; +} + +NetworkProtocol & NetworkProtocol::operator=(NetworkProtocol && other) +{ + sock = other.sock; + other.sock = -1; + return *this; +} + +NetworkProtocol::~NetworkProtocol() +{ + if (sock >= 0) + close(sock); +} + +bool NetworkProtocol::recvfrom(vector<uint8_t> & buffer, sockaddr_in6 & addr) +{ + socklen_t addrlen = sizeof(addr); + buffer.resize(4096); + ssize_t ret = ::recvfrom(sock, buffer.data(), buffer.size(), 0, + (sockaddr *) &addr, &addrlen); + if (ret < 0) + throw std::system_error(errno, std::generic_category()); + if (ret == 0) + return false; + + buffer.resize(ret); + return true; +} + +void NetworkProtocol::sendto(const vector<uint8_t> & buffer, sockaddr_in addr) +{ + ::sendto(sock, buffer.data(), buffer.size(), 0, + (sockaddr *) &addr, sizeof(addr)); +} + +void NetworkProtocol::sendto(const vector<uint8_t> & buffer, sockaddr_in6 addr) +{ + ::sendto(sock, buffer.data(), buffer.size(), 0, + (sockaddr *) &addr, sizeof(addr)); +} + +void NetworkProtocol::shutdown() +{ + ::shutdown(sock, SHUT_RDWR); +} + +} diff --git a/src/network/protocol.h b/src/network/protocol.h new file mode 100644 index 0000000..6a22f3b --- /dev/null +++ b/src/network/protocol.h @@ -0,0 +1,33 @@ +#pragma once + +#include <netinet/in.h> + +#include <cstdint> +#include <vector> + +namespace erebos { + +using std::vector; + +class NetworkProtocol +{ +public: + NetworkProtocol(); + explicit NetworkProtocol(int sock); + NetworkProtocol(const NetworkProtocol &) = delete; + NetworkProtocol(NetworkProtocol &&); + NetworkProtocol & operator=(const NetworkProtocol &) = delete; + NetworkProtocol & operator=(NetworkProtocol &&); + ~NetworkProtocol(); + + bool recvfrom(vector<uint8_t> & buffer, sockaddr_in6 & addr); + void sendto(const vector<uint8_t> & buffer, sockaddr_in addr); + void sendto(const vector<uint8_t> & buffer, sockaddr_in6 addr); + + void shutdown(); + +private: + int sock; +}; + +} |