From d55e7bfe307d6719df2ef8681c7bf1033074cbdc Mon Sep 17 00:00:00 2001 From: Christos Houtouridis Date: Tue, 1 Oct 2019 13:39:00 +0300 Subject: [PATCH] Init commit --- .gitignore | 5 + eclipse_usb/.cproject | 142 ++++ eclipse_usb/.gdbinit | 1 + eclipse_usb/.project | 26 + eclipse_usb/.settings/language.settings.xml | 25 + eclipse_usb/src | 1 + eclipse_wifi/.cproject | 141 ++++ eclipse_wifi/.gdbinit | 1 + eclipse_wifi/.project | 26 + eclipse_wifi/.settings/language.settings.xml | 25 + eclipse_wifi/src | 1 + src/client.c | 111 +++ src/client.h | 15 + src/core.c | 375 +++++++++ src/core.h | 44 + src/listener.c | 112 +++ src/listener.h | 17 + src/main.c | 231 ++++++ src/messenger.c | 806 +++++++++++++++++++ src/msg_impl.h | 204 +++++ 20 files changed, 2309 insertions(+) create mode 100644 .gitignore create mode 100755 eclipse_usb/.cproject create mode 100755 eclipse_usb/.gdbinit create mode 100755 eclipse_usb/.project create mode 100755 eclipse_usb/.settings/language.settings.xml create mode 120000 eclipse_usb/src create mode 100755 eclipse_wifi/.cproject create mode 100755 eclipse_wifi/.gdbinit create mode 100755 eclipse_wifi/.project create mode 100755 eclipse_wifi/.settings/language.settings.xml create mode 120000 eclipse_wifi/src create mode 100755 src/client.c create mode 100755 src/client.h create mode 100755 src/core.c create mode 100755 src/core.h create mode 100644 src/listener.c create mode 100644 src/listener.h create mode 100755 src/main.c create mode 100644 src/messenger.c create mode 100755 src/msg_impl.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..54905f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +Requirements/* +Various/* + +*Debug +*Release diff --git a/eclipse_usb/.cproject b/eclipse_usb/.cproject new file mode 100755 index 0000000..c22b1bc --- /dev/null +++ b/eclipse_usb/.cproject @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eclipse_usb/.gdbinit b/eclipse_usb/.gdbinit new file mode 100755 index 0000000..37eaf41 --- /dev/null +++ b/eclipse_usb/.gdbinit @@ -0,0 +1 @@ +set sysroot D:\SysGCC\Raspberry\arm-linux-gnueabihf\sysroot diff --git a/eclipse_usb/.project b/eclipse_usb/.project new file mode 100755 index 0000000..2066ae5 --- /dev/null +++ b/eclipse_usb/.project @@ -0,0 +1,26 @@ + + + RTES_Final_usb + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/eclipse_usb/.settings/language.settings.xml b/eclipse_usb/.settings/language.settings.xml new file mode 100755 index 0000000..9051cd6 --- /dev/null +++ b/eclipse_usb/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eclipse_usb/src b/eclipse_usb/src new file mode 120000 index 0000000..5cd551c --- /dev/null +++ b/eclipse_usb/src @@ -0,0 +1 @@ +../src \ No newline at end of file diff --git a/eclipse_wifi/.cproject b/eclipse_wifi/.cproject new file mode 100755 index 0000000..5cf7b23 --- /dev/null +++ b/eclipse_wifi/.cproject @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eclipse_wifi/.gdbinit b/eclipse_wifi/.gdbinit new file mode 100755 index 0000000..37eaf41 --- /dev/null +++ b/eclipse_wifi/.gdbinit @@ -0,0 +1 @@ +set sysroot D:\SysGCC\Raspberry\arm-linux-gnueabihf\sysroot diff --git a/eclipse_wifi/.project b/eclipse_wifi/.project new file mode 100755 index 0000000..c9ff9b8 --- /dev/null +++ b/eclipse_wifi/.project @@ -0,0 +1,26 @@ + + + RTES_Final_wifi + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/eclipse_wifi/.settings/language.settings.xml b/eclipse_wifi/.settings/language.settings.xml new file mode 100755 index 0000000..20962da --- /dev/null +++ b/eclipse_wifi/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eclipse_wifi/src b/eclipse_wifi/src new file mode 120000 index 0000000..5cd551c --- /dev/null +++ b/eclipse_wifi/src @@ -0,0 +1 @@ +../src \ No newline at end of file diff --git a/src/client.c b/src/client.c new file mode 100755 index 0000000..722f03d --- /dev/null +++ b/src/client.c @@ -0,0 +1,111 @@ +/*! + * \file client.c + * + * \author Christos Choutouridis AEM:8997 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "client.h" + + +// Calculating the Check Sum +static unsigned short _checksum(void *b, int len) { + unsigned short *buf = b; + unsigned int sum=0; + unsigned short result; + + for ( sum = 0; len > 1; len -= 2 ) + sum += *buf++; + if ( len == 1 ) + sum += *(unsigned char*)buf; + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + result = ~sum; + return result; +} + +static void _mk_ping_pkt (ping_pkt_t* pkt) { + memset ((void*)&pkt->hdr, 0, sizeof(pkt->hdr)); + //memset ((void*)&pkt->msg, '0', sizeof(pkt->msg)); + pkt->msg[PING_MSG_S -1] = 0; + + pkt->hdr.type = ICMP_ECHO; + pkt->hdr.un.echo.id = getpid(); + pkt->hdr.un.echo.sequence = 0; + pkt->hdr.checksum = _checksum (&pkt, sizeof(pkt)); +} + +bool ping (device_t* dev) { + static int sockfd =-1; + int ttl_val =64; + struct timeval tv_out = { 1, 0 }; + + + if (sockfd == -1 && dev) { + // create socket and set options at ip to TTL and value to 64 and timeout of recv + if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { + log_error ("Error: Can not create raw socket for icmp\n"); + return false; + } + #ifndef NO_DEBUG + log_debug("Debug: Raw socket for icmp created\n"); + #endif + int ret = setsockopt(sockfd, SOL_IP, IP_TTL, &ttl_val, sizeof(ttl_val)); + ret |= setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv_out, sizeof(tv_out)); + if (ret == -1) { + log_error ("Error: Can not set options to socket\n"); + close (sockfd); + sockfd =-1; + return false; + } + #ifndef NO_DEBUG + log_debug("Debug: Raw socket options set\n"); + #endif + } + + if (!dev) { + // Close socket + close (sockfd); + sockfd =-1; + #ifndef NO_DEBUG + log_debug ("Debug: Raw socket closed\n"); + #endif + return true; + } + else { + // ping packet structure + ping_pkt_t pkt; + _mk_ping_pkt (&pkt); + int st; + + //send packet + struct sockaddr_in ping_addr = { + .sin_family = AF_INET, + .sin_addr = { htonl (device2addr (dev)) } + }; + if ((st=sendto (sockfd, &pkt, sizeof(pkt), 0, (struct sockaddr*)&ping_addr, sizeof(ping_addr))) <= 0) + return false; + #ifndef NO_DEBUG + log_debug ("Debug: Echo send to %s\n", inet_ntoa(ping_addr.sin_addr)); + #endif + //receive packet + struct sockaddr_in r_addr; + socklen_t addr_len =sizeof(r_addr); + if ((st=recvfrom (sockfd, &pkt, sizeof(pkt), 0, (struct sockaddr*)&r_addr, &addr_len)) <= 0) + return false; + #ifndef NO_DEBUG + log_debug ("Debug: Echo received from %s\n", inet_ntoa(ping_addr.sin_addr)); + #endif + return (pkt.hdr.type == 69 && pkt.hdr.code == 0) ? true: false; + } + return false; +} + + diff --git a/src/client.h b/src/client.h new file mode 100755 index 0000000..562c059 --- /dev/null +++ b/src/client.h @@ -0,0 +1,15 @@ +/*! + * \file client.h + * + * \author Christos Choutouridis AEM:8997 + */ + +#ifndef __client_h__ +#define __client_h__ + +#include "core.h" +#include "msg_impl.h" + +bool ping (device_t* dev); + +#endif /* __client_h__ */ diff --git a/src/core.c b/src/core.c new file mode 100755 index 0000000..793c019 --- /dev/null +++ b/src/core.c @@ -0,0 +1,375 @@ +/*! + * \file core.c + * + * \author Christos Choutouridis AEM:8997 + */ + + +#include +#include +#include +#include +#include + +#include "core.h" + +pthread_mutex_t lock_msgList; + +//! Helper API +//! @{ + +#define _ADHOC_SUBNET(A, B, C, D) (((A)<<24) | ((B)<<16) | ((C)<<8) | (D)) + +device_t addr2device (uint32_t in_addr) { + device_t dev = { + .id = (in_addr & 0x000000FF) + ((in_addr >> 8) & 0x000000FF) * 100, + .next = NULL + }; + return dev; +} + +uint32_t device2addr (const device_t* dev) { + uint32_t add = _adhoc_subnet; + add |= (dev->id % 100) & 0x000000FF; + add |= ((dev->id / 100) & 0x000000FF) << 8; + return add; +} + +device_t ip2device (devIP_t* ip) { + device_t dev = { + .id = ip->C*100 + ip->D, + .next = NULL + }; + return dev; +} + +devIP_t device2ip (const device_t* dev) { + devIP_t ip = { + .A=0, .B=0, .C=dev->id/100, .D=dev->id%100 + }; + return ip; +} + +devIP_t addr2ip (uint32_t in_addr) { + devIP_t ip = { + .A=0, .B=0, + .C=(in_addr >> 8) & 0x000000FF, + .D=in_addr & 0x000000FF + }; + return ip; +} +//! @} + + +//! cMsg_t API +//! @{ + +/*! + * Parse an incoming message + * + * @param cMsg Pointer to cMsg object to store the parsed data + * @param rawMsg Pointer to raw message + * @param size The size f raw message buffer + * @return The status of the operation + * @arg MSG_OK Success + * @arg MSG_ERROR Parse failure, incoming message format error + */ +status_t cMsg_parse (cMsg_t* cMsg, char_t* rawMsg, size_t size) { + + // Check message integrity + if (size > MSG_TEXT_SIZE) + return MSG_ERROR; + int d =0; + for (size_t i =0; rawMsg[i] && imsg, rawMsg); + + // Parse message + char_t del[2] = {MSG_DELIMITER, '\0'}; + char_t* tok; + + tok = strtok (cMsg->msg, del); + cMsg->from = atoi (tok); + + tok = strtok(NULL, del); + cMsg->to = atoi (tok); + + tok = strtok(NULL, del); + cMsg->ts = atoll (tok); + + tok = strtok(NULL, del); + cMsg->text = tok - cMsg->msg; + + return MSG_OK; +} + +/*! getter for cMsg_t member fromAEM */ +uint32_t cMsg_getFrom(cMsg_t* cMsg) { return cMsg->from; } +/*! getter for cMsg_t member toAEM */ +uint32_t cMsg_getTo(cMsg_t* cMsg) { return cMsg->to; } +/*! getter for cMsg_t member fromAEM */ +uint64_t cMsg_getTs(cMsg_t* cMsg) { return cMsg->ts; } +/*! getter for payload text member */ +char_t* cMsg_getText(cMsg_t* cMsg) { return (char_t*)& cMsg->msg[cMsg->text]; } + +/*! + * Predicate to check core message equality + * @param m1 Pointer to message 1 + * @param m2 Pointer to message 2 + * @return Equality result (true, false) + */ +bool cMsg_equal (cMsg_t* m1, cMsg_t* m2) { + if (m1->from != m2->from) return false; + if (m1->to != m2->to) return false; + if (m1->ts != m2->ts) return false; + if (strncmp (cMsg_getText(m1), cMsg_getText(m2), sizeof(m1->msg))) + return false; + return true; +} +//! @} + +/*! + * Create a message list for our application. + */ +msgList_t msgList; + + +//! msgList API +//! @{ + +/*! Macro helper to saturate increased values */ +#define _top_saturate(test, apply, value) do { \ + if (test >= value) apply = value; \ +} while (0) + +/*! Macro helper to saturate decreased values */ +#define _btm_saturate(test, apply, value) do { \ + if (test < value) apply = value; \ +while (0) + +/*! + * @brief msgList iterator pre-increment in the msg_t direction + * + * This iterator force a ring buffer behavior. This function takes pointer + * to iterator to alter but return the altered value so it can be directly + * used in expressions + * + * @param it Pointer to iterator to increase + * @return The iterator values + */ +static mIter_t _preInc(mIter_t* it) { + if (++*it >= MSG_LIST_SIZE) *it = 0; + return *it; +} + +/*! + * @brief msgList iterator pre-decrement in the msg_t direction + * + * This iterator force a ring buffer behavior. This function takes pointer + * to iterator to alter but return the altered value so it can be directly + * used in expressions + * + * @param it Pointer to iterator to decrease + * @return The iterator values + */ +static mIter_t _preDec(mIter_t* it) { + if (--*it < 0) *it = MSG_LIST_SIZE; + return *it; +} + +/*! + * @brief Access devices in the device_t direction. + * + * This function returns the first device on the recipient list if there is one. + * + * @param this The msgList object to work with + * @param it The iterator value [msg_t direction] + * @return Pointer to first device on the list, or NULL if the list is empty + */ +static device_t* devList_get (msgList_t* this, mIter_t it) { + device_t* d = this->m[it].recipients; + return (d) ? d->next : NULL; +} + +/*! + * Iterate through device list. + * + * This function return the next device on the recipient list if there is one. + * [device direction] + * + * @param d Pointer to current device + * @return Pointer to next device on the list, or NULL if the list is empty + */ +//static device_t* devList_getNext (device_t* d) { +// return (d) ? d->next : NULL; +//} + +/*! + * @brief Adds a new device on the recipients list + * + * @param this The msgList object to work with + * @param it The iterator value [msg_t direction] + * @param dev Pointer to device to add [device direction] + * @return The status of the operation + * @arg MSG_OK Success + * @arg MSG_ERROR memory allocation error + */ +status_t devList_add (msgList_t* this, mIter_t it, device_t* dev) { + pthread_mutex_lock (&lock_msgList); + device_t* last = devList_get (this, it); + while (last && last->next) + last = last->next; + last = (device_t*)malloc (sizeof(device_t)); + *last = *dev; + pthread_mutex_unlock (&lock_msgList); + return (last) ? MSG_OK : MSG_ERROR; +} + +/*! + * Frees up all allocated memory in a device list. + * + * @param this The msgList object to work with + * @param it The iterator value [msg_t direction] + */ +static void devList_free (msgList_t* this, mIter_t it) { + device_t* last = devList_get (this, it); + while (last) { + device_t* next = last->next; + free(last); + last = next; + } +} + +status_t msgList_init (msgList_t* msgList) { + if (pthread_mutex_init(&lock_msgList, NULL) != 0) { + fprintf (stderr, "Error %s: mutex init has failed\n", __FUNCTION__ ); + return MSG_ERROR; + } + memset((void*)msgList, 0, sizeof(msgList_t)); + msgList->last =-1; + return MSG_OK; +} + +/*! + * Searches for a message in the message list. + * + * @param this The msgList object to work with + * @param msg Pointer to message to search + * @return Iterator to message if found, or -1 if not + */ +mIter_t msgList_find (msgList_t* this, msg_t* msg) { + pthread_mutex_lock (&lock_msgList); + mIter_t it =this->last; // get iterator + // search from end to start to find msg, return on success + for (size_t i=0 ; i < this->size ; ++i) { + if (cMsg_equal (&this->m[it].cMsg, &msg->cMsg)) { + pthread_mutex_unlock (&lock_msgList); + return it; + } + _preDec(&it); + // We start from the end as we think, its more possible + // to find msg in the recent messages. + } + pthread_mutex_unlock (&lock_msgList); + return (mIter_t)-1; // fail to find +} + +/*! + * Add a new message in the message list + * + * @param this The msgList object to work with + * @param msg Pointer to message + */ +void msgList_add (msgList_t* this, msg_t* msg) { + pthread_mutex_lock (&lock_msgList); + devList_free (this, _preInc(&this->last)); // free up possible previous recipients list + this->m[this->last] = *msg; // store data + pthread_mutex_unlock (&lock_msgList); + _top_saturate(++this->size, this->size, MSG_LIST_SIZE); // count the items +} + +//! @} + + + +static char_t* _frm_msg_io = "dev=%d, message: from=%d, to=%d, timestamp=%lld, text=%s"; +static char_t* _frm_msg_new = "new message: from=%d, to=%d, timestamp=%lld, text=%s"; + +pthread_mutex_t lock_stderr; +pthread_mutex_t lock_stdout; + + +status_t log_init (void) { + if (pthread_mutex_init(&lock_stderr, NULL) != 0) { + fprintf (stderr, "Error %s: mutex init has failed\n", __FUNCTION__ ); + return MSG_ERROR; + } + if (pthread_mutex_init(&lock_stdout, NULL) != 0) { + fprintf (stderr, "Error %s: mutex init has failed\n", __FUNCTION__ ); + return MSG_ERROR; + } + return MSG_OK; +} + +void log_msg_io (msg_t* msg) { + if (settings.outLevel >= OUTLEVEL_1) { + char_t head[16]; + strncpy (head, cMsg_getText(&msg->cMsg), sizeof(head)); + head[16] = 0; + pthread_mutex_lock(&lock_stdout); + fprintf (stdout, _frm_msg_io, + msg->sender.id, + cMsg_getFrom (&msg->cMsg), + cMsg_getTo (&msg->cMsg), + cMsg_getTs (&msg->cMsg), + head + ); + fflush(stdout); + pthread_mutex_unlock(&lock_stdout); + } +} + +void log_msg_new (msg_t* msg) { + if (settings.outLevel >= OUTLEVEL_1) { + char_t head[16]; + strncpy (head, cMsg_getText(&msg->cMsg), sizeof(head)); + head[16] = 0; + pthread_mutex_lock(&lock_stdout); + fprintf (stdout, _frm_msg_new, + cMsg_getFrom (&msg->cMsg), + cMsg_getTo (&msg->cMsg), + cMsg_getTs (&msg->cMsg), + head + ); + fflush(stdout); + pthread_mutex_unlock(&lock_stdout); + } +} + +void log_debug (const char *fmt, ...) { + if (settings.outLevel >= OUTLEVEL_2) { + va_list ap; + va_start(ap, fmt); + pthread_mutex_lock(&lock_stdout); + vfprintf (stdout, fmt, ap); + fflush(stdout); + pthread_mutex_unlock(&lock_stdout); + va_end(ap); + } +} + +void log_error (const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + pthread_mutex_lock(&lock_stderr); + vfprintf (stderr, fmt, ap); + fflush(stderr); + pthread_mutex_unlock(&lock_stderr); + va_end(ap); +} + diff --git a/src/core.h b/src/core.h new file mode 100755 index 0000000..45de32a --- /dev/null +++ b/src/core.h @@ -0,0 +1,44 @@ +/*! + * \file core.h + * + * \author Christos Choutouridis AEM:8997 + */ + +#ifndef __core__ +#define __core__ + +#include "msg_impl.h" + +extern msgList_t msgList; + +device_t addr2device (uint32_t in_addr); +uint32_t device2addr (const device_t* dev); +device_t ip2device (devIP_t* ip); +devIP_t device2ip (const device_t* dev); +devIP_t addr2ip (uint32_t in_addr); + +status_t cMsg_parse (cMsg_t* cMsg, char_t* rawMsg, size_t size); +uint32_t cMsg_getFrom (cMsg_t* cMsg); +uint32_t cMsg_getTo (cMsg_t* cMsg); +uint64_t cMsg_getTs (cMsg_t* cMsg); +char_t* cMsg_getText (cMsg_t* cMsg); +bool cMsg_equal (cMsg_t* m1, cMsg_t* m2); + +//device_t* devList_get (msgList_t* this, mIter_t it); +//device_t* devList_getNext (device_t* d); +status_t devList_add (msgList_t* this, mIter_t it, device_t* dev); +//void devList_free (msgList_t* this, mIter_t it); + +status_t msgList_init (msgList_t* msgList); +mIter_t msgList_find (msgList_t* this, msg_t* msg); +void msgList_add (msgList_t* this, msg_t* msg); + + +status_t log_init (void); + +void log_msg_io (msg_t* msg); +void log_msg_new (msg_t* msg); +void log_debug (const char *fmt, ...); +void log_error (const char *fmt, ...); + +#endif /* __core__ */ diff --git a/src/listener.c b/src/listener.c new file mode 100644 index 0000000..c58ecf7 --- /dev/null +++ b/src/listener.c @@ -0,0 +1,112 @@ +/*! + * \file listener.c + * \brief Listener related functionality + * + * \author Christos Choutouridis AEM:8997 + */ + +#include +#include +#include +#include +#include +//#include + +#include "listener.h" + +static void srv_action (device_t* d, char_t* buffer, size_t size) { + msg_t msg = { .sender =*d, .recipients =NULL }; + cMsg_parse (&msg.cMsg, buffer, size); + + mIter_t myCopy = msgList_find (&msgList, &msg); + if (myCopy == -1) { + // I don't have a copy after all + msgList_add (&msgList, &msg); + log_msg_io (&msg); // semaphore + } + else { + // Do not forward a duplicate message to sender, he already has it + devList_add (&msgList, myCopy, &msg.sender); + #ifndef NO_DEBUG + log_debug("Debug: Duplicate message from: %d\n", msg.sender.id); + #endif + } +} + +status_t listener() { + int srvSock; + struct sockaddr_in srvAddPort; + char_t buffer[256]; + + memset(&srvAddPort, 0, sizeof(srvAddPort)); + srvAddPort.sin_family= AF_INET; + srvAddPort.sin_port= htons(settings.port); + srvAddPort.sin_addr.s_addr = htonl(INADDR_ANY); + + if ((srvSock = socket (PF_INET, SOCK_STREAM, 0)) == -1) { + log_error ("Error: Can not create socket\n"); + return MSG_ERROR; + } + #ifndef NO_DEBUG + log_debug("Debug: Socket for listening created\n"); + #endif + if(bind(srvSock, (struct sockaddr *) &srvAddPort, sizeof(srvAddPort)) == -1) { + log_error ("Error: Can not bind socket to port %d\n", settings.port); + close (srvSock); + return MSG_ERROR; + } + if (listen (srvSock, DEVICE_LIST_SIZE) == -1) { + log_error ("Error: Can not enable socket\n"); + close (srvSock); + return MSG_ERROR; + } + #ifndef NO_DEBUG + log_debug("Debug: Listening on [0.0.0.0], port %d\n", settings.port); + #endif + while (1) { + struct sockaddr_in clntAddr; + size_t clntLen= sizeof(clntAddr); + int clntSock; + int rcvBytes; + + if ((clntSock = accept (srvSock, (struct sockaddr *)&clntAddr, (socklen_t*)&clntLen)) == -1) { + close (srvSock); + continue; + } + #ifndef NO_DEBUG + devIP_t ip = addr2ip(ntohl(clntAddr.sin_addr.s_addr)); + log_debug ("Debug: Connection from %u.%u.%u.%u port:%u received\n", + ip.A, ip.B, ip.C, ip.D, clntAddr.sin_port + ); + #endif + if ((rcvBytes = recv(clntSock, buffer, sizeof(buffer), 0)) < 0) { + log_error ("Error: Fail to receive from socket\n"); + close (srvSock); + close (clntSock); + continue; + } + buffer[rcvBytes] = '\0'; + close(clntSock); + + device_t dev = addr2device (ntohl(clntAddr.sin_addr.s_addr)); + #ifndef NO_DEBUG + log_debug ("Debug: Message from %u.%u.%u.%u port:%u received\n"); + #endif + srv_action (&dev, buffer, rcvBytes); + } + + close(srvSock); + #ifndef NO_DEBUG + log_debug ("Debug: Socket for listening closed\n"); + #endif + return MSG_OK; +} + + + +void* thListener(void* ptr) { + (void)&ptr; // use parameter + listener(); + return NULL; +} + diff --git a/src/listener.h b/src/listener.h new file mode 100644 index 0000000..bd66a68 --- /dev/null +++ b/src/listener.h @@ -0,0 +1,17 @@ +/*! + * \file listener.h + * \brief Listener related functionality + * + * \author Christos Choutouridis AEM:8997 + */ + +#ifndef __listener_h__ +#define __listener_h__ + +#include "core.h" +#include "msg_impl.h" + +status_t listener(); +void* thListener(void* ptr); + +#endif /* __listener_h__ */ diff --git a/src/main.c b/src/main.c new file mode 100755 index 0000000..1746077 --- /dev/null +++ b/src/main.c @@ -0,0 +1,231 @@ + +#include + +#include "listener.h" +#include "client.h" +#include "msg_impl.h" + + +settings_t settings_init (settings); + + +//status_t client (char_t* ip) { +// int sockid; +// struct sockaddr_in srvAddPort; +//// struct sockaddr_in clntAddr; +//// char buffer[256]; +// +// memset(&srvAddPort, 0, sizeof(srvAddPort)); +// srvAddPort.sin_family= AF_INET; +// srvAddPort.sin_port= htons(2288); +// srvAddPort.sin_addr.s_addr = inet_addr(ip); +// +// if ((sockid = socket (PF_INET, SOCK_STREAM, 0)) == -1) +// return MSG_ERROR; +// +// if (connect(sockid, (struct sockaddr*)&srvAddPort, sizeof(srvAddPort)) == -1) { +// close (sockid); +// return MSG_ERROR; +// } +// +// if (send(sockid, sms, strlen(sms), MSG_CONFIRM) == -1) { +// close(sockid); +// return MSG_ERROR; +// } +// +// close(sockid); +// return MSG_OK; +//} + + + +#include +#include +#include +#include +#include + + + +//// make a ping request +//void send_ping(int ping_sockfd, struct sockaddr_in *ping_addr, +// char *ping_dom, char *ping_ip, char *rev_host) +//{ +// int ttl_val=64, msg_count=0, i, addr_len, flag=1, +// msg_received_count=0; +// +// struct ping_pkt pckt; +// struct sockaddr_in r_addr; +// struct timespec time_start, time_end, tfs, tfe; +// long double rtt_msec=0, total_msec=0; +// struct timeval tv_out; +// int failure_cnt= 0; +// int cnt; +// +// tv_out.tv_sec = RECV_TIMEOUT; +// tv_out.tv_usec = 0; +// +// clock_gettime(CLOCK_MONOTONIC, &tfs); +// +// +// // set socket options at ip to TTL and value to 64, +// // change to what you want by setting ttl_val +// if (setsockopt(ping_sockfd, SOL_IP, IP_TTL, +// &ttl_val, sizeof(ttl_val)) != 0) +// { +// printf("\nSetting socket options to TTL failed!\n"); +// return; +// } +// +// else +// { +// printf("\nSocket set to TTL..\n"); +// } +// +// // setting timeout of recv setting +// setsockopt(ping_sockfd, SOL_SOCKET, SO_RCVTIMEO, +// (const char*)&tv_out, sizeof tv_out); +// +// // send icmp packet in an infinite loop +// while(pingloop) +// { +// // flag is whether packet was sent or not +// flag=1; +// +// //filling packet +// bzero(&pckt, sizeof(pckt)); +// +// pckt.hdr.type = ICMP_ECHO; +// pckt.hdr.un.echo.id = getpid(); +// +// for ( i = 0; i < sizeof(pckt.msg)-1; i++ ) +// pckt.msg[i] = i+'0'; +// +// pckt.msg[i] = 0; +// pckt.hdr.un.echo.sequence = msg_count++; +// pckt.hdr.checksum = checksum(&pckt, sizeof(pckt)); +// +// +// usleep(PING_SLEEP_RATE); +// +// //send packet +// clock_gettime(CLOCK_MONOTONIC, &time_start); +// if ( sendto(ping_sockfd, &pckt, sizeof(pckt), 0, +// (struct sockaddr*) ping_addr, +// sizeof(*ping_addr)) <= 0) +// { +// printf("\nPacket Sending Failed!\n"); +// flag=0; +// } +// +// //receive packet +// addr_len=sizeof(r_addr); +//REC: +// cnt = recvfrom(ping_sockfd, &pckt, sizeof(pckt), 0, +// (struct sockaddr*)&r_addr, &addr_len); +// if ( cnt <= 0 ) +// { +// printf("\nPacket receive failed!\n"); +// failure_cnt++; +// if(failure_cnt > 5){ +// break; +// } +// } +// +// else +// { +// clock_gettime(CLOCK_MONOTONIC, &time_end); +// +// double timeElapsed = ((double)(time_end.tv_nsec - +// time_start.tv_nsec))/1000000.0; +// rtt_msec = (time_end.tv_sec- +// time_start.tv_sec) * 1000.0 +// + timeElapsed; +// +// // if packet was not sent, don't receive +// if(flag) +// { +// struct icmp* icmp_hdr; +// if (cnt >= 76) { +// struct iphdr *iphdr = (struct iphdr *) &pckt; +// /* skip ip hdr */ +// icmp_hdr = (struct icmp *) (((char* )&pckt) + (iphdr->ihl << 2)); +// } +// if(icmp_hdr->icmp_type == ICMP_ECHO){ +// goto REC; +// } +// +// if(!(icmp_hdr->icmp_type !=ICMP_ECHOREPLY) ) +// { +// printf("Error..Packet received with ICMP" +// "type %d code %d\n", +// icmp_hdr->icmp_type, icmp_hdr->icmp_code); +// } +// else +// { +// printf("%d bytes from %s (h: %s)" +// "(%s) msg_seq=%d ttl=%d " +// "rtt = %Lf ms.\n", +// PING_PKT_S, ping_dom, rev_host, +// ping_ip, msg_count, +// ttl_val, rtt_msec); +// +// msg_received_count++; +// } +// } +// } +// } +// clock_gettime(CLOCK_MONOTONIC, &tfe); +// double timeElapsed = ((double)(tfe.tv_nsec - +// tfs.tv_nsec))/1000000.0; +// +// total_msec = (tfe.tv_sec-tfs.tv_sec)*1000.0+ +// timeElapsed; +// +// printf("\n===%s ping statistics===\n", ping_ip); +// printf("\n%d packets sent, %d packets received, %f percent " +// "packet loss. Total time: %Lf ms.\n\n", +// msg_count, msg_received_count, +// ((msg_count - msg_received_count)/msg_count) * 100.0, +// total_msec); +//} + + +int main(int argc, char const *argv[]) { + + pthread_t tL; + pthread_create( &tL, NULL, thListener, NULL); + + log_init (); + msgList_init (&msgList); + + bool b =true; + while (b) { + device_t d = { 0, NULL }; + + d.id = 43; + if (ping (&d)) printf ("found: 10.0.0.43\n"); + else printf ("not found: 10.0.0.43\n"); + + d.id = 8997; + if (ping (&d)) printf ("found: 10.0.89.97\n"); + else printf ("not found 10.0.89.97\n"); + + d.id = 7; + if (ping (&d)) printf ("found: 10.0.0.7\n"); + else printf ("not found: 10.0.0.7\n"); + + d.id = 1; + if (ping (&d)) printf ("found: 10.0.0.1\n"); + else printf ("not found: 10.0.0.1\n"); + + ping (NULL); + sleep (10); + } + + + + while (b) { } + pthread_join( tL, NULL); + return 0; +} diff --git a/src/messenger.c b/src/messenger.c new file mode 100644 index 0000000..8238a0c --- /dev/null +++ b/src/messenger.c @@ -0,0 +1,806 @@ +#define DEBUG +#define FU08 "%hhu" +#define FU16 "%hu" +#define FU32 "%lu" +#define FU64 "%llu" +#define FSTR "%s" + +#include +#include +#include + +#include +#include +#include +#include + + +//--Tools Module +#include +uint64_t TIME_u64Current(void) { + return time(NULL); +} +uint16_t RAND_u16GetNumber(uint16_t u16Min, uint16_t u16Max) { + static uint8_t i = 0; + if (i == 0) { + srand(time(NULL)); + i++; + } + return rand() % (u16Max + 1 - u16Min) + u16Min; +} + + +//--Log Module +#include +sem_t semLog; +void LOG_vSetup(void) { + sem_init(&semLog, 0, 1); +} +void LOG_vPrintf(const char* format, ...) { + sem_wait(&semLog); + + va_list args; + va_start(args, format); + +#ifdef DEBUG + printf(FU64":", TIME_u64Current()); + vprintf(format, args); +#endif + + FILE* fp; + fp = fopen("/tmp/log.txt", "a"); + if (fp != NULL) { + fprintf(fp, FU64":", TIME_u64Current()); + vfprintf(fp, format, args); + fclose(fp); + } + + va_end(args); + sem_post(&semLog); +} + + +//--File Module +#define FILE_EOF 0xFF +int8_t FILE_i08Compare(char* pchPath1, char* pchPath2) { + FILE* file1 = fopen(pchPath1, "r"); + FILE* file2 = fopen(pchPath2, "r"); + + if (file1 == NULL) { + if (file2 != NULL) + fclose(file2); + return 1; + } + + if (file2 == NULL) { + fclose(file1); + return 2; + } + + char ch1, ch2; + do { + ch1 = fgetc(file1); + ch2 = fgetc(file2); + + if (ch1 != ch2) { + fclose(file1); + fclose(file2); + return 0; + } + } while (ch1 != FILE_EOF && ch2 != FILE_EOF); + + if (ch1 == FILE_EOF && ch2 == FILE_EOF) { + fclose(file1); + fclose(file2); + return 3; + } + else { + fclose(file1); + fclose(file2); + return 0; + } +} + + +//--WiFi Module +#define NETWORK_TYPE "wlan0" +#include +#include +#define WIFI_BUFFER 2000 +#include +struct ParserArgs { + int sock; + struct sockaddr_in client_address; + socklen_t client_address_len; + bool (*bParse)(uint8_t* pu08Address, char* pchBuffer); +}; +void WiFi_vParser(void* ptr) { + struct ParserArgs temp; + memcpy(&temp, ptr, sizeof(struct ParserArgs)); + + char pchRemoteAddress[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(temp.client_address.sin_addr), pchRemoteAddress, INET_ADDRSTRLEN); + //uint16_t pu16RemotePort = temp.client_address.sin_port; + + char pchBuffer[WIFI_BUFFER]; + char* pchTemp = (char*)pchBuffer; + int16_t i16New = 0; + uint16_t u16Length = 0; + uint16_t u16Remaining = WIFI_BUFFER; + while ((i16New = recv(temp.sock, pchTemp, u16Remaining, 0)) > 0) { + pchTemp += i16New; + u16Remaining -= i16New; + u16Length += i16New; + pchTemp[0] = '\0'; + } + + uint8_t pu08Levels[4]; + sscanf(pchRemoteAddress, FU08"."FU08"."FU08"."FU08, &pu08Levels[0], &pu08Levels[1], &pu08Levels[2], &pu08Levels[3]); + temp.bParse(pu08Levels, pchBuffer); + + close(temp.sock); +} +bool WiFi_bListener(int32_t i32ServerPort, bool (*bParse)(uint8_t* pu08Address, char* pchBuffer)) { + struct sockaddr_in server_address; + memset(&server_address, 0, sizeof(server_address)); + server_address.sin_family = AF_INET; + + server_address.sin_port = htons(i32ServerPort); + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + + int listen_sock; + if ((listen_sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) + return false; + + if ((bind(listen_sock, (struct sockaddr *)&server_address, sizeof(server_address))) == -1) { + close(listen_sock); + return false; + } + + if (listen(listen_sock, WIFI_BUFFER) == -1) { + close(listen_sock); + return false; + } + + while (true) { + LOG_vPrintf("WiFiListener-New\n"); + + struct ParserArgs client; + client.client_address_len = sizeof(client.client_address); + client.bParse = bParse; + + LOG_vPrintf("WiFiListener-Start\n"); + if ((client.sock = accept(listen_sock, (struct sockaddr *)&client.client_address, &client.client_address_len)) == -1) { + return false; + } + WiFi_vParser(&client); + LOG_vPrintf("WiFiListener-Stop\n"); + } + + close(listen_sock); + return true; +} +bool WiFi_bSend(char* pchServerAddress, int32_t i32ServerPort, char* pchServerText) { + LOG_vPrintf("WiFi-Send-Sock\n"); + int sock; + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + LOG_vPrintf("WiFi-Send-Fail\n"); + return false; + } + + LOG_vPrintf("WiFi-Send-Init\n"); + struct sockaddr_in server_address; + memset(&server_address, 0, sizeof(server_address)); + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = inet_addr(pchServerAddress); + server_address.sin_port = htons(i32ServerPort); + + LOG_vPrintf("WiFi-Send-Connect\n"); + if (connect(sock, (struct sockaddr*)&server_address, sizeof(server_address)) == -1) { + LOG_vPrintf("WiFi-Send-Fail\n"); + close(sock); + return false; + } + + LOG_vPrintf("WiFi-Send-Send\n"); + if (send(sock, pchServerText, strlen(pchServerText), MSG_CONFIRM) == -1) { + LOG_vPrintf("WiFi-Send-NoConfirmation\n"); + close(sock); + return false; + } + + LOG_vPrintf("WiFi-Send-Close\n"); + close(sock); + return true; +} + + +//--Messages Module +#define PAYLOAD_SIZE 256 +#define PAYLOAD_DELIMITER '_' +#define MESSAGES_SIZE 2000 +typedef struct tMessage { + uint32_t u32Sender; + uint32_t u32Receiver; + uint64_t u64Timestamp; + char pchMessage[PAYLOAD_SIZE]; + bool bDone; + uint32_t* pu32Sent; + uint32_t u32Sent; +} sMessage; +typedef struct tMessages { + uint32_t u32Owner; + sMessage psArray[MESSAGES_SIZE]; + uint16_t u16ArrayIndex; + bool bFull; + uint32_t u32CheckedMessages; + uint32_t u32LoggedMessages; + sem_t semAccess; +} sMessages; +void MSG_vSetup(sMessages* psMessages, uint32_t u32Owner) { + sem_init(&psMessages->semAccess, 0, 1); + + psMessages->u32Owner = u32Owner; + + psMessages->u16ArrayIndex = 0; + psMessages->bFull = false; + + psMessages->u32CheckedMessages = 0; + psMessages->u32LoggedMessages = 0; +} +static inline sMessage* MSG_mGet(sMessages* psMessages, uint16_t u16Index) { + //sem_wait(&semMessages); + + sMessage* temp; + if (psMessages->bFull) { + temp = &psMessages->psArray[(psMessages->u16ArrayIndex + u16Index) % MESSAGES_SIZE]; + } else + temp = &psMessages->psArray[u16Index]; + + //sem_post(&semMessages); + + return temp; +} +static inline uint16_t MSG_u16Length(sMessages* psMessages) { + //sem_wait(&semMessages); + + uint16_t temp; + if (psMessages->bFull) + temp = MESSAGES_SIZE; + else + temp = psMessages->u16ArrayIndex; + + //sem_post(&semMessages); + + return temp; +} +void MSG_vInsert(sMessages* psMessages, sMessage* psMessage, bool bSent, uint32_t u32Device) { + sem_wait(&psMessages->semAccess); + + psMessages->psArray[psMessages->u16ArrayIndex].u32Sender = psMessage->u32Sender; + psMessages->psArray[psMessages->u16ArrayIndex].u32Receiver = psMessage->u32Receiver; + psMessages->psArray[psMessages->u16ArrayIndex].u64Timestamp = psMessage->u64Timestamp; + psMessages->psArray[psMessages->u16ArrayIndex].bDone = (psMessage->u32Receiver == psMessages->u32Owner); + memcpy(psMessages->psArray[psMessages->u16ArrayIndex].pchMessage, psMessage->pchMessage, strlen(psMessage->pchMessage)); + if (bSent) { + psMessages->psArray[psMessages->u16ArrayIndex].u32Sent = 1; + psMessages->psArray[psMessages->u16ArrayIndex].pu32Sent = (uint32_t*)malloc(1 * sizeof(uint32_t)); + psMessages->psArray[psMessages->u16ArrayIndex].pu32Sent[0] = u32Device; + } + else + psMessages->psArray[psMessages->u16ArrayIndex].u32Sent = 0; + + psMessages->u16ArrayIndex = (psMessages->u16ArrayIndex + 1) % MESSAGES_SIZE; + if (psMessages->u16ArrayIndex == 0) + psMessages->bFull = true; + + psMessages->u32LoggedMessages++; + sem_post(&psMessages->semAccess); +} +bool MSG_bCheck(sMessages* psMessages, sMessage* psMessage) { + sem_wait(&psMessages->semAccess); + + uint16_t u16ArrayLength = MSG_u16Length(psMessages); + + bool flag = false; + for (uint16_t i = 0; i < u16ArrayLength; i++) { + sMessage* temp = MSG_mGet(psMessages, i); + if (temp->u32Sender != psMessage->u32Sender) + continue; + if (temp->u32Receiver != psMessage->u32Receiver) + continue; + if (temp->u64Timestamp != psMessage->u64Timestamp) + continue; + if (strcmp(temp->pchMessage, psMessage->pchMessage) != 0) + continue; + flag = true; + break; + } + + psMessages->u32CheckedMessages++; + sem_post(&psMessages->semAccess); + return flag; +} +bool MSG_bParse(sMessage* psMessage, char* pchBuffer) { + char* pchArrays[4]; + bool bFlag = false; + + uint16_t i; + char* s = pchBuffer; + for (i = 0; s[i]; s[i] == PAYLOAD_DELIMITER ? i++ : *s++); + if (i != 3) + return false; + + char* pchRest = pchBuffer; + for (uint8_t i = 0; i < 3; i++) { + const char s[2] = { PAYLOAD_DELIMITER, '\0'}; + pchArrays[i] = strtok(pchRest, s); + + if (pchArrays[i] == NULL) { + bFlag = true; + break; + } else { + pchRest += strlen(pchRest) + 1; + } + } + pchArrays[3] = pchRest; + + if (!bFlag) { + psMessage->u32Sender = atoi(pchArrays[0]); + psMessage->u32Receiver = atoi(pchArrays[1]); + psMessage->u64Timestamp = atoi(pchArrays[2]); + strcpy(psMessage->pchMessage, pchArrays[3]); + } + + return (!bFlag); +} +void MSG_vExport(sMessages* psMessages) { + sem_wait(&psMessages->semAccess); + + uint16_t u16ArrayLength = MSG_u16Length(psMessages); + FILE* file = fopen("/tmp/messages.txt", "w"); + if (file == NULL) { + sem_post(&psMessages->semAccess); + return; + } + fprintf(file, "Checked:"FU32"\n", psMessages->u32CheckedMessages); + fprintf(file, "Logged:"FU32"\n", psMessages->u32LoggedMessages); + fprintf(file, "Index:"FU32"\n", psMessages->u16ArrayIndex); + fprintf(file, "index:sender_receiver_timestamp_message:sent:done\n"); + for (uint16_t i = 0; i < u16ArrayLength; i++) { + sMessage* temp = MSG_mGet(psMessages, i); + fprintf(file, FU16":"FU32"_"FU32"_"FU64"_"FSTR":"FU32":"FU08"\n", i, temp->u32Sender, temp->u32Receiver, temp->u64Timestamp, temp->pchMessage, temp->u32Sent, (temp->bDone ? 1 : 0)); + } + fclose(file); + + sem_post(&psMessages->semAccess); +} +void MSG_vSend(sMessages* psMessages, uint32_t u32Receiver, bool (*bSend)(char* pchBuffer)) { + sem_wait(&psMessages->semAccess); + + uint16_t u16Length; + if (psMessages->bFull) + u16Length = MESSAGES_SIZE; + else + u16Length = psMessages->u16ArrayIndex; + + for (uint16_t i = 0; i < u16Length; i++) { + sMessage* temp = MSG_mGet(psMessages, i); + + bool bFlag = false; + if (temp->bDone) + bFlag = true; + else { + for (uint32_t j = 0 ; j < temp->u32Sent; j++) { + if (temp->pu32Sent[j] == u32Receiver) { + bFlag = true; + break; + } + } + } + + + if (bFlag) + continue; + else { + LOG_vPrintf("Message-Send-"FU32"-Start\n", i); + char pchBuffer[5 + 5 + 3 + 10 + 256]; + sprintf(pchBuffer, FU32"_"FU32"_"FU64"_"FSTR, temp->u32Sender, temp->u32Receiver, temp->u64Timestamp, temp->pchMessage); + LOG_vPrintf("Message-Send-"FU32"-Send\n", i); + if (bSend(pchBuffer)) { + if (temp->u32Sent == 0) + temp->pu32Sent = (uint32_t*)malloc(1 * sizeof(uint32_t)); + else + temp->pu32Sent = (uint32_t*)realloc(temp->pu32Sent, (temp->u32Sent + 1) * sizeof(uint32_t)); + temp->pu32Sent[temp->u32Sent] = u32Receiver; + temp->u32Sent++; + + temp->bDone = (temp->u32Receiver == u32Receiver); + } else { + LOG_vPrintf("Message-Send-"FU32"-Error\n", i); + } + LOG_vPrintf("Message-Send-"FU32"-Stop\n", i); + } + } + + sem_post(&psMessages->semAccess); +} +sMessages sMessagesList; + + +//--Devices Module +#define DEVICES_SIZE 100 +typedef struct tDevice { + uint32_t u32Id; + bool bActive; + uint64_t u64Start; + uint64_t u64Last; +} sDevice; +typedef struct tDevices { + sDevice psArray[DEVICES_SIZE]; + uint16_t u16ArrayIndex; + bool bFull; + sem_t semAccess; +} sDevices; +void DVC_vSetup(sDevices* psDevices) { + sem_init(&psDevices->semAccess, 0, 1); + + psDevices->u16ArrayIndex = 0; + psDevices->bFull = false; +} +void DVC_vInsert(sDevices* psDevices, uint16_t u32Id) { + //sem_wait(&semDevices); + + psDevices->psArray[psDevices->u16ArrayIndex].u32Id = u32Id; + psDevices->psArray[psDevices->u16ArrayIndex].bActive = true; + psDevices->psArray[psDevices->u16ArrayIndex].u64Start = TIME_u64Current(); + psDevices->psArray[psDevices->u16ArrayIndex].u64Last = 0; + + psDevices->u16ArrayIndex = (psDevices->u16ArrayIndex + 1) % DEVICES_SIZE; + if (psDevices->u16ArrayIndex == 0) + psDevices->bFull = true; + + //sem_post(&semDevices); +} +uint16_t DVC_u16Update(sDevices* psDevices, uint32_t* pu32Id, uint16_t u16IdSize, uint32_t* pu32New) { + sem_wait(&psDevices->semAccess); + + uint16_t u16ArrayLength; + if (psDevices->bFull) + u16ArrayLength = DEVICES_SIZE; + else + u16ArrayLength = psDevices->u16ArrayIndex; + + bool pbFlag[u16IdSize]; + for (uint16_t j = 0; j < u16IdSize; j++) { + pbFlag[j] = false; + } + for (uint16_t i = 0; i < u16ArrayLength; i++) { + bool bFlag = false; + for (uint16_t j = 0; j < u16IdSize; j++) { + if (psDevices->psArray[i].u32Id == pu32Id[j]) { + bFlag = true; + pbFlag[j] = true; + break; + } + } + + if (bFlag) { + if (psDevices->psArray[i].bActive) + psDevices->psArray[i].u64Last = TIME_u64Current(); + else { + psDevices->psArray[i].bActive = true; + psDevices->psArray[i].u64Start = TIME_u64Current(); + psDevices->psArray[i].u64Last = 0; + } + } else { + psDevices->psArray[i].bActive = false; + } + } + + uint16_t u16Cnt = 0; + for (uint16_t j = 0; j < u16IdSize; j++) { + if (!pbFlag[j]) { + DVC_vInsert(psDevices, pu32Id[j]); + pu32New[u16Cnt] = pu32Id[j]; + u16Cnt++; + } + } + + sem_post(&psDevices->semAccess); + return u16Cnt; +} +void DVC_vExport(sDevices* psDevices) { + sem_wait(&psDevices->semAccess); + + uint16_t u16ArrayLength; + if (psDevices->bFull) + u16ArrayLength = DEVICES_SIZE; + else + u16ArrayLength = psDevices->u16ArrayIndex; + + FILE* file = fopen("/tmp/devices.txt", "w"); + if (file == NULL) { + sem_post(&psDevices->semAccess); + return; + } + fprintf(file, FU32"\n", psDevices->u16ArrayIndex); + fprintf(file, "index:active,id,start,stop\n"); + for (uint16_t i = 0; i < u16ArrayLength; i++) + fprintf(file, FU32":"FSTR","FU32","FU64","FU64"\n", i, psDevices->psArray[i].bActive ? "true" : "false", psDevices->psArray[i].u32Id, psDevices->psArray[i].u64Start, psDevices->psArray[i].u64Last); + fclose(file); + + sem_post(&psDevices->semAccess); +} +sDevices sDevicesList; + + +//--Timer Module +#include +#include +typedef struct tInterrupt { + bool bRunning; + uint32_t u32Ticks; + void (*vCallback)(uint32_t); +} sInterrupt; +sInterrupt sTimer; +void TMR_vHandler(int sig) { + static uint32_t i = 0; + sTimer.vCallback(i - 1); + + i++; + if (sTimer.u32Ticks > 0 && i >= sTimer.u32Ticks) { + struct itimerval sInterval = {0}; + setitimer(ITIMER_REAL, &sInterval, NULL); + sTimer.bRunning = false; + } +} +bool TMR_bSetup(suseconds_t susInterval, void (*vCallback)(uint32_t)) { + sTimer.vCallback = vCallback; + sTimer.u32Ticks = 0; + sTimer.bRunning = true; + + signal(SIGALRM, TMR_vHandler); + + struct itimerval sInterval; + sInterval.it_interval.tv_usec = susInterval % 1000000; + sInterval.it_interval.tv_sec = susInterval / 1000000; + sInterval.it_value = sInterval.it_interval; + + if (setitimer(ITIMER_REAL, &sInterval, NULL) != 0) + return false; + + return true; +} + + +//--High Level Application +#include +#include +#include +#define AEM 8844 +#define SERVER_PORT 2288 +#define INTERRUPTS +#ifdef INTERRUPTS +sem_t semSearcher; +#endif +const uint32_t pu32FriendsList[] = {7000, 7001, 7002, 7003, 8845}; +const uint8_t u08FriendsSize = 5; + +#define CREATE_PERIOD_MIN 1 //secs +#define CREATE_PERIOD_MAX 1 //secs +//#define CREATE_PERIOD_MIN 1*60 //secs +//#define CREATE_PERIOD_MAX 5*60 //secs +uint32_t u32Selector(void) { + static uint32_t count = 0; + count++; + + uint8_t index = RAND_u16GetNumber(0, u08FriendsSize - 1); + sMessage temp; + temp.u32Sender = AEM; + temp.u32Receiver = pu32FriendsList[index]; + temp.u64Timestamp = TIME_u64Current(); + sprintf(temp.pchMessage, "I am message #%d of GKyri", count); + temp.u32Sent = 0; + + LOG_vPrintf("Selector-Insert\n"); + MSG_vInsert(&sMessagesList, &temp, false, 0); + /* + LOG_vPrintf("Selector-Export\n"); + MSG_vExport(&sMessagesList); + */ + + return pu32FriendsList[index]; +} +void APP_vCallback(uint32_t u32Tick) { + static bool bRunning = false; + if (!bRunning) { + bRunning = true; + + LOG_vPrintf("Callback-Start\n"); + u32Selector(); + LOG_vPrintf("Callback-Stop\n"); + + #ifdef INTERRUPTS + sem_post(&semSearcher); + #endif + + bRunning = false; + } +} +void APP_vCreator(void) { + uint16_t u16Interval = RAND_u16GetNumber(CREATE_PERIOD_MIN, CREATE_PERIOD_MAX); + if (TMR_bSetup(500000, APP_vCallback)) { + //if (TMR_bSetup(u16Interval * 1000000, APP_vCallback)) { + while (true) + pause(); + } +} + +bool APP_bReceiveBuffer(uint8_t* pu08Address, char* pchBuffer) { + LOG_vPrintf("Receiver-Start\n"); + uint32_t u32Id = (uint32_t)pu08Address[2] * 100 + pu08Address[3]; + + sMessage temp; + if (!MSG_bParse(&temp, pchBuffer)) + return false; + temp.u32Sent = 0; + if (!MSG_bCheck(&sMessagesList, &temp)) { + LOG_vPrintf("Receiver-Insert\n"); + MSG_vInsert(&sMessagesList, &temp, true, u32Id); + /* + LOG_vPrintf("Receiver-Export\n"); + MSG_vExport(&sMessagesList); + */ + } + LOG_vPrintf("Receiver-Stop\n"); + +#ifdef INTERRUPTS + sem_post(&semSearcher); +#endif + return true; +} +void APP_vListener(void) { + WiFi_bListener(SERVER_PORT, APP_bReceiveBuffer); +} + +char pchMessageReceiver[15 + 1]; +bool APP_bSendBuffer(char* pchBuffer) { + return WiFi_bSend(pchMessageReceiver, SERVER_PORT, pchBuffer); +} +bool APP_bSender(uint32_t u32Receiver) { + sprintf(pchMessageReceiver, "10.0."FU08"."FU08, u32Receiver / 100, u32Receiver % 100); + + char pchTest[13 + 15 + 12 + 1]; + sprintf(pchTest, "ping -c1 -w1 "FSTR" > /dev/null", pchMessageReceiver); + if (system(pchTest) == 0) { + MSG_vSend(&sMessagesList, u32Receiver, APP_bSendBuffer); + return true; + } else { + return false; + } +} +#define SEARCHER_SLEEP_PERIOD 60 //secs +#define SEARCHER_SLEEP_DELAY 30 //secs +void APP_vSearcher(void) { +#ifdef INTERRUPTS + sem_init(&semSearcher, 0, 0); +#endif + + sleep(SEARCHER_SLEEP_PERIOD); + while (true) { + LOG_vPrintf("Searcher-Start\n"); + + uint16_t u16Cnt = 0; + uint32_t* pu32Id = (uint32_t*)malloc(1 * sizeof(uint32_t)); + for (uint8_t i = 0; i < u08FriendsSize; i++) { + uint32_t u32Receiver = pu32FriendsList[i]; + sprintf(pchMessageReceiver, "10.0."FU08"."FU08, u32Receiver / 100, u32Receiver % 100); + + char pchTest[13 + 15 + 12 + 1]; + sprintf(pchTest, "ping -c1 -w1 "FSTR" > /dev/null", pchMessageReceiver); + if (system(pchTest) == 0) { + pu32Id[u16Cnt] = u32Receiver; + u16Cnt++; + pu32Id = (uint32_t*)realloc(pu32Id, (u16Cnt + 1) * sizeof(uint32_t)); + } + } + + LOG_vPrintf("Searcher-Send-Start\n"); + uint32_t pu32New[u16Cnt]; + //uint16_t u16NewLength = DVC_u16Update(&sDevicesList, pu32Id, u16Cnt, pu32New); + DVC_u16Update(&sDevicesList, pu32Id, u16Cnt, pu32New); + + for (uint16_t i = 0; i < u16Cnt; i++) { + LOG_vPrintf("Searcher-Send-"FU32"-Start\n", i); + APP_bSender(pu32Id[i]); + LOG_vPrintf("Searcher-Send-"FU32"-Stop\n", i); + } + free(pu32Id); + LOG_vPrintf("Searcher-Send-Stop\n"); + + LOG_vPrintf("Searcher-Export\n"); + DVC_vExport(&sDevicesList); + MSG_vExport(&sMessagesList); + LOG_vPrintf("Searcher-Stop\n"); + +#ifdef INTERRUPTS + for (uint16_t i = 0; i < SEARCHER_SLEEP_PERIOD; i++) { + int value; + sem_getvalue(&semSearcher, &value); + if (value > 0) { + if (i > SEARCHER_SLEEP_DELAY) { + LOG_vPrintf("Searcher-Interrupt\n"); + sem_wait(&semSearcher); + break; + } + } + sleep(1); + } +#else + sleep(SLEEP_PERIOD); +#endif + } +} + +void APP_vSetup(void){ + int8_t i08Result; + + bool bFlag = false; + i08Result = FILE_i08Compare("/root/wpa_supplicant.conf", "/etc/wpa_supplicant/wpa_supplicant.conf"); + if (i08Result == 0 || i08Result == 2) { + bFlag = true; + LOG_vPrintf("Replacing 'wpa_supplicant'\n"); + system("sudo cp /root/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf"); + } + + i08Result = FILE_i08Compare("/root/interfaces", "/etc/network/interfaces"); + if (i08Result == 0 || i08Result == 2) { + bFlag = true; + LOG_vPrintf("Replacing 'interfaces'\n"); + system("sudo cp /root/interfaces /etc/network/interfaces"); + } + + i08Result = FILE_i08Compare("/root/messenger.service", "/etc/systemd/system/messenger.service"); + if (i08Result == 0 || i08Result == 2) { + bFlag = true; + LOG_vPrintf("Replacing 'messenger.service'\n"); + system("sudo cp /root/messenger.service /etc/systemd/system"); + system("systemctl enable messenger"); + } + + if (bFlag) { + LOG_vPrintf("Restarting\n"); + system("shutdown -r 0"); + exit(EXIT_SUCCESS); + } +} +void* Th1Func(void* ptr) { + APP_vListener(); + return NULL; +} +void* Th2Func(void* ptr) { + APP_vCreator(); + return NULL; +} +void* Th3Func(void* ptr) { + APP_vSearcher(); + return NULL; +} +int main( int argc, char* const* argv) { + APP_vSetup(); + LOG_vSetup(); + MSG_vSetup(&sMessagesList, AEM); + DVC_vSetup(&sDevicesList); + + pthread_t thread1, thread2, thread3; + pthread_create( &thread1, NULL, Th1Func, NULL); + pthread_create( &thread2, NULL, Th2Func, NULL); + pthread_create( &thread3, NULL, Th3Func, NULL); + + pthread_join( thread1, NULL); + pthread_join( thread2, NULL); + pthread_join( thread3, NULL); + + return EXIT_SUCCESS; +} diff --git a/src/msg_impl.h b/src/msg_impl.h new file mode 100755 index 0000000..c75220a --- /dev/null +++ b/src/msg_impl.h @@ -0,0 +1,204 @@ +/*! + * \file msg_impl.h + * + * Contain all the implementation specific types + * + * \author: Christos Choutouridis 8997 + */ + +#ifndef __msg_impl__ +#define __msg_impl__ + +#include +#include +#include +#include + +/*! + * General options + */ +//! @{ +#define LISTENER_PORT 2288 //!< The server port +#define MSG_TEXT_SIZE 256 //!< Maximum size of each message +#define MSG_LIST_SIZE 2000 //!< Maximum size of message history buffer +#define DEVICE_LIST_SIZE 100 //!< Maximum size of the device list + +#define MSG_DELIMITER '_' //!< Message delimiter +#define ADHOC_NET_A 10 //!< [A.B.C.D] +#define ADHOC_NET_B 0 +#define ADHOC_NET_C 0 +#define ADHOC_NET_D 0 + +//#define NO_DEBUG 1 + +//! @} + +/*! + * Helper macros + */ +#define _MK_ADHOC_SUBNET(A, B, C, D) (((A)<<24) | ((B)<<16) | ((C)<<8) | (D)) +#define _adhoc_subnet _MK_ADHOC_SUBNET(ADHOC_NET_A, ADHOC_NET_B, ADHOC_NET_C, ADHOC_NET_D) +/*! + * Messenger types + */ + +//! @{ + +/*! + * Application status type + */ +typedef enum { + MSG_OK =0, //!< Indicate success + MSG_ERROR //!< Indicate error +} status_t; + +typedef bool bool_t; //!< Boolean type +typedef char char_t; //!< Application wide character type +typedef uint32_t aem_t; //!< AEM data type +typedef int64_t tstamp_t; //!< UNIX time in 64 bit wide signed integer + +/*! + * IP wrapper type + */ +typedef struct { + uint16_t A, B, C, D; +}devIP_t; + +/*! + * A RTES node device representation + * \note + * Objects of this type are also acting as fwd list nodes. + */ +typedef struct device { + aem_t id; //!< AEM of the device + struct device* next; //!< link to the next linked device on the chain +} device_t; + +typedef device_t* devList_t; //!< device list alias + + +/*! + * \brief + * Core message representation as it described in the requirements + * + * Object of this type constructed upon creation or when receiving a message. + * \note + * associate functions -- mutable-like interface: + * \sa cMsg_parse() used for parsing and creation + * \sa cMsg_getFromAEM() used as fromAEM getter + * \sa cMsg_getToAEM() used as toAEM getter + * \sa cMsg_getTs() used as timestamp getter + * \sa cMsg_getText() used as text getter + */ +typedef struct { + aem_t from; //!< sender's AEM + aem_t to; //!< destination AEM + tstamp_t ts; //!< UNIX timestamp compatible + size_t text; //!< text offset + char_t msg[MSG_TEXT_SIZE]; //!< The actual message stream +} cMsg_t; + + +/*! + * \brief + * Mid and application layer message representation + * + * This type + */ +typedef struct { + device_t sender; //!< The sender's device + devList_t recipients; //!< List of all devices the message has reach + cMsg_t cMsg; //!< actual message payload +} msg_t; + +typedef int32_t mIter_t; //!< message list iterator type + +/*! + * \brief Message list + * + * This holds the last \a MSG_LIST_SIZE messages exchanged from this + * device(including the ones we have create). + * + * With this we create a 2 dimensional map of msg/dev where each item + * of the list is linked with all the devices reached by us as a fwd-list. + * The items on the msgList are: + * - Messages we create + * - Messages received by the listener + * + * Here we define 2 directions for iteration. The message direction and the device + * direction. + * + * Every node on the msgList.m array represents a message. Every node in the device + * list inside msgList[m].recipients represent devices we don't anymore need to send + * the current message to them. + * + * Layout example: + * + * msgList.m + * [ 0 ] --> [devx] --> [devy] -- >0 + * | [ 1 ] --> [devy] -- > 0 + * time | [ 2 ] --> 0 + * [*1] | [ 3 ] ... + * \|/ + * ... + * + * [MAX] + * + * [*1]: msgList is actually implemented as a ring buffer so in that + * content, "time is a loop". + */ +typedef struct { + msg_t m[MSG_LIST_SIZE]; //!< The actual data representation + mIter_t last; //!< A ring buffer iterator marking the last item on .m + size_t size; +} msgList_t; + +//! @} + +/*! + * Client types + */ +//! @{ + +#define PING_PKT_S (64) +#define PING_MSG_S (PING_PKT_S - sizeof(struct icmphdr)) +typedef struct { + struct icmphdr hdr; + char msg[PING_MSG_S]; +}ping_pkt_t; + +//! @} + + + +/*! + * Application settings + */ +//! @{ + +typedef enum { + OUTLEVEL_0, //!< Output only results [default] + OUTLEVEL_1, //!< Output results and every message also + OUTLEVEL_2 //!< Debug level, use with care! +}outLevel_en; + + +typedef struct { + uint16_t port; + time_t duration; + time_t msgInterval; + outLevel_en outLevel; +}settings_t; + +extern settings_t settings; + +#define settings_init(s) s = { \ + .port = 2288, \ + .duration = 7200, \ + .msgInterval = 60, \ + .outLevel = OUTLEVEL_1 \ +} + +//! @} + +#endif /* __msg_impl__ */