summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/aa_socket.cc254
-rw-r--r--src/aa_socket.h42
-rw-r--r--src/cprlisten.cc50
-rw-r--r--src/cprlisten.h10
-rw-r--r--src/cprquerydialog.cc29
-rw-r--r--src/cprquerydialog.h7
-rw-r--r--src/thread.cc12
-rw-r--r--src/thread.h1
8 files changed, 393 insertions, 12 deletions
diff --git a/src/aa_socket.cc b/src/aa_socket.cc
new file mode 100644
index 0000000..28ecead
--- /dev/null
+++ b/src/aa_socket.cc
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+#include "aa_socket.h"
+
+//#include <string.h>
+
+#include <iostream>
+using namespace std;
+
+#include <unistd.h>
+//#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+
+#include <netinet/in.h>
+#if defined(linux)
+#include <endian.h>
+#else
+#include <sys/endian.h>
+#endif /*defined(linux)*/
+
+// for gethostbyname
+#include <netdb.h>
+
+// These functions are wrappers, to preserve my nice method naming!
+inline int _socket(int a,int b,int c){return socket(a,b,c);}
+inline int _connect(int a,const struct sockaddr *b,socklen_t c){return connect(a,b,c);}
+inline int _listen(int a,int b){return listen(a,b);}
+inline int _send(int a,char *b,unsigned int c, int d){return send(a,b,c,d);}
+
+
+AASocket::AASocket()
+{
+}
+
+AASocket::~AASocket()
+{
+ int err = close(socket); // close server
+ if(err == -1) throw Network_error("close", strerror(errno));
+}
+
+void AASocket::connect(char *host, unsigned short port)
+{
+ // create socket
+ socket = _socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ // PF_INET: ipv4, PF_INET6: ipv6
+ // tcp: IPPROTO_TCP
+ // upd: IPPROTO_UDP
+
+ if (socket == -1) throw Network_error("socket", strerror(errno));
+
+ socketaddr.sin_family = AF_INET; // Use "internet protocol" IP
+ socketaddr.sin_port = htons(port); // connect to that port
+ socketaddr.sin_addr.s_addr = INADDR_ANY;
+ // INADDR_ANY puts your IP address automatically
+
+
+
+ struct hostent *hp = gethostbyname(host);
+ // memcpy(&socketaddr.sin_addr.s_addr, *(hp->h_addr_list),sizeof(struct in_addr));
+ memcpy(&(socketaddr.sin_addr),*(hp->h_addr_list),sizeof(struct in_addr));
+
+ // FIXME: gethostbyname()
+ // socketaddr.sin_addr.s_addr = inet_addr(host);
+ //inet_aton (ip, &socketaddr.sin_addr);
+
+ int err = _connect(socket, (struct sockaddr*)&socketaddr, sizeof(socketaddr));
+ if(err == -1) throw Network_error("connect", strerror(errno));
+}
+
+void AASocket::listen(unsigned short port)
+{
+ int err;
+
+ bind_socket = _socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if(bind_socket == -1) throw Network_error("tmp socket", strerror(errno));
+
+ int optval = 1;
+ err = setsockopt(bind_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+ if(err == -1) throw Network_error("setsockopt", strerror(errno));
+
+ socketaddr.sin_family = AF_INET; // Use "internet protocol" IP
+ socketaddr.sin_port = htons(port); // connect to that port
+ socketaddr.sin_addr.s_addr = INADDR_ANY;
+ // INADDR_ANY puts your IP address automatically
+
+ // bind socket to address specified by "sa" parameter
+ err = bind(bind_socket, (struct sockaddr*)&socketaddr, sizeof(socketaddr));
+ if(err == -1) throw Network_error("bind", strerror(errno));
+
+ err = _listen(bind_socket, 5);
+ if(err == -1) throw Network_error("listen", strerror(errno));
+
+ int csalen = sizeof(socketaddr);
+ socket = accept(bind_socket,
+ (struct sockaddr*)&socketaddr,
+ (socklen_t*)&csalen);
+ if(socket == -1) throw Network_error("accept", strerror(errno));
+
+ err = close(bind_socket); // We don't need this anymore
+ bind_socket = -1;
+ if(err == -1) throw Network_error("tmp close", strerror(errno));
+}
+
+
+void AASocket::force_close()
+{
+ if(bind_socket != -1) close(bind_socket); // This should break the accept call
+}
+
+
+void AASocket::send(char* buf, unsigned int size)
+{
+ //unsigned int newsize = size + sizeof(unsigned int);
+ // char *newbuf = new char[newsize];
+
+ unsigned int nsize = htonl(size);
+ int n = _send(socket, (char*)&nsize, sizeof(unsigned int), MSG_WAITALL);
+ if(n == -1) throw Network_error("send", strerror(errno));
+
+ n = _send(socket, buf, size, MSG_WAITALL);
+ if(n == -1) throw Network_error("send", strerror(errno));
+}
+
+
+int AASocket::receive(char* buf, unsigned int size)
+{
+ unsigned int insize;
+
+ int n = recv(socket, &insize, sizeof(unsigned int), MSG_WAITALL);
+ if(n == -1) throw Network_error("recv", strerror(errno));
+
+ insize = ntohl(insize);
+ if(insize > size) {
+ char err_buf[256];
+ sprintf(err_buf, "Buffer is too small. Should be %d is %d." , insize, size);
+ throw Network_error("receive", err_buf);
+ }
+
+ n = recv(socket, buf, insize, MSG_WAITALL);
+ if(n == -1) throw Network_error("recv", strerror(errno));
+
+ return n;
+}
+
+
+void AASocket::send_string(string str)
+{
+ this->send((char*)str.c_str(), str.length());
+}
+
+
+string AASocket::receive_string()
+{
+ char buf[1024];
+ memset(buf, 0, sizeof(buf));
+
+ receive(buf, sizeof(buf));
+
+ return string(buf);
+}
+
+
+
+#ifdef TEST_SOCKET
+
+/**
+ * Test application for AASocket
+ * It should print the following to stdout:
+ * A: Hello, how are you?
+ * B: Fine thanks.
+ * A: What about you?
+ * B: I'm fine too.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <iostream>
+
+int main()
+{
+ char buf[1024];
+ memset(buf, 0, sizeof(buf));
+ int f = fork();
+ switch(f) {
+ case -1: // Fork error
+ perror("Fork failed!");
+ return 1;
+
+ case 0: // Forked child
+ {
+ try {
+ AASocket out;
+
+ sleep(1); // Make sure the other end is listening
+
+ // Test connect
+ out.connect("127.0.0.1", 6666);
+
+ // Test raw communication send
+ sprintf(buf, "Hello how are you?");
+ out.send(buf, sizeof(buf));
+
+ // Test raw communication receive
+ out.receive(buf, sizeof(buf));
+ std::cout << "B: " << buf << std::endl;
+
+ // Test string receive
+ std::string q = out.receive_string();
+ std::cout << "B: " << q << std::endl;
+
+ // Test string send
+ out.send_string(std::string("I'm fine too."));
+ return 0;
+ } catch(Network_error e) {
+ std::cerr << "Out: " << e.error << std::endl;
+ }
+ }
+ default: // Parent
+ {
+ try {
+ AASocket in;
+
+ // Test listen
+ in.listen(6666);
+
+ // Test raw communication receive
+ in.receive(buf, sizeof(buf));
+ std::cout << "A: " << buf << std::endl;
+
+ // Test raw communication send
+ sprintf(buf, "Fine thanks.");
+ in.send(buf, sizeof(buf));
+
+ // Test string send
+ in.send_string(std::string("What about you?"));
+
+ // Test string receive
+ std::string a = in.receive_string();
+ std::cout << "A: " << a << std::endl;
+ return 0;
+ } catch(Network_error e) {
+ std::cerr << "In: " << e.error << std::endl;
+ }
+ }
+ }
+ return 0;
+}
+#endif/*TEST_SOCKET*/
diff --git a/src/aa_socket.h b/src/aa_socket.h
new file mode 100644
index 0000000..0d02723
--- /dev/null
+++ b/src/aa_socket.h
@@ -0,0 +1,42 @@
+#ifndef __SOCKET_H__
+#define __SOCKET_H__
+
+#include <string>
+
+#include <netinet/in.h>
+//#include <sys/socket.h>
+
+
+/**
+ * Exceptions
+ */
+struct Network_error {
+ Network_error(char *event, char *err) {
+ error = std::string(err) + " - in " + std::string(event);
+ }
+ std::string error;
+};
+
+class AASocket {
+public:
+ AASocket();
+ ~AASocket();
+
+ void listen(unsigned short port);
+ void connect(char *ip, unsigned short port);
+
+ void send(char* buf, unsigned int buf_size);
+ int receive(char* buf, unsigned int buf_size);
+
+ void send_string(std::string buf);
+ std::string receive_string();
+
+ void force_close();
+
+private:
+ struct sockaddr_in socketaddr;
+ int socket;
+ int bind_socket; // Tmp socket for listen.
+};
+
+#endif/*__SOCKET_H__*/
diff --git a/src/cprlisten.cc b/src/cprlisten.cc
index 9a816d2..9ecac86 100644
--- a/src/cprlisten.cc
+++ b/src/cprlisten.cc
@@ -26,36 +26,68 @@
*/
#include "cprlisten.h"
-#include "socket.h"
+#include "aa_socket.h"
#include <iostream>
#include <string>
using namespace std;
+#define MAGIC_STOP_STRING "SHUTTHEFUCKUP"
+
CPRListen::CPRListen(unsigned short port)
{
this->port = port;
cpr = "N/A";
+ cprchanged = false;
+ running = true;
}
CPRListen::~CPRListen()
{
}
+void CPRListen::stop()
+{
+ running = false;
+ try {
+ AASocket socket;
+ socket.connect("localhost", port);
+ socket.send_string(MAGIC_STOP_STRING);
+ } catch(Network_error &e) {
+ cerr << "In stop(): " << e.error << endl;
+ }
+}
+
void CPRListen::thread_main()
{
- while(1) {
+ while(running) {
try {
- Socket socket;
+ string newcpr;
+ AASocket socket;
socket.listen(port);
- mutex.lock();
- cpr = socket.receive_string();
- mutex.unlock();
- cerr << "Got CPR: " << cpr << endl;
+ newcpr = socket.receive_string();
+
+ if(newcpr == MAGIC_STOP_STRING) {
+ running = false;
+ } else {
+ mutex.lock();
+ cprchanged = true;
+ cpr = newcpr;
+ mutex.unlock();
+ // cerr << "Got CPR: " << cpr << endl;
+ }
+
} catch(Network_error &e) {
- cerr << e.error << endl;
+ cerr << "In thread_main(): " << e.error << endl;
+ running = false;
}
}
+ // cout << "fisk!" << endl;
+}
+
+bool CPRListen::cprChanged()
+{
+ return cprchanged;
}
string CPRListen::getCpr()
@@ -66,5 +98,7 @@ string CPRListen::getCpr()
cpr_copy = cpr;
mutex.unlock();
+ cprchanged = false;
+
return cpr_copy;
}
diff --git a/src/cprlisten.h b/src/cprlisten.h
index 57551f5..5808aec 100644
--- a/src/cprlisten.h
+++ b/src/cprlisten.h
@@ -33,15 +33,25 @@
#include "thread.h"
#include "mutex.h"
+#include "aa_socket.h"
+
class CPRListen: public Thread {
public:
CPRListen(unsigned short port);
~CPRListen();
+ bool cprChanged();
std::string getCpr();
void thread_main();
+ void stop(); // Stops the call to listen
+
private:
+
+ volatile bool running;
+ AASocket *socket;
+
+ bool cprchanged;
unsigned short port;
std::string cpr;
Mutex mutex;
diff --git a/src/cprquerydialog.cc b/src/cprquerydialog.cc
index 4506e42..552aeb6 100644
--- a/src/cprquerydialog.cc
+++ b/src/cprquerydialog.cc
@@ -114,11 +114,40 @@ CPRQueryDialog::CPRQueryDialog(QLabel *lcpr,
connect(bca,SIGNAL(clicked()), SLOT(b_c_clicked()));
this->move(175,150);
+
+ listen = new CPRListen(config->readInt("cprlisten_port"));
+ listen_timer = new QTimer(this);
+ connect(listen_timer, SIGNAL(timeout()), SLOT(listen_timeout()));
+ listen->run();
+ listen_timer->start(500); // Check every 500 ms
+
show();
}
CPRQueryDialog::~CPRQueryDialog()
{
+ // Cleanup
+ // delete timer;
+ // delete cprSocket
+
+ // Cleanup after cpr listen
+ listen->stop();
+ // listen->wait_stop();
+ delete listen;
+ // delete listen_timer;
+}
+
+void CPRQueryDialog::listen_timeout()
+{
+ string newcpr;
+ if(listen->cprChanged()) {
+ char newcpr_buf[32];
+ newcpr = listen->getCpr();
+ sprintf(newcpr_buf, "%s-%s", newcpr.substr(0,6).c_str(), newcpr.substr(6,4).c_str());
+ // printf("cprbuf[%s]\n", newcpr_buf);
+ lbl_cpr->setText(newcpr_buf);
+ verifycpr(newcpr_buf);
+ }
}
/**
diff --git a/src/cprquerydialog.h b/src/cprquerydialog.h
index 2acf1b4..d9c7341 100644
--- a/src/cprquerydialog.h
+++ b/src/cprquerydialog.h
@@ -86,6 +86,8 @@ using namespace std;
#include "messagebox.h"
+#include "cprlisten.h"
+
class CPRQueryDialog : public QDialog {
Q_OBJECT
public:
@@ -106,8 +108,13 @@ public slots:
void cprSocket_connected();
void cprSocket_error(int errnum);
void cprSocket_timeout();
+ void listen_timeout();
+
private:
+ CPRListen *listen;
+ QTimer *listen_timer;
+
QStatusBar *statusbar;
QLabel *lbl_cpr;
diff --git a/src/thread.cc b/src/thread.cc
index 2791c53..147cf00 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -36,17 +36,21 @@ static void* thread_run(void *data) {
}
Thread::Thread()
-{}
+{
+}
Thread::~Thread()
-{}
+{
+}
void Thread::run()
{
- pthread_create (&tid, NULL, thread_run, this);
+ pthread_attr_init(&attr);
+
+ pthread_create(&tid, &attr, thread_run, this);
}
void Thread::wait_stop()
{
- pthread_join (tid, NULL);
+ pthread_join(tid, NULL);
}
diff --git a/src/thread.h b/src/thread.h
index 6b7a52a..3d58d74 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -42,6 +42,7 @@ public:
virtual void thread_main() = 0;
private:
+ pthread_attr_t attr;
pthread_t tid;
};