From 773234f231ae549323d7e40a44631e8d762fc89f Mon Sep 17 00:00:00 2001 From: Thulinma Date: Mon, 3 Feb 2014 16:50:37 +0100 Subject: [PATCH] Added UDP sending support to socket library. --- lib/socket.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/socket.h | 20 +++++++++ 2 files changed, 127 insertions(+) diff --git a/lib/socket.cpp b/lib/socket.cpp index 105bdfdd..6fb08f61 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef __FreeBSD__ #include @@ -896,3 +897,109 @@ bool Socket::Server::connected() const{ int Socket::Server::getSocket(){ return sock; } + +/// Create a new UDP Socket. +/// \param nonblock Whether the socket should be nonblocking. +Socket::UDPConnection::UDPConnection(bool nonblock){ + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock == -1){ + sock = socket(AF_INET, SOCK_DGRAM, 0); + } + if (sock == -1){ + DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); + } + up = 0; + down = 0; + destAddr = 0; + destAddr_size = 0; + if (nonblock){ + setBlocking(!nonblock); + } +} //Socket::UDPConnection UDP Contructor + +Socket::UDPConnection::UDPConnection(const UDPConnection & o){ + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock == -1){ + sock = socket(AF_INET, SOCK_DGRAM, 0); + } + if (sock == -1){ + DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); + } + up = 0; + down = 0; + if (o.destAddr && o.destAddr_size){ + destAddr = malloc(o.destAddr_size); + if (destAddr){ + memcpy(destAddr, o.destAddr, o.destAddr_size); + } + }else{ + destAddr = 0; + destAddr_size = 0; + } +} + +Socket::UDPConnection::~UDPConnection(){ + if (sock != -1){ + errno = EINTR; + while (::close(sock) != 0 && errno == EINTR){ + } + sock = -1; + } + if (destAddr){ + free(destAddr); + destAddr = 0; + } +} + +void Socket::UDPConnection::SetDestination(std::string destIp, uint32_t port){ + destAddr = malloc(sizeof(struct sockaddr_in6)); + if (destAddr){ + destAddr_size = sizeof(struct sockaddr_in6); + memset(destAddr, 0, destAddr_size); + ((struct sockaddr_in6*)destAddr)->sin6_family = AF_INET6; + ((struct sockaddr_in6*)destAddr)->sin6_port = htons(port); + if(inet_pton(AF_INET6, destIp.c_str(), &(((struct sockaddr_in6*)destAddr)->sin6_addr)) == 1){ + return; + } + free(destAddr); + destAddr = 0; + } + destAddr = malloc(sizeof(struct sockaddr_in)); + if (destAddr){ + destAddr_size = sizeof(struct sockaddr_in); + memset(destAddr, 0, destAddr_size); + ((struct sockaddr_in*)destAddr)->sin_family = AF_INET; + ((struct sockaddr_in*)destAddr)->sin_port = htons(port); + if(inet_pton(AF_INET, destIp.c_str(), &(((struct sockaddr_in*)destAddr)->sin_addr)) == 1){ + return; + } + free(destAddr); + destAddr = 0; + } + DEBUG_MSG(DLVL_FAIL, "Could not set destination for UDP socket: %s:%d", destIp.c_str(), port); +}//Socket::UDPConnection SetDestination + +void Socket::UDPConnection::setBlocking(bool blocking){ + if (sock >= 0){ + setFDBlocking(sock, blocking); + } +} + +void Socket::UDPConnection::SendNow(const std::string & data){ + SendNow(data.c_str(), data.size()); +} + +void Socket::UDPConnection::SendNow(const char* data){ + int len = strlen(data); + SendNow(data, len); +} + +void Socket::UDPConnection::SendNow(const char * data, size_t len){ + if (len < 1){return;} + int r = sendto(sock, data, len, 0, (sockaddr*)destAddr, destAddr_size); + if (r > 0){ + up += r; + }else{ + DEBUG_MSG(DLVL_FAIL, "Could not send UDP data through %d: %s", sock, strerror(errno)); + } +} diff --git a/lib/socket.h b/lib/socket.h index 3b9d5db7..474262b7 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -118,5 +118,25 @@ namespace Socket { void drop(); ///< Close connection without shutdown. int getSocket(); ///< Returns internal socket number. }; + + class UDPConnection{ + private: + int sock; ///< Internally saved socket number. + std::string remotehost;///< Stores remote host address + void * destAddr; + unsigned int destAddr_size; + unsigned int up; + unsigned int down; + public: + UDPConnection(const UDPConnection & o); ///< Copy constructor + UDPConnection(bool nonblock = false); ///< Create new UDP socket + ~UDPConnection(); + void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false). + void SetDestination(std::string hostname, uint32_t port); ///< Sets the hostname and port destination for this UDP socket. + void Close();///< Closes the local socket + void SendNow(const std::string & data); ///< Will not buffer anything but always send right away. Blocks. + void SendNow(const char * data); ///< Will not buffer anything but always send right away. Blocks. + void SendNow(const char * data, size_t len); ///< Will not buffer anything but always send right away. Blocks. + }; }