boodt::program_options works, dut there are

other todos like fix a little crash on disconnect
or do some error handling.
This commit is contained in:
Jan Losinshi 2008-08-22 13:30:32 +02:00
parent 12fbe224af
commit 28e4ceb2e1
3 changed files with 225 additions and 131 deletions

View File

@ -7,7 +7,12 @@
*/
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "socket.hxx"
#include <iostream>
namespace xerxes
{
@ -16,8 +21,10 @@ namespace xerxes
int domain)
: fd(socket(protocol, type, domain))
{
std::cerr << "new socket" << std::endl;
if(fd < 0)
{
perror("--");
throw std::runtime_error("could not create socket.");
}
}
@ -35,6 +42,60 @@ namespace xerxes
}
}
SocketOption::SocketOption(std::string new_file)
: type(UNIX), file(new_file)
{
}
SocketOption::SocketOption(std::string new_hostname, std::string new_port)
: type(TCP), hostname(new_hostname), port(new_port)
{
}
Socket*
SocketOption::gen_socket()
{
if(type == TCP)
{
return new Socket(PF_INET, SOCK_STREAM, 0);
}
else
{
return new Socket(AF_UNIX, SOCK_STREAM, 0);
}
}
void validate(boost::any& v,
const std::vector<std::string>& values,
SocketOption* target_type, int)
{
static boost::regex r("(tcp|unix):(([\\d\\w_-]|\\.|/)+)(:(\\d+))?");
using namespace boost::program_options;
using namespace std;
validators::check_first_occurrence(v);
const std::string& s = validators::get_single_string(values);
boost::smatch match;
if(regex_match(s, match, r))
{
if(match[1] == "tcp")
{
v = boost::any(SocketOption(match[2], match[5]));
}
else
{
v = boost::any(SocketOption(match[2]));
}
}
else
{
throw validation_error("invalid value");
}
}
MysqlData
makeData(int len)
{
@ -69,6 +130,37 @@ namespace xerxes
return ::connect(socket.fd, serv_addr, addrlen);
}
int
connect_inet(Socket& socket,
SocketOption& opt)
{
addrinfo hints;
addrinfo* res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
getaddrinfo(opt.hostname.c_str(), opt.port.c_str(), &hints, &res);
int ret = connect(socket, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
return ret;
}
int
connect_unix(Socket& socket,
SocketOption& opt)
{
struct sockaddr_un adr;
memset(&adr, 0, sizeof(adr));
adr.sun_family = AF_UNIX;
strncpy(adr.sun_path, opt.file.c_str(), sizeof(adr.sun_path));
return connect(socket, (struct sockaddr *) &adr, SUN_LEN(&adr));
}
int
recv(Socket& socket,
MysqlData& data,
@ -111,4 +203,41 @@ namespace xerxes
{
return ::bind(socket.fd, bind_address, addrlen);
}
int
bind_inet(Socket& socket,
SocketOption& opt)
{
addrinfo hints;
addrinfo* res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
getaddrinfo(opt.hostname.c_str(), opt.port.c_str(), &hints, &res);
int ret = bind(socket, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
return ret;
}
int
bind_unix(Socket& socket,
SocketOption& opt)
{
unlink(opt.file.c_str());
struct sockaddr_un adr;
memset(&adr, 0, sizeof(adr));
adr.sun_family = AF_UNIX;
strncpy(adr.sun_path, opt.file.c_str(), sizeof(adr.sun_path));
return bind(socket, (struct sockaddr *) &adr, SUN_LEN(&adr));
}
}

View File

@ -15,6 +15,9 @@
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/any.hpp>
#include <boost/regex.hpp>
#include <boost/program_options.hpp>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
@ -41,6 +44,31 @@ namespace xerxes
MysqlData
makeData(int len);
enum sock_opt_types
{
TCP,
UNIX
};
class SocketOption
{
public:
SocketOption(std::string new_file);
SocketOption(std::string new_hostname, std::string new_port);
Socket* gen_socket();
int type;
std::string file;
std::string hostname;
std::string port;
};
void validate(boost::any& v,
const std::vector<std::string>& values,
SocketOption* target_type, int);
boost::shared_ptr<Socket>
accept(Socket& socket,
sockaddr* address,
@ -54,6 +82,14 @@ namespace xerxes
sockaddr const* const serv_address,
socklen_t address_len);
int
connect_inet(Socket& socket,
SocketOption& opt);
int
connect_unix(Socket& socket,
SocketOption& opt);
int
recv(Socket& socket,
MysqlData& data,
@ -70,6 +106,13 @@ namespace xerxes
sockaddr const* const bind_address,
socklen_t addrlen);
int
bind_inet(Socket& socket,
SocketOption& opt);
int
bind_unix(Socket& socket,
SocketOption& opt);
class SocketErr{};
class ConResetErr: public SocketErr{};

View File

@ -6,6 +6,10 @@
* Maximilian Marx <mmarx@wh2.tu-dresden.de>
*/
/**
* TODO : Fix crash on disconnect
* TODO : Do some Error handling
*/
#include <iostream>
#include <sys/types.h>
@ -14,75 +18,8 @@
#include "socket.hxx"
#include "epoll.hxx"
#include <boost/utility.hpp>
#include <boost/any.hpp>
#include <boost/regex.hpp>
#include <boost/program_options.hpp>
#include <vector>
enum sock_opt_types{
TCP,
UNIX
};
class SocketOption {
public:
SocketOption(std::string new_file)
: type(UNIX), file(new_file)
{
}
SocketOption(std::string new_hostname, std::string new_port)
: type(TCP), hostname(new_hostname), port(new_port)
{
}
int type;
std::string file;
std::string hostname;
std::string port;
};
void validate(boost::any& v,
const std::vector<std::string>& values,
SocketOption* target_type, int)
{
//static boost::regex r("(tcp|unix):([\\d\\w_-/.]+)(:(\\d+))?");
static boost::regex r("(tcp|unix):(([\\d\\w_-]|\\.|/)+)(:(\\d+))?");
using namespace boost::program_options;
using namespace std;
// Make sure no previous assignment to 'a' was made.
validators::check_first_occurrence(v);
// Extract the first string from 'values'. If there is more than
// one string, it's an error, and exception will be thrown.
const std::string& s = validators::get_single_string(values);
// Do regex match and convert the interesting part to
// int.
boost::smatch match;
if(regex_match(s, match, r))
{
cout << "1: " << match[1] << endl; // Type
cout << "2: " << match[2] << endl; // File-/Hostname
cout << "5: " << match[5] << endl; // Port
if(match[1] == "tcp")
{
cout << "TCP" << endl;
v = boost::any(SocketOption(match[2], match[5]));
}
else
{
cout << "UNIX" << endl;
v = boost::any(SocketOption(match[2]));
}
}
else
{
throw validation_error("invalid value");
}
}
@ -110,48 +47,47 @@ po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
if (vm.count("help")) {
if (vm.count("help"))
{
cout << desc << "\n";
return 1;
}
if (vm.count("src")) {
if (vm.count("src"))
{
SocketOption sock = vm["src"].as<SocketOption>();
}
if (vm.count("dst"))
{
SocketOption sock = vm["dst"].as<SocketOption>();
if(sock.type == TCP)
{
cout << "TCP Source is " << sock.hostname << "," << sock.port << ".\n";
cout << "TCP Destination is " << sock.hostname << "," << sock.port << ".\n";
}
else
{
cout << "UNIX Source is " << sock.file << ".\n";
cout << "UNIX Destination is " << sock.file << ".\n";
}
} else {
cout << "Source was not set.\n";
}
else
{
cout << "Destination was not set.\n";
exit(0);
}
Socket lstn(PF_INET, SOCK_STREAM, 0);
addrinfo hints;
addrinfo* res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
getaddrinfo("127.0.0.1", "13337", &hints, &res);
bind(lstn, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
SocketOption src = vm["src"].as<SocketOption>();
Socket &lstn = *(src.gen_socket());
if(src.type == TCP)
{
cout << "TCP Source is " << src.hostname << "," << src.port << ".\n";
bind_inet(lstn, src);
}
else
{
cout << "UNIX Source is " << src.file << ".\n";
bind_unix(lstn, src);
}
int ret = listen(lstn, 3);
if( ret != 0)
@ -177,23 +113,9 @@ exit(0);
if((events[i].data.fd == -1)
&& (events[i].events & EPOLLIN))
{
//close(accept(lstn, 0, 0));
//cout << "hollo!" << endl;
boost::shared_ptr<Socket> target(new Socket(PF_INET, SOCK_STREAM, 0));
addrinfo hints;
addrinfo* res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
getaddrinfo("127.0.0.1", "3306", &hints, &res);
//getaddrinfo("127.0.0.1", "25", &hints, &res);
connect(*target, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
SocketOption dst = vm["dst"].as<SocketOption>();
boost::shared_ptr<Socket> target(dst.gen_socket());
connect_inet(*target, dst);
sockets[target->fd] = target;
boost::shared_ptr<Socket> source(accept(lstn, 0, 0));