diff --git a/Makefile b/Makefile index 30126f2..f14b267 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,15 @@ -OBJECTS=xerxes.cxx +OBJECTS=xerxes.cxx socket.cxx BIN=xerxes $(BIN): $(OBJECTS) - g++ -o $(BIN) $(OBJECTS) -Wall -pedantic -ggdb \ No newline at end of file + g++ -o $(BIN) $(OBJECTS) -Wall -pedantic -ggdb + +all: $(BIN) + +test: $(BIN) + ./$(BIN) + +clean: + rm -f $(BIN) *.o *.cxx~ *.hxx~ Makefile~ + +.PHONY: all \ No newline at end of file diff --git a/socket.cxx b/socket.cxx index e62ccbf..1bd5090 100644 --- a/socket.cxx +++ b/socket.cxx @@ -6,7 +6,6 @@ * Maximilian Marx */ -#include #include #include "socket.hxx" @@ -23,6 +22,11 @@ namespace xerxes } } + Socket::Socket(int new_fd) + { + fd = new_fd; + } + Socket::~Socket() { if(fd) @@ -43,12 +47,18 @@ namespace xerxes return ::listen(socket.fd, backlog); } - int + boost::shared_ptr accept(Socket& socket, sockaddr* address, socklen_t* address_len) { - return ::accept(socket.fd, address, address_len); + int new_fd = ::accept(socket.fd, address, address_len); + if(new_fd == -1) + { + throw std::runtime_error("could not accept socket."); + } + + return boost::shared_ptr(new Socket(new_fd)); } int diff --git a/socket.hxx b/socket.hxx index ac015d7..b70d527 100644 --- a/socket.hxx +++ b/socket.hxx @@ -9,16 +9,21 @@ #ifndef XERXES_SOCKET_HXX #define XERXES_SOCKET_HXX +#include #include +#include #include +#include #include #include #include +#include namespace xerxes { struct Socket : boost::noncopyable { + Socket(int fd); Socket(int domain, int type, int protocol); @@ -35,8 +40,8 @@ namespace xerxes MysqlData makeData(int len); - - int + + boost::shared_ptr accept(Socket& socket, sockaddr* address, socklen_t* address_len); @@ -47,7 +52,7 @@ namespace xerxes int connect(Socket& socket, sockaddr const* const serv_address, - socklen_t* address_len); + socklen_t address_len); int recv(Socket& socket, @@ -64,6 +69,63 @@ namespace xerxes sockaddr const* const bind_address, socklen_t addrlen); + struct EPoll + { + EPoll() : fd(epoll_create(64)) + { + if(fd < 0) + { + throw std::runtime_error("could not create epoll descriptor."); + } + } + + virtual ~EPoll() + { + if(fd > 0) + { + close(fd); + } + } + + typedef boost::shared_ptr event_t; + + void + add(Socket const& source, + Socket const& target) + { + events[source.fd] = event_t(new epoll_event); + events[target.fd] = event_t(new epoll_event); + events[source.fd]->events = EPOLLIN; + | EPOLLPRI | EPOLLERR | EPOLLHUP; + events[target.fd]->events = events[source.fd]->events; + events[source.fd]->data.fd = target.fd; + events[target.fd]->data.fd = source.fd; + + epoll_ctl(fd, EPOLL_CTL_ADD, source.fd, events[source.fd].get()); + epoll_ctl(fd, EPOLL_CTL_ADD, target.fd, events[target.fd].get()); + } + + void + add(Socket const& socket) + { + events[socket.fd] = event_t(new epoll_event); + events[socket.fd]->events = EPOLLIN; + events[socket.fd]->data.fd = -1; + + epoll_ctl(fd, EPOLL_CTL_ADD, socket.fd, events[socket.fd].get()); + } + + void + del(Socket const& socket) + { + epoll_ctl(fd, EPOLL_CTL_DEL, socket.fd, 0); + + events.erase(socket.fd); + } + + int fd; + std::map events; + }; } #endif diff --git a/xerxes.cxx b/xerxes.cxx index 572b3bf..299bbac 100644 --- a/xerxes.cxx +++ b/xerxes.cxx @@ -4,14 +4,90 @@ * (c) 2008 * Jan Losinski * Maximilian Marx - */ + */ + #include +#include +#include +#include +#include "socket.hxx" int main(int argc, char* argv[]) { - std::cout << "Hello, World!"; + using namespace std; + using namespace xerxes; + cout << "Hello, World!" << endl + << "ich kanns auch lassen, hier `Hello, World!' zu schreiben..." + << endl; + + 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); + + int ret = listen(lstn, 3); + + EPoll epoll; + epoll.add(lstn); + + const int max_events = 23; + boost::shared_array events(new epoll_event[max_events]); + std::map > sockets; + + for(;;) + { + int num = epoll_wait(epoll.fd, events.get(), max_events, -1); + + for(int i = 0; i < num; ++i) + { + if((events[i].data.fd == -1) + && (events[i].events & EPOLLIN)) + { + //close(accept(lstn, 0, 0)); + //cout << "hollo!" << endl; + boost::shared_ptr 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); + + connect(*target, res->ai_addr, res->ai_addrlen); + + freeaddrinfo(res); + + sockets[target->fd] = target; + + boost::shared_ptr source(accept(lstn, 0, 0)); + + sockets[source->fd] = source; + + epoll.add(*source, *target); + } + else{ cout << "hollo!" << events[i].data.fd << endl; } + } + } return 0; }