summaryrefslogtreecommitdiff
path: root/server/src/tcpsocket.cc
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/tcpsocket.cc')
-rw-r--r--server/src/tcpsocket.cc178
1 files changed, 119 insertions, 59 deletions
diff --git a/server/src/tcpsocket.cc b/server/src/tcpsocket.cc
index 4bb7a4b..b6049c7 100644
--- a/server/src/tcpsocket.cc
+++ b/server/src/tcpsocket.cc
@@ -27,6 +27,9 @@
#include "tcpsocket.h"
#include "debug.h"
+#include <config.h>
+
+//#define WITH_DEBUG
// for gethostbyname
#include <netdb.h>
@@ -74,17 +77,28 @@
#include <unistd.h>
#include <fcntl.h>
-TCPSocket::TCPSocket()
+TCPSocket::TCPSocket(std::string name, int sock)
throw(TCPSocketException)
{
- if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
- throw TCPSocketException(strerror(errno));
+ this->name = name;
+ if(sock == -1) {
+ if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ throw TCPSocketException(strerror(errno));
+ }
}
isconnected = false;
+ this->sock = sock;
+
+#ifdef WITH_DEBUG
+ printf("TCPSocket %s: %p %d (%d)\n", name.c_str(), this, sock, getpid());
+#endif/*WITH_DEBUG*/
}
TCPSocket::~TCPSocket()
{
+#ifdef WITH_DEBUG
+ printf("~TCPSocket %s: %p %d (%d)\n", name.c_str(), this, sock, getpid());
+#endif/*WITH_DEBUG*/
disconnect();
}
@@ -94,13 +108,8 @@ void TCPSocket::listen(unsigned short int port)
throw(TCPListenException)
{
- if(sock == -1) {
- throw TCPListenException("Socket not initialized.");
- }
-
- if(isconnected) {
- throw TCPListenException("Socket already connected.");
- }
+ if(sock == -1) throw TCPListenException("Socket not initialized.");
+ if(isconnected) throw TCPListenException("Socket already connected.");
struct sockaddr_in socketaddr;
memset((char *) &socketaddr, sizeof(socketaddr), 0);
@@ -119,35 +128,52 @@ void TCPSocket::listen(unsigned short int port)
isconnected = true;
}
-
+/**
+ **
+ ** Accept connections and block until one gets in.
+ ** Return the new connection on incoming.
+ ** It throws exceptions if an error occurres.
+ ** On interrupts, it returns NULL
+ **
+ **/
static int _accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{return accept(sockfd, addr, addrlen);}
-TCPSocket TCPSocket::accept()
+TCPSocket *TCPSocket::accept()
throw(TCPAcceptException)
{
- TCPSocket child;
-
- if(sock == -1) {
- throw TCPAcceptException("Socket not initialized.");
- }
-
- if(!isconnected) {
- throw TCPAcceptException("Socket not connected.");
- }
+ if(sock == -1) throw TCPAcceptException("Socket not initialized.");
+ if(!isconnected) throw TCPAcceptException("Socket not connected.");
// accept new connection and get its connection descriptor
struct sockaddr_in ssocketaddr;
int csalen = sizeof(ssocketaddr);
- child.disconnect(); // We need to close the existing socket
- child.sock = _accept(sock, (struct sockaddr*)&ssocketaddr, (socklen_t*)&csalen);
-
- if (child.sock == -1) {
- throw TCPAcceptException(std::string("accept failed - ") + strerror(errno));
+ // Select
+ fd_set fset;
+ int ret;
+ FD_ZERO(&fset);
+ FD_SET(sock, &fset);
+ if( (ret = select (sock+1, &fset, NULL, NULL, NULL)) < 0) {
+ if(errno == EINTR) {
+ printf("Accept got interrupt!\n");
+ return NULL; // a signal caused select to return. That is OK with me
+ } else {
+ throw TCPAcceptException("Select on socket failed.");
+ }
+ }
+ if(FD_ISSET(sock, &fset)) {
+ int csock = _accept(sock, (struct sockaddr*)&ssocketaddr, (socklen_t*)&csalen);
+ TCPSocket *child = new TCPSocket(name + "-child", csock);
+
+ if (child->sock == -1) {
+ throw TCPAcceptException(std::string("accept failed - ") + strerror(errno));
+ }
+ child->isconnected = true;
+ return child;
+ } else {
+ printf("Accept returned with no socket - This should not happen!\n");
+ return NULL;
}
-
- child.isconnected = true;
- return child;
}
@@ -155,11 +181,8 @@ static int _connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addr
{return connect(sockfd, serv_addr, addrlen);}
void TCPSocket::connect(std::string addr, unsigned short int port)
throw(TCPConnectException)
-
{
- if(isconnected) {
- throw TCPConnectException("Socket already connected.", "", "");
- }
+ if(isconnected) throw TCPConnectException("Socket already connected.", "", "");
#ifndef BYPASS_STATICALLOCATIONS
// Do DNS lookup
@@ -199,7 +222,13 @@ void TCPSocket::connect(std::string addr, unsigned short int port)
void TCPSocket::disconnect()
{
if(sock != -1) {
- close(sock);
+#ifdef WITH_DEBUG
+ printf("Closing TCPSocket %s: %p %d (%d)\n", name.c_str(), this, sock, getpid());
+#endif/*WITH_DEBUG*/
+ int ret = close(sock);
+ if(ret == -1) {
+ perror(name.c_str());
+ }
sock = -1;
}
isconnected = false;
@@ -210,41 +239,69 @@ bool TCPSocket::connected()
return sock != -1 && isconnected;
}
-int TCPSocket::read(char *buf, int size)
+
+
+/**
+ **
+ ** Read read a number of bytes from the network.
+ ** It returns the number of bytes read.
+ ** It throws exceptions if an error occurres.
+ ** On interrupts, it returns -1
+ **
+ **/
+ssize_t _read(int fd, void *buf, size_t count) { return read(fd, buf, count); }
+int TCPSocket::read(char *buf, int size, long timeout)
throw(TCPReadException)
{
int res = 0;
- if(sock == -1) {
- throw TCPReadException("Socket not initialized.");
- }
-
- if(!isconnected) {
- throw TCPReadException("Socket is not connected.");
- }
-
- /*
- if( (res = recv(sock, buf, size, MSG_WAITALL)) == -1 ) {
- throw TCPReadException(strerror(errno));
- }
- */
+ if(sock == -1) throw TCPReadException("Socket not initialized.");
+ if(!isconnected) throw TCPReadException("Socket is not connected.");
+
+ // Select
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout;
+
+ struct timeval *ptv = NULL;
+ if(timeout >= 0) ptv = &tv;
+
+ fd_set fset;
+ int ret;
+ FD_ZERO(&fset);
+ FD_SET(sock, &fset);
+ ret = select (sock+1, &fset, NULL, NULL, ptv);
+ switch(ret) {
+ case -1:
+ if(errno == EINTR) {
+ printf("EINTR - got interrupt\n");
+ return -1; // a signal caused select to return. That is OK with me
+ } else {
+ throw TCPReadException("Select on socket (read) failed.");
+ }
+ break;
- // Wait until something is ready to be read ( peek'a'loop ).
- errno = EAGAIN;
- while( recv(sock, buf, 1, MSG_PEEK) == -1 && errno == EAGAIN) {
- usleep(10);
- }
+ case 0:
+ // timeout
+ printf("Timeout\n");
+ break;
- // Now read it
- if( (res = recv(sock, buf, size, MSG_DONTWAIT)) == -1 ) {
- throw TCPReadException(strerror(errno));
+ default:
+ if(FD_ISSET(sock, &fset)) {
+ // res = recv(sock, buf, size, MSG_DONTWAIT);
+ if( (res = _read(sock, buf, size)) == -1 ) {
+ throw TCPReadException(strerror(errno));
+ }
+ } else {
+ printf("FD_ISSET failed (timeout?)\n");
+ return 0;
+ }
}
- // fwrite(buf, size, 1, stdout); fflush(stdout);
-
return res;
}
+ssize_t _write(int fd, const void *buf, size_t count) { return write(fd, buf, count); }
int TCPSocket::write(char *data, int size)
throw(TCPWriteException)
{
@@ -257,10 +314,13 @@ int TCPSocket::write(char *data, int size)
}
int res;
- if( (res = send(sock, data, size, MSG_WAITALL)) == -1 ) {
+ // if( (res = send(sock, data, size, MSG_WAITALL)) == -1 ) {
+ if( (res = _write(sock, data, size)) == -1 ) {
throw TCPWriteException(strerror(errno));
}
+ printf("Outputted %d byes\n", res);
+
return res;
}