You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
3.9 KiB

/////////////////////////////////////////////////////////////////////////////////
//
// nwthread.cc is part of TestModbus-Client.
//
/////////////////////////////////////////////////////////////////////////////////
#include <errno.h>
#include <glib.h>
#include <sys/time.h>
#include <string>
#include <string.h>
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
#include <unistd.h> /* close() */
#endif
#include "tcp.h"
#include "nwthread.h"
#include "client.h"
extern NetworkThread netthread;
// c / C++ wrapper
gpointer _Thread (gpointer data) {
netthread.Thread ();
return NULL;
};
NetworkThread::NetworkThread() {
g_mutex_init (&mutex);
thread = NULL;
state = 0;
host = "";
port = "";
req_fc = -1;
req_offset = 0;
req_size = 0;
memset (&req_time, 0x0, sizeof (req_time));
req_timeout = 0;
};
NetworkThread::~NetworkThread() {
Disconnect();
g_mutex_clear(&mutex);
};
void NetworkThread::Lock() {
g_mutex_lock(&mutex);
};
void NetworkThread::UnLock() {
g_mutex_unlock(&mutex);
};
/*
* start network thread and connect
*/
int NetworkThread::Connect(std::string dest_host, std::string dest_port) {
printf ("%s:%d NetworkThread::Connect to %s:%s\n", __FILE__, __LINE__, dest_host.c_str(), dest_port.c_str());
//
// if there is an open connection close this one first
if (GetState() != NWT_nothing) Disconnect();
host = dest_host;
port = dest_port;
thread = g_thread_new("network thread", _Thread, NULL);
return -1;
};
/*
* stop network connection
*/
int NetworkThread::Disconnect() {
printf ("%s:%d NetworkThread::Disconnect\n", __FILE__, __LINE__);
Lock();
if (state != NWT_nothing) state = NWT_close;
UnLock();
while (GetState() != NWT_nothing) { usleep(1000); };
if (thread != NULL) g_thread_unref(thread);
thread = NULL;
return 0;
};
void NetworkThread::SetState(int s) {
Lock();
state = s;
UnLock();
};
int NetworkThread::GetState() {
int s;
Lock();
s = state;
UnLock();
return s;
};
void NetworkThread::ClientSendStatustext(char *txt) {
char *msg = NULL;
if (txt) {
int l = strlen (txt)+1;
msg = (char*) malloc(l+1);
memset (msg, 0x0, l+1);
strncpy (msg, txt, strlen (txt));
}
gdk_threads_add_idle(mbcli_thread_cb_status, msg);
}
#define BUFFER_SIZE 0x10000
void NetworkThread::Thread() {
int i;
long int len;
TCP tcp;
char buffer[BUFFER_SIZE];
printf ("%s:%d NetworkThread::Thread Started\n", __FILE__, __LINE__);
ClientSendStatustext((char*)"connecting");
Lock();
req_fc = 0;
UnLock();
//
// connect to ip address
//
SetState (NWT_connect);
i = tcp.Connect(host, port);
if (i < 0) {
//
// error on connect, stop thread.
ClientSendStatustext(strerror(errno));
SetState(NWT_nothing);
ClientSendStatustext(NULL);
printf ("%s:%d NetworkThread::Thread Finished on connect\n", __FILE__, __LINE__);
return;
}
if (i == 1) ClientSendStatustext((char*)"connected");
// FIXME: else: still connecting need some timeout and checks.
SetState(NWT_running);
//
// connection established
// go into the main loop
while (GetState() == NWT_running) {
//
// check for new data
i = tcp.IsData(1000);
if (i < 0) {
SetState(NWT_error);
break;
}
else if (i == 0) continue;
//
// we got some data
printf ("read data\n");
len = tcp.Read(buffer, BUFFER_SIZE);
Lock();
if (len < 0) state = NWT_close;
else {
//
// we could get some data, if busy reset connection
if (req_fc == 0) {
// got data without request? - Protokol error
errno = EPROTO;
state = NWT_error;
break;
}
//
// return data
}
UnLock();
}
//
// main loop stopped, clean up
i = GetState();
switch (i) {
case NWT_error:
ClientSendStatustext(strerror(errno));
tcp.Close();
break;
case NWT_close:
ClientSendStatustext((char*)"Connection Closed");
tcp.Close();
break;
default:
ClientSendStatustext((char*)"Unknown Error");
tcp.Close();
break;
}
SetState(NWT_nothing);
printf ("%s:%d NetworkThread::Thread Finished\n", __FILE__, __LINE__);
};