summaryrefslogtreecommitdiffstats
path: root/src/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon')
-rw-r--r--src/daemon/main.c48
-rw-r--r--src/daemon/net.c99
-rw-r--r--src/daemon/proto_stdio.c43
-rw-r--r--src/daemon/purple.c7
4 files changed, 141 insertions, 56 deletions
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 94e59fd..37b1a51 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -23,31 +23,46 @@
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include "settings.h"
#include "net.h"
#include "purple.h"
+#include "proto_stdio.h"
static struct _state {
int nd;
-} _progstate;
+} __progstate;
-void cleanup(void);
+static void cleanup(void);
+static int __main_loop(const struct timespec * const iter_len);
/* the logic is a placeholder right now */
int main(int argc, char **argv)
{
extern const char * const version;
- struct timespec t = {3600, 0}; /* one hour */
+ static const struct timespec t = {0, 250 * 1000 * 1000}; /* 250ms */
+ char *proto;
printf("Usurpation daemon version %s starting\n", version);
atexit(cleanup);
settings_init();
- _progstate.nd = net_init(setting_port());
- if (purple_init() && setting_verbose()) {
- fprintf(stderr, "libpurple initialization failed\n");
+ __progstate.nd = net_init(setting_port());
+ proto = setting_im_proto();
+
+ if (strcmp(proto, "null")) {
+ if (purple_init() && setting_verbose()) {
+ fprintf(stderr, "libpurple initialization failed\n");
+ }
+ } else {
+ if (proto_stdio_init() && setting_verbose()) {
+ fprintf(stderr, "libpurple initialization failed\n");
+ }
}
+ free(proto);
+ proto = NULL;
+
/* by default and if running by as a system service, the init system
* needs to keep control of the process and thus only detach if
* requested when ran manually by a user.
@@ -56,17 +71,28 @@ int main(int argc, char **argv)
daemon(0, 0);
}
- while(!(nanosleep(&t, NULL))) {
- /* noop */
+ return __main_loop(&t);
+}
+
+/* TODO: semi-stub */
+static int __main_loop(const struct timespec * const iter_len)
+{
+ struct timespec t;
+ int ret = A_OK;
+
+ t = *iter_len;
+ while (!ret) {
+ nanosleep(&t, NULL);
}
- return 0;
+ return ret;
}
-void cleanup(void)
+static void cleanup(void)
{
purple_close();
- net_close(_progstate.nd);
+ proto_stdio_close();
+ net_close(__progstate.nd);
settings_cleanup();
}
diff --git a/src/daemon/net.c b/src/daemon/net.c
index 9180344..62172fe 100644
--- a/src/daemon/net.c
+++ b/src/daemon/net.c
@@ -45,10 +45,11 @@ struct netstate {
size_t bufsize;
unsigned int available;
int status;
- pthread_mutex_t datamutex;
+ pthread_mutex_t mutex;
+ struct sockaddr_in clientaddr;
};
-static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static struct netstate *state;
static ssize_t count;
static size_t available_count;
@@ -63,7 +64,7 @@ int net_init(const unsigned short int port)
ssize_t i;
int sizechanged = 0;
- pthread_mutex_lock(&initmutex);
+ pthread_mutex_lock(&mutex);
if (available_count) {
for (i = 0; !state[i].available; ++i) {
if (i == count) {
@@ -98,7 +99,7 @@ int net_init(const unsigned short int port)
memset(state[i].data, 0, MTU);
state[i].bufsize = MTU;
state[i].status = NONEWDATA;
- pthread_mutex_init(&state[i].datamutex, NULL);
+ pthread_mutex_init(&state[i].mutex, NULL);
if (pthread_create(&state[i].listner, NULL, dolisten, state + i)) {
ret = ERROR;
@@ -111,7 +112,7 @@ out:
state = realloc(state, sizeof(struct netstate) * --count);
}
- pthread_mutex_unlock(&initmutex);
+ pthread_mutex_unlock(&mutex);
return ret;
}
@@ -119,7 +120,7 @@ int net_close(int nd)
{
int ret;
- pthread_mutex_lock(&initmutex);
+ pthread_mutex_lock(&mutex);
if (nd > count || nd < 1 || state[nd - 1].available) {
ret = ERROR;
} else {
@@ -132,7 +133,7 @@ int net_close(int nd)
ret = A_OK;
}
- pthread_mutex_unlock(&initmutex);
+ pthread_mutex_unlock(&mutex);
return ret;
}
@@ -158,14 +159,69 @@ out:
return ret;
}
-static void *dolisten(void * state)
+int net_send(int nd, const char * const buf, size_t buf_size)
+{
+ int ret = A_OK;
+ ssize_t sent;
+ struct timespec now;
+
+ if (nd > count || nd < 1 || state[--nd].available || state[nd].status != A_OK) {
+ ret = ERROR;
+ } else {
+ if (setting_verbose() >= INFO) {
+ clock_gettime(CLOCK_MONOTONIC_RAW, &now);
+ fprintf(stderr, "Sending DATA, timestap: %li \n", now.tv_sec);
+ }
+
+ sent = sendto( state[nd].sock, buf, buf_size, MSG_DONTWAIT,
+ (struct sockaddr *) &state[nd].clientaddr,
+ sizeof(state[nd].clientaddr));
+
+ if (sent == -1) {
+ ret = DEAD;
+ if (setting_verbose() >= ERR) {
+ fprintf(stderr, "Sending packet to %s failed.\n", inet_ntoa(state[nd].clientaddr.sin_addr));
+ }
+ }
+ }
+
+ return ret;
+}
+
+int net_send_addr(int nd, const char * const buf, size_t buf_size, const struct sockaddr_in * const addr)
{
+ int ret = A_OK;
+ ssize_t sent;
+ struct timespec now;
- static const char servermagic[] = "I love coffee!";
- static const char clientmagic[] = "I love tea!";
+
+ if (nd > count || nd < 1 || state[--nd].available) {
+ ret = ERROR;
+ } else {
+ if (setting_verbose() >= INFO) {
+ clock_gettime(CLOCK_MONOTONIC_RAW, &now);
+ fprintf(stderr, "Sending DATA, timestap: %li \n", now.tv_sec);
+ }
+
+ sent = sendto( state[nd].sock, buf, buf_size, MSG_DONTWAIT,
+ (struct sockaddr *) addr,
+ sizeof(*addr));
+
+ if (sent == -1) {
+ ret = DEAD;
+ if (setting_verbose() >= ERR) {
+ fprintf(stderr, "Sending packet to %s failed.\n", inet_ntoa(addr->sin_addr));
+ }
+ }
+ }
+
+ return ret;
+}
+
+static void *dolisten(void * state)
+{
struct timespec now;
struct timespec wait = {0, 10 * 1000 * 1000}; /* 10 ms */
- struct sockaddr_in clientaddr;
struct netstate *st;
ssize_t recvbufsize;
int cancelstate;
@@ -176,17 +232,12 @@ static void *dolisten(void * state)
do {
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelstate);
- pthread_mutex_lock(&st->datamutex);
+ pthread_mutex_lock(&st->mutex);
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
- st->status = getpacket(st->data, st->bufsize, &recvbufsize, st->sock, &clientaddr);
+ st->status = getpacket(st->data, st->bufsize, &recvbufsize, st->sock, &st->clientaddr);
if (!st->status) {
st->lastreply = now;
- if (st->data[0] == 'I' && !(strcmp(st->data, servermagic))) {
- sendto(st->sock, clientmagic, sizeof(clientmagic),
- MSG_DONTWAIT, (struct sockaddr *) &clientaddr, sizeof(clientaddr));
- setting_verbose() ? fprintf(stderr, "Sending DATA, timestap: %li \n", st->lastreply.tv_sec) : 0;
- }
}
/* no packets in five seconds */
@@ -199,15 +250,15 @@ static void *dolisten(void * state)
if (oldstatus != st->status)
{
oldstatus = st->status;
- if(st->status == DEAD) {
+ if (st->status == DEAD) {
/* this timestamp is arbitraty */
- setting_verbose() ? fprintf(stderr, "Connection with the client has been lost. Last reply since: %li \n", st->lastreply.tv_sec) : 0;
- } else {
- ipstring = inet_ntoa(clientaddr.sin_addr);
- setting_verbose() ? fprintf(stderr, "Successful incoming connection from %s\n", ipstring) : 0;
+ setting_verbose() >= INFO ? fprintf(stderr, "Connection with the client has been lost. Last reply since: %li \n", st->lastreply.tv_sec) : 0;
+ } else if (st->status == A_OK) {
+ ipstring = inet_ntoa(st->clientaddr.sin_addr);
+ setting_verbose() >= INFO ? fprintf(stderr, "Successful incoming connection from %s\n", ipstring) : 0;
}
}
- pthread_mutex_unlock(&st->datamutex);
+ pthread_mutex_unlock(&st->mutex);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancelstate);
pthread_testcancel();
diff --git a/src/daemon/proto_stdio.c b/src/daemon/proto_stdio.c
index f0a22a6..9aecdf0 100644
--- a/src/daemon/proto_stdio.c
+++ b/src/daemon/proto_stdio.c
@@ -27,32 +27,31 @@
void message_receive(char *arg)
{
int cancelstate;
- int done = 0;
- while (!done) {
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelstate);
- pthread_mutex_lock(&state.out_m);
- if (!state.writebuf) {
- state.writebuf = strdup(arg);
- done = 1;
- }
- pthread_mutex_unlock(&state.out_m);
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancelstate);
- pthread_testcancel();
- }
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelstate);
+ pthread_mutex_lock(&state.out_m);
+ state.writebuf = strdup(arg);
+ pthread_mutex_unlock(&state.out_m);
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancelstate);
+ pthread_testcancel();
+ nanosleep(&respite, NULL);
}
char *message_send(void)
{
- char *ret;
+ char *ret = NULL;
int cancelstate;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelstate);
pthread_mutex_lock(&state.out_m);
- ret = strdup(state.readbuf);
- free(state.readbuf);
- state.readbuf = NULL;
- state.readbufsize = 0;
+
+ if (state.readbuf) {
+ ret = strdup(state.readbuf);
+ free(state.readbuf);
+ state.readbuf = NULL;
+ state.readbufsize = 0;
+ }
+
pthread_mutex_unlock(&state.out_m);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancelstate);
pthread_testcancel();
@@ -140,12 +139,16 @@ int proto_stdio_init(void)
void proto_stdio_close(void)
{
- if (pthread_mutex_trylock(&state.mutex) == EBUSY) {
+ int status;
+
+ status = pthread_mutex_trylock(&state.mutex);
+
+ if (status == EBUSY) {
pthread_cancel(state.stdio_in);
pthread_cancel(state.stdio_out);
pthread_join(state.stdio_in, NULL);
pthread_join(state.stdio_out, NULL);
+ } else if (!status) {
+ pthread_mutex_unlock(&state.mutex);
}
-
- pthread_mutex_unlock(&state.mutex);
}
diff --git a/src/daemon/purple.c b/src/daemon/purple.c
index 138b30b..fc4f49f 100644
--- a/src/daemon/purple.c
+++ b/src/daemon/purple.c
@@ -251,9 +251,14 @@ int purple_init(void)
void purple_close(void)
{
+ int status;
- if (pthread_mutex_trylock(&state.mutex) == EBUSY) {
+ status = pthread_mutex_trylock(&state.mutex);
+
+ if (status == EBUSY) {
pthread_cancel(state.purple);
pthread_join(state.purple, NULL);
+ } else if (!status) {
+ pthread_mutex_unlock(&state.mutex);
}
}