summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/server/main.c91
-rw-r--r--src/server/net.c149
-rw-r--r--src/server/net.h36
3 files changed, 208 insertions, 68 deletions
diff --git a/src/server/main.c b/src/server/main.c
index 8e4f413..1b36c2f 100644
--- a/src/server/main.c
+++ b/src/server/main.c
@@ -31,99 +31,54 @@
#include <stddef.h>
#include <stdlib.h>
#include <time.h>
+#include "net.h"
-static void init(const unsigned int port, int *sock);
-static int getpacket(char *data, size_t buffsize, int *sock, struct sockaddr_in *sender);
+static struct netstate *init(const unsigned int port);
static void draw_idle(void);
static void draw_busy(const char * const data);
static float digest_temp(const short int rawdata);
int main(void)
{
- static const char servermagic[] = "I love coffee!";
- static const char clientmagic[] = "I love tea!";
- struct sockaddr_in srvaddr = {0};
- char buff[9001] = {0};
- int sock;
- int pstatus;
- struct timespec lastreply;
- struct timespec now;
+ struct netstate *state;
+ char data[8] = {0};
+ int status;
+ struct timespec wait = {0, 500 * 1000 * 1000};
- init(2191, &sock);
-
- clock_gettime(CLOCK_MONOTONIC_RAW, &now);
- lastreply = now;
- lastreply.tv_sec -= 5;
+ state = init(2191);
do {
- clock_gettime(CLOCK_MONOTONIC_RAW, &now);
- pstatus = getpacket(buff, sizeof(buff), &sock, &srvaddr);
-
- switch (pstatus) {
- case 0:
- if ((now.tv_sec - lastreply.tv_sec) >= 5) {
- draw_idle();
- }
- break;
- case 1:
- lastreply = now;
- if (buff[0] == 'I') {
- if (!(strcmp(buff, servermagic))) {
- sendto(sock, clientmagic, sizeof(clientmagic),
- MSG_DONTWAIT, (struct sockaddr *) &srvaddr, sizeof(srvaddr));
- }
- draw_idle();
- continue;
- }
- draw_busy(buff);
+ status = state->getlastdata(data, state);
+ switch (status) {
+ case NET_OK:
+ /*fall-through */
+ case NET_NONEWDATA:
+ draw_busy(data);
break;
+ case NET_ERROR:
+ goto fail;
default:
+ draw_idle();
; /* noop */
}
- } while (getch() != 'q' && pstatus >= 0);
+ nanosleep(&wait, NULL);
+ } while (getch() != 'q');
- close(sock);
+fail:
+ net_close(&state);
endwin();
return 0;
}
-static void init(const unsigned int port, int *sock)
+static struct netstate *init(const unsigned int port)
{
- struct sockaddr_in bindaddress = {0};
-
- bindaddress.sin_family = AF_INET;
- bindaddress.sin_port = htons(port);
- *sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- bind(*sock, (struct sockaddr*) &bindaddress, sizeof(bindaddress));
+ struct netstate *ret;
+ ret = net_init(port);
initscr();
nodelay(stdscr, 1);
noecho();
-}
-
-static int getpacket(char *data, size_t buffsize, int *sock, struct sockaddr_in *sender)
-{
- static struct pollfd pfd = {0};
- int ret;
- socklen_t sender_len = sizeof(*sender);
-
- if (!pfd.fd) {
- pfd.fd = *sock;
- pfd.events = POLLIN;
- pfd.revents = 0;
- }
-
- ret = poll(&pfd, 1, 25);
- if (ret <= 0) {
- return ret;
- }
- if (pfd.revents & POLLIN) {
- recvfrom(*sock, data, buffsize, MSG_DONTWAIT, (struct sockaddr *) sender, &sender_len);
- ret = 1;
- } else {
- ret = 0;
- }
return ret;
}
diff --git a/src/server/net.c b/src/server/net.c
new file mode 100644
index 0000000..cecf10c
--- /dev/null
+++ b/src/server/net.c
@@ -0,0 +1,149 @@
+/*
+ * Hot Beverage Companion – desktop app network module
+ *
+ * Copyright (C) 2017 Gediminas Jakutis
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <poll.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include "net.h"
+
+struct netstate_internal {
+ int (*getlastdata)(char * const data, struct netstate * const state);
+ unsigned int handle;
+ struct timespec lastreply;
+ int sock;
+};
+
+static int dolisten(char * const data, struct netstate_internal * const state);
+static int getpacket(char *data, size_t buffsize, int sock, struct sockaddr_in *sender);
+static int getlastdata_internal(char * const data, struct netstate * const state);
+
+struct netstate *net_init(const unsigned int port)
+{
+ struct netstate_internal *ret;
+ struct sockaddr_in bindaddress = {0};
+
+ ret = malloc(sizeof(struct netstate_internal));
+ bindaddress.sin_family = AF_INET;
+ bindaddress.sin_port = htons(port);
+ ret->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (bind(ret->sock, (struct sockaddr*) &bindaddress, sizeof(bindaddress))) {
+ free(ret);
+ return NULL;
+ }
+
+ clock_gettime(CLOCK_MONOTONIC_RAW, &ret->lastreply);
+ ret->lastreply.tv_sec -= 5;
+ ret->handle = 0; /* currently unused */
+ ret->getlastdata = &getlastdata_internal;
+
+ return (struct netstate *) ret;
+}
+
+int net_close(struct netstate **state) {
+ close((*(struct netstate_internal **)state)->sock);
+ free(*state);
+ *state = NULL;
+ return 0;
+}
+
+static int dolisten(char * const data, struct netstate_internal * const state)
+{
+ char buff[9001] = {0};
+ static const char servermagic[] = "I love coffee!";
+ static const char clientmagic[] = "I love tea!";
+ struct timespec now;
+ struct timespec wait = {0, 25 * 1000 * 1000};
+ struct sockaddr_in clientaddr;
+ size_t i = 10;
+ int ret;
+
+ do {
+ clock_gettime(CLOCK_MONOTONIC_RAW, &now);
+ ret = getpacket(buff, sizeof(buff), state->sock, &clientaddr);
+
+ switch (ret) {
+ case NET_OK:
+ state->lastreply = now;
+ if (buff[0] == 'I') {
+ if (!(strcmp(buff, servermagic))) {
+ sendto(state->sock, clientmagic, sizeof(clientmagic),
+ MSG_DONTWAIT, (struct sockaddr *) &clientaddr, sizeof(clientaddr));
+ }
+ ret = NET_NONEWDATA; /* consume packet and lie about it */
+ continue;
+ } else {
+ memcpy(data, buff, 8ul);
+ }
+ break;
+ default:
+ ; /* noop */
+ }
+
+ if (!ret) {
+ nanosleep(&wait, NULL);
+ }
+ } while (--i && ret != 0);
+
+ /* no packets in five seconds */
+ if ((now.tv_sec - state->lastreply.tv_sec) >= 5) {
+ ret = NET_DEAD;
+ }
+
+ return ret;
+}
+
+static int getpacket(char *data, size_t buffsize, int sock, struct sockaddr_in *sender)
+{
+ static struct pollfd pfd = {0};
+ int ret;
+ socklen_t sender_len = sizeof(*sender);
+
+ if (!pfd.fd) {
+ pfd.fd = sock;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+ }
+
+ ret = poll(&pfd, 1, 0);
+ if (ret < 0) {
+ /* NOOP */
+ } else if (!ret) {
+ ret = NET_NONEWDATA;
+ } else if (pfd.revents & POLLIN) {
+ recvfrom(sock, data, buffsize, MSG_DONTWAIT, (struct sockaddr *) sender, &sender_len);
+ ret = NET_OK;
+ } else {
+ ret = NET_NONEWDATA;
+ }
+
+ return ret;
+}
+
+
+static int getlastdata_internal(char * const data, struct netstate * const state)
+{
+ return dolisten(data, (struct netstate_internal *) state);
+}
diff --git a/src/server/net.h b/src/server/net.h
new file mode 100644
index 0000000..57c17f6
--- /dev/null
+++ b/src/server/net.h
@@ -0,0 +1,36 @@
+/*
+ * Hot Beverage Companion – desktop app network module
+ *
+ * Copyright (C) 2017 Gediminas Jakutis
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef NET_H_INCLUDED
+#define NET_H_INCLUDED
+
+#define NET_ERROR -1
+#define NET_OK 0
+#define NET_NONEWDATA 1
+#define NET_DEAD 2
+
+struct netstate {
+ int (*getlastdata)(char * const data, struct netstate * const state);
+};
+
+struct netstate *net_init(const unsigned int port);
+int net_close(struct netstate **state);
+
+#endif /* NET_H_INCLUDED */