Compare commits

...

28 Commits
init ... master

Author SHA1 Message Date
Steffen dfd75f2f67 makefile updated
7 months ago
Steffen Pohle 0c3b402c17 adding timeout when reading web data
2 years ago
Steffen Pohle 9817a6b5a8 ignore some files
4 years ago
Steffen Pohle a08592e3f8 TCP::GetWebFile is working fine now. Windows WinSock initialisation is working better.
4 years ago
steffen 62b191f37d make dist fixed
4 years ago
steffen 120b99579f ipv6 and ipv4 can not work with one socket at the same time.
5 years ago
steffen a30fcb9ad0 fixing getremoteaddr
5 years ago
steffen c9108c6d81 added better windows support
5 years ago
steffen 7d0b48d7bf added better windows support
5 years ago
steffen dd9359c709 added better windows support
5 years ago
steffen d4b300f576 update windows build
5 years ago
steffen 1b795fdb6b update windows build
5 years ago
steffen 3b10916f8f added windows support
5 years ago
steffen df22906ada added tcp::islisten
5 years ago
steffen 5ecd53c277 adding UDP setBlock option
6 years ago
steffen 49709b7915 update
6 years ago
steffen 43a2e79418 added nonblocking support for SSL
6 years ago
steffen 9888a7411a added nonblocking support for SSL
6 years ago
steffen eb8b60d2cf adding basic support for SSL. need to add nonblocking
6 years ago
steffen a51d1c9bef update tcp connections
7 years ago
steffen 5f77b45d24 some bug fixes
7 years ago
steffen 228ff862b2 fixed TCP::Accept, lenght os sockaddr was not passed right
7 years ago
steffen 37be3de810 unix socket without error messages...
7 years ago
steffen 1acdca5dad update
7 years ago
steffen 549f23afd8 fixeing connection problems..
7 years ago
steffen 14ff60053b need more cxx flags
7 years ago
steffen fe87c3f425 adding unix sockets
7 years ago
steffen 058d69b97c update
7 years ago

162
.gitignore vendored

@ -0,0 +1,162 @@
fbconfig.config
*.oo
*.o
*.so.*
*.so
test-ssl
test-tcpclient
test-tcpserver
test-udp
.depend
.Makefile.rules
# ---> Eclipse
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
.project
# ---> C++
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

@ -0,0 +1,45 @@
2023-11-17:
- TCP::WebGetFile timeout increased to 20000ms and added another function including an timeout parameter.
2022-02-02:
- TCP::WebGetFile downloaading from web is working fine now.
- TCP constructor is dealing better on windows now. WinSock is Hell.
2020-10-18:
- needed to disable ipv6 on windows for the moment, as long as i can't
get both ipv4 and ipv6 to work at the same time.
- fixed getpeername was not supported on accept connections
- fixed windows support with TCP sockets. Needed to call closesocket on windows.
- added support for windows. Everything should work but UNIX sockets.
2020-10-15:
- added: TCP::isListen function
2019-12-29:
- added: UDP reads can be set to non blocked mode.
2019-07-21:
- fixed: compile will work with older versions of SSL.
2019-05-05:
- added SSLSocket support. SSL.Connect (TCP.GetSocket())
it supports as well as non blocking connections with a defined timeout.
2019-03-04:
- added: TCP connections have set up a timeout of 2 seconds.
- fixed: TCP connect set up the sock struct too fast so threaded applications had some
problem if the connect went into a time out.
2019-02-21:
- fixed: TCP::Accept needed to set up the lenght of the sockaddr structure
2019-02-03:
- fixed: if connection could not established we need to clear sock to -1
- fixed: setsockopt SO_REUSE was not right option was not setup properly
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

@ -1,38 +1,56 @@
# .SILENT:
VERSION=0.1
PREFIX=/usr/local
ETCPREFIX=/etc
.SILENT: help
VERSION=0.2
OBJLIB_NAME=UDPTCPNetwork
CXX=g++
CXXFLAGS= -ggdb -fPIC -pg -Wno-write-strings -I./
LDFLAGS= -lm -lc -pg
-include Makefile.rules
DEFAULT_TCPPORT=6131
DEFAULT_UDPPORT=6131
DEFAULT_SERVER=localhost
OBJLIB=network.o udp.o tcp.o
INCLIB=config.h UDPTCPNetwork.h
OBJLIB_NAME=UDPTCPNetwork
TARGET=lib$(OBJLIB_NAME).so.$(VERSION)
OBJLIB=network.o udp.o tcp.o unix.o ssl.o
INCLIB=UDPTCPNetwork.h
DISTNAME=libUDPTCPNetwork-$(VERSION)
DEPENDFILE=.depend
all: dep $(TARGET) test-udp test-tcp
ifeq ($(TARGET),)
noconfig: help
endif
all: dep $(TARGET) test-udp test-tcpserver test-tcpclient test-ssl
help:
echo "set up configuration"
echo " make configwindows to generate the windows build"
echo " make configlinux to generate the linix build"
configlinux: clean
cp -f Makefile.rules.linux Makefile.rules
test-tcp: $(TARGET) test-tcp.o config.h
$(CXX) test-tcp.o -o $@ $(LDFLAGS) -lUDPTCPNetwork -L./ -I./
configwindows: clean
cp -f Makefile.rules.windows Makefile.rules
test-udp: $(TARGET) test-udp.o config.h
$(CXX) test-udp.o -o $@ $(LDFLAGS) -lUDPTCPNetwork -L./ -I./
test-tcpserver: $(TARGET) test-tcpserver.o
$(CXX) test-tcpserver.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
test-tcpclient: $(TARGET) test-tcpclient.o
$(CXX) test-tcpclient.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
test-ssl: $(TARGET) test-ssl.o
$(CXX) test-ssl.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
test-udp: $(TARGET) test-udp.o
$(CXX) test-udp.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
keygen:
# openssl req -nodes -new -newkey rsa:2048 -sha256 -out csr.pem -keyout privkey.pem
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privkey.pem -out cert.pem
install: $(TARGET)
cp -f $(TARGET) $(PREFIX)/lib/
ln -sf $(TARGET) $(PREFIX)/lib/lib$(OBJLIB_NAME).so
if test -f "lib$(OBJLIB_NAME).so"; then cp -a -f --preserve=links lib$(OBJLIB_NAME).so $(PREFIX)/lib/ ; fi
cp -f UDPTCPNetwork.h $(PREFIX)/include/
uninstall:
rm -f $(PREFIX)/lib/$(TARGET)
rm -f $(PREFIX)/lib/lib$(OBJLIB_NAME).so
@ -41,18 +59,22 @@ uninstall:
rebuild: clean all
$(TARGET): $(OBJLIB) $(INCLIB)
$(CXX) -shared -Wl,-soname,lib$(OBJLIB_NAME).so -o $(TARGET) $^ -lc $(LDFLAGS)
ln -sf $(TARGET) lib$(OBJLIB_NAME).so
$(CXX) -shared $(LINKPARAMS) -o $(TARGET) $^ $(LDFLAGS)
if test -f "lib$(OBJLIB_NAME).so.$(VERSION)"; then ln -sf $(TARGET) lib$(OBJLIB_NAME).so; fi
ar rcs lib$(OBJLIB_NAME).a $(OBJLIB)
dep:
$(CXX) -MM `ls *.cc` $(CXXFLAGS) > $(DEPENDFILE)
clean:
rm test-tcp -rf
rm Makefile.rules -rf
rm test-tcpserver -rf
rm test-tcpclient -rf
rm test-udp -rf
rm test-ssl -rf
rm -rf gmon.out
rm *.s -rf
rm *.exe -rf
rm *.o -rf
rm *.oo -rf
rm *~ -rf
@ -60,12 +82,9 @@ clean:
rm -rf .depend
rm -rf *.so
rm -rf *.a
rm -rf *.dll
rm -rf *.so.*
cleanall: clean
source: cleanall
rm -rf *.pem -rf
config:
echo "#ifndef _CONFIG_H_" > config.h
@ -80,7 +99,8 @@ config:
dist: clean
mkdir -p $(DISTNAME)
cp -rf Makefile $(DISTNAME)
cp -rf Makefile* $(DISTNAME)
cp -rf Changelog $(DISTNAME)
cp -rf *.h $(DISTNAME)
cp -rf *.cc $(DISTNAME)
tar cvzf $(DISTNAME).tgz --exclude=*/CVS/* --exclude=*/CVS/ $(DISTNAME)

