diff options
Diffstat (limited to 'src/net/tcpserver.cc')
-rw-r--r-- | src/net/tcpserver.cc | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/net/tcpserver.cc b/src/net/tcpserver.cc new file mode 100644 index 0000000..f194a63 --- /dev/null +++ b/src/net/tcpserver.cc @@ -0,0 +1,131 @@ +/* + net/tcpserver.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include <unistd.h> +#include <errno.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/wait.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <iostream> + +#include "sys/sys.h" +#include "net/tcpserver.h" +#include "net/net.h" + +namespace net +{ + +TCPServer::TCPServer(std::string const host, unsigned int const port) +{ + tcpserver_fd = -1; + tcpserver_error = true; + + con_debug << "TCPServer: starting." << std::endl; + + // initialize socket + tcpserver_fd = ::socket(PF_INET, SOCK_STREAM, 0); + if (tcpserver_fd == -1) { + // FIXME error handling + con_error << "Network can't create socket!" << std::endl; + perror("socket"); + return; + } + + // set socket options + socklen_t yes = 1; + if (::setsockopt(tcpserver_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(socklen_t)) == -1) { + // FIXME error handling + std::cerr << "Network can't set socket options!" << std::endl; + perror("setsockopt"); + return; + } + + // Get the local adress to bind to + struct sockaddr_in listen_addr; + listen_addr.sin_family = AF_INET; + listen_addr.sin_port = htons(port); + //listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); + listen_addr.sin_addr.s_addr = inet_addr(host.c_str()); + memset(listen_addr.sin_zero, '\0', sizeof(listen_addr.sin_zero)); + + // bind the local address to the socket ( note the typecast) + if (::bind(tcpserver_fd, (struct sockaddr *) &listen_addr, sizeof(struct sockaddr)) == -1) { + // FIXME error handling + con_error << "Network can't bind to local address!" << std::endl; + perror("bind"); + return; + } + + // listen + if (::listen(tcpserver_fd, MAXPENDINGCONNECTIONS) == -1) { + // FIXME error handling + con_error << "Network failed to listen on socket!" << std::endl; + perror("listen"); + return; + } + + tcpserver_error = false; + con_print << "Listening on " << inet_ntoa(listen_addr.sin_addr) << + ":" << ntohs(listen_addr.sin_port) << std::endl; +} + +TCPServer::~TCPServer() +{ + if (tcpserver_fd != -1) + ::close(tcpserver_fd); + con_debug << "TCPServer: terminated." << std::endl; +} + +bool TCPServer::valid() const +{ + return (tcpserver_fd != -1); +} + +bool TCPServer::invalid() const +{ + return (tcpserver_fd == -1); +} + +bool TCPServer::error() const +{ + return tcpserver_error; +} + +int TCPServer::fd() const +{ + return tcpserver_fd; +} + +void TCPServer::abort() +{ + tcpserver_error = true; +} + +void TCPServer::accept() +{ + con_debug << "TCPServer: accept()" << std::endl; + struct sockaddr_in client_addr; + socklen_t addrlen = sizeof(struct sockaddr_in); + + int clientfd = ::accept(tcpserver_fd, (struct sockaddr *) &client_addr, &addrlen); + if (clientfd == -1) { + // FIXME error handling + con_error << "Network accept() error!" << std::endl; + perror("accept"); + return; + } else { + std::string host(inet_ntoa(client_addr.sin_addr)); + int port = client_addr.sin_port; + client_connect(clientfd, host, port); + } +} + +} |