Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/tcpserver.cc')
-rw-r--r--src/net/tcpserver.cc131
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);
+ }
+}
+
+}