@ -0,0 +1,16 @@
PREFIX = /usr/local
ETCPREFIX = /etc
LINUXVERSION = 1
CXX = g++
CXXFLAGS = -ggdb -fPIC -pg -Wno-write-strings -I./ -std=c++11 -DBUILD_LINUX=1
LDFLAGS = -lm -pg -lssl -lcrypto
TARGET = lib$(OBJLIB_NAME).so.$(VERSION)
DISTNAME = lib$(OBJLIB_NAME)-$(VERSION)
DEPENDFILE = .depend
LINKPARAMS = -Wl,-soname,lib$(OBJLIB_NAME).so

@ -0,0 +1,14 @@
VERSION = 0.1
PREFIX = /usr
ETCPREFIX = /etc
WINVERSION = 1
CXX = g++
CXXFLAGS = -ggdb -fPIC -Wno-write-strings -I./ -std=c++11 -DBUILD_WINDOWS=1
LDFLAGS = -lm -lssl -lcrypto -lwsock32 -lws2_32
TARGET = $(OBJLIB_NAME).dll
DISTNAME = lib$(OBJLIB_NAME)-$(VERSION)
DEPENDFILE = .depend
LINKPARAMS = -Wl,--out-implib,libUDPTCPNetwork.a

@ -0,0 +1,108 @@
# .SILENT:
#
# to build the windows version please install MSYS2
#
# this file should not been used anymore use make configwindows; make ; make install instead
#
#
VERSION=0.1
PREFIX=/usr
ETCPREFIX=/etc
WINVERSION = 1
CXX=g++
CXXFLAGS= -ggdb -fPIC -Wno-write-strings -I./ -std=c++11 -DBUILD_WINDOWS
LDFLAGS= -lm -lssl -lcrypto -lwsock32 -lws2_32
DEFAULT_TCPPORT=6131
DEFAULT_UDPPORT=6131
DEFAULT_SERVER=localhost
OBJLIB=network.o udp.o tcp.o unix.o ssl.o
INCLIB=config.h UDPTCPNetwork.h
OBJLIB_NAME=UDPTCPNetwork
TARGET=UDPTCPNetwork.dll
DISTNAME=libUDPTCPNetwork-$(VERSION)
DEPENDFILE=.depend
all: dep $(TARGET) test-udp test-tcp test-ssl
test-tcp: $(TARGET) test-tcp.o config.h
$(CXX) test-tcp.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
test-ssl: $(TARGET) test-ssl.o config.h
$(CXX) test-ssl.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
test-udp: $(TARGET) test-udp.o config.h
$(CXX) test-udp.o -o $@ -lUDPTCPNetwork -L./ -I./ $(LDFLAGS)
keygen:
# openssl req -nodes -new -newkey rsa:2048 -sha256 -out csr.pem -keyout privkey.pem
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privkey.pem -out cert.pem
install: $(TARGET)
cp -f $(TARGET) $(PREFIX)/lib/
cp -f UDPTCPNetwork.h $(PREFIX)/include/
uninstall:
rm -f $(PREFIX)/lib/$(TARGET)
rm -f $(PREFIX)/lib/lib$(OBJLIB_NAME).so
rm -f $(PREFIX)/include/UDPTCPNetwork.h
rebuild: clean all
$(TARGET): $(OBJLIB) $(INCLIB)
$(CXX) -shared $(LINKPARAMS) -o $(TARGET) $^ $(LDFLAGS)
ln -sf $(TARGET) lib$(OBJLIB_NAME).so
ar rcs lib$(OBJLIB_NAME).a $(OBJLIB)
dep:
$(CXX) -MM `ls *.cc` $(CXXFLAGS) > $(DEPENDFILE)
clean:
rm test-tcp -rf
rm test-udp -rf
rm test-ssl -rf
rm -rf gmon.out
rm *.s -rf
rm *.a -rf
rm -rf *.dll
rm *.o -rf
rm *.oo -rf
rm *~ -rf
rm -rf config.h
rm -rf .depend
rm -rf *.so
rm -rf *.a
rm -rf *.so.*
rm -rf *.pem -rf
cleanall: clean
source: cleanall
config:
echo "#ifndef _CONFIG_H_" > config.h
echo "#define _CONFIG_H_" >> config.h
echo "" >> config.h
echo "#define UDPTCPNETWORK_VERSION \"$(VERSION)\"" >> config.h
echo "" >> config.h
echo "#define PREFIX \"$(PREFIX)\"" >> config.h
echo "#define ETCPREFIX \"$(ETCPREFIX)\"" >> config.h
echo "" >> config.h
echo "#endif" >> config.h
dist: clean
mkdir -p $(DISTNAME)
cp -rf Makefile $(DISTNAME)
cp -rf *.h $(DISTNAME)
cp -rf *.cc $(DISTNAME)
tar cvzf $(DISTNAME).tgz --exclude=*/CVS/* --exclude=*/CVS/ $(DISTNAME)
rm -rf $(DISTNAME)
-include $(DEPENDFILE)

