1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

PacketSender is not copyable and movable.

This commit is contained in:
Matias Fontanini
2013-04-23 11:05:44 -03:00
parent fdfb8b0dea
commit 8afbe14c82
5 changed files with 107 additions and 52 deletions

View File

@@ -58,8 +58,7 @@ subdir = .
DIST_COMMON = README $(am__configure_deps) $(libtins_include_HEADERS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/libtins.pc.in $(top_srcdir)/configure AUTHORS THANKS \
TODO config.guess config.sub depcomp install-sh ltmain.sh \
missing
config.guess config.sub depcomp install-sh ltmain.sh missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \

View File

@@ -38,6 +38,8 @@
#define TINS_CXXSTD_GCC_FIX 0
#endif // __GXX_EXPERIMENTAL_CXX0X__
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1)
namespace Tins{
namespace Internals {
template<typename T>
@@ -51,6 +53,4 @@ struct smart_ptr {
}
}
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1)
#endif // TINS_CXXSTD_H

View File

@@ -86,6 +86,44 @@ public:
return "Invalid interface";
}
};
/**
* \brief Exception thrown when PacketSender fails to open a socket.
*/
class socket_open_error : public std::runtime_error {
public:
socket_open_error(const std::string &msg)
: std::runtime_error(msg) { }
};
/**
* \brief Exception thrown when PacketSender fails to close a socket.
*/
class socket_close_error : public std::runtime_error {
public:
socket_close_error(const std::string &msg)
: std::runtime_error(msg) { }
};
/**
* \brief Exception thrown when PacketSender fails to write on a socket.
*/
class socket_write_error : public std::runtime_error {
public:
socket_write_error(const std::string &msg)
: std::runtime_error(msg) { }
};
/**
* \brief Exception thrown when an invalid socket type is provided
* to PacketSender.
*/
class invalid_socket_type : public std::exception {
public:
const char *what() const throw() {
return "The provided socket type is invalid";
}
};
}
#endif // TINS_EXCEPTIONS_H

View File

