From fe87c3f42501033f6a4fed41a3ad1bb788098a21 Mon Sep 17 00:00:00 2001 From: steffen Date: Wed, 30 Jan 2019 21:57:25 +0000 Subject: [PATCH] adding unix sockets --- Changelog | 3 + Makefile | 2 +- UDPTCPNetwork.h | 32 ++++++++ tcp.cc | 4 +- unix.cc | 212 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 250 insertions(+), 3 deletions(-) create mode 100644 unix.cc diff --git a/Changelog b/Changelog index 1c629f0..d5d496e 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,6 @@ +2019-01-30: +- Adding unix socket to the possible connections + 2019-01-26: - TCP::Write - added MSG_NOSIGNAL to send, in case something gets wrong the application would stop working diff --git a/Makefile b/Makefile index e40a81c..75ddd82 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ DEFAULT_TCPPORT=6131 DEFAULT_UDPPORT=6131 DEFAULT_SERVER=localhost -OBJLIB=network.o udp.o tcp.o +OBJLIB=network.o udp.o tcp.o unix.o INCLIB=config.h UDPTCPNetwork.h OBJLIB_NAME=UDPTCPNetwork TARGET=lib$(OBJLIB_NAME).so.$(VERSION) diff --git a/UDPTCPNetwork.h b/UDPTCPNetwork.h index c6d573d..1617ee7 100644 --- a/UDPTCPNetwork.h +++ b/UDPTCPNetwork.h @@ -104,5 +104,37 @@ public: int WebGetFile (string url, char *buffer, int maxsize); }; + + +/************************************************************************ + * unix socket related functions + */ +class UNIX { +private: + int sock; + string fname; + int readcnt; + int writecnt; + +public: + UNIX(); + UNIX(int fd, string filename); + ~UNIX(); + + int Connect(string file); + long int ReadTimeout(char *buffer, long int len, int timeout); + long int Read(char *buffer, long int len); + long int Write(char *buffer, long int len); + void Close(); + + int IsConnected(); + int IsData(int timeout); // timeout in ms; + + int Listen(string filename); + UNIX* Accept(); + + int GetSocket() { return sock; }; +}; + #endif diff --git a/tcp.cc b/tcp.cc index e66f507..e7f899c 100644 --- a/tcp.cc +++ b/tcp.cc @@ -103,8 +103,8 @@ TCP* TCP::Accept() { FD_ZERO(&rfds); FD_SET(sock, &rfds); - tv.tv_sec = 1; - tv.tv_usec = 0; + tv.tv_sec = 0; + tv.tv_usec = 1000; retval = select (sock+1, &rfds, NULL, NULL, &tv); if (retval == -1 && errno == EINTR) { diff --git a/unix.cc b/unix.cc new file mode 100644 index 0000000..508acfd --- /dev/null +++ b/unix.cc @@ -0,0 +1,212 @@ +/* + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* close() */ +#include +#include /* memset() */ +#include +#include + +#include "UDPTCPNetwork.h" + +UNIX::~UNIX() { + Close(); +} + +UNIX::UNIX() { + sock = 0; + fname = ""; + writecnt = 0; + readcnt = 0; +}; + + +UNIX::UNIX (int fd, string filename) { + sock = fd; + fname = filename; + writecnt = 0; + readcnt = 0; +}; + + +int UNIX::Listen(string filename) { + char buffer[NET_BUFFERSIZE]; + int err, i; + struct sockaddr_un addr; + + if (sock > 0) Close(); + unlink(filename.c_str()); + + memset (&addr,0, sizeof addr); + addr.sun_family = AF_UNIX; + strncpy (addr.sun_path, filename.c_str(), sizeof (addr.sun_path)); + + if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + sock = 0; + return 0; + } + + if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + close (sock); + sock = 0; + return 0; + } + + if (listen(sock, 8) == -1) { + close (sock); + sock = 0; + return 0; + } + + return 1; +}; + + +UNIX* UNIX::Accept() { + fd_set rfds; + struct timeval tv; + int retval, newsock, err, i; + char host[NET_BUFFERSIZE]; + char port[NET_BUFFERSIZE]; + UNIX *named = NULL; + struct sockaddr_storage cli_addr; + unsigned int cli_len; + + if (sock <= 0) return NULL; + + FD_ZERO(&rfds); + FD_SET(sock, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 1000; + + retval = select (sock+1, &rfds, NULL, NULL, &tv); + if (retval == -1 && errno == EINTR) { + retval = 0; + } + else if (retval == -1) { + return NULL; + } + + else if (retval) { + newsock = accept (sock, NULL, NULL); + if (newsock < 0) { + return NULL; + } + + named = new UNIX(newsock, fname); + return named; + } + return NULL; +} + + +int UNIX::Connect(string filename) { + struct sockaddr_un addr; + + if (sock > 0) Close(); + + memset (&addr,0, sizeof addr); + addr.sun_family = AF_UNIX; + strncpy (addr.sun_path, filename.c_str(), sizeof (addr.sun_path)); + if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + printf ("socket: error:%s\n", strerror(errno)); + return 0; + } + if (connect(sock,(struct sockaddr *) &addr, sizeof (addr)) == -1) { + printf ("connect: error:%s\n", strerror(errno)); + close (sock); + sock = 0; + return 0; + } + return 1; +}; + + +long int UNIX::Read(char *buffer, long int len) { + long int len_ = len; + + if (sock <= 0) return -2; + len_ = read (sock, (void*)buffer, len); + + if (len_ < 0 && errno == EAGAIN) len_ = 0; + else if (len_ < 0 && errno != EAGAIN) { + len_ = -2; + } + else if (len_ == 0) len_ = -1; + if (len_ < 0) Close(); + + readcnt += len_; + + return len_; +}; + + +long int UNIX::ReadTimeout(char *buffer, long int len, int timeout) { + int data = IsData (timeout); + + if (data > 0) return Read (buffer, len); + else if (data < 0) return -1; + else return 0; +}; + + +////////////////////////////////////////////////////////// +// +// write data, generate no signal if some error occures +long int UNIX::Write(char *buffer, long int len) { + int i; + int to = NET_MAX_RETRY; + + if (sock <= 0) return -1; + + do { + i = send (sock, buffer, len, MSG_NOSIGNAL); + } while (i == -1 && (to--) > 0 && errno == EINTR); + + if (i < 0) Close (); + writecnt += i; + + return i; +}; + + +void UNIX::Close() { + if (sock > 0) close (sock); + sock = -1; +}; + + +int UNIX::IsConnected() { + return (sock > 0); +}; + + +int UNIX::IsData(int timeout) { + fd_set sockset; + struct timeval tval; + + if (sock <= 0) return -1; + + FD_ZERO (&sockset); + FD_SET (sock, &sockset); + tval.tv_sec = timeout / 1000; + tval.tv_usec = (timeout % 1000); + if ((select (sock + 1, &sockset, NULL, NULL, &tval)) != -1) { + if (FD_ISSET (sock, &sockset)) return 1; + return 0; + } + else { + if (errno == EBADF) sock = -1; + } + return 0; +}; + +