mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-22 03:40:04 +02:00
removed genericSocket
This commit is contained in:
parent
0de0d82a1a
commit
3dbd6a33f7
@ -10,7 +10,6 @@
|
|||||||
#include "Fifo.h"
|
#include "Fifo.h"
|
||||||
#include "GeneralData.h"
|
#include "GeneralData.h"
|
||||||
#include "container_utils.h" // For sls::make_unique<>
|
#include "container_utils.h" // For sls::make_unique<>
|
||||||
#include "genericSocket.h"
|
|
||||||
#include "sls_detector_exceptions.h"
|
#include "sls_detector_exceptions.h"
|
||||||
#include "UdpRxSocket.h"
|
#include "UdpRxSocket.h"
|
||||||
|
|
||||||
@ -164,10 +163,10 @@ void Listener::CreateUDPSockets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShutDownUDPSocket();
|
ShutDownUDPSocket();
|
||||||
|
// InterfaceNameToIp(eth).str().c_str()
|
||||||
try{
|
try{
|
||||||
udpSocket = sls::make_unique<SELECTED_SOCKET>(*udpPortNumber, genericSocket::UDP,
|
udpSocket = sls::make_unique<sls::UdpRxSocket>(*udpPortNumber,
|
||||||
generalData->packetSize, ((*eth).length() ? (*eth).c_str() : nullptr), generalData->headerPacketSize,
|
generalData->packetSize, ((*eth).length() ? sls::InterfaceNameToIp(*eth).str().c_str() : nullptr),
|
||||||
*udpSocketBufferSize);
|
*udpSocketBufferSize);
|
||||||
LOG(logINFO) << index << ": UDP port opened at port " << *udpPortNumber;
|
LOG(logINFO) << index << ": UDP port opened at port " << *udpPortNumber;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@ -216,8 +215,8 @@ void Listener::CreateDummySocketForUDPSocketBufferSize(int64_t s) {
|
|||||||
|
|
||||||
//create dummy socket
|
//create dummy socket
|
||||||
try {
|
try {
|
||||||
SELECTED_SOCKET g(*udpPortNumber, genericSocket::UDP,
|
sls::UdpRxSocket g(*udpPortNumber,
|
||||||
generalData->packetSize, ((*eth).length() ? (*eth).c_str() : nullptr), generalData->headerPacketSize,
|
generalData->packetSize, ((*eth).length() ? sls::InterfaceNameToIp(*eth).str().c_str() : nullptr),
|
||||||
*udpSocketBufferSize);
|
*udpSocketBufferSize);
|
||||||
|
|
||||||
// doubled due to kernel bookkeeping (could also be less due to permissions)
|
// doubled due to kernel bookkeeping (could also be less due to permissions)
|
||||||
|
@ -15,15 +15,11 @@
|
|||||||
|
|
||||||
class GeneralData;
|
class GeneralData;
|
||||||
class Fifo;
|
class Fifo;
|
||||||
class genericSocket;
|
|
||||||
namespace sls{
|
namespace sls{
|
||||||
class UdpRxSocket;
|
class UdpRxSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #define SELECTED_SOCKET genericSocket
|
|
||||||
#define SELECTED_SOCKET sls::UdpRxSocket
|
|
||||||
|
|
||||||
class Listener : private virtual slsDetectorDefs, public ThreadObject {
|
class Listener : private virtual slsDetectorDefs, public ThreadObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -194,7 +190,7 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
|
|||||||
std::atomic<runStatus>* status;
|
std::atomic<runStatus>* status;
|
||||||
|
|
||||||
/** UDP Socket - Detector to Receiver */
|
/** UDP Socket - Detector to Receiver */
|
||||||
std::unique_ptr<SELECTED_SOCKET> udpSocket;
|
std::unique_ptr<sls::UdpRxSocket> udpSocket;
|
||||||
|
|
||||||
/** UDP Port Number */
|
/** UDP Port Number */
|
||||||
uint32_t* udpPortNumber;
|
uint32_t* udpPortNumber;
|
||||||
|
@ -9,7 +9,7 @@ this might be deprecated in the future
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "genericSocket.h"
|
// #include "genericSocket.h"
|
||||||
#include "network_utils.h"
|
#include "network_utils.h"
|
||||||
#include "sls_detector_exceptions.h"
|
#include "sls_detector_exceptions.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -75,14 +75,14 @@ class UdpRxSocket {
|
|||||||
buff = new char[packet_size];
|
buff = new char[packet_size];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delegating constructor to allow drop in replacement for old socket class
|
// // Delegating constructor to allow drop in replacement for old socket class
|
||||||
// This one might be removed in the future
|
// // This one might be removed in the future
|
||||||
UdpRxSocket(unsigned short int const port_number,
|
// UdpRxSocket(unsigned short int const port_number,
|
||||||
genericSocket::communicationProtocol p,
|
// genericSocket::communicationProtocol p,
|
||||||
int ps = DEFAULT_PACKET_SIZE, const char *eth = NULL,
|
// int ps = DEFAULT_PACKET_SIZE, const char *eth = NULL,
|
||||||
int hsize = 0, uint64_t buf_size = SOCKET_BUFFER_SIZE)
|
// int hsize = 0, uint64_t buf_size = SOCKET_BUFFER_SIZE)
|
||||||
: UdpRxSocket(port_number, ps, InterfaceNameToIp(eth).str().c_str(),
|
// : UdpRxSocket(port_number, ps, InterfaceNameToIp(eth).str().c_str(),
|
||||||
buf_size) {}
|
// buf_size) {}
|
||||||
|
|
||||||
~UdpRxSocket() {
|
~UdpRxSocket() {
|
||||||
delete[] buff;
|
delete[] buff;
|
||||||
|
@ -1,822 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @libdoc genericSocket provides some functions to open/close sockets both TCP and UDP
|
|
||||||
*
|
|
||||||
* @short some functions to open/close sockets both TCP and UDP
|
|
||||||
* @author Anna Bergamaschi
|
|
||||||
* @version 0.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ansi.h"
|
|
||||||
#include "sls_detector_exceptions.h"
|
|
||||||
|
|
||||||
#ifdef __CINT__
|
|
||||||
//class sockaddr_in;
|
|
||||||
class socklen_t;
|
|
||||||
class uint32_t;
|
|
||||||
class uint32_t_ss;
|
|
||||||
// CINT view of types:
|
|
||||||
class sockaddr_in;
|
|
||||||
// {
|
|
||||||
// unsigned short int sa_family;
|
|
||||||
// unsigned char sa_data[14];
|
|
||||||
// };
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <ifaddrs.h>
|
|
||||||
#include <sys/prctl.h> // capabilities
|
|
||||||
#include <linux/capability.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h> /******exit */
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <math.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
#define DEFAULT_PACKET_SIZE 1286
|
|
||||||
#define SOCKET_BUFFER_SIZE (100*1024*1024) //100 MB
|
|
||||||
#define DEFAULT_BACKLOG 5
|
|
||||||
|
|
||||||
using sls::SocketError;
|
|
||||||
|
|
||||||
class genericSocket{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/** Communication protocol */
|
|
||||||
enum communicationProtocol{
|
|
||||||
TCP, /**< TCP/IP */
|
|
||||||
UDP /**< UDP */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The constructor for a client
|
|
||||||
* throws an exception if the hostname/ip could not be converted to an internet address
|
|
||||||
* @param host_ip_or_name hostname or ip of the client
|
|
||||||
* @param port_number port number to connect to
|
|
||||||
* @param p TCP or UDP
|
|
||||||
* @param ps a single packet size
|
|
||||||
*/
|
|
||||||
genericSocket(const char* const host_ip_or_name,
|
|
||||||
unsigned short int const port_number,
|
|
||||||
communicationProtocol p, int ps = DEFAULT_PACKET_SIZE) :
|
|
||||||
portno(port_number),
|
|
||||||
protocol(p),
|
|
||||||
is_a_server(0),
|
|
||||||
packet_size(ps),
|
|
||||||
nsending(0),
|
|
||||||
nsent(0),
|
|
||||||
total_sent(0),// sender (client): where to? ip
|
|
||||||
header_packet_size(0),
|
|
||||||
actual_udp_socket_buffer_size(0) {
|
|
||||||
memset(&serverAddress, 0, sizeof(serverAddress));
|
|
||||||
memset(&clientAddress, 0, sizeof(clientAddress));
|
|
||||||
memset(lastClientIP,0,INET_ADDRSTRLEN);
|
|
||||||
memset(thisClientIP,0,INET_ADDRSTRLEN);
|
|
||||||
memset(dummyClientIP,0,INET_ADDRSTRLEN);
|
|
||||||
differentClients = 0;
|
|
||||||
|
|
||||||
struct addrinfo *result;
|
|
||||||
if (ConvertHostnameToInternetAddress(host_ip_or_name, &result)) {
|
|
||||||
sockfd.fd = -1;
|
|
||||||
throw SocketError("Could convert hostname to address");
|
|
||||||
}
|
|
||||||
|
|
||||||
sockfd.fd = 0;
|
|
||||||
serverAddress.sin_family = result->ai_family;
|
|
||||||
memcpy((char *) &serverAddress.sin_addr.s_addr,
|
|
||||||
&((struct sockaddr_in *) result->ai_addr)->sin_addr, sizeof(in_addr_t));
|
|
||||||
freeaddrinfo(result);
|
|
||||||
serverAddress.sin_port = htons(port_number);
|
|
||||||
clientAddress_length=sizeof(clientAddress);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The constructor for a server
|
|
||||||
* throws an exception if socket could not be created, closes descriptor before throwing
|
|
||||||
* @param port_number port number to connect to
|
|
||||||
* @param p TCP or UDP
|
|
||||||
* @param ps a single packet size
|
|
||||||
* @param eth interface name or IP address to listen to (if NULL, listen to all interfaces)
|
|
||||||
*/
|
|
||||||
genericSocket(unsigned short int const port_number, communicationProtocol p,
|
|
||||||
int ps = DEFAULT_PACKET_SIZE, const char *eth=NULL, int hsize=0,
|
|
||||||
uint64_t buf_size=SOCKET_BUFFER_SIZE):
|
|
||||||
portno(port_number),
|
|
||||||
protocol(p),
|
|
||||||
is_a_server(1),
|
|
||||||
packet_size(ps),
|
|
||||||
nsending(0),
|
|
||||||
nsent(0),
|
|
||||||
total_sent(0),
|
|
||||||
header_packet_size(hsize),
|
|
||||||
actual_udp_socket_buffer_size(0) {
|
|
||||||
|
|
||||||
|
|
||||||
memset(&serverAddress, 0, sizeof(serverAddress));
|
|
||||||
memset(&clientAddress, 0, sizeof(clientAddress));
|
|
||||||
memset(lastClientIP,0,INET_ADDRSTRLEN);
|
|
||||||
memset(thisClientIP,0,INET_ADDRSTRLEN);
|
|
||||||
memset(dummyClientIP,0,INET_ADDRSTRLEN);
|
|
||||||
differentClients = 0;
|
|
||||||
|
|
||||||
// same port
|
|
||||||
if(serverAddress.sin_port == htons(port_number)){
|
|
||||||
sockfd.fd = -10;
|
|
||||||
throw SocketError("Cannot create socket on same port");
|
|
||||||
}
|
|
||||||
|
|
||||||
char ip[20];
|
|
||||||
|
|
||||||
strcpy(ip,"0.0.0.0");
|
|
||||||
clientAddress_length=sizeof(clientAddress);
|
|
||||||
if (eth) {
|
|
||||||
strcpy(ip,nameToIp(std::string(eth)).c_str());
|
|
||||||
if (std::string(ip)==std::string("0.0.0.0"))
|
|
||||||
strcpy(ip,eth);
|
|
||||||
}
|
|
||||||
|
|
||||||
sockfd.fd = socket(AF_INET, getProtocol(),0); //tcp
|
|
||||||
|
|
||||||
if (sockfd.fd < 0) {
|
|
||||||
LOG(logERROR) << "Can not create socket";
|
|
||||||
sockfd.fd =-1;
|
|
||||||
throw SocketError("Can not create socket");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set some fields in the serverAddress structure.
|
|
||||||
serverAddress.sin_family = AF_INET;
|
|
||||||
serverAddress.sin_port = htons(port_number);
|
|
||||||
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
|
|
||||||
|
|
||||||
if (std::string(ip)!=std::string("0.0.0.0")) {
|
|
||||||
if (inet_pton(AF_INET, ip, &(serverAddress.sin_addr)));
|
|
||||||
else
|
|
||||||
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// reuse port
|
|
||||||
{
|
|
||||||
int val=1;
|
|
||||||
if (setsockopt(sockfd.fd,SOL_SOCKET,SO_REUSEADDR,
|
|
||||||
&val,sizeof(int)) == -1) {
|
|
||||||
LOG(logERROR) << "setsockopt REUSEADDR failed";
|
|
||||||
sockfd.fd =-1;
|
|
||||||
throw SocketError("setsockopt REUSEADDR failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//increase socket buffer size if its udp
|
|
||||||
if (p == UDP) {
|
|
||||||
uint64_t desired_size = buf_size;
|
|
||||||
uint64_t real_size = desired_size * 2; // kernel doubles this value for bookkeeping overhead
|
|
||||||
uint64_t ret_size = 0;
|
|
||||||
socklen_t optlen = sizeof(uint64_t);
|
|
||||||
|
|
||||||
// confirm if sufficient
|
|
||||||
if (getsockopt(sockfd.fd, SOL_SOCKET, SO_RCVBUF, &ret_size, &optlen) == -1) {
|
|
||||||
LOG(logWARNING) << "[Port " << port_number << "] "
|
|
||||||
"Could not get rx socket receive buffer size";
|
|
||||||
} else if (ret_size >= real_size) {
|
|
||||||
actual_udp_socket_buffer_size = ret_size;
|
|
||||||
LOG(logINFO) << "[Port " << port_number << "] "
|
|
||||||
"UDP rx socket real buffer size is sufficient (" << ret_size << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
// not sufficient, enhance size
|
|
||||||
else {
|
|
||||||
LOG(logINFO) << "[Port " << port_number << "] UDP rx socket real buffer size to be modified from " << ret_size << " to " << real_size;
|
|
||||||
// set buffer size (could not set)
|
|
||||||
if (setsockopt(sockfd.fd, SOL_SOCKET, SO_RCVBUF,
|
|
||||||
&desired_size, optlen) == -1) {
|
|
||||||
LOG(logWARNING) << "[Port " << port_number << "] "
|
|
||||||
"Could not set rx socket buffer size to "
|
|
||||||
<< desired_size << ". (No Root Privileges?)";
|
|
||||||
}
|
|
||||||
// confirm size
|
|
||||||
else if (getsockopt(sockfd.fd, SOL_SOCKET, SO_RCVBUF,
|
|
||||||
&ret_size, &optlen) == -1) {
|
|
||||||
LOG(logWARNING) << "[Port " << port_number << "] "
|
|
||||||
"Could not get rx socket buffer size";
|
|
||||||
}
|
|
||||||
else if (ret_size >= real_size) {
|
|
||||||
actual_udp_socket_buffer_size = ret_size;
|
|
||||||
LOG(logINFO) << "[Port " << port_number << "] "
|
|
||||||
"UDP rx socket buffer size modified to " << ret_size;
|
|
||||||
}
|
|
||||||
// buffer size too large
|
|
||||||
else {
|
|
||||||
actual_udp_socket_buffer_size = ret_size;
|
|
||||||
// force a value larger than system limit
|
|
||||||
// (if run in a privileged context (capability CAP_NET_ADMIN set))
|
|
||||||
int ret = setsockopt(sockfd.fd, SOL_SOCKET, SO_RCVBUFFORCE,
|
|
||||||
&desired_size, optlen);
|
|
||||||
getsockopt(sockfd.fd, SOL_SOCKET, SO_RCVBUF,
|
|
||||||
&ret_size, &optlen);
|
|
||||||
if (ret == -1) {
|
|
||||||
LOG(logWARNING) << "[Port " << port_number << "] "
|
|
||||||
"Could not force rx socket buffer size to "
|
|
||||||
<< desired_size << ".\n Real size: " << ret_size <<
|
|
||||||
". (No Root Privileges?)\n"
|
|
||||||
" To remove this warning: set rx_udpsocksize from client to <= " <<
|
|
||||||
(ret_size/2) << " (Real size:" << ret_size << ").";
|
|
||||||
} else {
|
|
||||||
LOG(logINFO) << "[Port " << port_number << "] "
|
|
||||||
"UDP rx socket buffer size (force) modified to " << ret_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(bind(sockfd.fd,(struct sockaddr *) &serverAddress,sizeof(serverAddress))<0){
|
|
||||||
LOG(logERROR) << "Can not bind socket. Please check if another process is running.";
|
|
||||||
sockfd.fd =-1;
|
|
||||||
throw SocketError("Can not bind socket. Please check if another process is running.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (getProtocol()==SOCK_STREAM)
|
|
||||||
listen(sockfd.fd, DEFAULT_BACKLOG);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The destructor: disconnects and close the socket
|
|
||||||
*/
|
|
||||||
~genericSocket() {
|
|
||||||
//mySocketDescriptor destructor also gets called
|
|
||||||
serverAddress.sin_port=-1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns actual udp socket buffer size/2.
|
|
||||||
* Halving is because of kernel book keeping
|
|
||||||
* @returns actual udp socket buffer size/2
|
|
||||||
*/
|
|
||||||
uint64_t getActualUDPSocketBufferSize(){return actual_udp_socket_buffer_size;};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get protocol TCP or UDP
|
|
||||||
- * @returns TCP or UDP
|
|
||||||
*/
|
|
||||||
int getCommunicationProtocol(){return protocol;};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get port number
|
|
||||||
* @retrns port number
|
|
||||||
*/
|
|
||||||
uint16_t getPortNumber(){return ntohs(serverAddress.sin_port);}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get TCP Server File Descriptor
|
|
||||||
* @returns TCP Server file descriptor
|
|
||||||
*/
|
|
||||||
int getFileDes(){return sockfd.newfd;};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get socket descriptor
|
|
||||||
* @returns socket descriptor
|
|
||||||
*/
|
|
||||||
int getsocketDescriptor(){return sockfd.fd;};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get total bytes sent/received
|
|
||||||
* Makes sense only for udp socket as there is only receive data
|
|
||||||
*/
|
|
||||||
int getCurrentTotalReceived(){return total_sent;};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get type of protocol based on protocol
|
|
||||||
* @param p TCP or UDP
|
|
||||||
* @returns SOCK_STREAM/SOCK_DGRAM or -1
|
|
||||||
*/
|
|
||||||
int getProtocol(communicationProtocol p) {
|
|
||||||
switch (p) {
|
|
||||||
case TCP:
|
|
||||||
return SOCK_STREAM;
|
|
||||||
break;
|
|
||||||
case UDP:
|
|
||||||
return SOCK_DGRAM;
|
|
||||||
default:
|
|
||||||
LOG(logERROR) << "unknown protocol: " << p;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current protocol type
|
|
||||||
* @returns SOCK_STREAM/SOCK_DGRAM or -1
|
|
||||||
*/
|
|
||||||
int getProtocol() {return getProtocol(protocol);};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close TCP Server socket descriptor
|
|
||||||
*/
|
|
||||||
void CloseServerTCPSocketDescriptor() {
|
|
||||||
if (protocol == TCP && is_a_server) {
|
|
||||||
if (sockfd.fd >= 0) {
|
|
||||||
close(sockfd.fd);
|
|
||||||
sockfd.fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect
|
|
||||||
*/
|
|
||||||
void Disconnect(){
|
|
||||||
if (protocol == TCP && is_a_server) {
|
|
||||||
if (sockfd.newfd >= 0) {
|
|
||||||
close(sockfd.newfd);
|
|
||||||
sockfd.newfd = -1;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sockfd.fd >= 0) {
|
|
||||||
close(sockfd.fd);
|
|
||||||
sockfd.fd = -1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Establishes connection
|
|
||||||
* @returns 1 if error
|
|
||||||
*/
|
|
||||||
int Connect(){
|
|
||||||
|
|
||||||
if(sockfd.newfd>0) return sockfd.newfd;
|
|
||||||
if (protocol==UDP) return -1;
|
|
||||||
|
|
||||||
if(is_a_server && protocol==TCP){ //server tcp; the server will wait for the clients connection
|
|
||||||
if (sockfd.fd>0) {
|
|
||||||
if ((sockfd.newfd = accept(sockfd.fd,(struct sockaddr *) &clientAddress, &clientAddress_length)) < 0) {
|
|
||||||
LOG(logERROR) << "with server accept, connection refused";
|
|
||||||
switch(errno) {
|
|
||||||
case EWOULDBLOCK:
|
|
||||||
LOG(logERROR) << "ewouldblock eagain";
|
|
||||||
break;
|
|
||||||
case EBADF:
|
|
||||||
LOG(logERROR) << "ebadf";
|
|
||||||
break;
|
|
||||||
case ECONNABORTED:
|
|
||||||
LOG(logERROR) << "econnaborted";
|
|
||||||
break;
|
|
||||||
case EFAULT:
|
|
||||||
LOG(logERROR) << "efault";
|
|
||||||
break;
|
|
||||||
case EINTR:
|
|
||||||
LOG(logERROR) << "eintr";
|
|
||||||
break;
|
|
||||||
case EINVAL:
|
|
||||||
LOG(logERROR) << "einval";
|
|
||||||
break;
|
|
||||||
case EMFILE:
|
|
||||||
LOG(logERROR) << "emfile";
|
|
||||||
break;
|
|
||||||
case ENFILE:
|
|
||||||
LOG(logERROR) << "enfile";
|
|
||||||
break;
|
|
||||||
case ENOTSOCK:
|
|
||||||
LOG(logERROR) << "enotsock";
|
|
||||||
break;
|
|
||||||
case EOPNOTSUPP:
|
|
||||||
LOG(logERROR) << "eOPNOTSUPP";
|
|
||||||
break;
|
|
||||||
case ENOBUFS:
|
|
||||||
LOG(logERROR) << "ENOBUFS";
|
|
||||||
break;
|
|
||||||
case ENOMEM:
|
|
||||||
LOG(logERROR) << "ENOMEM";
|
|
||||||
break;
|
|
||||||
case ENOSR:
|
|
||||||
LOG(logERROR) << "ENOSR";
|
|
||||||
break;
|
|
||||||
case EPROTO:
|
|
||||||
LOG(logERROR) << "EPROTO";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG(logERROR) << "unknown error";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
inet_ntop(AF_INET, &(clientAddress.sin_addr), dummyClientIP, INET_ADDRSTRLEN);
|
|
||||||
LOG(logDEBUG1) << "client connected " << sockfd.newfd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG(logDEBUG1) << "fd " << sockfd.newfd;
|
|
||||||
return sockfd.newfd;
|
|
||||||
} else {
|
|
||||||
if (sockfd.fd<=0)
|
|
||||||
sockfd.fd = socket(AF_INET, getProtocol(),0);
|
|
||||||
// SetTimeOut(10);
|
|
||||||
if (sockfd.fd < 0){
|
|
||||||
LOG(logERROR) << "Can not create socket";
|
|
||||||
} else {
|
|
||||||
if(connect(sockfd.fd,(struct sockaddr *) &serverAddress,sizeof(serverAddress))<0){
|
|
||||||
LOG(logERROR) << "Can not connect to socket";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sockfd.fd;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exit server
|
|
||||||
*/
|
|
||||||
void exitServer(){
|
|
||||||
Disconnect();
|
|
||||||
CloseServerTCPSocketDescriptor();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shut down socket
|
|
||||||
*/
|
|
||||||
void ShutDownSocket(){
|
|
||||||
shutdown(sockfd.fd, SHUT_RDWR);
|
|
||||||
Disconnect();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the socket timeout ts is in seconds
|
|
||||||
* @param ts time in seconds
|
|
||||||
* @returns 0 for success, else -1
|
|
||||||
*/
|
|
||||||
int SetTimeOut(int ts){
|
|
||||||
if (ts<=0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
struct timeval tout;
|
|
||||||
tout.tv_sec = 0;
|
|
||||||
tout.tv_usec = 0;
|
|
||||||
if(::setsockopt(sockfd.fd, SOL_SOCKET, SO_RCVTIMEO,
|
|
||||||
&tout, sizeof(struct timeval)) <0) {
|
|
||||||
LOG(logERROR) << "setsockopt SO_RCVTIMEO " << 0;
|
|
||||||
}
|
|
||||||
tout.tv_sec = ts;
|
|
||||||
tout.tv_usec = 0;
|
|
||||||
if(::setsockopt(sockfd.fd, SOL_SOCKET, SO_SNDTIMEO,
|
|
||||||
&tout, sizeof(struct timeval)) < 0) {
|
|
||||||
LOG(logERROR) << "setsockopt SO_SNDTIMEO " << ts;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set packet size
|
|
||||||
* @param i packet size
|
|
||||||
* @returns current packet size
|
|
||||||
*/
|
|
||||||
int setPacketSize(int i=-1) { if (i>=0) packet_size=i;return packet_size;};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert IP to hostname
|
|
||||||
* @param ip IP
|
|
||||||
* @returns hostname
|
|
||||||
*/
|
|
||||||
static std::string ipToName(std::string ip) {
|
|
||||||
struct ifaddrs *addrs, *iap;
|
|
||||||
struct sockaddr_in *sa;
|
|
||||||
|
|
||||||
char buf[32];
|
|
||||||
const int buf_len = sizeof(buf);
|
|
||||||
memset(buf,0,buf_len);
|
|
||||||
strcpy(buf,"none");
|
|
||||||
|
|
||||||
getifaddrs(&addrs);
|
|
||||||
for (iap = addrs; iap != NULL; iap = iap->ifa_next) {
|
|
||||||
if (iap->ifa_addr && (iap->ifa_flags & IFF_UP) && iap->ifa_addr->sa_family == AF_INET) {
|
|
||||||
sa = (struct sockaddr_in *)(iap->ifa_addr);
|
|
||||||
inet_ntop(iap->ifa_addr->sa_family, (void *)&(sa->sin_addr), buf, buf_len);
|
|
||||||
if (ip==std::string(buf)) {
|
|
||||||
strcpy(buf,iap->ifa_name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
freeifaddrs(addrs);
|
|
||||||
return std::string(buf);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert interface to mac address
|
|
||||||
* @param inf interface
|
|
||||||
* @returns mac address
|
|
||||||
*/
|
|
||||||
static std::string nameToMac(std::string inf) {
|
|
||||||
struct ifreq ifr;
|
|
||||||
int sock, j, k;
|
|
||||||
char mac[32];
|
|
||||||
const int mac_len = sizeof(mac);
|
|
||||||
memset(mac,0,mac_len);
|
|
||||||
|
|
||||||
sock=getSock(inf,&ifr);
|
|
||||||
|
|
||||||
if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) {
|
|
||||||
perror("ioctl(SIOCGIFHWADDR) ");
|
|
||||||
return std::string("00:00:00:00:00:00");
|
|
||||||
}
|
|
||||||
for (j=0, k=0; j<6; j++) {
|
|
||||||
k+=snprintf(mac+k, mac_len-k-1, j ? ":%02X" : "%02X",
|
|
||||||
(int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]);
|
|
||||||
}
|
|
||||||
mac[mac_len-1]='\0';
|
|
||||||
|
|
||||||
if(sock!=1){
|
|
||||||
close(sock);
|
|
||||||
}
|
|
||||||
return std::string(mac);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert hostname to ip
|
|
||||||
* @param inf hostname
|
|
||||||
* @returns IP
|
|
||||||
*/
|
|
||||||
static std::string nameToIp(std::string inf){
|
|
||||||
struct ifreq ifr;
|
|
||||||
int sock;
|
|
||||||
char *p, addr[32];
|
|
||||||
const int addr_len = sizeof(addr);
|
|
||||||
memset(addr,0,addr_len);
|
|
||||||
|
|
||||||
sock=getSock(inf,&ifr);
|
|
||||||
|
|
||||||
if (-1==ioctl(sock, SIOCGIFADDR, &ifr)) {
|
|
||||||
perror("ioctl(SIOCGIFADDR) ");
|
|
||||||
return std::string("0.0.0.0");
|
|
||||||
}
|
|
||||||
p=inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr);
|
|
||||||
strncpy(addr,p,addr_len-1);
|
|
||||||
addr[addr_len-1]='\0';
|
|
||||||
|
|
||||||
if(sock!=1){
|
|
||||||
close(sock);
|
|
||||||
}
|
|
||||||
return std::string(addr);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get socket
|
|
||||||
* @param inf hostname
|
|
||||||
* @param ifr interface request structure
|
|
||||||
* @returns sock
|
|
||||||
*/
|
|
||||||
static int getSock(std::string inf, struct ifreq *ifr) {
|
|
||||||
|
|
||||||
int sock;
|
|
||||||
sock=socket(PF_INET, SOCK_STREAM, 0);
|
|
||||||
if (-1==sock) {
|
|
||||||
perror("socket() ");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
strncpy(ifr->ifr_name,inf.c_str(),sizeof(ifr->ifr_name)-1);
|
|
||||||
ifr->ifr_name[sizeof(ifr->ifr_name)-1]='\0';
|
|
||||||
|
|
||||||
return sock;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert Hostname to Internet address info structure
|
|
||||||
* One must use freeaddrinfo(res) after using it
|
|
||||||
* @param hostname hostname
|
|
||||||
* @param res address of pointer to address info structure
|
|
||||||
* @return 1 for fail, 0 for success
|
|
||||||
*/
|
|
||||||
// Do not make this static (for multi threading environment)
|
|
||||||
int ConvertHostnameToInternetAddress (const char* const hostname, struct addrinfo **res) {
|
|
||||||
// criteria in selecting socket address structures returned by res
|
|
||||||
struct addrinfo hints;
|
|
||||||
memset (&hints, 0, sizeof (hints));
|
|
||||||
hints.ai_family = AF_INET;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
// get host info into res
|
|
||||||
int errcode = getaddrinfo (hostname, NULL, &hints, res);
|
|
||||||
if (errcode != 0) {
|
|
||||||
LOG(logERROR) << "Could not convert hostname (" << hostname << ") to internet address (zmq):" <<
|
|
||||||
gai_strerror(errcode);
|
|
||||||
} else {
|
|
||||||
if (*res == NULL) {
|
|
||||||
LOG(logERROR) << "Could not converthostname (" << hostname << ") to internet address (zmq):"
|
|
||||||
"gettaddrinfo returned null";
|
|
||||||
} else{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG(logERROR) << "Could not convert hostname to internet address";
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert Internet Address structure pointer to ip string (char*)
|
|
||||||
* Clears the internet address structure as well
|
|
||||||
* @param res pointer to internet address structure
|
|
||||||
* @param ip pointer to char array to store result in
|
|
||||||
* @param ipsize size available in ip buffer
|
|
||||||
* @return 1 for fail, 0 for success
|
|
||||||
*/
|
|
||||||
// Do not make this static (for multi threading environment)
|
|
||||||
int ConvertInternetAddresstoIpString (struct addrinfo *res, char* ip, const int ipsize) {
|
|
||||||
if (inet_ntop (res->ai_family, &((struct sockaddr_in *) res->ai_addr)->sin_addr, ip, ipsize) != NULL) {
|
|
||||||
freeaddrinfo(res);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
LOG(logERROR) << "Could not convert internet address to ip string";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive data only
|
|
||||||
* @param buf data
|
|
||||||
* @param length size of data expecting, 0 for a single packet
|
|
||||||
* @returns size of data received
|
|
||||||
*/
|
|
||||||
int ReceiveDataOnly(void* buf,int length=0){
|
|
||||||
|
|
||||||
if (buf==NULL) return -1;
|
|
||||||
|
|
||||||
total_sent=0;
|
|
||||||
int tcpfd = sockfd.fd;
|
|
||||||
|
|
||||||
switch(protocol) {
|
|
||||||
case TCP:
|
|
||||||
tcpfd = (is_a_server ? sockfd.newfd : sockfd.fd);
|
|
||||||
if (tcpfd<0) return -1;
|
|
||||||
while(length>0){
|
|
||||||
nsending = (length>packet_size) ? packet_size:length;
|
|
||||||
nsent = read(tcpfd,(char*)buf+total_sent,nsending);
|
|
||||||
if(!nsent) {
|
|
||||||
if(!total_sent) {
|
|
||||||
return -1; //to handle it
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
length-=nsent;
|
|
||||||
total_sent+=nsent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (total_sent>0)
|
|
||||||
strcpy(thisClientIP,dummyClientIP);
|
|
||||||
|
|
||||||
if (strcmp(lastClientIP,thisClientIP))
|
|
||||||
differentClients=1;
|
|
||||||
else
|
|
||||||
differentClients=0;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case UDP:
|
|
||||||
if (sockfd.fd<0) return -1;
|
|
||||||
//if length given, listens to length, else listens for packetsize till length is reached
|
|
||||||
if(length){
|
|
||||||
while(length>0){
|
|
||||||
nsending = (length>packet_size) ? packet_size:length;
|
|
||||||
nsent = recvfrom(sockfd.fd,(char*)buf+total_sent,nsending, 0, (struct sockaddr *) &clientAddress, &clientAddress_length);
|
|
||||||
if(nsent == header_packet_size)
|
|
||||||
continue;
|
|
||||||
if(nsent != nsending){
|
|
||||||
if(nsent && (nsent != -1)) {
|
|
||||||
LOG(logERROR) << "Incomplete Packet size " << nsent;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
length-=nsent;
|
|
||||||
total_sent+=nsent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//listens to only 1 packet
|
|
||||||
else{
|
|
||||||
//normal
|
|
||||||
nsending=packet_size;
|
|
||||||
while(1){
|
|
||||||
nsent = recvfrom(sockfd.fd,(char*)buf+total_sent,nsending, 0, (struct sockaddr *) &clientAddress, &clientAddress_length);
|
|
||||||
//break out of loop only if read one packets size or read didnt work (cuz of shutdown)
|
|
||||||
if(nsent<=0 || nsent == packet_size)
|
|
||||||
break;
|
|
||||||
//incomplete packets or header packets ignored and read buffer again
|
|
||||||
if(nsent != packet_size && nsent != header_packet_size) {
|
|
||||||
LOG(logERROR) << portno << ": Incomplete Packet size " << nsent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//nsent = 1040;
|
|
||||||
if(nsent > 0)total_sent+=nsent;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
LOG(logDEBUG1) << "sent " << total_sent << " Bytes";
|
|
||||||
return total_sent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send data only
|
|
||||||
* @param buf data
|
|
||||||
* @param length size of data expecting
|
|
||||||
* @returns size of data sent
|
|
||||||
*/
|
|
||||||
int SendDataOnly(void *buf, int length) {
|
|
||||||
LOG(logDEBUG1) << "want to send " << length << " Bytes";
|
|
||||||
if (buf==NULL) return -1;
|
|
||||||
|
|
||||||
total_sent=0;
|
|
||||||
|
|
||||||
int tcpfd = sockfd.fd;
|
|
||||||
|
|
||||||
switch(protocol) {
|
|
||||||
case TCP:
|
|
||||||
tcpfd = (is_a_server ? sockfd.newfd : sockfd.fd);
|
|
||||||
if (tcpfd<0) return -1;
|
|
||||||
while(length>0){
|
|
||||||
nsending = (length>packet_size) ? packet_size:length;
|
|
||||||
nsent = write(tcpfd,(char*)buf+total_sent,nsending);
|
|
||||||
if(is_a_server && nsent < 0) {
|
|
||||||
LOG(logERROR) << "Could not write to socket. Possible client socket crash";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!nsent) break;
|
|
||||||
length-=nsent;
|
|
||||||
total_sent+=nsent;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UDP:
|
|
||||||
if (sockfd.fd<0) return -1;
|
|
||||||
while(length>0){
|
|
||||||
nsending = (length>packet_size) ? packet_size:length;
|
|
||||||
nsent = sendto(sockfd.fd,(char*)buf+total_sent,nsending, 0, (struct sockaddr *) &clientAddress, clientAddress_length);
|
|
||||||
if(!nsent) break;
|
|
||||||
length-=nsent;
|
|
||||||
total_sent+=nsent;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
LOG(logDEBUG1) << "sent "<< total_sent << " Bytes";
|
|
||||||
return total_sent;
|
|
||||||
}
|
|
||||||
|
|
||||||
char lastClientIP[INET_ADDRSTRLEN];
|
|
||||||
char thisClientIP[INET_ADDRSTRLEN];
|
|
||||||
int differentClients;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Class to close socket descriptors automatically
|
|
||||||
* upon encountering exceptions in the genericSocket constructor
|
|
||||||
*/
|
|
||||||
class mySocketDescriptors {
|
|
||||||
public:
|
|
||||||
|
|
||||||
/** Constructor */
|
|
||||||
mySocketDescriptors():fd(-1), newfd(-1){};
|
|
||||||
/** Destructor */
|
|
||||||
~mySocketDescriptors() {
|
|
||||||
// close TCP server new socket descriptor from accept
|
|
||||||
if (newfd >= 0) {
|
|
||||||
close(newfd);
|
|
||||||
}
|
|
||||||
// close socket descriptor
|
|
||||||
if (fd >= 0) {
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/** socket descriptor */
|
|
||||||
int fd;
|
|
||||||
/** new socket descriptor in TCP server from accept */
|
|
||||||
int newfd;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int portno;
|
|
||||||
communicationProtocol protocol;
|
|
||||||
int is_a_server;
|
|
||||||
mySocketDescriptors sockfd;
|
|
||||||
int packet_size;
|
|
||||||
struct sockaddr_in clientAddress, serverAddress;
|
|
||||||
socklen_t clientAddress_length;
|
|
||||||
char dummyClientIP[INET_ADDRSTRLEN];
|
|
||||||
|
|
||||||
private:
|
|
||||||
int nsending;
|
|
||||||
int nsent;
|
|
||||||
int total_sent;
|
|
||||||
int header_packet_size;
|
|
||||||
uint64_t actual_udp_socket_buffer_size;
|
|
||||||
};
|
|
Loading…
x
Reference in New Issue
Block a user