diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/aa_socket.cc | 254 | ||||
-rw-r--r-- | src/aa_socket.h | 42 | ||||
-rw-r--r-- | src/cprlisten.cc | 50 | ||||
-rw-r--r-- | src/cprlisten.h | 10 | ||||
-rw-r--r-- | src/cprquerydialog.cc | 29 | ||||
-rw-r--r-- | src/cprquerydialog.h | 7 | ||||
-rw-r--r-- | src/thread.cc | 12 | ||||
-rw-r--r-- | src/thread.h | 1 |
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; }; |