///////////////////////////////////////////////////////////////////////////////// // // nwthread.cc is part of TestModbus-Client. // ///////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) #else #include /* 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__); };