Improved isAddress() function for sockets with masking support, added several socket convenience functions.
This commit is contained in:
parent
0afbaaaa41
commit
fe805f40a8
2 changed files with 146 additions and 70 deletions
207
lib/socket.cpp
207
lib/socket.cpp
|
@ -33,6 +33,107 @@ static const char* addrFam(int f){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string getIPv6BinAddr(const struct sockaddr_in6 & remoteaddr){
|
||||||
|
char tmpBuffer[17] = "\000\000\000\000\000\000\000\000\000\000\377\377\000\000\000\000";
|
||||||
|
switch (remoteaddr.sin6_family){
|
||||||
|
case AF_INET:
|
||||||
|
memcpy(tmpBuffer + 12, &(reinterpret_cast<const sockaddr_in*>(&remoteaddr)->sin_addr.s_addr), 4);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
memcpy(tmpBuffer, &(remoteaddr.sin6_addr.s6_addr), 16);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return std::string(tmpBuffer, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function that matches two binary-format IPv6 addresses with prefix bits of prefix.
|
||||||
|
bool Socket::matchIPv6Addr(const std::string &A, const std::string &B, uint8_t prefix){
|
||||||
|
if (!prefix){prefix = 128;}
|
||||||
|
if (Util::Config::printDebugLevel >= DLVL_MEDIUM){
|
||||||
|
std::string Astr, Bstr;
|
||||||
|
Socket::hostBytesToStr(A.data(), 16, Astr);
|
||||||
|
Socket::hostBytesToStr(B.data(), 16, Bstr);
|
||||||
|
MEDIUM_MSG("Matching: %s to %s with %u prefix", Astr.c_str(), Bstr.c_str(), prefix);
|
||||||
|
}
|
||||||
|
if (memcmp(A.data(), B.data(), prefix / 8)){return false;}
|
||||||
|
if ((prefix % 8) && ((A.data()[prefix / 8] & (0xFF << (8 - (prefix % 8)))) !=
|
||||||
|
(B.data()[prefix / 8] & (0xFF << (8 - (prefix % 8)))))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempts to match the given address with optional subnet to the given binary-form IPv6 address.
|
||||||
|
/// Returns true if match could be made, false otherwise.
|
||||||
|
bool Socket::isBinAddress(const std::string &binAddr, std::string addr){
|
||||||
|
//Check if we need to do prefix matching
|
||||||
|
uint8_t prefixLen = 0;
|
||||||
|
if (addr.find('/') != std::string::npos){
|
||||||
|
prefixLen = atoi(addr.c_str() + addr.find('/') + 1);
|
||||||
|
addr.erase(addr.find('/'), std::string::npos);
|
||||||
|
}
|
||||||
|
//Loops over all IPs for the given address and matches them in IPv6 form.
|
||||||
|
struct addrinfo *result, *rp, hints;
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
|
||||||
|
hints.ai_protocol = 0;
|
||||||
|
hints.ai_canonname = NULL;
|
||||||
|
hints.ai_addr = NULL;
|
||||||
|
hints.ai_next = NULL;
|
||||||
|
int s = getaddrinfo(addr.c_str(), 0, &hints, &result);
|
||||||
|
if (s != 0){return false;}
|
||||||
|
|
||||||
|
for (rp = result; rp != NULL; rp = rp->ai_next){
|
||||||
|
std::string tBinAddr = getIPv6BinAddr(*((sockaddr_in6 *)rp->ai_addr));
|
||||||
|
if (rp->ai_family == AF_INET){
|
||||||
|
if (matchIPv6Addr(tBinAddr, binAddr, prefixLen ? prefixLen + 96 : 0)){return true;}
|
||||||
|
}else{
|
||||||
|
if (matchIPv6Addr(tBinAddr, binAddr, prefixLen)){return true;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts the given address with optional subnet to binary IPv6 form.
|
||||||
|
/// Returns 16 bytes of address, followed by 1 byte of subnet bits, zero or more times.
|
||||||
|
std::string Socket::getBinForms(std::string addr){
|
||||||
|
//Check if we need to do prefix matching
|
||||||
|
uint8_t prefixLen = 128;
|
||||||
|
if (addr.find('/') != std::string::npos){
|
||||||
|
prefixLen = atoi(addr.c_str() + addr.find('/') + 1);
|
||||||
|
addr.erase(addr.find('/'), std::string::npos);
|
||||||
|
}
|
||||||
|
//Loops over all IPs for the given address and converts to IPv6 binary form.
|
||||||
|
struct addrinfo *result, *rp, hints;
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
|
||||||
|
hints.ai_protocol = 0;
|
||||||
|
hints.ai_canonname = NULL;
|
||||||
|
hints.ai_addr = NULL;
|
||||||
|
hints.ai_next = NULL;
|
||||||
|
int s = getaddrinfo(addr.c_str(), 0, &hints, &result);
|
||||||
|
if (s != 0){return "";}
|
||||||
|
std::string ret;
|
||||||
|
for (rp = result; rp != NULL; rp = rp->ai_next){
|
||||||
|
ret += getIPv6BinAddr(*((sockaddr_in6 *)rp->ai_addr));
|
||||||
|
if (rp->ai_family == AF_INET){
|
||||||
|
ret += (char)(prefixLen<=32 ? prefixLen + 96 : prefixLen);
|
||||||
|
}else{
|
||||||
|
ret += (char)prefixLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks bytes (length len) containing a binary-encoded IPv4 or IPv6 IP address, and writes it in human-readable notation to target.
|
/// Checks bytes (length len) containing a binary-encoded IPv4 or IPv6 IP address, and writes it in human-readable notation to target.
|
||||||
/// Writes "unknown" if it cannot decode to a sensible value.
|
/// Writes "unknown" if it cannot decode to a sensible value.
|
||||||
void Socket::hostBytesToStr(const char *bytes, size_t len, std::string &target){
|
void Socket::hostBytesToStr(const char *bytes, size_t len, std::string &target){
|
||||||
|
@ -624,40 +725,31 @@ std::string Socket::Connection::getHost() const{
|
||||||
return remotehost;
|
return remotehost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets hostname for connection, if available.
|
/// Gets binary IPv6 address for connection, if available.
|
||||||
/// Guaranteed to be either empty or 16 bytes long.
|
/// Guaranteed to be either empty or 16 bytes long.
|
||||||
std::string Socket::Connection::getBinHost(){
|
std::string Socket::Connection::getBinHost(){
|
||||||
if (remotehost.size()){
|
return getIPv6BinAddr(remoteaddr);
|
||||||
struct addrinfo *result, *rp, hints;
|
|
||||||
memset(&hints, 0, sizeof(struct addrinfo));
|
|
||||||
hints.ai_family = AF_UNSPEC;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
hints.ai_flags = AI_ADDRCONFIG;
|
|
||||||
hints.ai_protocol = 0;
|
|
||||||
hints.ai_canonname = NULL;
|
|
||||||
hints.ai_addr = NULL;
|
|
||||||
hints.ai_next = NULL;
|
|
||||||
int s = getaddrinfo(remotehost.c_str(), 0, &hints, &result);
|
|
||||||
if (s != 0){
|
|
||||||
DEBUG_MSG(DLVL_FAIL, "Could not resolve '%s'! Error: %s", remotehost.c_str(), gai_strerror(s));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
char tmpBuffer[17] = "\000\000\000\000\000\000\000\000\000\000\377\377\000\000\000\000";
|
|
||||||
for (rp = result; rp != NULL; rp = rp->ai_next){
|
|
||||||
if (rp->ai_family == AF_INET){memcpy(tmpBuffer + 12, &((sockaddr_in *)rp->ai_addr)->sin_addr.s_addr, 4);}
|
|
||||||
if (rp->ai_family == AF_INET6){memcpy(tmpBuffer, ((sockaddr_in6 *)rp->ai_addr)->sin6_addr.s6_addr, 16);}
|
|
||||||
}
|
|
||||||
freeaddrinfo(result);
|
|
||||||
return std::string(tmpBuffer, 16);
|
|
||||||
}else{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets hostname for connection manually.
|
/// Sets hostname for connection manually.
|
||||||
/// Overwrites the detected host, thus possibily making it incorrect.
|
/// Overwrites the detected host, thus possibily making it incorrect.
|
||||||
void Socket::Connection::setHost(std::string host){
|
void Socket::Connection::setHost(std::string host){
|
||||||
remotehost = host;
|
remotehost = host;
|
||||||
|
struct addrinfo *result, *rp, hints;
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
|
||||||
|
hints.ai_protocol = 0;
|
||||||
|
hints.ai_canonname = NULL;
|
||||||
|
hints.ai_addr = NULL;
|
||||||
|
hints.ai_next = NULL;
|
||||||
|
int s = getaddrinfo(host.c_str(), 0, &hints, &result);
|
||||||
|
if (s != 0){return;}
|
||||||
|
if (result){
|
||||||
|
remoteaddr = *((sockaddr_in6 *)result->ai_addr);
|
||||||
|
}
|
||||||
|
freeaddrinfo(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if these sockets are the same socket.
|
/// Returns true if these sockets are the same socket.
|
||||||
|
@ -680,35 +772,10 @@ Socket::Connection::operator bool() const{
|
||||||
|
|
||||||
/// Returns true if the given address can be matched with the remote host.
|
/// Returns true if the given address can be matched with the remote host.
|
||||||
/// Can no longer return true after any socket error have occurred.
|
/// Can no longer return true after any socket error have occurred.
|
||||||
bool Socket::Connection::isAddress(std::string addr){
|
bool Socket::Connection::isAddress(const std::string &addr){
|
||||||
struct addrinfo *result, *rp, hints;
|
//Retrieve current socket binary address
|
||||||
memset(&hints, 0, sizeof(struct addrinfo));
|
std::string myBinAddr = getBinHost();
|
||||||
hints.ai_family = AF_UNSPEC;
|
return isBinAddress(myBinAddr, addr);
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
|
|
||||||
hints.ai_protocol = 0;
|
|
||||||
hints.ai_canonname = NULL;
|
|
||||||
hints.ai_addr = NULL;
|
|
||||||
hints.ai_next = NULL;
|
|
||||||
int s = getaddrinfo(addr.c_str(), 0, &hints, &result);
|
|
||||||
if (s != 0){return false;}
|
|
||||||
|
|
||||||
char newaddr[INET6_ADDRSTRLEN];
|
|
||||||
newaddr[0] = 0;
|
|
||||||
for (rp = result; rp != NULL; rp = rp->ai_next){
|
|
||||||
if (rp->ai_family == AF_INET && inet_ntop(rp->ai_family, &(((sockaddr_in *)rp->ai_addr)->sin_addr), newaddr, INET6_ADDRSTRLEN)){
|
|
||||||
INSANE_MSG("Comparing '%s' to '%s'", remotehost.c_str(), newaddr);
|
|
||||||
if (remotehost == newaddr){return true;}
|
|
||||||
INSANE_MSG("Comparing '%s' to '::ffff:%s'", remotehost.c_str(), newaddr);
|
|
||||||
if (remotehost == std::string("::ffff:") + newaddr){return true;}
|
|
||||||
}
|
|
||||||
if (rp->ai_family == AF_INET6 && inet_ntop(rp->ai_family, &(((sockaddr_in6 *)rp->ai_addr)->sin6_addr), newaddr, INET6_ADDRSTRLEN)){
|
|
||||||
INSANE_MSG("Comparing '%s' to '%s'", remotehost.c_str(), newaddr);
|
|
||||||
if (remotehost == newaddr){return true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
freeaddrinfo(result);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Socket::Connection::isLocal(){
|
bool Socket::Connection::isLocal(){
|
||||||
|
@ -719,23 +786,23 @@ bool Socket::Connection::isLocal(){
|
||||||
|
|
||||||
getifaddrs(&ifAddrStruct);
|
getifaddrs(&ifAddrStruct);
|
||||||
|
|
||||||
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
|
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next){
|
||||||
if (!ifa->ifa_addr) {
|
if (!ifa->ifa_addr){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
|
if (ifa->ifa_addr->sa_family == AF_INET){// check it is IP4
|
||||||
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
|
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
|
||||||
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
|
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
|
||||||
INSANE_MSG("Comparing '%s' to '%s'", remotehost.c_str(), addressBuffer);
|
INSANE_MSG("Comparing '%s' to '%s'", remotehost.c_str(), addressBuffer);
|
||||||
if (remotehost == addressBuffer){return true;}
|
if (remotehost == addressBuffer){return true;}
|
||||||
INSANE_MSG("Comparing '%s' to '::ffff:%s'", remotehost.c_str(), addressBuffer);
|
INSANE_MSG("Comparing '%s' to '::ffff:%s'", remotehost.c_str(), addressBuffer);
|
||||||
if (remotehost == std::string("::ffff:") + addressBuffer){return true;}
|
if (remotehost == std::string("::ffff:") + addressBuffer){return true;}
|
||||||
} else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6
|
}else if (ifa->ifa_addr->sa_family == AF_INET6){// check it is IP6
|
||||||
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
|
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
|
||||||
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
|
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
|
||||||
INSANE_MSG("Comparing '%s' to '%s'", remotehost.c_str(), addressBuffer);
|
INSANE_MSG("Comparing '%s' to '%s'", remotehost.c_str(), addressBuffer);
|
||||||
if (remotehost == addressBuffer){return true;}
|
if (remotehost == addressBuffer){return true;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
|
if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
|
||||||
return false;
|
return false;
|
||||||
|
@ -907,10 +974,10 @@ Socket::Server::Server(std::string address, bool nonblock){
|
||||||
/// \returns A Socket::Connection, which may or may not be connected, depending on settings and circumstances.
|
/// \returns A Socket::Connection, which may or may not be connected, depending on settings and circumstances.
|
||||||
Socket::Connection Socket::Server::accept(bool nonblock){
|
Socket::Connection Socket::Server::accept(bool nonblock){
|
||||||
if (sock < 0){return Socket::Connection(-1);}
|
if (sock < 0){return Socket::Connection(-1);}
|
||||||
struct sockaddr_in6 addrinfo;
|
struct sockaddr_in6 tmpaddr;
|
||||||
socklen_t len = sizeof(addrinfo);
|
socklen_t len = sizeof(tmpaddr);
|
||||||
static char addrconv[INET6_ADDRSTRLEN];
|
static char addrconv[INET6_ADDRSTRLEN];
|
||||||
int r = ::accept(sock, (sockaddr *)&addrinfo, &len);
|
int r = ::accept(sock, (sockaddr *)&tmpaddr, &len);
|
||||||
// set the socket to be nonblocking, if requested.
|
// set the socket to be nonblocking, if requested.
|
||||||
// we could do this through accept4 with a flag, but that call is non-standard...
|
// we could do this through accept4 with a flag, but that call is non-standard...
|
||||||
if ((r >= 0) && nonblock){
|
if ((r >= 0) && nonblock){
|
||||||
|
@ -919,21 +986,22 @@ Socket::Connection Socket::Server::accept(bool nonblock){
|
||||||
fcntl(r, F_SETFL, flags);
|
fcntl(r, F_SETFL, flags);
|
||||||
}
|
}
|
||||||
Socket::Connection tmp(r);
|
Socket::Connection tmp(r);
|
||||||
|
tmp.remoteaddr = tmpaddr;
|
||||||
if (r < 0){
|
if (r < 0){
|
||||||
if ((errno != EWOULDBLOCK) && (errno != EAGAIN) && (errno != EINTR)){
|
if ((errno != EWOULDBLOCK) && (errno != EAGAIN) && (errno != EINTR)){
|
||||||
DEBUG_MSG(DLVL_FAIL, "Error during accept - closing server socket %d.", sock);
|
DEBUG_MSG(DLVL_FAIL, "Error during accept - closing server socket %d.", sock);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if (addrinfo.sin6_family == AF_INET6){
|
if (tmpaddr.sin6_family == AF_INET6){
|
||||||
tmp.remotehost = inet_ntop(AF_INET6, &(addrinfo.sin6_addr), addrconv, INET6_ADDRSTRLEN);
|
tmp.remotehost = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
|
||||||
DEBUG_MSG(DLVL_HIGH, "IPv6 addr [%s]", tmp.remotehost.c_str());
|
DEBUG_MSG(DLVL_HIGH, "IPv6 addr [%s]", tmp.remotehost.c_str());
|
||||||
}
|
}
|
||||||
if (addrinfo.sin6_family == AF_INET){
|
if (tmpaddr.sin6_family == AF_INET){
|
||||||
tmp.remotehost = inet_ntop(AF_INET, &(((sockaddr_in *)&addrinfo)->sin_addr), addrconv, INET6_ADDRSTRLEN);
|
tmp.remotehost = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN);
|
||||||
DEBUG_MSG(DLVL_HIGH, "IPv4 addr [%s]", tmp.remotehost.c_str());
|
DEBUG_MSG(DLVL_HIGH, "IPv4 addr [%s]", tmp.remotehost.c_str());
|
||||||
}
|
}
|
||||||
if (addrinfo.sin6_family == AF_UNIX){
|
if (tmpaddr.sin6_family == AF_UNIX){
|
||||||
DEBUG_MSG(DLVL_HIGH, "Unix connection");
|
DEBUG_MSG(DLVL_HIGH, "Unix connection");
|
||||||
tmp.remotehost = "UNIX_SOCKET";
|
tmp.remotehost = "UNIX_SOCKET";
|
||||||
}
|
}
|
||||||
|
@ -1251,7 +1319,7 @@ uint16_t Socket::UDPConnection::bind(int port, std::string iface, const std::str
|
||||||
}
|
}
|
||||||
if (multicast){
|
if (multicast){
|
||||||
const int optval = 1;
|
const int optval = 1;
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0){
|
||||||
WARN_MSG("Could not set multicast UDP socket re-use!");
|
WARN_MSG("Could not set multicast UDP socket re-use!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1408,3 +1476,4 @@ bool Socket::UDPConnection::Receive(){
|
||||||
int Socket::UDPConnection::getSock(){
|
int Socket::UDPConnection::getSock(){
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,9 @@ namespace Buffer{
|
||||||
namespace Socket{
|
namespace Socket{
|
||||||
|
|
||||||
void hostBytesToStr(const char *bytes, size_t len, std::string &target);
|
void hostBytesToStr(const char *bytes, size_t len, std::string &target);
|
||||||
|
bool isBinAddress(const std::string &binAddr, std::string matchTo);
|
||||||
|
bool matchIPv6Addr(const std::string &A, const std::string &B, uint8_t prefix);
|
||||||
|
std::string getBinForms(std::string addr);
|
||||||
|
|
||||||
/// A buffer made out of std::string objects that can be efficiently read from and written to.
|
/// A buffer made out of std::string objects that can be efficiently read from and written to.
|
||||||
class Buffer{
|
class Buffer{
|
||||||
|
@ -49,12 +52,16 @@ namespace Socket{
|
||||||
};
|
};
|
||||||
// Buffer
|
// Buffer
|
||||||
|
|
||||||
|
class Server;
|
||||||
|
|
||||||
/// This class is for easy communicating through sockets, either TCP or Unix.
|
/// This class is for easy communicating through sockets, either TCP or Unix.
|
||||||
class Connection{
|
class Connection{
|
||||||
|
friend Server;
|
||||||
private:
|
private:
|
||||||
int sock; ///< Internally saved socket number.
|
int sock; ///< Internally saved socket number.
|
||||||
int pipes[2]; ///< Internally saved file descriptors for pipe socket simulation.
|
int pipes[2]; ///< Internally saved file descriptors for pipe socket simulation.
|
||||||
std::string remotehost; ///< Stores remote host address.
|
std::string remotehost; ///< Stores remote host address.
|
||||||
|
struct sockaddr_in6 remoteaddr;///< Stores remote host address.
|
||||||
uint64_t up;
|
uint64_t up;
|
||||||
uint64_t down;
|
uint64_t down;
|
||||||
long long int conntime;
|
long long int conntime;
|
||||||
|
@ -84,7 +91,7 @@ namespace Socket{
|
||||||
int getPureSocket(); ///< Returns non-piped internal socket number.
|
int getPureSocket(); ///< Returns non-piped internal socket number.
|
||||||
std::string getError(); ///< Returns a string describing the last error that occured.
|
std::string getError(); ///< Returns a string describing the last error that occured.
|
||||||
bool connected() const; ///< Returns the connected-state for this socket.
|
bool connected() const; ///< Returns the connected-state for this socket.
|
||||||
bool isAddress(std::string addr);
|
bool isAddress(const std::string &addr);
|
||||||
bool isLocal(); ///< Returns true if remote address is a local address.
|
bool isLocal(); ///< Returns true if remote address is a local address.
|
||||||
// buffered i/o methods
|
// buffered i/o methods
|
||||||
bool spool(); ///< Updates the downbufferinternal variables.
|
bool spool(); ///< Updates the downbufferinternal variables.
|
||||||
|
|
Loading…
Add table
Reference in a new issue