1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
ULib/include/ulib/utility/socket_ext.h
stefanocasazza 224f4cc5b4 sync+fix
2018-09-07 16:39:24 +02:00

230 lines
7.6 KiB
C++

// ============================================================================
//
// = LIBRARY
// ULib - c++ library
//
// = FILENAME
// socket_ext.h
//
// = AUTHOR
// Stefano Casazza
//
// ============================================================================
#ifndef ULIB_SOCKET_EXT_H
#define ULIB_SOCKET_EXT_H 1
#include <ulib/string.h>
#include <ulib/net/socket.h>
typedef void (*vPFsu)(UString&,uint32_t);
class URPC;
class UHTTP;
class UHTTP2;
class UWebSocket;
class UMimeHeader;
class USmtpClient;
class UPop3Client;
class UClient_Base;
class UServer_Base;
class UStreamPlugIn;
class URPCClient_Base;
class UHttpClient_Base;
class UClientImage_Base;
class U_EXPORT USocketExt {
public:
// SERVICES
static UString getNodeName()
{
U_TRACE_NO_PARAM(0, "USocketExt::getNodeName()")
U_INTERNAL_ASSERT_MAJOR(u_hostname_len, 0)
UString result(u_hostname, u_hostname_len);
U_INTERNAL_ASSERT(result.isNullTerminated())
U_RETURN_STRING(result);
}
static void setRemoteInfo(USocket* sk, UString& logbuf)
{
U_TRACE(0, "USocketExt::setRemoteInfo(%p,%V)", sk, logbuf.rep)
UString x(100U);
x.snprintf(U_CONSTANT_TO_PARAM("%2d '%s:%u'"), sk->iSockDesc, sk->cRemoteAddress.pcStrAddress, sk->iRemotePort);
(void) logbuf.insert(0, x);
}
static bool getARPCache(UString& cache, UVector<UString>& vec);
static UString getNetworkDevice(const char* exclude = "eth0");
static UString getIPAddress(int fd, const char* device = "eth0");
static UString getMacAddress(int fd, const char* device = "eth0");
static UString getMacAddress(USocket* s, const char* device = "eth0");
static UString getNetworkAddress(int fd, const char* device = "eth0");
static UString getMacAddress( const char* ip, uint32_t ip_len);
static UString getNetworkInterfaceName(const char* ip, uint32_t ip_len);
static UString getGatewayAddress(const char* network, uint32_t network_len);
static UString getMacAddress( const UString& ip) { return getMacAddress( U_STRING_TO_PARAM(ip)); }
static UString getNetworkInterfaceName(const UString& ip) { return getNetworkInterfaceName(U_STRING_TO_PARAM(ip)); }
static UString getGatewayAddress(const UString& network) { return getGatewayAddress(U_STRING_TO_PARAM(network)); }
// Send a command to a server and wait for a response (single line)
static int vsyncCommand(USocket* sk, const char* format, uint32_t fmt_size, va_list argp)
{
U_TRACE(0, "USocketExt::vsyncCommand(%p,%.*S,%u)", sk, fmt_size, format, fmt_size)
U_INTERNAL_ASSERT_EQUALS(u_buffer_len, 0)
return vsyncCommand(sk, u_buffer, U_BUFFER_SIZE, format, fmt_size, argp);
}
static int vsyncCommand(USocket* sk, char* buffer, uint32_t buffer_size, const char* format, uint32_t fmt_size, va_list argp);
// response from server (single line)
static int readLineReply(USocket* sk)
{
U_TRACE(0, "USocketExt::readLineReply(%p)", sk)
U_INTERNAL_ASSERT_EQUALS(u_buffer_len, 0)
return readLineReply(sk, u_buffer, U_BUFFER_SIZE);
}
static int readLineReply(USocket* sk, char* buffer, uint32_t buffer_size);
static void readLineReply(USocket* sk, UString& buffer)
{
U_TRACE(0, "USocketExt::readLineReply(%p,%p)", sk, &buffer)
U_ASSERT(buffer.uniq())
buffer.rep->_length = readLineReply(sk, buffer.data(), buffer.capacity());
}
// Send a command to a server and wait for a response (multi line)
static int vsyncCommandML(USocket* sk, const char* format, uint32_t fmt_size, va_list argp)
{
U_TRACE(0, "USocketExt::vsyncCommandML(%p,%.*S,%u)", sk, fmt_size, format, fmt_size)
U_INTERNAL_ASSERT_EQUALS(u_buffer_len, 0)
return vsyncCommandML(sk, u_buffer, U_BUFFER_SIZE, format, fmt_size, argp);
}
static int vsyncCommandML(USocket* sk, char* buffer, uint32_t buffer_size, const char* format, uint32_t fmt_size, va_list argp);
// response from server (multi line)
static int readMultilineReply(USocket* sk)
{
U_TRACE(0, "USocketExt::readMultilineReply(%p)", sk)
U_INTERNAL_ASSERT_EQUALS(u_buffer_len, 0)
return readMultilineReply(sk, u_buffer, U_BUFFER_SIZE);
}
static int readMultilineReply(USocket* sk, char* buffer, uint32_t buffer_size);
// Send a command to a server and wait for a response (check for token line)
static int vsyncCommandToken(USocket* sk, UString& buffer, const char* format, uint32_t fmt_size, va_list argp);
#ifdef USE_C_ARES
static char* endResolv()
{
U_TRACE_NO_PARAM(0, "USocketExt::endResolv()")
U_INTERNAL_ASSERT_POINTER(resolv_channel)
return (resolv_status == 0 ? resolv_hostname : U_NULLPTR);
}
static void waitResolv();
static void startResolv(const char* name, int family = AF_INET); // AF_INET6
#endif
private:
#ifdef USE_C_ARES
static int resolv_status;
static char resolv_hostname[INET6_ADDRSTRLEN];
static void* resolv_channel;
static void callbackResolv(void* arg, int status, int timeouts, struct hostent* host) U_NO_EXPORT;
#endif
static inline bool parseCommandResponse(char* buffer, int r, int response) U_NO_EXPORT;
/**
* Read data from socket
*
* @param timeoutMS specified the timeout value, in milliseconds. A negative value indicates no timeout, i.e. an infinite wait
* @param time_limit specified the maximum execution time, in seconds. If set to zero, no time limit is imposed
*/
static bool read(USocket* sk, UString& buffer, uint32_t count = U_SINGLE_READ, int timeoutMS = -1, uint32_t time_limit = 0); // read while not received almost count data
// read while received data
static void readEOF(USocket* sk, UString& buffer)
{
U_TRACE(0, "USocketExt::readEOF(%p,%p)", sk, &buffer)
while (USocketExt::read(sk, buffer, U_SINGLE_READ, -1, 0)) {}
}
// read while not received token, return position of token in buffer
static uint32_t readWhileNotToken(USocket* sk, UString& buffer, const char* token, uint32_t token_len, int timeoutMS = -1);
// write data
static uint32_t write(USocket* sk, const UString& buffer, int timeoutMS) { return write(sk, U_STRING_TO_PARAM(buffer), timeoutMS); }
static uint32_t write(USocket* sk, const char* ptr, uint32_t count, int timeoutMS);
// write data from multiple buffers
static uint32_t iov_resize(struct iovec* liov, const struct iovec* iov, int iovcnt, uint32_t byte_written);
static uint32_t writev(USocket* sk, struct iovec* iov, int iovcnt, uint32_t count, int timeoutMS);
/**
* sendfile() copies data between one file descriptor and another. Either or both of these file descriptors may refer to a socket.
* OUT_FD should be a descriptor opened for writing. POFFSET is a pointer to a variable holding the input file pointer position from
* which sendfile() will start reading data. When sendfile() returns, this variable will be set to the offset of the byte following
* the last byte that was read. COUNT is the number of bytes to copy between file descriptors. Because this copying is done within
* the kernel, sendfile() does not need to spend time transferring data to and from user space
*/
static uint32_t sendfile(USocket* sk, int in_fd, off_t* poffset, off_t count, int timeoutMS);
friend class URPC;
friend class UHTTP;
friend class UHTTP2;
friend class UWebSocket;
friend class UMimeHeader;
friend class USmtpClient;
friend class UPop3Client;
friend class UServer_Base;
friend class UClient_Base;
friend class UStreamPlugIn;
friend class URPCClient_Base;
friend class UHttpClient_Base;
friend class UClientImage_Base;
};
#endif