@@ -38,6 +38,7 @@
#include <map>
#include "network_interface.h"
#include "macros.h"
#include "cxxstd.h"
struct timeval;
struct sockaddr;
@@ -80,6 +81,20 @@ namespace Tins {
PacketSender(const NetworkInterface &iface = NetworkInterface(),
uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
#if TINS_IS_CXX11
/**
* \brief Move constructor.
* \param rhs The sender to be moved.
*/
PacketSender(PacketSender &&rhs);
/**
* \brief Move assignment operator.
* \param rhs The sender to be moved.
*/
PacketSender& operator=(PacketSender &&rhs);
#endif
/**
* \brief PacketSender destructor.
*
@@ -91,7 +106,7 @@ namespace Tins {
/**
* \brief Opens a layer 2 socket.
*
* If this operation fails, then a SocketOpenError will be thrown.
* If this operation fails, then a socket_open_error will be thrown.
*/
void open_l2_socket(const NetworkInterface& iface = NetworkInterface());
#endif // WIN32
@@ -100,9 +115,9 @@ namespace Tins {
* \brief Opens a layer 3 socket, using the corresponding protocol
* for the given flag.
*
* If this operation fails, then a SocketOpenError will be thrown.
* If the provided socket type is not valid, a InvalidSocketTypeError
* will be throw.
* If this operation fails, then a socket_open_error will be thrown.
* If the provided socket type is not valid, an invalid_socket_type
* exception will be throw.
*
* \param type The type of socket which will be used to pick the protocol flag
* for this socket.
@@ -113,9 +128,9 @@ namespace Tins {
* \brief Closes the socket associated with the given flag.
*
* If the provided type is invalid, meaning no such open socket
* exists, a InvalidSocketTypeError is thrown.
* exists, an invalid_socket_type exception is thrown.
*
* If any socket close errors are encountered, a SocketCloseError
* If any socket close errors are encountered, a socket_close_error
* is thrown.
*
* \param type The type of the socket to be closed.
@@ -143,7 +158,7 @@ namespace Tins {
* This method opens the appropriate socket, if it's not open yet,
* and sends the PDU on the open socket.
*
* If any send error occurs, then a SocketWriteError is thrown.
* If any send error occurs, then a socket_write_error is thrown.
*
* If the PDU contains a link layer protocol, then default_interface
* is used.
@@ -220,7 +235,7 @@ namespace Tins {
* using the corresponding flag, according to the given type of
* protocol.
*
* If any socket write error occurs, a SocketWriteError is thrown.
* If any socket write error occurs, a socket_write_error is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
@@ -250,7 +265,7 @@ namespace Tins {
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
* according to the given type of protocol.
*
* If any socket write error occurs, a SocketWriteError is thrown.
* If any socket write error occurs, a socket_write_error is thrown.
*
* \param pdu The PDU to send.
* \param link_addr The sockaddr struct which will be used to send the PDU.
@@ -263,6 +278,8 @@ namespace Tins {
typedef std::map<SocketType, int> SocketTypeMap;
PacketSender(const PacketSender&);
PacketSender& operator=(const PacketSender&);
int find_type(SocketType type);
int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
#ifndef WIN32
@@ -289,32 +306,6 @@ namespace Tins {
uint32_t _timeout, _timeout_usec;
NetworkInterface default_iface;
};
class SocketOpenError : public std::runtime_error {
public:
SocketOpenError(const std::string &msg)
: std::runtime_error(msg) { }
};
class SocketCloseError : public std::runtime_error {
public:
SocketCloseError(const std::string &msg)
: std::runtime_error(msg) { }
};
class SocketWriteError : public std::runtime_error {
public:
SocketWriteError(const std::string &msg)
: std::runtime_error(msg) { }
};
class InvalidSocketTypeError : public std::exception {
public:
const char *what() const throw() {
return "The provided socket type is invalid";
}
};
}
#endif // TINS_PACKET_SENDER_H

View File

@@ -97,6 +97,33 @@ PacketSender::PacketSender(const NetworkInterface &iface, uint32_t recv_timeout,
_types[ICMP_SOCKET] = IPPROTO_ICMP;
}
#if TINS_IS_CXX11
PacketSender::PacketSender(PacketSender &&rhs)
{
*this = std::move(rhs);
}
PacketSender& PacketSender::operator=(PacketSender &&rhs)
{
_sockets = std::move(rhs._sockets);
rhs._sockets = std::vector<int>(SOCKETS_END, INVALID_RAW_SOCKET);
#ifndef WIN32
#if defined(BSD) || defined(__FreeBSD_kernel__)
_ether_socket = std::move(rhs._ether_socket);
#else
_ether_socket = rhs._ether_socket;
rhs._ether_socket = INVALID_RAW_SOCKET;
#endif
#endif
_types = rhs._types; // no move
_timeout = rhs._timeout;
_timeout_usec = rhs._timeout_usec;
default_iface = rhs.default_iface;
return *this;
}
#endif
PacketSender::~PacketSender() {
for(unsigned i(0); i < _sockets.size(); ++i) {
if(_sockets[i] != INVALID_RAW_SOCKET)
@@ -153,13 +180,13 @@ void PacketSender::open_l2_socket(const NetworkInterface& iface) {
sock = open(oss.str().c_str(), O_RDWR);
}
if(sock == -1)
throw SocketOpenError(make_error_string());
throw socket_open_error(make_error_string());
struct ifreq ifr;
strncpy(ifr.ifr_name, iface.name().c_str(), sizeof(ifr.ifr_name) - 1);
if(ioctl(sock, BIOCSETIF, (caddr_t)&ifr) < 0) {
::close(sock);
throw SocketOpenError(make_error_string());
throw socket_open_error(make_error_string());
}
_ether_socket[iface.id()] = sock;
#else
@@ -167,7 +194,7 @@ void PacketSender::open_l2_socket(const NetworkInterface& iface) {
_ether_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (_ether_socket == -1)
throw SocketOpenError(make_error_string());
throw socket_open_error(make_error_string());
}
#endif
}
@@ -176,12 +203,12 @@ void PacketSender::open_l2_socket(const NetworkInterface& iface) {
void PacketSender::open_l3_socket(SocketType type) {
int socktype = find_type(type);
if(socktype == -1)
throw InvalidSocketTypeError();
throw invalid_socket_type();
if(_sockets[type] == INVALID_RAW_SOCKET) {
int sockfd;
sockfd = socket((type == IPV6_SOCKET) ? AF_INET6 : AF_INET, SOCK_RAW, socktype);
if (sockfd < 0)
throw SocketOpenError(make_error_string());
throw socket_open_error(make_error_string());
const int on = 1;
#ifndef WIN32
@@ -200,24 +227,24 @@ void PacketSender::close_socket(SocketType type, const NetworkInterface &iface)
#if defined(BSD) || defined(__FreeBSD_kernel__)
BSDEtherSockets::iterator it = _ether_socket.find(iface.id());
if(it == _ether_socket.end())
throw InvalidSocketTypeError();
throw invalid_socket_type();
if(::close(it->second) == -1)
throw SocketCloseError(make_error_string());
throw socket_close_error(make_error_string());
_ether_socket.erase(it);
#elif !defined(WIN32)
if(_ether_socket == INVALID_RAW_SOCKET)
throw InvalidSocketTypeError();
throw invalid_socket_type();
if(::close(_ether_socket) == -1)
throw SocketCloseError(make_error_string());
throw socket_close_error(make_error_string());
_ether_socket = INVALID_RAW_SOCKET;
#endif
}
else {
if(type >= SOCKETS_END || _sockets[type] == INVALID_RAW_SOCKET)
throw InvalidSocketTypeError();
throw invalid_socket_type();
#ifndef WIN32
if(close(_sockets[type]) == -1)
throw SocketCloseError(make_error_string());
throw socket_close_error(make_error_string());
#else
closesocket(_sockets[type]);
#endif
@@ -275,7 +302,7 @@ void PacketSender::send_l2(PDU &pdu, struct sockaddr* link_addr,
#else
if(::sendto(sock, &buffer[0], buffer.size(), 0, link_addr, len_addr) == -1)
#endif
throw SocketWriteError(make_error_string());
throw socket_write_error(make_error_string());
}
}
@@ -297,7 +324,7 @@ void PacketSender::send_l3(PDU &pdu, struct sockaddr* link_addr, uint32_t len_ad
int sock = _sockets[type];
PDU::serialization_type buffer = pdu.serialize();
if(sendto(sock, (const char*)&buffer[0], buffer.size(), 0, link_addr, len_addr) == -1)
throw SocketWriteError(make_error_string());
throw socket_write_error(make_error_string());
}
PDU *PacketSender::recv_match_loop(int sock, PDU &pdu, struct sockaddr* link_addr, uint32_t addrlen) {