Finished implementing external hostname resolution.

parent bb72875b
......@@ -15,10 +15,13 @@
namespace Arc {
#define READ_TIMEOUT (60000)
#define WRITE_TIMEOUT (60000)
static bool sread(Run& r,void* buf,size_t size) {
while(size) {
int l = r.ReadStdout(-1,(char*)buf,size);
if(l < 0) return false;
int l = r.ReadStdout(READ_TIMEOUT,(char*)buf,size);
if(l <= 0) return false;
size-=l;
buf = (void*)(((char*)buf)+l);
};
......@@ -27,8 +30,8 @@ namespace Arc {
static bool swrite(Run& r,const void* buf,size_t size) {
while(size) {
int l = r.WriteStdin(-1,(const char*)buf,size);
if(l < 0) return false;
int l = r.WriteStdin(WRITE_TIMEOUT,(const char*)buf,size);
if(l <= 0) return false;
size-=l;
buf = (void*)(((char*)buf)+l);
};
......@@ -162,28 +165,34 @@ namespace Arc {
return false;
}
int HostnameResolver::hr_resolve(std::string const& hostname, std::list<SockAddr> addrs) {
int HostnameResolver::hr_resolve(std::string const& node, std::string const& service, bool local, std::list<SockAddr>& addrs) {
NORETRYLOOP {
STARTHEADER(CMD_RESOLVE,hostname.length());
if(!swrite_string(*hostname_resolver_,hostname)) ABORTALL;
int command = local?CMD_RESOLVE_TCP_LOCAL:CMD_RESOLVE_TCP_REMOTE;
STARTHEADER(command,sizeof(int)+node.length()+sizeof(int)+service.length());
if(!swrite_string(*hostname_resolver_,node)) ABORTALL;
if(!swrite_string(*hostname_resolver_,service)) ABORTALL;
int res = 0;
header_t header;
if(!sread(*hostname_resolver_,&header,sizeof(header))) ABORTALL;
if((header.cmd != CMD_RESOLVE) || (header.size < (sizeof(res)+sizeof(errno_)))) ABORTALL; \
if((header.cmd != command) || (header.size < (sizeof(res)+sizeof(errno_)))) ABORTALL; \
if(!sread(*hostname_resolver_,&res,sizeof(res))) ABORTALL;
if(!sread(*hostname_resolver_,&errno_,sizeof(errno_))) ABORTALL;
header.size -= sizeof(res)+sizeof(errno_);
while(header.size > 0) {
while(hostname_resolver_ && (header.size > 0)) {
SockAddr addr;
if(header.size < sizeof(addr.family)) ABORTALL;
if(!sread(*hostname_resolver_,&addr.family,sizeof(addr.family))) ABORTALL;
header.size-=sizeof(addr.family);
if(header.size < sizeof(addr.length)) ABORTALL;
if(!sread(*hostname_resolver_,&addr.length,sizeof(addr.length))) ABORTALL;
header.size-=sizeof(addr.length);
if(header.size < addr.length) ABORTALL;
if((addr.addr = (sockaddr*)::malloc(addr.length)) == NULL) ABORTALL;
if(!sread(*hostname_resolver_,addr.addr,addr.length)) ABORTALL;
header.size-=addr.length;
addrs.push_back(addr);
};
if(!hostname_resolver_) continue;
return res;
}
errno_ = -1;
......
......@@ -60,7 +60,7 @@ namespace Arc {
/// Check if communication with proxy works
bool ping(void);
/// Performs resolution of provided host name.
int hr_resolve(std::string const& hostname, std::list<SockAddr> addrs);
int hr_resolve(std::string const& node, std::string const& service, bool local, std::list<SockAddr>& addrs);
/// Get errno of last operation. Every operation resets errno.
int geterrno() { return errno_; };
/// Returns true if this instance is in useful condition
......
......@@ -12,7 +12,7 @@ endif
lib_LTLIBRARIES = libarccommon.la
pgmpkglibdir = $(pkglibdir)
pgmpkglib_PROGRAMS = arc-file-access
pgmpkglib_PROGRAMS = arc-file-access arc-hostname-resolver
libarccommon_ladir = $(pkgincludedir)
libarccommon_la_HEADERS = ArcVersion.h ArcConfig.h ArcLocation.h \
......@@ -49,3 +49,7 @@ libarccommon_la_LDFLAGS = -version-info 3:0:0
arc_file_access_SOURCES = file_access.cpp file_access.h
arc_file_access_CXXFLAGS = -I$(top_srcdir)/include $(AM_CXXFLAGS)
arc_file_access_LDADD =
arc_hostname_resolver_SOURCES = hostname_resolver.cpp hostname_resolver.h
arc_hostname_resolver_CXXFLAGS = -I$(top_srcdir)/include $(AM_CXXFLAGS)
arc_hostname_resolver_LDADD =
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <cstring>
// NOTE: On Solaris errno is not working properly if cerrno is included first
#include <cerrno>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#ifndef WIN32
#include <poll.h>
#endif
#include <dirent.h>
#include <fcntl.h>
#include <netdb.h>
#include "hostname_resolver.h"
typedef struct {
unsigned int size;
unsigned int cmd;
} header_t;
// How long it is allowed for controlling side to react
#define COMMUNICATION_TIMEOUT (10)
static bool sread_start = true;
static bool sread(int s,void* buf,size_t size) {
while(size) {
#ifndef WIN32
struct pollfd p[1];
p[0].fd = s;
p[0].events = POLLIN;
p[0].revents = 0;
int err = poll(p,1,sread_start?-1:(COMMUNICATION_TIMEOUT*1000));
if(err == 0) return false;
if((err == -1) && (errno != EINTR)) return false;
if(err == 1) {
#else
{
#endif
ssize_t l = ::read(s,buf,size);
if(l <= 0) return false;
size-=l;
buf = (void*)(((char*)buf)+l);
sread_start = false;
};
};
return true;
}
static bool swrite(int s,const void* buf,size_t size) {
while(size) {
#ifndef WIN32
struct pollfd p[1];
p[0].fd = s;
p[0].events = POLLOUT;
p[0].revents = 0;
int err = poll(p,1,COMMUNICATION_TIMEOUT*1000);
if(err == 0) return false;
if((err == -1) && (errno != EINTR)) return false;
if(err == 1) {
#else
{
#endif
ssize_t l = ::write(s,buf,size);
if(l < 0) return false;
size-=l;
buf = (void*)(((char*)buf)+l);
};
};
return true;
}
static bool sread_string(int s,std::string& str,unsigned int& maxsize) {
unsigned int ssize;
if(sizeof(ssize) > maxsize) return false;
if(!sread(s,&ssize,sizeof(ssize))) return false;
maxsize -= sizeof(ssize);
if(ssize > maxsize) return false;
str.assign(ssize,' ');
// Not nice but saves memory copying
if(!sread(s,(void*)(str.c_str()),ssize)) return false;
maxsize -= ssize;
return true;
}
static bool sread_buf(int s,void* buf,unsigned int& bufsize,unsigned int& maxsize) {
char dummy[1024];
unsigned int size;
if(sizeof(size) > maxsize) return false;
if(!sread(s,&size,sizeof(size))) return false;
maxsize -= sizeof(size);
if(size > maxsize) return false;
if(size <= bufsize) {
if(!sread(s,buf,size)) return false;
bufsize = size;
maxsize -= size;
} else {
if(!sread(s,buf,bufsize)) return false;
maxsize -= bufsize;
// skip rest
size -= bufsize;
while(size > sizeof(dummy)) {
if(!sread(s,dummy,sizeof(dummy))) return false;
size -= sizeof(dummy);
maxsize -= sizeof(dummy);
};
if(!sread(s,dummy,size)) return false;
maxsize -= size;
};
return true;
}
static bool swrite_result(int s,int cmd,int res,int err) {
header_t header;
header.cmd = cmd;
header.size = sizeof(res) + sizeof(err);
if(!swrite(s,&header,sizeof(header))) return -1;
if(!swrite(s,&res,sizeof(res))) return -1;
if(!swrite(s,&err,sizeof(err))) return -1;
return true;
}
static bool swrite_result(int s,int cmd,int res,int err,const void* add,int addsize) {
header_t header;
header.cmd = cmd;
header.size = sizeof(res) + sizeof(err) + addsize;
if(!swrite(s,&header,sizeof(header))) return -1;
if(!swrite(s,&res,sizeof(res))) return -1;
if(!swrite(s,&err,sizeof(err))) return -1;
if(!swrite(s,add,addsize)) return -1;
return true;
}
static bool swrite_result(int s,int cmd,int res,int err,const void* add1,int addsize1,const void* add2,int addsize2) {
header_t header;
header.cmd = cmd;
header.size = sizeof(res) + sizeof(err) + addsize1 + addsize2;
if(!swrite(s,&header,sizeof(header))) return -1;
if(!swrite(s,&res,sizeof(res))) return -1;
if(!swrite(s,&err,sizeof(err))) return -1;
if(!swrite(s,add1,addsize1)) return -1;
if(!swrite(s,add2,addsize2)) return -1;
return true;
}
static bool swrite_result(int s,int cmd,int res,int err,const std::string& str) {
unsigned int l = str.length();
header_t header;
header.cmd = cmd;
header.size = sizeof(res) + sizeof(err) + sizeof(l) + str.length();
if(!swrite(s,&header,sizeof(header))) return -1;
if(!swrite(s,&res,sizeof(res))) return -1;
if(!swrite(s,&err,sizeof(err))) return -1;
if(!swrite(s,&l,sizeof(l))) return -1;
if(!swrite(s,str.c_str(),l)) return -1;
return true;
}
int main(int argc,char* argv[]) {
if(argc != 3) return -1;
char* e;
e = argv[1];
int sin = strtoul(argv[1],&e,10);
if((e == argv[1]) || (*e != 0)) return -1;
e = argv[2];
int sout = strtoul(argv[2],&e,10);
if((e == argv[2]) || (*e != 0)) return -1;
while(true) {
header_t header;
sread_start = true;
if(!sread(sin,&header,sizeof(header))) break;
switch(header.cmd) {
case CMD_PING: {
if(header.size != 0) return -1;
if(!swrite(sout,&header,sizeof(header))) return -1;
}; break;
case CMD_RESOLVE_TCP_LOCAL:
case CMD_RESOLVE_TCP_REMOTE: {
std::string node;
std::string service;
if(!sread_string(sin,node,header.size)) return -1;
if(!sread_string(sin,service,header.size)) return -1;
if(header.size) return -1;
errno = 0;
struct addrinfo hint;
::memset(&hint,0,sizeof(hint));
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = IPPROTO_TCP;
hint.ai_family = AF_UNSPEC;
if (header.cmd == CMD_RESOLVE_TCP_LOCAL) hint.ai_flags = AI_PASSIVE;
struct addrinfo* addrs = NULL;
std::string data;
int res = getaddrinfo(node.c_str(),service.c_str(),&hint,&addrs);
if(res == 0) {
for (struct addrinfo* addr = addrs; addr != NULL; addr = addr->ai_next) {
int family = addr->ai_family;
socklen_t length = addr->ai_addrlen;
struct sockaddr* saddr = addr->ai_addr;
data.append((char const*)&family,sizeof(family));
data.append((char const*)&length,sizeof(length));
data.append((char const*)saddr,length);
};
freeaddrinfo(addrs);
errno = 0;
};
if(!swrite_result(sout,header.cmd,res,errno,data.c_str(),data.length())) return -1;
}; break;
default: return -1;
};
};
return 0;
}
#define CMD_PING (0)
// -
#define CMD_RESOLVE (1)
#define CMD_RESOLVE_TCP_LOCAL (1)
#define CMD_RESOLVE_TCP_REMOTE (2)
// string hostname
// -
// result
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment