From 36879aa9c54f2066248d06549c4cfefce31968ce Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Sun, 27 Aug 2023 12:00:53 +0200 Subject: [PATCH] initial base codebase --- .gitignore | 2 + Changelog | 3 + LICENSE | 6 + Makefile.rules.crosswindows | 9 + Makefile.rules.linux | 8 + Makefile.rules.windows | 8 + client.cc | 52 ++++ client.h | 35 +++ copydlls.sh | 39 +++ copyshare.sh | 10 + tcp.cc | 519 ++++++++++++++++++++++++++++++++++++ tcp.h | 123 +++++++++ testmodbus-client.ui | 289 ++++++++++++++++++++ 13 files changed, 1103 insertions(+) create mode 100644 Changelog create mode 100644 LICENSE create mode 100644 Makefile.rules.crosswindows create mode 100644 Makefile.rules.linux create mode 100644 Makefile.rules.windows create mode 100644 client.cc create mode 100644 client.h create mode 100755 copydlls.sh create mode 100755 copyshare.sh create mode 100644 tcp.cc create mode 100644 tcp.h create mode 100644 testmodbus-client.ui diff --git a/.gitignore b/.gitignore index 52873f5..e3f130d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.project + # ---> Autotools # http://www.gnu.org/software/automake diff --git a/Changelog b/Changelog new file mode 100644 index 0000000..b1d89a7 --- /dev/null +++ b/Changelog @@ -0,0 +1,3 @@ +2023-08-27: +- prepare basic codebase + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fcff9ba --- /dev/null +++ b/LICENSE @@ -0,0 +1,6 @@ + +The license model for this software (TestModbus-Client) is not yet choosen. +At the moment you can use this software free of charge at your own risk. + +27.Aug.2023 Steffen Pohle + diff --git a/Makefile.rules.crosswindows b/Makefile.rules.crosswindows new file mode 100644 index 0000000..58a2bbe --- /dev/null +++ b/Makefile.rules.crosswindows @@ -0,0 +1,9 @@ + +TARGETEXT = .exe +CONFIGSET = YES +CROSSENV = /opt/W64-cross-compile/ +CPP = /usr/bin/x86_64-w64-mingw32-g++ +CPPFLAGS = -ggdb -Wall -O0 `PKG_CONFIG_PATH=$(CROSSENV)/lib/pkgconfig pkg-config --cflags gtk+-3.0 gmodule-export-2.0` -Wl,--export-dynamic -DBUILD_WINDOWS=1 -Wdeprecated +INCLUDES = +LDFLAGS = -lws2_32 +LIBS = `PKG_CONFIG_PATH=$(CROSSENV)/lib/pkgconfig pkg-config --libs gtk+-3.0 gmodule-export-2.0` -L/usr/lib -mwindows diff --git a/Makefile.rules.linux b/Makefile.rules.linux new file mode 100644 index 0000000..b5e0556 --- /dev/null +++ b/Makefile.rules.linux @@ -0,0 +1,8 @@ + +TARGETEXT = +CONFIGSET = YES +CPP = c++ +CPPFLAGS = -ggdb -Wall -O0 `pkg-config --cflags gtk+-3.0 gmodule-export-2.0` -Wl,--export-dynamic -I/usr/include -DBUILD_LINUX=1 +INCLUDES = +LDFLAGS = +LIBS = `pkg-config --libs gtk+-3.0 gmodule-export-2.0` -L/usr/lib diff --git a/Makefile.rules.windows b/Makefile.rules.windows new file mode 100644 index 0000000..826eb30 --- /dev/null +++ b/Makefile.rules.windows @@ -0,0 +1,8 @@ + +TARGETEXT = .exe +CONFIGSET = YES +CPP = g++ +CPPFLAGS = -ggdb -Wall -O0 `pkg-config --cflags gtk+-3.0 gmodule-export-2.0` -Wl,--export-dynamic -I/usr/include -DBUILD_WINDOWS=1 +INCLUDES = +LDFLAGS = -lWs2_32 +LIBS = `pkg-config --libs gtk+-3.0 gmodule-export-2.0` -L/usr/lib diff --git a/client.cc b/client.cc new file mode 100644 index 0000000..fc71d78 --- /dev/null +++ b/client.cc @@ -0,0 +1,52 @@ +#include + +#include "config.h" +#include "client.h" + +#define BUILDER_FILE "testmodbus-client.ui" + +/************************************************************************************ + * Global Variables + */ +GtkBuilder *_builder_ = NULL; // work around for the thread situation +gboolean modbuscli_callback(gpointer data); // callback for threads + +int main (int argc, char **argv) { + GtkBuilder *builder; + GObject *window; + +#ifdef BUILD_WINDOWS + char buffer[16]; + setvbuf (stdout, buffer, _IONBF, 16); +#endif + + printf ("TestModbus-Client - %s\n", VERSION); + printf (" https://steffen.gulpe.de/modbus-tcpip\n"); + printf (" written by Steffen Pohle \n"); + + gtk_init (&argc, &argv); + _builder_ = builder = gtk_builder_new (); + gtk_builder_add_from_file (builder, BUILDER_FILE, NULL); + gtk_builder_connect_signals(builder, builder); + + // + // #if defined _WIN32 || defined _WIN64 || defined __CYGWIN__ + // #else + // #endif + // + +// modbuscli.SetCallback(&modbus_callback); + window = gtk_builder_get_object (builder, "testmodbus-client"); + gtk_widget_show_all (GTK_WIDGET(window)); + gtk_main (); + + return 0; +} + + +gboolean modbuscli_callback(gpointer data) { + void *mdata = data; + free (mdata); + + return FALSE; +}; diff --git a/client.h b/client.h new file mode 100644 index 0000000..468b010 --- /dev/null +++ b/client.h @@ -0,0 +1,35 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// client.h is part of TestModbus-Client. +// +///////////////////////////////////////////////////////////////////////////////// + +#ifndef _CLIENT_H_ +#define _CLIENT_H_ + +#include +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +// *********************************************************************** +// +// main windows call backs +// + +G_MODULE_EXPORT gboolean modbus_callback (gpointer data); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/copydlls.sh b/copydlls.sh new file mode 100755 index 0000000..7b7cbb4 --- /dev/null +++ b/copydlls.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +CROSS_DEST_DIR=/opt/W64-cross-compile/lib +CROSS_COMPILER_DIR=/usr/x86_64-w64-mingw32/lib +CROSS_GCC_DIR=/usr/lib/gcc/x86_64-w64-mingw32/10-win32 + +cp -v $CROSS_COMPILER_DIR/zlib1.dll ./ + +# copy dll dependencys +copy_dependency() { + local I + for I in `strings $1 | grep -i '\.dll$' | grep -e "^lib"` + do + if [ -e ./$I ] + then + echo "File Exist" + + elif [ -e $CROSS_COMPILER_DIR/$I ] + then + cp -v $CROSS_COMPILER_DIR/$I ./ + copy_dependency $CROSS_COMPILER_DIR/$I + + elif [ -e $CROSS_GCC_DIR/$I ] + then + cp -v $CROSS_GCC_DIR/$I ./ + copy_dependency $CROSS_GCC_DIR/$I + + elif [ -e $CROSS_DEST_DIR/$I ] + then + cp -v $CROSS_DEST_DIR/$I ./ + copy_dependency $CROSS_DEST_DIR/$I + fi + + done +} + +copy_dependency testmodbus-server.exe +copy_dependency testmodbus-client.exe + diff --git a/copyshare.sh b/copyshare.sh new file mode 100755 index 0000000..2eb2180 --- /dev/null +++ b/copyshare.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +CROSS_PREFIX=/opt/W64-cross-compile + +mkdir share +cp -rf $CROSS_PREFIX/share/glib-2.0 share/glib-2.0 +cp -rf $CROSS_PREFIX/share/gtk-2.0 share/gtk-4.0 +cp -rf $CROSS_PREFIX/share/gtk-3.0 share/gtk-3.0 +cp -rf $CROSS_PREFIX/share/icons share/icons + diff --git a/tcp.cc b/tcp.cc new file mode 100644 index 0000000..8689944 --- /dev/null +++ b/tcp.cc @@ -0,0 +1,519 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// tcp.cc is part of TestModbus-Server. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "tcp.h" +#include +#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) +#else + #include /* close() */ +#endif +#include +#include /* memset() */ +#include + +using namespace std; + +int tcpinit; +// +// convert host and port to sockaddr_in6 +// +int dns_filladdr (string host, string port, int ai_family, struct sockaddr_storage *sAddr) { + struct addrinfo hints, *res; + int err; + + bzero (&hints, sizeof (struct addrinfo)); + hints.ai_family = ai_family; + hints.ai_socktype = SOCK_DGRAM; + + if ((err = getaddrinfo (host.c_str(), port.c_str(), &hints, &res)) < 0) { + fprintf (stdout, "dns_filladdr (getaddrinfo):%s\n", gai_strerror (err)); + return -1; + } + + memcpy (sAddr, res->ai_addr, res->ai_addrlen); + freeaddrinfo (res); + + return 1; +}; + + +// +// convert int to char* +// +char* itoa(char* buffer, int number, int size) { + snprintf (buffer, size, "%d", number); + return buffer; +} + + +TCP::~TCP() { + Close(); +} + +TCP::TCP() { + if (tcpinit == 0) { +#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) || defined(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) { + TCP(); + sock = s; +// memset (&localaddr, 0x0, sizeof(localaddr)); +// memset (&remoteaddr, 0x0, sizeof(remoteaddr)); + writecnt = 0; + readcnt = 0; + islisten = 0; +}; + +TCP::TCP(string h, string p) { + TCP(); + Connect (h,p); +}; + + +/* + * puts the tcp server to listen mode. This code works on linux with IPV4 and IPV6 + */ +int TCP::Listen(int port) { + char buffer[NET_BUFFERSIZE]; + int err, i; + struct addrinfo hints, *res, *rp; + + if (sock > 0) Close(); + 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; + } + + // + // 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; + + 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) { // maximum of 8 connections at the time + close (sock); + sock = -1; + continue; + } + break; + } + + freeaddrinfo (res); + + if (rp == NULL) { + sock = -1; + return 0; + } + + islisten = 1; + + return 1; +}; + + +TCP* TCP::Accept() { + fd_set rfds; + struct timeval tv; + 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 = 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) { +#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, &cliaddr, cliaddr_len); + + return tcp; + } + return NULL; +} + + +int TCP::Connect(string h, string p) { + remote_host = h; + remote_port = p; + + return Connect(); +}; + + +int TCP::Connect(string hostport, int defaultport) { + char buffer[32]; + int pos = hostport.rfind(':', hostport.length()); + if (pos == -1) { + remote_port = itoa (buffer, defaultport, 32); + remote_host = hostport; + } + else { + remote_port = hostport.substr (pos+1, hostport.length() - pos); + remote_host = hostport.substr (0, pos); + } + + return Connect(); +}; + + +int TCP::Connect() { + int err, s; + struct addrinfo hints, *res, *rp; + struct timeval timeout; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6 + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = 0; + hints.ai_protocol = 0; + + err = getaddrinfo(remote_host.c_str(), remote_port.c_str(), &hints, &res); + if (err != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err)); + return 0; + } + + // + // walk through all results until we could connect + // + for (rp = res; rp != NULL; rp = rp->ai_next) { + 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); + + // + // connect not successfull + // + if (rp == NULL) return 0; + + writecnt = 0; + readcnt = 0; + + return 1; +}; + + +long int TCP::ReadPop (char *buffer, long int pktlen, long int bufferlen) { + memmove (buffer, buffer+pktlen, bufferlen-pktlen); + return bufferlen-pktlen; +} + + +long int TCP::Read(char *buffer, long int len) { + long int len_ = len; + + if (sock <= 0) return -2; + len_ = recv (sock, buffer, len, 0); + + if (len_ < 0 && errno == EAGAIN) len_ = 0; + else if (len_ < 0 && errno != EAGAIN) { +#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; + if (len_ < 0) Close(); + + readcnt += len_; + + return len_; +}; + + +long int TCP::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 TCP::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 TCP::Close() { +#ifdef BUILD_WINDOWS + closesocket(sock); +#else + if (sock > 0) close (sock); +#endif + sock = -1; + islisten = false; +}; + + +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) { + 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 + } + } + } + else sock = -1; +}; + + +int TCP::IsConnected() { + return (sock > 0); +}; + + +int TCP::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; +}; + + +int TCP::WebGetFile (string url, char *buffer, int maxsize) { + char outdata[NET_BUFFERSIZE]; + char indata[NET_BUFFERSIZE]; + char host[NET_HOSTLEN]; + char port[NET_PORTLEN]; + int breakup, len, head, i, buffpos = 0; + + 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: unknown \nHost: %s\n\n", WebGetURLFile (url).c_str(), host); + 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); + } + + else if (strncmp (indata+i, "Content-Length:", 15) == 0) { + i = i + 16; + } + + else if (strncmp (indata+i, "403 ", 4) == 0) breakup = 1; + else i++; + } + } + + // read data + while (!breakup && (len = ReadTimeout (indata, NET_BUFFERSIZE-1, 2000)) >= 0) { + i = len; + if (i > maxsize-buffpos) i = maxsize-buffpos; + if (i > 0) { + memcpy (buffer+buffpos, indata, i); + buffpos += i; + } + } + + 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); + + return result; +}; + +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::WebGetURLFile (string url) { + string result; + int posEServPort = 0; // end Server:Port + + posEServPort = url.find("/", 7); + result = url.substr (posEServPort); + + 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::GetLocalAddr() { + string ret; + + return ret; +}; + + diff --git a/tcp.h b/tcp.h new file mode 100644 index 0000000..23ca6b9 --- /dev/null +++ b/tcp.h @@ -0,0 +1,123 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// tcp.h is part of TestModbus-Server. +// +///////////////////////////////////////////////////////////////////////////////// + +#ifndef _TCP_H_ +#define _TCP_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 +#include +#include +#include +#include + +#define socklen_t size_t + +#ifndef bzero +#define bzero(__z__, __x__) memset (__z__, 0x0, __x__) +#endif + +#ifndef MSG_NOSIGNAL +# define MSG_NOSIGNAL 0 +#endif + +#else + +#include +#include +#include +#include +#include +#include + +#endif + +#include + +using namespace std; + +#define SOCKET int + +#define NET_HOSTLEN 256 +#define NET_PORTLEN 6 +#define NET_BUFFERSIZE 1024 +#define NET_MAX_RETRY 5 // retry to send data EINTR +#define NET_MAX_TIMEOUT 30000 // timeout in ms + + +/************************************************************************ + * + * global functions needed for networking + * + */ +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; + + +/************************************************************************ + * tcp related functions + */ +class TCP { +private: + SOCKET sock; + struct sockaddr_storage peeraddr; + string remote_host; + string remote_port; + int readcnt; + int writecnt; + int islisten; +public: + TCP(); + 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 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); + long int Write(char *buffer, long int len); + void Close(); + int IsConnected(); + int IsData(int timeout); // timeout in ms; + int IsListen() { return islisten; }; + + int Listen(int port); + TCP* Accept(); + + 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); +}; + +#endif + diff --git a/testmodbus-client.ui b/testmodbus-client.ui new file mode 100644 index 0000000..6bdd1a5 --- /dev/null +++ b/testmodbus-client.ui @@ -0,0 +1,289 @@ + + + + + + False + + + + True + False + vertical + + + True + False + 4 + 4 + 4 + 4 + 0 + + + True + False + 12 + + + True + False + vertical + 4 + + + True + False + 4 + + + True + False + vertical + 4 + + + True + False + 4 + + + True + False + Host: + + + False + True + 0 + + + + + True + True + localhost + + + False + True + 1 + + + + + True + False + Port: + + + False + True + 2 + + + + + True + True + 6 + 502 + + + False + True + 3 + + + + + False + True + 0 + + + + + True + False + 4 + + + True + False + Refresh [ms]: + + + False + True + 0 + + + + + True + True + 4 + 1000 + + + False + True + 1 + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + vertical + + + Auto Reconnect + True + True + False + True + True + + + False + True + 0 + + + + + Read Only + True + True + False + True + True + + + False + True + 1 + + + + + + + + False + True + 1 + + + + + True + False + vertical + 3 + + + gtk-connect + True + True + True + True + True + + + False + True + 0 + + + + + gtk-disconnect + True + False + True + True + True + True + + + False + True + 1 + + + + + False + True + end + 2 + + + + + False + True + 0 + + + + + True + False + last error | status + + + False + False + 1 + + + + + + + + + True + False + Destination Host + + + + + + + + + False + False + 0 + + + + + + + + + + + +