diff --git a/.gitignore b/.gitignore
index 0f3bd91..8639914 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,4 @@ gmon.out
test-driver
/assets/html/_documentation.html
tags
+trio.h
diff --git a/include/tr/interface/socket.h b/include/tr/interface/socket.h
new file mode 100644
index 0000000..04f3a87
--- /dev/null
+++ b/include/tr/interface/socket.h
@@ -0,0 +1,52 @@
+/**
+ * \file
+ * Inteface for common socket operations. (bind, send, recv)
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2012 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __TR_INTERFACE_SOCKET_H__
+#define __TR_INTERFACE_SOCKET_H__
+
+#include
+
+#include "trbase.h"
+#include "tr/remote_data.h"
+
+typedef int (* fptr_TR_socketBind)(void *);
+typedef int (* fptr_TR_socketConnect)(void *);
+typedef TR_RemoteData (* fptr_TR_socketRecv)(void *, size_t);
+typedef ssize_t (* fptr_TR_socketSend)(void *, TR_RemoteData);
+
+TR_INTERFACE(TR_Socket) {
+ TR_IFID;
+ fptr_TR_socketBind bind;
+ fptr_TR_socketConnect connect;
+ fptr_TR_socketRecv recv;
+ fptr_TR_socketSend send;
+};
+
+extern int TR_socketBindAction(void *);
+extern int TR_socketConnectAction(void *);
+extern TR_RemoteData TR_socketRecv(void *, size_t);
+extern ssize_t TR_socketSend(void *, TR_RemoteData);
+
+#endif // __TR_INTERFACE_SOCKET_H__
+
+// vim: set ts=4 sw=4:
diff --git a/include/tr/remote_data.h b/include/tr/remote_data.h
new file mode 100644
index 0000000..2433b98
--- /dev/null
+++ b/include/tr/remote_data.h
@@ -0,0 +1,48 @@
+/**
+ * \file
+ * Abstraction layer above BSD sockets. Capsules and simplifies connect
+ * accept and listen.
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2012 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __TR_REMOTE_DATA_H__
+#define __TR_REMOTE_DATA_H__
+
+#include
+#include
+#include
+
+#include "trbase.h"
+
+TR_CLASS(TR_RemoteData) {
+ unsigned char * data;
+ size_t ndata;
+ struct sockaddr_in addr; // for now... should be more generic
+ socklen_t addrlen;
+};
+
+extern TR_RemoteData TR_emptyRemoteData;
+
+void TR_remoteDataSetData(TR_RemoteData, unsigned char *, size_t);
+
+#endif // __TR_REMOTE_DATA_H__
+
+// vim: set ts=4 sw=4:
+
diff --git a/include/tr/socket.h b/include/tr/socket.h
index 932c1e5..78c0042 100644
--- a/include/tr/socket.h
+++ b/include/tr/socket.h
@@ -1,7 +1,8 @@
/**
* \file
* Abstraction layer above BSD sockets. Capsules and simplifies connect
- * accept and listen.
+ * accept and listen for TCP and UDP sockets.
+ * It also provides a mostly unified interface to both types of sockets.
*
* \author Georg Hopp
*
@@ -25,24 +26,82 @@
#ifndef __TR_SOCKET_H__
#define __TR_SOCKET_H__
-#include // for in_port_t
+#include
+#include
+#include
+#include
+
+//#include // for in_port_t
#include "trbase.h"
+#include "tr/interface/socket.h"
#include "tr/logger.h"
-TR_CLASS(TR_Sock) {
- TR_Logger log;
- in_port_t port;
- struct sockaddr_in addr;
- int handle;
+typedef enum TR_e_socket_fin {
+ TR_FIN_NO = 0,
+ TR_FIN_RD = 1,
+ TR_FIN_WR = 2,
+ TR_FIN_RDWR = 3
+} TR_SocketFin;
+
+TR_CLASS(TR_Socket) {
+ TR_Logger log;
+ int flags;
+ int type;
+ char * host;
+ char * cname;
+ int port;
+ time_t ttl;
+ struct sockaddr_in addr; // for now... should be more generic.
+ socklen_t addrlen;
+ int handle;
+ TR_SocketFin fin_state;
+};
+
+#define TR_socketLog(socket) (((TR_Socket)(socket))->log)
+#define TR_socketFlags(socket) (((TR_Socket)(socket))->flags)
+#define TR_socketType(socket) (((TR_Socket)(socket))->type)
+#define TR_socketHost(socket) (((TR_Socket)(socket))->host)
+#define TR_socketPort(socket) (((TR_Socket)(socket))->port)
+#define TR_socketCname(socket) (((TR_Socket)(socket))->cname)
+#define TR_socketTtl(socket) (((TR_Socket)(socket))->ttl)
+#define TR_socketAddr(socket) (((TR_Socket)(socket))->addr)
+#define TR_socketAddrlen(socket) (((TR_Socket)(socket))->addrlen)
+#define TR_socketHandle(socket) (((TR_Socket)(socket))->handle)
+#define TR_socketFinState(socket) (((TR_Socket)(socket))->fin_state)
+#define TR_socketFinRd(socket) ((TR_socketFinState((socket)) & 1) == 1)
+#define TR_socketFinWr(socket) ((TR_socketFinState((socket)) & 2) == 2)
+#define TR_socketFinRdWr(socket) ((TR_socketFinState((socket)) & 3) == 3)
+
+#define TR_socketGetIp(socket) (TR_socketAddr(socket).sin_addr.s_addr)
+#define TR_socketGetIpStr(socket) (inet_ntoa(TR_socketGetIp(socket)))
+
+TR_CLASS(TR_TcpSocket) {
+ TR_EXTENDS(TR_Socket);
+ int listen;
+ int connected;
};
-void TR_socketConnect(TR_Sock this, const char * addr, char (*)[16]);
-void TR_socketListen(TR_Sock this, int backlog);
-TR_Sock TR_socketAccept(TR_Sock this, char (*remoteAddr)[16]);
-void TR_socketNonblock(TR_Sock this);
-in_addr_t TR_socketGetIp(TR_Sock this);
-const char * const TR_socketGetIpStr(TR_Sock this);
+TR_CLASS(TR_UdpSocket) {
+ TR_EXTENDS(TR_Socket);
+};
+
+typedef int (* TR_socketAction_fptr)(void *);
+
+int TR_socketInit(TR_Socket, TR_socketAction_fptr);
+TR_SocketFin TR_socketShutdownRead(TR_Socket);
+TR_SocketFin TR_socketShutdownWrite(TR_Socket);
+TR_SocketFin TR_socketShutdown(TR_Socket);
+void TR_socketClose(TR_Socket);
+void TR_socketNonblock(TR_Socket);
+
+#define TR_socketBind(socket) \
+ (TR_socketInit((socket), TR_socketBindAction))
+
+TR_TcpSocket TR_socketAccept(TR_TcpSocket);
+
+#define TR_socketConnect(socket) \
+ (TR_socketInit((socket), TR_socketConnectAction))
#endif // __TR_SOCKET_H__
diff --git a/include/trio.h b/include/trio.h
index ad1dd59..2c7c7b5 100644
--- a/include/trio.h
+++ b/include/trio.h
@@ -1,10 +1,10 @@
#ifndef __TR_IO_H__
#define __TR_IO_H__
-#include "tr/logger.h"
#include "tr/socket.h"
+#include "tr/remote_data.h"
#include "tr/stream.h"
-#include "tr/interface/logger.h"
+#include "tr/interface/socket.h"
#include "tr/interface/reader.h"
#include "tr/interface/writer.h"
diff --git a/src/Makefile.am b/src/Makefile.am
index 8592cf4..13b930f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,12 +7,18 @@ TRIO = stream.c \
read.c \
write.c \
socket.c \
- accept.c \
- connect.c \
- listen.c \
- get_ip.c \
- get_ip_str.c \
- nonblock.c \
+ socket_init.c \
+ socket_accept.c \
+ socket_nonblock.c \
+ socket_close.c \
+ socket_shutdown.c \
+ socket_shutdown_read.c \
+ socket_shutdown_write.c \
+ tcp_socket.c \
+ udp_socket.c \
+ remote_data.c \
+ remote_data_set_data.c \
+ i_socket.c \
i_reader.c \
i_writer.c
diff --git a/src/i_socket.c b/src/i_socket.c
new file mode 100644
index 0000000..de543ef
--- /dev/null
+++ b/src/i_socket.c
@@ -0,0 +1,115 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2012 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+#include "tr/interface/socket.h"
+#include "tr/remote_data.h"
+#include "trbase.h"
+
+TR_CREATE_INTERFACE(TR_Socket, 4);
+
+int
+TR_socketBindAction(void * _this)
+{
+ int callret;
+
+ TR_RETCALL(_this, TR_Socket, bind, callret);
+
+ return callret;
+}
+
+int
+TR_socketConnectAction(void * _this)
+{
+ int callret;
+
+ TR_RETCALL(_this, TR_Socket, connect, callret);
+
+ return callret;
+}
+
+TR_RemoteData
+TR_socketRecv(void * _this, size_t size)
+{
+ TR_RemoteData remote_data;
+
+ TR_RETCALL(_this, TR_Socket, recv, remote_data, size);
+
+ if (remote_data->ndata < 0) {
+ switch (errno) {
+ case (EAGAIN|EWOULDBLOCK):
+ TR_delete(remote_data);
+ return TR_emptyRemoteData;
+
+ case EINTR:
+ case ENOMEM:
+ // these are fatal and should lead to a shutown
+ // of the whole application...
+ TR_delete(remote_data);
+ return NULL;
+
+ default:
+ TR_delete(remote_data);
+ return NULL;
+ }
+ } else if (remote_data->ndata == 0) {
+ // this is a remote close...
+ TR_delete(remote_data);
+ return NULL;
+ }
+
+ return remote_data;
+}
+
+ssize_t
+TR_socketSend(void * _this, TR_RemoteData data)
+{
+ ssize_t size;
+
+ TR_RETCALL(_this, TR_Socket, send, size, data);
+ TR_delete(data);
+
+ if (size < 0) {
+ switch (errno) {
+ case EINTR:
+ case ENOMEM:
+ // these are fatal and should lead to a shutown
+ // of the whole application...
+ return 0;
+
+ case (EAGAIN|EWOULDBLOCK):
+ return -1;
+
+ case ECONNRESET:
+ // this is a remote close...
+ return -2;
+
+ default:
+ return -2;
+ }
+ }
+
+ return size;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/listen.c b/src/listen.c
deleted file mode 100644
index bf4ed69..0000000
--- a/src/listen.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * \file
- *
- * \author Georg Hopp
- *
- * \copyright
- * Copyright © 2012 Georg Hopp
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include // for atoi() and exit()
-#include // for errno
-
-#include "tr/socket.h"
-#include "tr/logger.h"
-
-
-void
-TR_socketListen(TR_Sock this, int backlog)
-{
- (this->addr).sin_family = AF_INET; // Internet address family
- (this->addr).sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface
- //(this->addr).sin_addr.s_addr = inet_addr("127.0.0.1"); // Any incoming interface
- (this->addr).sin_port = htons(this->port); // Local port
-
- /**
- * Bind to the local address
- */
- if (-1 == bind(this->handle, (struct sockaddr *) &(this->addr), sizeof(this->addr))) {
- TR_loggerLog(this->log, TR_LOGGER_CRIT,
- "error binding socket: %s - service terminated",
- strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- /**
- * Mark the socket so it will listen for incoming connections
- */
- if (-1 == listen(this->handle, backlog)) {
- TR_loggerLog(this->log, TR_LOGGER_CRIT,
- "error binding socket: %s - service terminated",
- strerror(errno));
- exit(EXIT_FAILURE);
- }
-}
-
-// vim: set ts=4 sw=4:
diff --git a/src/remote_data.c b/src/remote_data.c
new file mode 100644
index 0000000..f7fa475
--- /dev/null
+++ b/src/remote_data.c
@@ -0,0 +1,66 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2012 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "tr/remote_data.h"
+#include "trbase.h"
+
+static
+int
+remoteDataCtor(void * _this, va_list * params)
+{
+ TR_RemoteData this = _this;
+ struct sockaddr * addr_ptr = va_arg(*params, struct sockaddr *);
+
+ this->addrlen = va_arg(*params, socklen_t);
+ memcpy(&(this->addr), addr_ptr, this->addrlen);
+
+ this->data = NULL;
+ this->ndata = 0;
+
+ return 0;
+}
+
+static
+void
+remoteDataDtor(void * _this)
+{
+ TR_RemoteData this = _this;
+
+ TR_MEM_FREE(this->data);
+}
+
+TR_INIT_IFACE(TR_Class, remoteDataCtor, remoteDataDtor, NULL);
+TR_CREATE_CLASS(TR_RemoteData, NULL, TR_IF(TR_Class));
+
+TR_INSTANCE(TR_RemoteData, TR_emptyRemoteData, NULL, 0, NULL, NULL);
+
+// vim: set ts=4 sw=4:
diff --git a/src/remote_data_set_data.c b/src/remote_data_set_data.c
new file mode 100644
index 0000000..d2862e0
--- /dev/null
+++ b/src/remote_data_set_data.c
@@ -0,0 +1,43 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2012 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include // for atoi() and exit()
+#include // for errno
+#include
+#include
+
+#include "tr/remote_data.h"
+#include "tr/logger.h"
+
+void
+TR_remoteDataSetData(TR_RemoteData this, unsigned char * data, size_t size)
+{
+ if (this->data && TR_getSize(this->data) < size) {
+ TR_MEM_FREE(this->data);
+ }
+
+ this->data = TR_malloc(size);
+ this->ndata = size;
+ memcpy(this->data, data, size);
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/socket.c b/src/socket.c
index a39f5fc..048be11 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -23,7 +23,14 @@
#include
#include
#include
+#include
+#include
+#include
+#include
+#include
+
+#include "tr/remote_data.h"
#include "tr/socket.h"
#include "tr/logger.h"
#include "trbase.h"
@@ -32,30 +39,15 @@ static
int
socketCtor(void * _this, va_list * params)
{
- TR_Sock this = _this;
- int reUse = 1; //! \todo make this configurable
- int port;
-
- this->log = va_arg(* params, TR_Logger);
- port = va_arg(* params, int);
-
- //! if port is -1 do not initialize the socket. (Used with accept)
- if (-1 == port) {
- return 0;
- } else {
- this->port = port;
- }
+ TR_Socket this = _this;
- //! Create socket for incoming connections
- if (-1 == (this->handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
- TR_loggerLog(this->log, TR_LOGGER_CRIT,
- "error opening socket: %s - service terminated",
- strerror(errno));
- return -1;
- }
-
- //! Make the socket REUSE a TIME_WAIT socket
- setsockopt(this->handle, SOL_SOCKET, SO_REUSEADDR, &reUse, sizeof(reUse));
+ this->type = 0;
+ this->handle = -1;
+ this->log = va_arg(*params, TR_Logger);
+ this->host = va_arg(*params, char*);
+ this->port = va_arg(*params, int);
+ this->flags = va_arg(*params, int);
+ this->fin_state = TR_FIN_RDWR;
return 0;
}
@@ -64,15 +56,33 @@ static
void
socketDtor(void * _this)
{
- TR_Sock this = _this;
+ TR_Socket this = _this;
+
+ TR_MEM_FREE(this->cname);
if (STDERR_FILENO < this->handle) {
- shutdown(this->handle, SHUT_RDWR);
- close(this->handle);
+ TR_socketClose(this);
+ }
+}
+
+static
+int
+socketBind(void * _this)
+{
+ TR_Socket this = _this;
+ int state;
+
+ state = bind(this->handle, (struct sockaddr *)&(this->addr), this->addrlen);
+
+ if (-1 == state) {
+ perror("bind");
}
+
+ return state;
}
TR_INIT_IFACE(TR_Class, socketCtor, socketDtor, NULL);
-TR_CREATE_CLASS(TR_Sock, NULL, TR_IF(TR_Class));
+TR_INIT_IFACE(TR_Socket, socketBind, NULL, NULL);
+TR_CREATE_CLASS(TR_Socket, NULL, TR_IF(TR_Class), TR_IF(TR_Socket));
// vim: set ts=4 sw=4:
diff --git a/src/accept.c b/src/socket_accept.c
similarity index 51%
rename from src/accept.c
rename to src/socket_accept.c
index e1872a5..cf76ef5 100644
--- a/src/accept.c
+++ b/src/socket_accept.c
@@ -20,38 +20,48 @@
* along with this program. If not, see .
*/
+#define _POSIX_SOURCE 1
+
+#include // for atoi() and exit()
#include // for errno
+#include
#include
#include
-#include "trbase.h"
+#include
+#include
+#include
+#include
+#include
+
#include "tr/socket.h"
#include "tr/logger.h"
-TR_Sock
-TR_socketAccept(TR_Sock this, char (*remoteAddr)[16])
+TR_TcpSocket
+TR_socketAccept(TR_TcpSocket this)
{
- TR_Sock sock; // Socket for client
- unsigned int len; // Length of client address data structure
+ TR_Socket remote = TR_new(TR_TcpSocket, TR_socketLog(this), NULL, 0, 0);
+ //int flags;
- // Set the size of the in-out parameter
- len = sizeof(this->addr);
+ remote->handle = accept(
+ TR_socketHandle(this),
+ (struct sockaddr *)&(remote->addr),
+ &(remote->addrlen));
- sock = TR_new(TR_Sock, this->log, -1);
+ //flags = fcntl(remote->handle, F_GETFL, 0);
+ //fcntl(remote->handle, F_SETFL, flags | O_NONBLOCK);
- // Wait for a client to connect
- sock->handle = accept(this->handle, (struct sockaddr *) &(sock->addr), &len);
- if (-1 == sock->handle) {
- TR_loggerLog(this->log, TR_LOGGER_WARNING,
- "error accepting connection: %s", strerror(errno));
- } else {
- strcpy(*remoteAddr, inet_ntoa((sock->addr).sin_addr));
+ remote->host = TR_strdup(inet_ntoa(remote->addr.sin_addr));
+ remote->port = ntohs(remote->addr.sin_port);
+ remote->type = TR_socketType(this);
+ remote->flags = TR_socketFlags(this);
- //loggerLog(this->log, LOGGER_INFO,
- // "handling client %s\n", inet_ntoa((sock->addr).sin_addr));
- }
+ if (-1 == remote->handle) {
+ perror("accept");
+ TR_delete(remote);
+ }
- return sock;
+ return (TR_TcpSocket)remote;
}
// vim: set ts=4 sw=4:
diff --git a/src/get_ip.c b/src/socket_close.c
similarity index 78%
rename from src/get_ip.c
rename to src/socket_close.c
index 8566c6b..a632d6c 100644
--- a/src/get_ip.c
+++ b/src/socket_close.c
@@ -20,16 +20,20 @@
* along with this program. If not, see .
*/
-#include
+#include // for atoi() and exit()
+#include // for errno
+#include
+#include
-#include "trbase.h"
#include "tr/socket.h"
#include "tr/logger.h"
-in_addr_t
-TR_socketGetIp(TR_Sock this)
+void
+TR_socketClose(TR_Socket this)
{
- return this->addr.sin_addr.s_addr;
+ TR_socketShutdown(this);
+ close(this->handle);
+ this->handle = -1;
}
// vim: set ts=4 sw=4:
diff --git a/src/socket_init.c b/src/socket_init.c
new file mode 100644
index 0000000..5400084
--- /dev/null
+++ b/src/socket_init.c
@@ -0,0 +1,103 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2012 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define _POSIX_SOURCE 1
+
+#include // for atoi() and exit()
+#include // for errno
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "tr/socket.h"
+#include "tr/logger.h"
+
+int
+TR_socketInit(TR_Socket this, TR_socketAction_fptr action)
+{
+ struct addrinfo hint;
+ struct addrinfo * info, * current_info;
+ char port_str[6];
+
+ hint.ai_socktype = this->type;
+ hint.ai_flags = this->flags;
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_protocol = 0;
+ hint.ai_addrlen = 0;
+ hint.ai_canonname = NULL;
+ hint.ai_addr = NULL;
+ hint.ai_next = NULL;
+
+ sprintf(port_str, "%u", this->port);
+ if (0 != getaddrinfo(this->host, port_str, &hint, &info)) {
+ // TODO error handling...
+ return FALSE;
+ }
+
+ current_info = info;
+ for (
+ current_info = info;
+ current_info;
+ current_info = current_info->ai_next)
+ {
+ this->handle = socket(
+ current_info->ai_family,
+ current_info->ai_socktype,
+ current_info->ai_protocol);
+
+ if (-1 == this->handle) {
+ continue;
+ }
+
+ this->addrlen = current_info->ai_addrlen;
+ memcpy(&(this->addr), current_info->ai_addr, this->addrlen);
+
+ if (0 == action(this)) {
+ break; // success / open and bind or open and connect...
+ }
+
+ close(this->handle);
+ this->handle = -1;
+ }
+
+ if (NULL != current_info) {
+ int reUse = 1; //! \todo make this configurable
+ //int flags = fcntl(this->handle, F_GETFL, 0);
+
+ //fcntl(this->handle, F_SETFL, flags | O_NONBLOCK);
+ this->cname = TR_strdup(current_info->ai_canonname);
+ this->fin_state = TR_FIN_NO;
+
+ //! Make the socket REUSE a TIME_WAIT socket
+ setsockopt(this->handle, SOL_SOCKET, SO_REUSEADDR, &reUse, sizeof(reUse));
+ }
+
+ freeaddrinfo(info);
+
+ return TRUE;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/nonblock.c b/src/socket_nonblock.c
similarity index 96%
rename from src/nonblock.c
rename to src/socket_nonblock.c
index f2a10f7..0d9873b 100644
--- a/src/nonblock.c
+++ b/src/socket_nonblock.c
@@ -28,7 +28,7 @@
#include "tr/logger.h"
void
-TR_socketNonblock(TR_Sock this)
+TR_socketNonblock(TR_Socket this)
{
int flags = fcntl(this->handle, F_GETFL, 0);
fcntl(this->handle, F_SETFL, flags | O_NONBLOCK);
diff --git a/src/get_ip_str.c b/src/socket_shutdown.c
similarity index 71%
rename from src/get_ip_str.c
rename to src/socket_shutdown.c
index 3c2f911..0e6b6fb 100644
--- a/src/get_ip_str.c
+++ b/src/socket_shutdown.c
@@ -20,16 +20,25 @@
* along with this program. If not, see .
*/
-#include
+#include // for atoi() and exit()
+#include // for errno
+#include
+#include
-#include "trbase.h"
#include "tr/socket.h"
#include "tr/logger.h"
-const char * const
-TR_socketGetIpStr(TR_Sock this)
+TR_SocketFin
+TR_socketShutdown(TR_Socket this)
{
- return inet_ntoa(this->addr.sin_addr);
+ if (TR_socketFinRdWr(this)) {
+ return this->fin_state;
+ }
+
+ shutdown(this->handle, SHUT_RDWR);
+ this->fin_state |= TR_FIN_RDWR;
+
+ return this->fin_state;
}
// vim: set ts=4 sw=4:
diff --git a/src/connect.c b/src/socket_shutdown_read.c
similarity index 54%
rename from src/connect.c
rename to src/socket_shutdown_read.c
index e1b9037..a9c2ff3 100644
--- a/src/connect.c
+++ b/src/socket_shutdown_read.c
@@ -22,32 +22,26 @@
#include // for atoi() and exit()
#include // for errno
+#include
+#include
#include "tr/socket.h"
#include "tr/logger.h"
-void
-TR_socketConnect(TR_Sock this, const char * addr, char (*remoteAddr)[16])
+TR_SocketFin
+TR_socketShutdownRead(TR_Socket this)
{
- inet_pton(AF_INET, addr, &((this->addr).sin_addr));
- (this->addr).sin_family = AF_INET; // Internet address family
- (this->addr).sin_port = htons(this->port); // Local port
+ if (TR_socketFinRd(this)) {
+ return this->fin_state;
+ }
- if (-1 == connect(
- this->handle,
- (struct sockaddr*) &(this->addr),
- sizeof(this->addr)))
- {
- TR_loggerLog(this->log, TR_LOGGER_CRIT,
- "error connection socket: %s - service terminated",
- strerror(errno));
- exit(EXIT_FAILURE);
- } else {
- strcpy(*remoteAddr, inet_ntoa((this->addr).sin_addr));
+ if (0 == shutdown(this->handle, SHUT_RD)) {
+ this->fin_state |= TR_FIN_RD;
+ } else {
+ this->fin_state |= TR_FIN_RDWR;
+ }
- TR_loggerLog(this->log, TR_LOGGER_INFO,
- "handling connection %s\n", inet_ntoa((this->addr).sin_addr));
- }
+ return this->fin_state;
}
// vim: set ts=4 sw=4:
diff --git a/src/socket_shutdown_write.c b/src/socket_shutdown_write.c
new file mode 100644
index 0000000..6eba445
--- /dev/null
+++ b/src/socket_shutdown_write.c
@@ -0,0 +1,47 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2012 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include // for atoi() and exit()
+#include // for errno
+#include
+#include
+
+#include "tr/socket.h"
+#include "tr/logger.h"
+
+TR_SocketFin
+TR_socketShutdownWrite(TR_Socket this)
+{
+ if (TR_socketFinWr(this)) {
+ return this->fin_state;
+ }
+
+ if (0 == shutdown(this->handle, SHUT_WR)) {
+ this->fin_state |= TR_FIN_WR;
+ } else {
+ this->fin_state |= TR_FIN_RDWR;
+ }
+
+ return this->fin_state;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/tcp_socket.c b/src/tcp_socket.c
new file mode 100644
index 0000000..293b41d
--- /dev/null
+++ b/src/tcp_socket.c
@@ -0,0 +1,121 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2012 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "tr/socket.h"
+#include "tr/logger.h"
+#include "trbase.h"
+
+static
+int
+tcpSocketCtor(void * _this, va_list * params)
+{
+ TR_TcpSocket this = _this;
+
+ TR_PARENTCALL(_this, TR_Class, ctor, params);
+
+ TR_socketType(this) = SOCK_STREAM;
+ this->listen = FALSE;
+ this->connected = FALSE;
+
+ return 0;
+}
+
+static
+int
+tcpSocketBind(void * _this)
+{
+ TR_TcpSocket this = _this;
+ int bind_ret;
+
+ TR_PARENTRETCALL(_this, TR_Socket, bind, bind_ret);
+
+ if (bind_ret != 0) {
+ return -1;
+ }
+
+ if (listen(TR_socketHandle(this), 128) != 0) {
+ // error
+ return -1;
+ }
+ this->listen = TRUE;
+
+ return 0;
+}
+
+static
+int
+tcpSocketConnect(void * _this)
+{
+ TR_Socket this = _this;
+
+ return connect(
+ this->handle,
+ (struct sockaddr *)&(this->addr),
+ this->addrlen);
+}
+
+static
+TR_RemoteData
+tcpSocketRecv(TR_Socket this, size_t size)
+{
+ TR_RemoteData rdata = TR_new(TR_RemoteData, &(this->addr), this->addrlen);
+ unsigned char buffer[size];
+ ssize_t received;
+
+ received = recv(this->handle, buffer, size, this->flags);
+
+ if (-1 == received) {
+ perror("recv");
+ TR_delete(rdata);
+ } else {
+ TR_remoteDataSetData(rdata, buffer, received);
+ }
+
+ return rdata;
+}
+
+static
+ssize_t
+tcpSocketSend(TR_Socket this, TR_RemoteData data)
+{
+ return send(this->handle, data->data, data->ndata, this->flags);
+}
+
+TR_INIT_IFACE(TR_Class, tcpSocketCtor, NULL, NULL);
+TR_INIT_IFACE(
+ TR_Socket,
+ tcpSocketBind,
+ tcpSocketConnect,
+ tcpSocketRecv,
+ tcpSocketSend);
+TR_CREATE_CLASS(TR_TcpSocket, TR_Socket, TR_IF(TR_Class), TR_IF(TR_Socket));
+
+// vim: set ts=4 sw=4:
diff --git a/src/udp_socket.c b/src/udp_socket.c
new file mode 100644
index 0000000..6f02fd5
--- /dev/null
+++ b/src/udp_socket.c
@@ -0,0 +1,102 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2012 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "tr/socket.h"
+#include "tr/logger.h"
+#include "trbase.h"
+
+static
+int
+udpSocketCtor(void * _this, va_list * params)
+{
+ TR_Socket this = _this;
+
+ TR_PARENTCALL(_this, TR_Class, ctor, params);
+
+ this->type = SOCK_DGRAM;
+
+ return 0;
+}
+
+static
+TR_RemoteData
+udpSocketRecv(TR_Socket this, size_t size)
+{
+ TR_RemoteData rdata;
+ struct sockaddr_in addr;
+ socklen_t addrlen = this->addrlen;
+ unsigned char buffer[size];
+ ssize_t received;
+
+ received = recvfrom(
+ this->handle,
+ buffer,
+ size,
+ this->flags,
+ (struct sockaddr *)&addr,
+ &addrlen);
+
+ if (-1 == received) {
+ perror("recvfrom");
+ } else {
+ rdata = TR_new(TR_RemoteData, &addr, addrlen);
+ TR_remoteDataSetData(rdata, buffer, received);
+ }
+
+ return rdata;
+}
+
+static
+ssize_t
+udpSocketSend(TR_Socket this, TR_RemoteData data)
+{
+ ssize_t send;
+
+ send = sendto(
+ this->handle,
+ data->data,
+ data->ndata,
+ this->flags,
+ (struct sockaddr *)&(data->addr),
+ data->addrlen);
+
+ if (-1 == send) {
+ perror("sendto");
+ }
+
+ return send;
+}
+
+TR_INIT_IFACE(TR_Class, udpSocketCtor, NULL, NULL);
+TR_INIT_IFACE(TR_Socket, NULL, NULL, udpSocketRecv, udpSocketSend);
+TR_CREATE_CLASS(TR_UdpSocket, TR_Socket, TR_IF(TR_Class), TR_IF(TR_Socket));
+
+// vim: set ts=4 sw=4:
diff --git a/trio.h b/trio.h
deleted file mode 100644
index 446b203..0000000
--- a/trio.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* trio.h. Generated from trio.h.in by configure. */
-/* trio.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `memset' function. */
-/* #undef HAVE_MEMSET */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if stdbool.h conforms to C99. */
-/* #undef HAVE_STDBOOL_H */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDIO_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYSLOG_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if the system has the type `_Bool'. */
-#define HAVE__BOOL 1
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#define LT_OBJDIR ".libs/"
-
-/* Name of package */
-#define PACKAGE "libtrio"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "Georg Hopp "
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libtrio"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libtrio 0.0.0"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libtrio"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.0.0"
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "0.0.0"
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-/* Define to `int' if does not define. */
-/* #undef pid_t */
-
-/* Define to `unsigned int' if does not define. */
-/* #undef size_t */