@ -2,14 +2,53 @@
#ifndef _UDPTCPNETWORK_H_
#define _UDPTCPNETWORK_H_
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#define WIN32_LEAN_AND_MEAN
#define _NTDDI_VERSION_FROM_WIN32_WINNT2(ver) ver##0000
#define _NTDDI_VERSION_FROM_WIN32_WINNT(ver) _NTDDI_VERSION_FROM_WIN32_WINNT2(ver)
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x501
#endif
#ifndef NTDDI_VERSION
# define NTDDI_VERSION _NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)
#endif
#include <winsock2.h>
#include <io.h>
#include <Ws2tcpip.h>
#include <string.h>
#ifndef bzero
#define bzero(__z__, __x__) memset (__z__, 0x0, __x__)
#endif
#ifndef MSG_NOSIGNAL
# define MSG_NOSIGNAL 0
#endif
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/un.h>
#endif
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string>
using namespace std;
#define SOCKET int
#define NET_HOSTLEN 256
#define NET_PORTLEN 6
#define NET_BUFFERSIZE 1024
@ -25,8 +64,9 @@ using namespace std;
int dns_filladdr (string host, string port, int ai_family,
struct sockaddr_storage *sAddr);
char *itoa(char* buffer, int number, int size);
void UDPTCPNetwork_Startup();
extern int UDPTCPNetwork_init;
#define UDPTCPNetwork() if(UDPTCPNetwork_init == 0) UDPTCPNetwork_Startup()
/************************************************************************
*
@ -35,7 +75,7 @@ char *itoa(char* buffer, int number, int size);
*/
class UDP {
private:
int sock;
SOCKET sock;
int localport;
size_t readcnt;
size_t writecnt;
@ -46,6 +86,7 @@ public:
int Listen(int port);
int SetBlocked(int bl);
long int ReadTimeout(string *srcaddr, char *buffer, long int len, int timeout_ms);
long int Read(string *srcaddr, char *buffer, long int len);
long int Write(string destaddr, char *buffer, long int len);
@ -63,24 +104,25 @@ public:
*/
class TCP {
private:
int sock;
// struct sockaddr_storage localaddr;
// struct sockaddr_storage remoteaddr;
SOCKET sock;
struct sockaddr_storage peeraddr;
string remote_host;
string remote_port;
int readcnt;
int writecnt;
int islisten;
int WebHeaderGetParamValue(std::string line, std::string *parm, std::string *value);
public:
TCP();
TCP(int s);
TCP(SOCKET s);
TCP(string h, string p);
TCP(string hostport, int defaultport);
~TCP();
int Connect();
int Connect(string h, string p);
int Connect(string host, int defaultport);
int Connect(string hostport, int defaultport);
long int ReadPop (char *buffer, long int pktlen, long int bufferlen);
long int ReadTimeout(char *buffer, long int len, int timeout);
long int Read(char *buffer, long int len);
@ -88,18 +130,92 @@ public:
void Close();
int IsConnected();
int IsData(int timeout); // timeout in ms;
int IsListen() { return islisten; };
int Listen(int port);
TCP* Accept();
int GetSocket() { return sock; };
void SetSocket(int s, struct sockaddr_storage *saddr, int saddrlen);
SOCKET GetSocket() { return sock; };
void SetSocket(SOCKET s, struct sockaddr_storage *saddr, socklen_t saddrlen);
const string GetRemoteAddr();
const string GetLocalAddr();
const string WebGetURLHost (string url);
const string WebGetURLPort (string url);
const string WebGetURLFile (string url);
int WebGetFile (string url, char *buffer, int maxsize);
int WebGetURLElements (string url, string *host, string *port, string *file);
int WebGetFile (string url, char *buffer, int maxsize, char *formdata);
int WebGetFile (string url, char *buffer, int maxsize, char *formdata, int timeout_ms);
};
/************************************************************************
* SSL functions
*/
class SSLSocket {
private:
int readcnt;
int writecnt;
string certfile;
string keyfile;
int timeout;
SSL *ssl;
SSL_CTX *ctx;
struct timeval timeout_start;
int NewServerCTX();
int NewClientCTX();
void TimeoutReset();
int TimeoutTime();
public:
int sslerror;
SSLSocket();
~SSLSocket();
const string GetSSLErrorText(int err);
int SetCertificat(string certf, string keyf);
int Connect(int sockfd, int block_timeout);
int Accept(int sockfd, int block_timeout);
long int Read(char *buffer, long int len);
long int Write(char *buffer, long int len);
int Close(); // returns socket
};
/************************************************************************
* unix socket related functions
*/
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
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
#endif

@ -1,11 +1,6 @@
#include "UDPTCPNetwork.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> /* close() */
#include <string.h> /* memset() */
@ -13,13 +8,12 @@
using namespace std;
char dnsip[NET_HOSTLEN];
int UDPTCPNetwork_init = 0;
//
// convert host and port to sockaddr_in6
//
int dns_filladdr (string host, string port, int ai_family,
struct sockaddr_storage *sAddr) {
int dns_filladdr (string host, string port, int ai_family, struct sockaddr_storage *sAddr) {
struct addrinfo hints, *res;
int err;
@ -46,3 +40,29 @@ char* itoa(char* buffer, int number, int size) {
snprintf (buffer, size, "%d", number);
return buffer;
}
void UDPTCPNetwork_Startup() {
if (UDPTCPNetwork_init != 0) return;
printf ("%s\n", __FUNCTION__);
#ifdef BUILD_WINDOWS
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error: %d\n", err);
return;
}
#endif
UDPTCPNetwork_init = 1;
}

307
ssl.cc

@ -0,0 +1,307 @@
/*
*
*/
#include <stdio.h>
#include <unistd.h> /* close() */
#include <stdlib.h>
#include <string.h> /* memset() */
#include <errno.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "UDPTCPNetwork.h"
static int ssl_init = 0;
SSLSocket::SSLSocket() {
readcnt = 0;
writecnt = 0;
certfile = "";
keyfile = "";
sslerror = SSL_ERROR_NONE;
timeout = 0;
ctx = NULL;
ssl = NULL;
if (ssl_init == 0) {
ssl_init = 1;
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
}
};
SSLSocket::~SSLSocket() {
if (ctx) SSL_CTX_free(ctx);
ctx = NULL;
if (ssl) SSL_free(ssl);
ssl = NULL;
};
int SSLSocket::NewServerCTX() {
struct stat st;
if (stat (certfile.c_str(), &st)) return 0;
if (stat (keyfile.c_str(), &st)) return 0;
if (ctx) SSL_CTX_free(ctx);
ctx = NULL;
#ifdef SSLv23_method
ctx = SSL_CTX_new(TLS_server_method());
#else
ctx = SSL_CTX_new(TLSv1_2_server_method());
#endif
if (SSL_CTX_use_certificate_file(ctx, certfile.c_str(), SSL_FILETYPE_PEM) <= 0 ) {
ERR_print_errors_fp(stderr);
if (ctx) SSL_CTX_free(ctx);
ctx = NULL;
errno = EPROTO;
return 0;
}
if ( SSL_CTX_use_PrivateKey_file(ctx, keyfile.c_str(), SSL_FILETYPE_PEM) <= 0 ) {
ERR_print_errors_fp(stderr);
if (ctx) SSL_CTX_free(ctx);
ctx = NULL;
errno = EPROTO;
return 0;
}
if (!SSL_CTX_check_private_key(ctx)) {
if (ctx) SSL_CTX_free(ctx);
ctx = NULL;
errno = EPROTO;
return 0;
}
return 1;
};
int SSLSocket::NewClientCTX() {
if (ctx) SSL_CTX_free(ctx);
ctx = NULL;
#ifdef SSLv23_method
ctx = SSL_CTX_new(TLS_client_method());
#else
ctx = SSL_CTX_new(TLSv1_2_client_method());
#endif
return 1;
};
int SSLSocket::SetCertificat(string certf, string keyf) {
certfile = certf;
keyfile = keyf;
return 1;
};
int SSLSocket::Connect (int sockfd, int block_timeout) {
int flags, res;
TimeoutReset();
sslerror = SSL_ERROR_NONE;
NewClientCTX();
timeout = block_timeout;
if (sockfd > 0 && block_timeout > 0) {
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
u_long mode = 1;
ioctlsocket(sockfd, FIONBIO, &mode);
#else
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
#endif
}
ssl = SSL_new(ctx);
SSL_set_fd (ssl, sockfd);
do {
res = SSL_connect(ssl);
if (res == -1) sslerror = SSL_get_error(ssl, -1);
} while (res == -1 && TimeoutTime() < timeout &&
(sslerror == SSL_ERROR_WANT_READ || sslerror == SSL_ERROR_WANT_WRITE));
if (res == -1) return 0;
return 1;
};
int SSLSocket::Accept (int sockfd, int block_timeout) {
int flags, res;
TimeoutReset();
sslerror = SSL_ERROR_NONE;
timeout = block_timeout;
NewServerCTX();
if (sockfd > 0 && block_timeout > 0) {
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
u_long mode = 1;
ioctlsocket(sockfd, FIONBIO, &mode);
#else
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
#endif
}
ssl = SSL_new(ctx);
SSL_set_fd (ssl, sockfd);
do {
res = SSL_accept(ssl);
if (res == -1) sslerror = SSL_get_error(ssl, -1);
} while (res == -1 && TimeoutTime() < timeout &&
(sslerror == SSL_ERROR_WANT_READ || sslerror == SSL_ERROR_WANT_WRITE));
return 1;
};
const string SSLSocket::GetSSLErrorText(int err) {
string s;
switch (err) {
case SSL_ERROR_NONE:
s = "SSL_ERROR_NONE";
break;
case SSL_ERROR_SSL:
s = "SSL_ERROR_SSL";
break;
case SSL_ERROR_WANT_READ:
s = "SSL_ERROR_WANT_READ";
break;
case SSL_ERROR_WANT_WRITE:
s = "SSL_ERROR_WANT_WRITE";
break;
case SSL_ERROR_SYSCALL:
s = "SSL_ERROR_SYSCALL";
break;
case SSL_ERROR_WANT_CONNECT:
s = "SSL_ERROR_WANT_CONNECT";
break;
case SSL_ERROR_ZERO_RETURN:
s = "SSL_ERROR_ZERO_RETURN";
break;
case SSL_ERROR_WANT_ACCEPT:
s = "SSL_ERROR_WANT_ACCEPT";
break;
default:
s = "SSL_ERROR unknown " + to_string(err);
break;
}
return s;
}
//
// close ssl and return socket.
int SSLSocket::Close () {
int sock = 0;
int flags;
if (ssl) {
sock = SSL_get_fd(ssl);
SSL_free(ssl);
ssl = NULL;
}
if (ctx) {
SSL_CTX_free(ctx);
ctx = NULL;
}
if (sock > 0 && timeout > 0) {
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
u_long mode = 0;
ioctlsocket(sock, FIONBIO, &mode);
#else
flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags & ~(O_NONBLOCK));
#endif
}
return sock;
};
//
//
long int SSLSocket::Read (char *buffer, long int len) {
int ret;
sslerror = SSL_ERROR_NONE;
TimeoutReset();
if (!ssl) {
errno = EPROTO;
return -1;
}
do {
ret = SSL_read(ssl, buffer, len);
if (ret == -1) sslerror = SSL_get_error(ssl, -1);
} while (ret == -1 && TimeoutTime() < timeout &&
(sslerror == SSL_ERROR_WANT_READ || sslerror == SSL_ERROR_WANT_WRITE));
return ret;
};
//
//
long int SSLSocket::Write (char *buffer, long int len) {
int ret;
sslerror = SSL_ERROR_NONE;
TimeoutReset();
if (!ssl) {
errno = EPROTO;
return -1;
}
do {
ret = SSL_write(ssl, buffer, len);
if (ret == -1) sslerror = SSL_get_error(ssl, -1);
} while (ret == -1 && TimeoutTime() < timeout &&
(sslerror == SSL_ERROR_WANT_READ || sslerror == SSL_ERROR_WANT_WRITE));
return ret;
};
//
// Reset Timeout Timer
void SSLSocket::TimeoutReset() {
gettimeofday (&timeout_start, NULL);
};
//
// Return time which has past since reset in ms.
int SSLSocket::TimeoutTime() {
struct timeval tv;
gettimeofday (&tv, NULL);
return ((tv.tv_sec-timeout_start.tv_sec) * 1000) +
((tv.tv_usec-timeout_start.tv_usec) / 1000);
};

457
tcp.cc

@ -1,28 +1,52 @@
/*
*
*/
/////////////////////////////////////////////////////////////////////////////////
//
// tcp.cc is part of TestModbus-Server.
//
/////////////////////////////////////////////////////////////////////////////////
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "UDPTCPNetwork.h"
#include <stdio.h>
#include <unistd.h> /* close() */
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
#include <unistd.h> /* close() */
#endif
#include <stdlib.h>
#include <string.h> /* memset() */
#include <errno.h>
#include "UDPTCPNetwork.h"
using namespace std;
int __tcpinit__ = 0;
TCP::~TCP() {
Close();
}
TCP::TCP() {
if (__tcpinit__ == 0) {
#ifdef BUILD_WINDOWS
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error: %d\n", err);
return;
}
#endif
__tcpinit__ = 1;
}
sock = 0;
writecnt = 0;
readcnt = 0;
islisten = 0;
};
TCP::TCP(int s) {
@ -32,6 +56,7 @@ TCP::TCP(int s) {
// memset (&remoteaddr, 0x0, sizeof(remoteaddr));
writecnt = 0;
readcnt = 0;
islisten = 0;
};
TCP::TCP(string h, string p) {
@ -46,10 +71,14 @@ int TCP::Listen(int port) {
struct addrinfo hints, *res, *rp;
if (sock > 0) Close();
bzero (&hints, sizeof (struct addrinfo));
// FIXME: solution to get both (IPV4 and IPV6) to work at the same time?
bzero (&hints, sizeof (struct addrinfo));
hints.ai_flags = AI_PASSIVE;
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
hints.ai_family = AF_INET;
#else
hints.ai_family = AF_INET6;
#endif
hints.ai_socktype = SOCK_STREAM;
if ((err = getaddrinfo (NULL, itoa(buffer, port, 32), &hints, &res)) != 0) {
return 0;
@ -62,15 +91,17 @@ int TCP::Listen(int port) {
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock == -1) continue;
if ((err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i))) != 0) {
i = 1;
if ((err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (char*)&i, sizeof (i))) != 0) {
printf ("%s:%d setsockopt error\n", __FILE__, __LINE__);
}
if ((err = bind (sock, rp->ai_addr, rp->ai_addrlen)) < 0) {
close (sock);
sock = -1;
continue;
}
if (listen (sock, 8) < 0) {
if (listen (sock, 8) < 0) { // maximum of 8 connections at the time
close (sock);
sock = -1;
continue;
@ -84,6 +115,9 @@ int TCP::Listen(int port) {
sock = -1;
return 0;
}
islisten = 1;
return 1;
};
@ -91,19 +125,18 @@ int TCP::Listen(int port) {
TCP* TCP::Accept() {
fd_set rfds;
struct timeval tv;
int retval, newsock, err, i;
struct sockaddr_storage cli_addr;
unsigned int cli_len;
char host[NET_BUFFERSIZE];
char port[NET_BUFFERSIZE];
int retval;
SOCKET newsock;
struct sockaddr_storage cliaddr;
socklen_t cliaddr_len = sizeof(struct sockaddr_storage);
TCP *tcp = NULL;
if (sock <= 0) return NULL;
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) {
@ -112,13 +145,16 @@ TCP* TCP::Accept() {
else if (retval == -1) {
return NULL;
}
else if (retval) {
newsock = accept (sock, (struct sockaddr *) &cli_addr, &cli_len);
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
newsock = accept (sock, (struct sockaddr *) &cliaddr, (int*) &cliaddr_len);
#else
newsock = accept (sock, (struct sockaddr *) &cliaddr, &cliaddr_len);
#endif
if (newsock < 0) return NULL;
tcp = new TCP();
tcp->SetSocket(newsock, &cli_addr, cli_len);
tcp->SetSocket(newsock, &cliaddr, cliaddr_len);
return tcp;
}
return NULL;
@ -126,12 +162,6 @@ TCP* TCP::Accept() {
int TCP::Connect(string h, string p) {
int i = 0;
// memset (&localaddr, 0x0, sizeof(localaddr));
// memset (&remoteaddr, 0x0, sizeof(remoteaddr));
// i = dns_filladdr(h, p, AF_INET, &remoteaddr);
// if (i == 0) return 0;
remote_host = h;
remote_port = p;
@ -156,8 +186,9 @@ int TCP::Connect(string hostport, int defaultport) {
int TCP::Connect() {
int err, s;
int err, s = 0;
struct addrinfo hints, *res, *rp;
struct timeval timeout;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6
@ -165,9 +196,9 @@ int TCP::Connect() {
hints.ai_flags = 0;
hints.ai_protocol = 0;
s = getaddrinfo(remote_host.c_str(), remote_port.c_str(), &hints, &res);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
err = getaddrinfo(remote_host.c_str(), remote_port.c_str(), &hints, &res);
if (err != 0) {
fprintf(stderr, "getaddrinfo: Host:'%s' Port:'%s' Error:%s\n", remote_host.c_str(), remote_port.c_str(), gai_strerror(err));
return 0;
}
@ -175,10 +206,19 @@ int TCP::Connect() {
// walk through all results until we could connect
//
for (rp = res; rp != NULL; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock == -1) continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) break;
close(sock);
s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
// setup timeout to max 2 secs
timeout.tv_sec = 2;
timeout.tv_usec = 0;
setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
if (s == -1) continue;
if (connect(s, rp->ai_addr, rp->ai_addrlen) != -1) {
sock = s;
break;
}
close(s);
}
freeaddrinfo(res);
@ -205,12 +245,15 @@ long int TCP::Read(char *buffer, long int len) {
long int len_ = len;
if (sock <= 0) return -2;
len_ = read (sock, (void*)buffer, len);
// printf ("read: "); debug_mem(buffer, len_);
len_ = recv (sock, buffer, len, 0);
if (len_ < 0 && errno == EAGAIN) len_ = 0;
else if (len_ < 0 && errno != EAGAIN) {
// fprintf (stderr, "%s ERROR:%s\n", __FUNCTION__, strerror (errno));
#ifdef BUILD_WINDOWS
printf ("%s ERROR:%s\n", __FUNCTION__, strerror (errno));
#else
fprintf (stderr, "%s ERROR:%s\n", __FUNCTION__, strerror (errno));
#endif
len_ = -2;
}
else if (len_ == 0) len_ = -1;
@ -231,6 +274,9 @@ long int TCP::ReadTimeout(char *buffer, long int len, int timeout) {
};
//////////////////////////////////////////////////////////
//
// write data, generate no signal if some error occures
long int TCP::Write(char *buffer, long int len) {
int i;
int to = NET_MAX_RETRY;
@ -238,7 +284,7 @@ long int TCP::Write(char *buffer, long int len) {
if (sock <= 0) return -1;
do {
i = send (sock, buffer, len, 0);
i = send (sock, buffer, len, MSG_NOSIGNAL);
} while (i == -1 && (to--) > 0 && errno == EINTR);
if (i < 0) Close ();
@ -249,26 +295,41 @@ long int TCP::Write(char *buffer, long int len) {
void TCP::Close() {
#ifdef BUILD_WINDOWS
closesocket(sock);
#else
if (sock > 0) close (sock);
#endif
sock = -1;
islisten = false;
};
void TCP::SetSocket(int s, struct sockaddr_storage *saddr, int saddrlen) {
void TCP::SetSocket(SOCKET s, struct sockaddr_storage *saddr, socklen_t saddrlen) {
char host[NET_HOSTLEN];
char port[NET_PORTLEN];
int err;
if (sock > 0) Close();
if (s > 0) {
sock = s;
if (saddr != NULL) {
if ((err = getnameinfo ((struct sockaddr*) &saddr, saddrlen, host, NET_HOSTLEN,
memcpy (&peeraddr, saddr, sizeof(peeraddr));
if ((err = getnameinfo ((struct sockaddr*) saddr, saddrlen, host, NET_HOSTLEN,
port, NET_PORTLEN, NI_NUMERICHOST | NI_NUMERICSERV)) == 0) {
remote_host = host;
remote_port = port;
} else {
printf ("error: getnameinfo");
/* if (err == EAI_AGAIN) printf ("EAI_AGAIN\n");
if (err == EAI_BADFLAGS) printf ("EAI_BADFLAGS\n");
if (err == EAI_FAIL) printf ("EAI_FAIL\n");
if (err == EAI_FAMILY) printf ("EAI_FAMILY\n");
if (err == EAI_MEMORY) printf ("EAI_MEMORY\n");
if (err == EAI_NONAME) printf ("EAI_NONAME\n");
if (err == EAI_OVERFLOW) printf ("EAI_OVERFLOW\n");
if (err == EAI_SYSTEM) printf ("EAI_SYSTEM\n"); */ // windows seem to have different error codes
}
}
}
@ -302,53 +363,178 @@ int TCP::IsData(int timeout) {
};
int TCP::WebGetFile (string url, char *buffer, int maxsize) {
/*
* Read a single line and split in parameter and value
* if value and parm is set to NULL this field will not be set
*/
int TCP::WebHeaderGetParamValue(std::string line, std::string *parm, std::string *value) {
size_t pos = line.find(" ");
if (pos == std::string::npos) {
fprintf (stderr, "%s error with protocol. HTTP/ without space? Line:'%s'\n",
__FUNCTION__, line.c_str());
return -1;
}
if (parm != NULL) *parm = line.substr (0, pos);
if (value != NULL) *value = line.substr (pos+1, std::string::npos);
return 0;
}
/*
* read any data from server
* Return Value:
* on error: -1
* success : size of buffer
*/
int TCP::WebGetFile (string url, char *buffer, int maxsize, char *formdata) {
return WebGetFile(url, buffer, maxsize, formdata, 20000);
}
int TCP::WebGetFile (string url, char *buffer, int maxsize, char *formdata, int timeout_ms) {
char outdata[NET_BUFFERSIZE];
char indata[NET_BUFFERSIZE];
char host[NET_HOSTLEN];
char port[NET_PORTLEN];
int breakup, len, head, i, buffpos = 0;
string host, port, file;
int len, line_cnt, i, buffpos = 0, c;
string protocol = "";
string type = "";
string line = "";
string lineUP = "";
string status = "";
int chunked_transfer = 0;
int chunked_bytes = 0;
//
// clear input buffer
if (buffer == NULL) return -1;
buffer[0] = '\0';
WebGetURLElements(url, &host, &port, &file);
if (!IsConnected()) {
strncpy (host, WebGetURLHost (url).c_str(), NET_HOSTLEN);
strncpy (port, WebGetURLPort (url).c_str(), NET_PORTLEN);
Connect (host, port);
}
if (!IsConnected()) return -1;
//
// send http request
snprintf (outdata, NET_BUFFERSIZE, "GET %s HTTP/1.0\nUser-Agent: tcpclient \nHost: %s\n\n", WebGetURLFile (url).c_str(), host);
//
if (formdata == NULL)
snprintf (outdata, NET_BUFFERSIZE, "GET %s HTTP/1.0\r\nUser-Agent: unknown\r\nHost: %s\r\nAccept:*.*\r\n\r\n", file.c_str(), host.c_str());
else
snprintf (outdata, NET_BUFFERSIZE, "POST %s HTTP/1.1\r\nUser-Agent: unknown\r\nHost: %s\r\nContent-Length: %ld\r\nContent-Type: application/x-www-form-urlencoded\r\nAccept:*.*\r\n\r\n%s\r\n",
file.c_str(), host.c_str(), strlen (formdata), formdata);
Write (outdata, strlen (outdata));
// wait for data start
i = breakup = 0;
head = 1;
while (!breakup && head && (len = ReadTimeout (indata, NET_BUFFERSIZE-1, 2000)) >= 0) {
indata[len] = 0;
while (i < len -4 && head && !breakup) {
if (indata[i] == 0x0d && indata [i+1] == 0x0a && indata [i+2] == 0x0d && indata [i+3] == 0x0a) {
head = 0;
i = i + 4;
buffpos = len-i;
if (buffpos > maxsize) buffpos = maxsize;
memcpy (buffer, indata+i, buffpos);
//
// read header
//
indata[0] = '\0';
len = ReadTimeout (indata, NET_BUFFERSIZE-1, timeout_ms);
if (len <= 0) {
fprintf (stderr, "%s:%d reading header Error:%s\n", __FILE__, __LINE__, strerror(errno));
return -1;
}
indata[len] = 0;
//
// read all lines until an empty line is reached
for (line = "", lineUP = "", line_cnt = 0, i = 0; i < len; i++) {
if (indata[i] == '\n' || indata[i] == '\r') {
if (i < len && (indata[i+1] == '\n' || indata[i+1] == '\r')) i++;
if (line.length() == 0) {
i++;
break; // break loop, read data
}
else if (strncmp (indata+i, "Content-Length:", 15) == 0) {
i = i + 16;
//
// HTTP Header
else if (lineUP.find ("HTTP/") == 0) {
if (WebHeaderGetParamValue(line, &protocol, &status) < 0) {
fprintf (stderr, "%s:%d reading header Error:%s\n", __FILE__, __LINE__, strerror(errno));
return -1;
}
}
else if (strncmp (indata+i, "403 ", 4) == 0) breakup = 1;
else i++;
//
// Transfer Encoding
else if (lineUP.find ("TRANSFER-ENCODING:") == 0) {
std::string temp;
if (WebHeaderGetParamValue(line, NULL, &temp) < 0) {
fprintf (stderr, "%s:%d reading header Error:%s\n", __FILE__, __LINE__, strerror(errno));
return -1;
}
for (int j = 0; (long int)j < (long int) temp.length(); j++)
temp[i] = toupper(temp[i]);
if (temp.find("chunked") != std::string::npos) chunked_transfer = 1;
}
//
// type of file
else if (lineUP.find ("CONTENT-TYPE:") == 0) {
if (WebHeaderGetParamValue(line, NULL, &type) < 0) {
fprintf (stderr, "%s:%d reading header Error:%s\n", __FILE__, __LINE__, strerror(errno));
return -1;
}
}
lineUP = line = "";
line_cnt++;
}
else {
line += indata[i];
lineUP += toupper(indata[i]);
}
}
//
// chunked data?
// size we need to load
if (chunked_transfer) {
int v;
for (v = 0, line_cnt = 0; i < len; i++) {
if (indata[i] == '\r' || indata[i] == '\n') {
i++;
if (i < len && (indata[i] == '\n' || indata[i] == '\r')) i++;
chunked_bytes = v;
break;
}
else {
v = v << 4;
indata[i] = tolower(indata[i]);
if (indata[i] >= '0' && indata[i] <= '9') v += (indata[i] - '0');
else if (indata[i] >= 'a' && indata[i] <= 'f') v += (10 + indata[i] - 'a');
else {
fprintf (stderr, "%s:%d reading chunk bytes, invalid HEX code indata:'%s'\n", __FILE__, __LINE__, indata);
errno = EINVAL;
return -1;
}
}
}
//
// check bytes to read, and remove these from chunked_bytes
if (chunked_bytes < len-i) c = chunked_bytes;
else c = len-i;
chunked_bytes -= c;
}
else c = len-i;
// read data
while (!breakup && (len = ReadTimeout (indata, NET_BUFFERSIZE-1, 2000)) >= 0) {
//
// read data, but first copy the left over bytes into the output buffer
if (c > 0) memcpy (buffer, indata+i, c);
buffpos = c;
while ((len = ReadTimeout (indata, NET_BUFFERSIZE-1, 2000)) > 0) {
i = len;
if (i > maxsize-buffpos) i = maxsize-buffpos;
if (i > 0) {
if (chunked_transfer) {
if (i > chunked_bytes) i = chunked_bytes;
chunked_bytes -= i;
}
memcpy (buffer+buffpos, indata, i);
buffpos += i;
}
@ -357,45 +543,110 @@ int TCP::WebGetFile (string url, char *buffer, int maxsize) {
return buffpos;
};
const string TCP::WebGetURLHost (string url) {
string result;
int posSServPort = 7; // begin server:port
int posEServPort = 0; // end Server:Port
int posPort = -1; // port Position
posEServPort = url.find("/", 7);
result = url.substr (posSServPort, posEServPort-posSServPort);
posPort = result.find(":");
if (posPort > 0)
result = url.substr (posSServPort, posPort);
// FIXME: everything below here is wrong...
/*
* fills the elements and returns 0 on success. Returns set bits if value was found
* 1 ... hostname
* 2 ... port
* 3 ... file
*/
enum _webgeturl_step_ {
_WEBGET_URL_PROTO = 0,
_WEBGET_URL_SERVER,
_WEBGET_URL_PORT,
_WEBGET_URL_FILE
};
int TCP::WebGetURLElements (string url, string *host, string *port, string *file) {
string h = "";
string p = "";
string f = "/";
const string prefix1 = "HTTP://";
const string prefix2 = "HTTPS://";
int retval = 0;
int i;
int curpos = 0;
int step = _WEBGET_URL_PROTO;
for (i = 0; i < 5; i++) url[i] = toupper(url[i]);
//
// try to find the protocol and //
if (url.find(prefix1) == 0) {
retval |= 2;
p = "80";
curpos = prefix1.length();
}
else if (url.find(prefix2) == 0) {
retval |= 2;
p = "443";
curpos = prefix2.length();
// FIXME: SSL needs to be implemented
}
else {
if (url.find ("//") != std::string::npos) {
errno = EPROTONOSUPPORT;
return -1;
}
else curpos = 0;
}
for (step = _WEBGET_URL_SERVER;curpos < (int)url.length(); curpos++) {
if (step == _WEBGET_URL_SERVER) {
if (url[curpos] == '/') step = _WEBGET_URL_FILE;
else if (url[curpos] == ':') {
step = _WEBGET_URL_PORT;
p = "";
}
else {
h += url[curpos];
retval |= 1;
}
}
else if (step == _WEBGET_URL_PORT) {
if (url[curpos] == '/') step = _WEBGET_URL_FILE;
else {
p += url[curpos];
retval |= 2;
}
}
else if (step == _WEBGET_URL_FILE) {
f += url[curpos];
retval |= 3;
}
}
return result;
if (host != NULL) *host = h;
if (file != NULL) *file = f;
if (port != NULL) *port = p;
return retval;
};
const string TCP::WebGetURLPort (string url) {
string result;
int posSServPort = 7; // begin server:port
int posEServPort = 0; // end Server:Port
int posPort = -1; // port Position
posEServPort = url.find("/", 7);
result = url.substr (posSServPort, posEServPort-posSServPort);
posPort = result.find(":");
if (posPort > 0)
result = result.substr (posPort+1);
else
result = "80";
return result;
const string TCP::GetRemoteAddr() {
string ret = "";
socklen_t addrlen = sizeof (peeraddr);
char host[256] = "";
char port[256] = "";
if (getnameinfo ((struct sockaddr*)&peeraddr, addrlen, host, 255, port, 255, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
printf ("getnameinfo error: %s\n", strerror(errno));
}
ret = (string)host + ":" + (string)port;
return ret;
};
const string TCP::WebGetURLFile (string url) {
string result;
int posEServPort = 0; // end Server:Port
posEServPort = url.find("/", 7);
result = url.substr (posEServPort);
const string TCP::GetLocalAddr() {
string ret;
return result;
return ret;
};

@ -0,0 +1,157 @@
#include <string.h>
#include <unistd.h>
#include "UDPTCPNetwork.h"
#define DEFAULT_PORT 12345
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
void server () {
TCP tcpserver;
TCP *connection;
SSLSocket ssl;
int i, timeout;
pid_t pid;
time_t time_start = time (NULL);
time_t time_now = time (NULL);
char buffer[NET_BUFFERSIZE];
//
// start the server
if (tcpserver.Listen(DEFAULT_PORT) != 1) {
printf ("cloud not start the tcp server\n");
exit (1);
}
//
// init SSL
if (ssl.SetCertificat("cert.pem", "privkey.pem") != 1) {
printf ("SetCertificat error:%s\n", strerror(errno));
exit (1);
}
//
// check for connections
for (;time_now - time_start < 10; time_now = time(NULL)) {
connection = tcpserver.Accept();
if (connection != NULL) {
//
// someone connected - create new process
// take care of parallel processing (parent is always the server)
//
printf (" server: got a connection forking new process\n");
pid = fork();
if (pid == 0) {
//
// child process - always close server since it will handeled
// by the parent process. Make sure the client exits and never
// returns.
tcpserver.Close();
if (ssl.Accept(connection->GetSocket(), 0) != 1) {
printf ("could not establish SSL connection:%s\n", strerror(errno));
exit (1);
}
i = ssl.Read(buffer, NET_BUFFERSIZE);
if (i > 0) {
int c;
printf (" server: got: '%s'\n", buffer);
for (c = 0; c < i; c++) buffer[c] = toupper(buffer[c]);
ssl.Write(buffer, i);
}
//
// just delete the class object, it will close the client connection
ssl.Close();
delete (connection);
//
// exit child process
exit (1);
}
else {
//
// parent process - just close the client connection
// it will be handeled by the child process.
delete (connection);
}
}
usleep (25000);
}
};
void client () {
TCP tcpclient;
SSLSocket ssl;
char buffer[NET_BUFFERSIZE];
int i, res;
sleep (1); // wait one second to start the server
//
// connect to the server
if (tcpclient.Connect ("localhost", DEFAULT_PORT) != 1) {
printf ("cloud not connect to server\n");
exit (1);
}
res = ssl.Connect(tcpclient.GetSocket(), 100);
if (res == -1) {
printf ("could not establish SSL connection:errno:%s sslerror:%s\n", strerror(errno), ssl.GetSSLErrorText(ssl.sslerror).c_str());
exit (1);
}
//
// send some data
snprintf (buffer, NET_BUFFERSIZE, "nur ein kleiner Test.");
printf ("client:send '%s' to the server.\n", buffer);
if (ssl.Write(buffer, strlen (buffer)) != strlen (buffer)) {
printf ("could not send all data. errno:%s sslerror:%s\n", strerror(errno), ssl.GetSSLErrorText(ssl.sslerror).c_str());
exit (1);
}
//
// read some data (wait maximum 10x1000ms)
for (i = 10; i > 0; i--)
if (ssl.Read(buffer, NET_BUFFERSIZE) > 0) {
printf ("client:got '%s' from server.\n", buffer);
break;
}
//
// close connection
ssl.Close();
tcpclient.Close();
};
#endif
int main (int argc, char **argv) {
pid_t pid;
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
pid = fork();
if (pid == 0) { // child process
printf ("start client\n");
client();
printf ("start client\n");
client();
printf ("start client\n");
client();
printf ("start client\n");
client();
}
else { // parent process
server();
}
#endif
return 0;
};

@ -6,12 +6,16 @@
#define DEFAULT_PORT 12345
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
void server () {
TCP tcpserver;
TCP *connection;
int i, timeout;
pid_t pid;
time_t time_start = time (NULL);
time_t time_now = time (NULL);
char buffer[NET_BUFFERSIZE];
//
@ -23,7 +27,7 @@ void server () {
//
// check for connections
for (timeout = 5; timeout > 0; timeout--) {
for (;time_now - time_start < 10; time_now = time(NULL)) {
connection = tcpserver.Accept();
if (connection != NULL) {
//
@ -38,7 +42,7 @@ void server () {
// by the parent process. Make sure the client exits and never
// returns.
tcpserver.Close();
i = connection->ReadTimeout(buffer, NET_BUFFERSIZE, 1000);
i = connection->Read(buffer, NET_BUFFERSIZE);
if (i > 0) {
int c;
@ -61,7 +65,7 @@ void server () {
delete (connection);
}
}
sleep (1);
usleep (25000);
}
};
@ -80,6 +84,8 @@ void client () {
exit (1);
}
sleep (1);
//
// send some data
snprintf (buffer, NET_BUFFERSIZE, "nur ein kleiner Test.");
@ -102,11 +108,13 @@ void client () {
tcpclient.Close();
};
#endif
int main (int argc, char **argv) {
pid_t pid;
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
pid = fork();
if (pid == 0) { // child process
client();
@ -117,6 +125,7 @@ int main (int argc, char **argv) {
else { // parent process
server();
}
#endif
return 0;
};

@ -0,0 +1,69 @@
#include <string.h>
#include <unistd.h>
#include "UDPTCPNetwork.h"
#define DEFAULT_PORT 12345
int main (int argc, char **argv) {
TCP tcpclient;
char buffer[NET_BUFFERSIZE];
int i;
int loop;
#ifdef BUILD_WINDOWS
char iobuffer[16];
setvbuf (stdout, iobuffer, _IONBF, 16);
#endif
//
// connect to the server
if (argc == 2) {
if (tcpclient.Connect(argv[1], DEFAULT_PORT) != 1) {
printf ("connect to: %s:%d\n",argv[1], DEFAULT_PORT);
printf ("cloud not connect to server\n");
exit (1);
}
}
else if (argc == 3) {
printf ("connect to: %s:%d\n",argv[1], atoi(argv[2]));
if (tcpclient.Connect(argv[1], argv[2]) != 1) {
printf ("cloud not connect to server\n");
exit (1);
}
}
else {
printf ("\nplease use the ollowing commands:\n\n");
printf (" test-tcpclient destination\n");
printf (" test-tcpclient destination port\n");
return 1;
}
for (loop = 0; loop < 5; loop++) {
//
// send some data
snprintf (buffer, NET_BUFFERSIZE, "nur ein kleiner Test.");
printf ("client:send '%s' to the server.\n", buffer);
if (tcpclient.Write(buffer, strlen (buffer)) != strlen (buffer)) {
printf ("could not send all data.\n");
exit (1);
}
//
// read some data (wait maximum 10x1000ms)
for (i = 10; i > 0; i--)
if (tcpclient.ReadTimeout(buffer, NET_BUFFERSIZE, 1000) > 0) {
printf ("client:got '%s' from server.\n", buffer);
break;
}
sleep (1);
}
//
// close connection
tcpclient.Close();
return 0;
};

@ -0,0 +1,62 @@
#include <string.h>
#include <unistd.h>
#include "UDPTCPNetwork.h"
#define DEFAULT_PORT 12345
int main(int argc, char **argv) {
TCP tcpserver;
TCP *connection = NULL;
int i, timeout;
pid_t pid;
time_t time_start = time (NULL);
time_t time_now = time (NULL);
char buffer[NET_BUFFERSIZE];
#ifdef BUILD_WINDOWS
char iobuffer[16];
setvbuf (stdout, iobuffer, _IONBF, 16);
#endif
//
// start the server
if (tcpserver.Listen(DEFAULT_PORT) != 1) {
printf ("cloud not start the tcp server\n");
exit (1);
}
printf ("server started\n");
//
// check for connections
while(1) {
if (connection == NULL) {
connection = tcpserver.Accept();
printf ("accept connection? %p\n", connection);
if (connection != NULL)
printf (" server: got a new connection from:%s\n", connection->GetRemoteAddr().c_str());
}
if (connection != NULL) {
memset (buffer, 0x0, NET_BUFFERSIZE);
i = connection->ReadTimeout(buffer, NET_BUFFERSIZE, 100);
if (i > 0) {
int c;
printf (" server: (child) got: '%s'\n", buffer);
for (c = 0; c < i; c++) buffer[c] = toupper(buffer[c]);
connection->Write(buffer, i);
}
else if (i < 0) {
delete connection;
connection = NULL;
}
}
usleep (25000);
}
tcpserver.Close();
};

@ -79,6 +79,8 @@ int main (int argc, char **argv) {
pid_t pid;
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
pid = fork();
if (pid == 0) { // child process
client.Loop ();
@ -86,7 +88,7 @@ int main (int argc, char **argv) {
else { // parent process
server.Loop ();
}
#endif
return 0;
};

@ -2,11 +2,7 @@
*
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h> /* close() */
#include <stdlib.h>
@ -16,6 +12,7 @@
#include "UDPTCPNetwork.h"
UDP::UDP() {
UDPTCPNetwork();
sock = -1;
localport = -1;
writecnt = 0;
@ -93,6 +90,21 @@ long int UDP::Read(string *source, char *buffer, long int len) {
}
int UDP::SetBlocked(int bl) {
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
u_long mode = bl;
return ioctlsocket(sock, FIONBIO, &mode);
#else
int flags = fcntl(sock, F_GETFL, 0);
if (bl) flags &= ~O_NONBLOCK;
else flags |= O_NONBLOCK;
return fcntl(sock, F_SETFL, flags | O_NONBLOCK);
#endif
}
long int UDP::Write(string destaddr, char *buffer, long int len) {
int s;
int addrlen = sizeof (struct sockaddr_in);

@ -0,0 +1,210 @@
/*
*
*/
#include <stdio.h>
#include <unistd.h> /* close() */
#include <stdlib.h>
#include <string.h> /* memset() */
#include <errno.h>
#include <string.h>
#include "UDPTCPNetwork.h"
// for now no support on windows
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#warning UNIX socket are not supported on windows.
#else
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) {
return 0;
}
if (connect(sock,(struct sockaddr *) &addr, sizeof (addr)) == -1) {
close (sock);
sock = -1;
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;
};
#endif
Loading…
Cancel
Save