From b528040d1193ba6e901313cf33c1fb532bbe79e8 Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Sat, 27 Jul 2019 15:46:04 +0200
Subject: [PATCH 1/5] libipc version 0.2
---
Makefile | 65 ++--
project.zsh | 3 +
src/communication.c | 703 ++++++++++++++++++++++++--------------------
src/error.c | 147 ++++-----
src/ipc.h | 406 ++++++++++++++++---------
src/logger.c | 78 ++++-
src/message.c | 203 +++----------
src/network.c | 163 ++++++++++
src/usocket.c | 234 +++++----------
src/usocket.h | 4 +-
src/utils.c | 38 ++-
src/utils.h | 1 -
12 files changed, 1147 insertions(+), 898 deletions(-)
create mode 100644 src/network.c
diff --git a/Makefile b/Makefile
index 567fa5c..980ca4e 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ MANDIR := $(SHAREDIR)/man
CC := cc
AR := ar
RANLIB := ranlib
-CFLAGS := -g
+CFLAGS := -Wall -Wextra -g
LDFLAGS :=
Q := @
@@ -19,7 +19,7 @@ Q := @
all: libipc src/ipc.h man/libipc.7
@:
-libipc: libipc.so libipc.a
+libipc: libipc.so libipc.a
@:
libipc.install: libipc.so.install libipc.a.install
@@ -27,7 +27,7 @@ libipc.clean: libipc.so.clean libipc.a.clean
libipc.uninstall: libipc.so.uninstall libipc.a.uninstall
-src/ipc.h.install: src/ipc.h
+src/ipc.h.install: src/ipc.h src
@echo '[01;31m IN > [01;37m$(INCLUDEDIR)/ipc.h[00m'
$(Q)mkdir -p '$(DESTDIR)$(INCLUDEDIR)'
$(Q)install -m0644 src/ipc.h $(DESTDIR)$(INCLUDEDIR)/ipc.h
@@ -39,7 +39,7 @@ src/ipc.h.uninstall:
@echo '[01;37m RM > [01;37m$(INCLUDEDIR)/ipc.h[00m'
$(Q)rm -f '$(DESTDIR)$(INCLUDEDIR)/ipc.h'
-man/libipc.7: man/libipc.7.md
+man/libipc.7: man/libipc.7.md man
@echo '[01;32m MAN > [01;37mman/libipc.7[00m'
$(Q)pandoc -s --from markdown --to man 'man/libipc.7.md' -o 'man/libipc.7'
@@ -57,9 +57,9 @@ man/libipc.7.uninstall:
@echo '[01;37m RM > [01;37m$(MANDIR)/man7/libipc.7[00m'
$(Q)rm -f '$(DESTDIR)$(MANDIR)/man7/libipc.7'
-libipc.so: src/communication.o src/error.o src/logger.o src/message.o src/usocket.o src/utils.o
+libipc.so: src/communication.o src/error.o src/logger.o src/message.o src/network.o src/usocket.o src/utils.o
@echo '[01;32m LD > [01;37mlibipc.so[00m'
- $(Q)$(CC) -o libipc.so -shared $(LDFLAGS) src/communication.o src/error.o src/logger.o src/message.o src/usocket.o src/utils.o
+ $(Q)$(CC) -o libipc.so -shared $(LDFLAGS) src/communication.o src/error.o src/logger.o src/message.o src/network.o src/usocket.o src/utils.o
libipc.so.install: libipc.so
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.so.0.1.0[00m'
@@ -86,9 +86,9 @@ libipc.so.uninstall:
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so[00m'
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so'
-libipc.a: src/communication.o src/error.o src/logger.o src/message.o src/usocket.o src/utils.o
+libipc.a: src/communication.o src/error.o src/logger.o src/message.o src/network.o src/usocket.o src/utils.o
@echo '[01;32m LD > [01;37mlibipc.a[00m'
- $(Q)$(AR) rc 'libipc.a' src/communication.o src/error.o src/logger.o src/message.o src/usocket.o src/utils.o
+ $(Q)$(AR) rc 'libipc.a' src/communication.o src/error.o src/logger.o src/message.o src/network.o src/usocket.o src/utils.o
libipc.a.install: libipc.a
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.a[00m'
@@ -103,9 +103,9 @@ libipc.a.uninstall:
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.a[00m'
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.a'
-src/communication.o: src/communication.c src/ipc.h src/utils.h src/message.h
+src/communication.o: src/communication.c src/ipc.h src/utils.h src/message.h
@echo '[01;34m CC > [01;37msrc/communication.o[00m'
- $(Q)$(CC) $(CFLAGS) -fPIC -c src/communication.c -fPIC -o src/communication.o
+ $(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/communication.c -fPIC -std=c11 -o src/communication.o
src/communication.o.install:
@@ -115,9 +115,9 @@ src/communication.o.clean:
src/communication.o.uninstall:
-src/error.o: src/error.c src/ipc.h
+src/error.o: src/error.c src/ipc.h
@echo '[01;34m CC > [01;37msrc/error.o[00m'
- $(Q)$(CC) $(CFLAGS) -fPIC -c src/error.c -fPIC -o src/error.o
+ $(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/error.c -fPIC -std=c11 -o src/error.o
src/error.o.install:
@@ -127,9 +127,9 @@ src/error.o.clean:
src/error.o.uninstall:
-src/logger.o: src/logger.c src/logger.h
+src/logger.o: src/logger.c src/logger.h
@echo '[01;34m CC > [01;37msrc/logger.o[00m'
- $(Q)$(CC) $(CFLAGS) -fPIC -c src/logger.c -fPIC -o src/logger.o
+ $(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/logger.c -fPIC -std=c11 -o src/logger.o
src/logger.o.install:
@@ -139,9 +139,9 @@ src/logger.o.clean:
src/logger.o.uninstall:
-src/message.o: src/message.c src/message.h src/usocket.h
+src/message.o: src/message.c src/message.h src/usocket.h
@echo '[01;34m CC > [01;37msrc/message.o[00m'
- $(Q)$(CC) $(CFLAGS) -fPIC -c src/message.c -fPIC -o src/message.o
+ $(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/message.c -fPIC -std=c11 -o src/message.o
src/message.o.install:
@@ -151,9 +151,21 @@ src/message.o.clean:
src/message.o.uninstall:
-src/usocket.o: src/usocket.c src/usocket.h src/utils.h
+src/network.o: src/network.c src/ipc.h
+ @echo '[01;34m CC > [01;37msrc/network.o[00m'
+ $(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/network.c -fPIC -std=c11 -o src/network.o
+
+src/network.o.install:
+
+src/network.o.clean:
+ @echo '[01;37m RM > [01;37msrc/network.o[00m'
+ $(Q)rm -f src/network.o
+
+src/network.o.uninstall:
+
+src/usocket.o: src/usocket.c src/usocket.h src/utils.h
@echo '[01;34m CC > [01;37msrc/usocket.o[00m'
- $(Q)$(CC) $(CFLAGS) -fPIC -c src/usocket.c -fPIC -o src/usocket.o
+ $(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/usocket.c -fPIC -std=c11 -o src/usocket.o
src/usocket.o.install:
@@ -163,9 +175,9 @@ src/usocket.o.clean:
src/usocket.o.uninstall:
-src/utils.o: src/utils.c src/utils.h
+src/utils.o: src/utils.c src/utils.h src/ipc.h
@echo '[01;34m CC > [01;37msrc/utils.o[00m'
- $(Q)$(CC) $(CFLAGS) -fPIC -c src/utils.c -fPIC -o src/utils.o
+ $(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/utils.c -fPIC -std=c11 -o src/utils.o
src/utils.o.install:
@@ -175,6 +187,10 @@ src/utils.o.clean:
src/utils.o.uninstall:
+src:
+ $(Q)mkdir -p src
+man:
+ $(Q)mkdir -p man
$(DESTDIR)$(PREFIX):
@echo '[01;35m DIR > [01;37m$(PREFIX)[00m'
$(Q)mkdir -p $(DESTDIR)$(PREFIX)
@@ -193,12 +209,12 @@ $(DESTDIR)$(INCLUDEDIR):
$(DESTDIR)$(MANDIR):
@echo '[01;35m DIR > [01;37m$(MANDIR)[00m'
$(Q)mkdir -p $(DESTDIR)$(MANDIR)
-install: subdirs.install libipc.install src/ipc.h.install man/libipc.7.install libipc.so.install libipc.a.install src/communication.o.install src/error.o.install src/logger.o.install src/message.o.install src/usocket.o.install src/utils.o.install src/communication.o.install src/error.o.install src/logger.o.install src/message.o.install src/usocket.o.install src/utils.o.install
+install: subdirs.install libipc.install src/ipc.h.install man/libipc.7.install libipc.so.install libipc.a.install src/communication.o.install src/error.o.install src/logger.o.install src/message.o.install src/network.o.install src/usocket.o.install src/utils.o.install src/communication.o.install src/error.o.install src/logger.o.install src/message.o.install src/network.o.install src/usocket.o.install src/utils.o.install
@:
subdirs.install:
-uninstall: subdirs.uninstall libipc.uninstall src/ipc.h.uninstall man/libipc.7.uninstall libipc.so.uninstall libipc.a.uninstall src/communication.o.uninstall src/error.o.uninstall src/logger.o.uninstall src/message.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall src/communication.o.uninstall src/error.o.uninstall src/logger.o.uninstall src/message.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall
+uninstall: subdirs.uninstall libipc.uninstall src/ipc.h.uninstall man/libipc.7.uninstall libipc.so.uninstall libipc.a.uninstall src/communication.o.uninstall src/error.o.uninstall src/logger.o.uninstall src/message.o.uninstall src/network.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall src/communication.o.uninstall src/error.o.uninstall src/logger.o.uninstall src/message.o.uninstall src/network.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall
@:
subdirs.uninstall:
@@ -208,7 +224,7 @@ test: all subdirs subdirs.test
subdirs.test:
-clean: libipc.clean src/ipc.h.clean man/libipc.7.clean libipc.so.clean libipc.a.clean src/communication.o.clean src/error.o.clean src/logger.o.clean src/message.o.clean src/usocket.o.clean src/utils.o.clean src/communication.o.clean src/error.o.clean src/logger.o.clean src/message.o.clean src/usocket.o.clean src/utils.o.clean
+clean: libipc.clean src/ipc.h.clean man/libipc.7.clean libipc.so.clean libipc.a.clean src/communication.o.clean src/error.o.clean src/logger.o.clean src/message.o.clean src/network.o.clean src/usocket.o.clean src/utils.o.clean src/communication.o.clean src/error.o.clean src/logger.o.clean src/message.o.clean src/network.o.clean src/usocket.o.clean src/utils.o.clean
distclean: clean
@@ -231,6 +247,7 @@ $(PACKAGE)-$(VERSION).tar.gz: distdir
$(PACKAGE)-$(VERSION)/src/error.c \
$(PACKAGE)-$(VERSION)/src/logger.c \
$(PACKAGE)-$(VERSION)/src/message.c \
+ $(PACKAGE)-$(VERSION)/src/network.c \
$(PACKAGE)-$(VERSION)/src/usocket.c \
$(PACKAGE)-$(VERSION)/src/utils.c \
$(PACKAGE)-$(VERSION)/src/logger.h \
@@ -250,6 +267,7 @@ $(PACKAGE)-$(VERSION).tar.xz: distdir
$(PACKAGE)-$(VERSION)/src/error.c \
$(PACKAGE)-$(VERSION)/src/logger.c \
$(PACKAGE)-$(VERSION)/src/message.c \
+ $(PACKAGE)-$(VERSION)/src/network.c \
$(PACKAGE)-$(VERSION)/src/usocket.c \
$(PACKAGE)-$(VERSION)/src/utils.c \
$(PACKAGE)-$(VERSION)/src/logger.h \
@@ -269,6 +287,7 @@ $(PACKAGE)-$(VERSION).tar.bz2: distdir
$(PACKAGE)-$(VERSION)/src/error.c \
$(PACKAGE)-$(VERSION)/src/logger.c \
$(PACKAGE)-$(VERSION)/src/message.c \
+ $(PACKAGE)-$(VERSION)/src/network.c \
$(PACKAGE)-$(VERSION)/src/usocket.c \
$(PACKAGE)-$(VERSION)/src/utils.c \
$(PACKAGE)-$(VERSION)/src/logger.h \
diff --git a/project.zsh b/project.zsh
index ac69258..918d376 100644
--- a/project.zsh
+++ b/project.zsh
@@ -2,10 +2,13 @@
package=ipc
version=0.1.0
+CFLAGS="-Wall -Wextra -g"
+
targets=(libipc src/ipc.h man/libipc.7)
type[libipc]=library
sources[libipc]="$(ls src/*.c)"
+cflags[libipc]="-std=c11"
type[src/ipc.h]=header
diff --git a/src/communication.c b/src/communication.c
index 78c58ef..0206d61 100644
--- a/src/communication.c
+++ b/src/communication.c
@@ -1,40 +1,41 @@
-#include "ipc.h"
-
-#include "utils.h"
+#include
#include
-#include
#include
#include // error numbers
#include
#include
+#include "ipc.h"
+#include "utils.h"
+
+// FOR THE PURPOSE OF SOME EXPERIMENT
+#include
+#include
+
// print structures
#include "message.h"
-
-#define IPC_CONNECTION_TYPE_IPC 'i'
-#define IPC_CONNECTION_TYPE_EXTERNAL 'a'
-
-void service_path (char *path, const char *sname, int32_t index, int32_t version)
+enum ipc_errors service_path (char *path, const char *sname, int32_t index, int32_t version)
{
- assert (path != NULL);
- assert (sname != NULL);
+ T_R ((path == NULL), IPC_ERROR_SERVICE_PATH__NO_PATH);
+ T_R ((sname == NULL), IPC_ERROR_SERVICE_PATH__NO_SERVICE_NAME);
memset (path, 0, PATH_MAX);
- char * rundir = getenv ("IPC_RUNDIR");
- if (rundir == NULL)
- rundir = RUNDIR;
+ char * rundir = getenv ("IPC_RUNDIR");
+ if (rundir == NULL)
+ rundir = RUNDIR;
snprintf (path, PATH_MAX-1, "%s/%s-%d-%d", rundir, sname, index, version);
+
+ return IPC_ERROR_NONE;
}
-/*calculer le max filedescriptor*/
static int32_t get_max_fd (struct ipc_connection_infos *cinfos)
{
- int32_t i;
+ size_t i;
int32_t max = 0;
for (i = 0; i < cinfos->size; i++ ) {
@@ -48,93 +49,133 @@ static int32_t get_max_fd (struct ipc_connection_infos *cinfos)
enum ipc_errors ipc_server_init (char **env, struct ipc_connection_info *srv, const char *sname)
{
- if (env == NULL)
- return IPC_ERROR_SERVER_INIT__NO_ENVIRONMENT_PARAM;
+ T_R ((env == NULL), IPC_ERROR_SERVER_INIT__NO_ENVIRONMENT_PARAM);
+ T_R ((srv == NULL), IPC_ERROR_SERVER_INIT__NO_SERVICE_PARAM);
+ T_R ((sname == NULL), IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM);
- if (srv == NULL)
- return IPC_ERROR_SERVER_INIT__NO_SERVICE_PARAM;
- if (sname == NULL)
- return IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM;
+#if 0
+ // For server init, no need for networkd evaluation
- // TODO: loop over environment variables
- // any IPC_NETWORK_* should be shared with the network service
- // in order to route requests over any chosen protocol stack
- // ex: IPC_NETWORK_AUDIO="tor://some.example.com/"
- env = env;
+ // TODO: loop over environment variables
+ // any IPC_NETWORK_* should be shared with the network service
+ // in order to route requests over any chosen protocol stack
+ // ex: IPC_NETWORK_AUDIO="tor://some.example.com/"
+ for (size_t i = 0 ; env[i] != NULL ; i++) {
+ // TODO: check for every IPC_NETWORK_* environment variable
+ }
+#endif
// gets the service path
- char buf [PATH_MAX];
- memset (buf, 0, PATH_MAX);
- service_path (buf, sname, srv->index, srv->version);
+ SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
+ TIPC_P_RR (service_path (buf, sname, srv->index, srv->version), "cannot get server path");
// gets the service path
- if (srv->spath != NULL) {
- free (srv->spath);
- srv->spath = NULL;
+ if (srv->spath != NULL) {
+ free (srv->spath);
+ srv->spath = NULL;
+ }
+
+ size_t s = strlen (buf);
+
+ SECURE_BUFFER_HEAP_ALLOCATION_R (srv->spath, s+1, , IPC_ERROR_SERVER_INIT__MALLOC);
+ memcpy (srv->spath, buf, s);
+ srv->spath[s] = '\0'; // to be sure
+
+ TIPC_F_RR (usock_init (&srv->fd, srv->spath), ("cannot init server %s", srv->spath) );
+
+ return IPC_ERROR_NONE;
+}
+
+enum ipc_errors ipc_write_fd (int fd, const struct ipc_message *m);
+
+// when networkd is not working properly (or do not retrieve the service): srv->fd = 0
+enum ipc_errors ipc_contact_networkd (struct ipc_connection_info *srv, const char *sname)
+{
+ T_R ((srv == NULL), IPC_ERROR_CONTACT_NETWORKD__NO_SERVER_PARAM);
+ T_R ((sname == NULL), IPC_ERROR_CONTACT_NETWORKD__NO_SERVICE_NAME_PARAM);
+
+ char *networkvar = getenv("IPC_NETWORK");
+ if (networkvar == NULL) {
+ srv->fd = 0;
+ return IPC_ERROR_NONE;
}
- size_t s = strlen (buf);
- srv->spath = malloc (s+1);
- if (srv->spath == NULL) {
- return IPC_ERROR_SERVER_INIT__MALLOC;
- }
- memcpy (srv->spath, buf, s);
- srv->spath[s] = '\0'; // to be sure
+ // TODO: is there another, more interesting way to do this?
+ // currently, IPC_NETWORK is shared with the network service
+ // in order to route requests over any chosen protocol stack
+ // ex: IPC_NETWORK="audio tor://some.example.com/audio ;pong tls://pong.example.com/pong"
- enum ipc_errors ret = usock_init (&srv->fd, srv->spath);
- if (ret != IPC_ERROR_NONE) {
- handle_err ("ipc_server_init", "usock_init");
- return ret;
+ // printf ("IPC_NETWORK: %s\n", networkvar);
+
+ SECURE_BUFFER_DECLARATION (char, columnthensname, BUFSIZ);
+ columnthensname[0] = ';';
+ memcpy (columnthensname +1, sname, strlen(sname));
+
+ if (strncmp (networkvar, sname, strlen(sname)) != 0 && strstr (networkvar, columnthensname) == NULL) {
+ // printf ("sname %s not found\n", sname);
+ srv->fd = 0;
+ return IPC_ERROR_NONE;
+ }
+ // printf ("(;)sname %s found\n", sname);
+
+ // gets the service path
+ SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
+ TIPC_P_RR (service_path (buf, "network", 0, 0), "cannot get network service path");
+
+ int networkdfd = 0;
+
+ TIPC_F_R (usock_connect (&networkdfd, buf), ("cannot initiates a connection [%s]", buf)
+ , IPC_ERROR_CONTACT_NETWORKD__NETWORKD);
+
+ SECURE_DECLARATION (struct ipc_message, msg);
+ msg.type = MSG_TYPE_NETWORK_LOOKUP;
+ msg.user_type = MSG_TYPE_NETWORK_LOOKUP;
+
+ SECURE_BUFFER_DECLARATION (char, content, BUFSIZ);
+ snprintf (content, BUFSIZ, "%s;%s", sname, networkvar);
+
+ msg.length = strlen (content);
+ msg.payload = content;
+
+ TIPC_P_RR (ipc_write_fd (networkdfd, &msg), "cannot send a message to networkd");
+
+ enum ipc_errors ret = ipc_receive_fd (networkdfd, &srv->fd);
+ if (ret == IPC_ERROR_NONE) {
+ usock_close (networkdfd);
}
- return IPC_ERROR_NONE;
+ return ret;
}
enum ipc_errors ipc_connection (char **env, struct ipc_connection_info *srv, const char *sname)
{
- // TODO: loop over environment variables
- // any IPC_NETWORK_* should be shared with the network service
- // in order to route requests over any chosen protocol stack
- // ex: IPC_NETWORK_AUDIO="tor://some.example.com/"
- env = env;
- if (env == NULL)
- return IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM;
+ T_R ((env == NULL), IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM);
+ T_R ((srv == NULL), IPC_ERROR_CONNECTION__NO_SERVER);
+ T_R ((sname == NULL), IPC_ERROR_CONNECTION__NO_SERVICE_NAME);
- assert (srv != NULL);
- assert (sname != NULL);
+ TIPC_P (ipc_contact_networkd (srv, sname), "error during networkd connection");
- if (srv == NULL) {
- return IPC_ERROR_CONNECTION__NO_SERVER;
+ // if networkd did not initiate the connection
+ if (srv->fd <= 0) {
+ // gets the service path
+ SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
+ TIPC_P_RR (service_path (buf, sname, srv->index, srv->version), "cannot get server path");
+ TIPC_F_RR (usock_connect (&srv->fd, buf), ("cannot initiates a connection [%s]", buf));
}
- if (sname == NULL) {
- return IPC_ERROR_CONNECTION__NO_SERVICE_NAME;
- }
-
- // gets the service path
- char buf [PATH_MAX];
- memset (buf, 0, PATH_MAX);
- service_path (buf, sname, srv->index, srv->version);
-
- enum ipc_errors ret = usock_connect (&srv->fd, buf);
- if (ret != IPC_ERROR_NONE) {
- handle_err ("ipc_connection", "usock_connect ret");
- return ret;
- }
-
return IPC_ERROR_NONE;
}
enum ipc_errors ipc_server_close (struct ipc_connection_info *srv)
{
- usock_close (srv->fd);
- enum ipc_errors ret = usock_remove (srv->spath);
- if (srv->spath != NULL) {
- free (srv->spath);
- srv->spath = NULL;
- }
- return ret;
+ usock_close (srv->fd);
+ enum ipc_errors ret = usock_remove (srv->spath);
+ if (srv->spath != NULL) {
+ free (srv->spath);
+ srv->spath = NULL;
+ }
+ return ret;
}
enum ipc_errors ipc_close (struct ipc_connection_info *p)
@@ -144,86 +185,210 @@ enum ipc_errors ipc_close (struct ipc_connection_info *p)
enum ipc_errors ipc_accept (struct ipc_connection_info *srv, struct ipc_connection_info *p)
{
- assert (srv != NULL);
- assert (p != NULL);
+ T_R ((srv == NULL), IPC_ERROR_ACCEPT__NO_SERVICE_PARAM);
+ T_R ((p == NULL), IPC_ERROR_ACCEPT__NO_CLIENT_PARAM);
- if (srv == NULL) {
- return IPC_ERROR_ACCEPT__NO_SERVICE_PARAM;
- }
-
- if (p == NULL) {
- return IPC_ERROR_ACCEPT__NO_CLIENT_PARAM;
- }
-
- enum ipc_errors ret = usock_accept (srv->fd, &p->fd);
- if (ret != IPC_ERROR_NONE) {
- handle_err ("ipc_accept", "usock_accept");
- return IPC_ERROR_ACCEPT;
- }
-
- p->type = IPC_CONNECTION_TYPE_IPC;
+ TIPC_P_R (usock_accept (srv->fd, &p->fd), "cannot accept fd", IPC_ERROR_ACCEPT);
+ p->type = IPC_CONNECTION_TYPE_IPC;
return IPC_ERROR_NONE;
}
+// receive then format in an ipc_message structure
enum ipc_errors ipc_read (const struct ipc_connection_info *p, struct ipc_message *m)
{
- return ipc_message_read (p->fd, m);
+ T_R ((m == NULL), IPC_ERROR_READ__NO_MESSAGE_PARAM);
+
+ char *buf = NULL;
+ size_t msize = IPC_MAX_MESSAGE_SIZE;
+
+ // on error or closed recipient, the buffer already freed
+ TIPC_NP_RR (usock_recv (p->fd, &buf, &msize));
+ TIPC_I_RR (ipc_message_format_read (m, buf, msize), if (buf != NULL) free (buf));
+
+ free (buf);
+
+ return IPC_ERROR_NONE; // propagates ipc_message_format return
+}
+
+enum ipc_errors ipc_write_fd (int fd, const struct ipc_message *m)
+{
+ T_R ((m == NULL), IPC_ERROR_WRITE__NO_MESSAGE_PARAM);
+
+ char *buf = NULL;
+ size_t msize = 0;
+ ipc_message_format_write (m, &buf, &msize);
+
+ size_t nbytes_sent = 0;
+ TIPC_I_RR (usock_send (fd, buf, msize, &nbytes_sent), if (buf != NULL) free (buf));
+
+ if (buf != NULL) {
+ free (buf);
+ }
+
+ // what was sent != what should have been sent
+ T_R ((nbytes_sent != msize), IPC_ERROR_WRITE__NOT_ENOUGH_DATA);
+
+ return IPC_ERROR_NONE;
}
enum ipc_errors ipc_write (const struct ipc_connection_info *p, const struct ipc_message *m)
{
- return ipc_message_write (p->fd, m);
+ return ipc_write_fd (p->fd, m);
}
enum ipc_errors handle_new_connection (struct ipc_connection_info *cinfo
- , struct ipc_connection_infos *cinfos
- , struct ipc_connection_info **new_client)
+ , struct ipc_connection_infos *cinfos
+ , struct ipc_connection_info **new_client)
{
- if (cinfo == NULL) {
- return IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFO_PARAM;
- }
+ T_R ((cinfo == NULL), IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFO_PARAM);
+ T_R ((cinfos == NULL), IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM);
- if (cinfos == NULL) {
- return IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM;
- }
+ SECURE_BUFFER_HEAP_ALLOCATION_R (*new_client, sizeof(struct ipc_connection_info), , IPC_ERROR_HANDLE_NEW_CONNECTION__MALLOC);
- *new_client = malloc (sizeof(struct ipc_connection_info));
- if (*new_client == NULL) {
- return IPC_ERROR_HANDLE_NEW_CONNECTION__MALLOC;
- }
- memset(*new_client, 0, sizeof(struct ipc_connection_info));
+ TIPC_P_RR (ipc_accept (cinfo, *new_client), "cannot accept the client during handle_new_connection");
+ TIPC_P_RR (ipc_add (cinfos, *new_client), "cannot add the new accepted client");
- enum ipc_errors ret = ipc_accept (cinfo, *new_client);
- if (ret != IPC_ERROR_NONE) {
- return ret;
- }
-
- ret = ipc_add (cinfos, *new_client);
- if (ret != IPC_ERROR_NONE) {
- return ret;
- }
-
- return IPC_ERROR_NONE;
+ return IPC_ERROR_NONE;
}
-enum ipc_errors ipc_wait_event (struct ipc_connection_infos *cinfos
- , struct ipc_connection_info *cinfo // NULL for clients
- , struct ipc_event *event)
+// new connection from a client
+enum ipc_errors handle_connection (struct ipc_event *event, struct ipc_connection_infos *cinfos, struct ipc_connection_info *cinfo)
{
- assert (cinfos != NULL);
+ // connection
+ struct ipc_connection_info *new_client = NULL;
- if (cinfos == NULL) {
- return IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM;
+ TIPC_P_RR (handle_new_connection (cinfo, cinfos, &new_client), "cannot add new client");
+
+ IPC_EVENT_SET (event, IPC_EVENT_TYPE_CONNECTION, NULL, new_client);
+ return IPC_ERROR_NONE;
+}
+
+// new message
+enum ipc_errors handle_message (struct ipc_event *event
+ , struct ipc_connection_infos *cinfos
+ , struct ipc_connection_info *pc
+ , struct ipc_switchings *switchdb)
+{
+ // if the socket is associated to another one for networkd
+ // read and write automatically and provide a new IPC_EVENT_TYPE indicating the switch
+ if (switchdb != NULL) {
+ int talkingfd = pc->fd;
+ int correspondingfd = ipc_switching_get (switchdb, talkingfd);
+ if (correspondingfd != -1) {
+ char *buf = NULL;
+ size_t msize = 0;
+
+ TIPC_T_P_I_R (
+ /* function to test */ usock_recv (talkingfd, &buf, &msize)
+ , /* error condition */ ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT
+ , /* to say on error */ "error while receiving message from client"
+ , /* to do on error */ if (buf != NULL) free (buf) ;
+ IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, NULL, pc)
+ , /* return function */ return (ret));
+
+ /** TODO: there is a message, send it to the corresponding fd **/
+ if (msize > 0) {
+ size_t nbytes_sent = 0;
+ TIPC_I_RR (usock_send (correspondingfd, buf, msize, &nbytes_sent), if (buf != NULL) free (buf));
+
+ if (nbytes_sent != msize) {
+ LOG_ERROR ("wrote not enough data from %d to fd %d", talkingfd, correspondingfd);
+ IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, NULL, pc);
+ return IPC_ERROR_NONE; // FIXME: return something else, maybe?
+ }
+
+ LOG_DEBUG ("received a message on fd %d => switch to fd %d", talkingfd, correspondingfd);
+
+ if (buf != NULL)
+ free (buf);
+
+ // everything is OK: inform networkd of a successful transfer
+ IPC_EVENT_SET (event, IPC_EVENT_TYPE_SWITCH, NULL, pc);
+ return IPC_ERROR_NONE;
+ }
+ else if (msize == 0) {
+ int delfd;
+
+ delfd = ipc_switching_del (switchdb, talkingfd);
+ if (delfd >= 0) {
+ close (delfd);
+ ipc_del_fd (cinfos, delfd);
+ }
+
+ close (talkingfd);
+ ipc_del_fd (cinfos, talkingfd);
+
+ if (delfd >= 0) {
+ LOG_DEBUG ("disconnection of %d (and related fd %d)", talkingfd, delfd);
+ }
+ else {
+ LOG_DEBUG ("disconnection of %d", talkingfd);
+ }
+
+ IPC_EVENT_SET(event, IPC_EVENT_TYPE_DISCONNECTION, NULL, pc);
+ return IPC_ERROR_CLOSED_RECIPIENT;
+ }
+ }
}
- if (event == NULL) {
- return IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM;
+ // no treatment of the socket if external socket
+ if (pc->type == IPC_CONNECTION_TYPE_EXTERNAL) {
+ IPC_EVENT_SET (event, IPC_EVENT_TYPE_EXTRA_SOCKET, NULL, pc);
+ return IPC_ERROR_NONE;
}
- IPC_EVENT_CLEAN(event);
+ // listen to what they have to say (disconnection or message)
+ // then add a client to `event`, the ipc_event structure
+ enum ipc_errors ret;
+ struct ipc_message *m = NULL;
- int32_t i, j;
+ SECURE_BUFFER_HEAP_ALLOCATION_R (m, sizeof(struct ipc_message), , IPC_ERROR_NOT_ENOUGH_MEMORY);
+
+ // current talking client
+ ret = ipc_read (pc, m);
+ if (ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT) {
+ enum ipc_errors rvalue = ret; // store the final return value
+ ipc_message_empty (m);
+ free (m);
+
+ // if there is a problem, just remove the client
+ TIPC_P (ipc_close (pc), "cannot close a connection in handle_message");
+ TIPC_P (ipc_del (cinfos, pc), "cannot delete a connection in handle_message");
+
+ IPC_EVENT_SET(event, IPC_EVENT_TYPE_ERROR, NULL, pc);
+ return rvalue;
+ }
+
+ // disconnection: close the client then delete it from cinfos
+ if (ret == IPC_ERROR_CLOSED_RECIPIENT) {
+ TIPC_P (ipc_close (pc), "cannot close a connection on closed recipient in handle_message");
+ TIPC_P (ipc_del (cinfos, pc), "cannot delete a connection on closed recipient in handle_message");
+
+ ipc_message_empty (m);
+ free (m);
+
+ IPC_EVENT_SET(event, IPC_EVENT_TYPE_DISCONNECTION, NULL, pc);
+
+ // warning: do not forget to free the ipc_client structure
+ return IPC_ERROR_NONE;
+ }
+
+ IPC_EVENT_SET (event, IPC_EVENT_TYPE_MESSAGE, m, pc);
+ return IPC_ERROR_NONE;
+}
+
+enum ipc_errors ipc_wait_event_networkd (struct ipc_connection_infos *cinfos
+ , struct ipc_connection_info *cinfo // NULL for clients
+ , struct ipc_event *event
+ , struct ipc_switchings *switchdb)
+{
+ T_R ((cinfos == NULL), IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM);
+ T_R ((event == NULL), IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM);
+
+ IPC_EVENT_CLEAN(event);
+
+ size_t i, j;
/* master file descriptor list */
fd_set master;
fd_set readf;
@@ -238,141 +403,64 @@ enum ipc_errors ipc_wait_event (struct ipc_connection_infos *cinfos
/* listening socket descriptor */
int32_t listener;
- if (cinfo != NULL) {
- listener = cinfo->fd;
+ if (cinfo != NULL) {
+ listener = cinfo->fd;
- /* add the listener to the master set */
- FD_SET(listener, &master);
+ /* add the listener to the master set */
+ FD_SET(listener, &master);
- // if listener is max fd
- if (fdmax < listener)
- fdmax = listener;
- }
+ // if listener is max fd
+ if (fdmax < listener)
+ fdmax = listener;
+ }
for (i=0; i < cinfos->size; i++) {
FD_SET(cinfos->cinfos[i]->fd, &master);
}
- readf = master;
- if(select(fdmax+1, &readf, NULL, NULL, NULL) == -1) {
- perror("select");
- return IPC_ERROR_WAIT_EVENT__SELECT;
- }
+ readf = master;
+ T_PERROR_R ((select(fdmax+1, &readf, NULL, NULL, NULL) == -1), "select", IPC_ERROR_WAIT_EVENT__SELECT);
- for (i = 0; i <= fdmax; i++) {
- if (FD_ISSET(i, &readf)) {
- if (cinfo != NULL && i == listener) {
- // connection
- struct ipc_connection_info *new_client = NULL;
- enum ipc_errors ret = handle_new_connection (cinfo, cinfos, &new_client);
- if (ret != IPC_ERROR_NONE) {
- // TODO: quit the program
- return ret;
- }
- IPC_EVENT_SET (event, IPC_EVENT_TYPE_CONNECTION, NULL, new_client);
- return IPC_ERROR_NONE;
- } else {
- for(j = 0; j < cinfos->size; j++) {
- if(i == cinfos->cinfos[j]->fd ) {
+ for (i = 0; i <= (size_t) fdmax; i++) {
+ if (FD_ISSET(i, &readf)) {
+ if (cinfo != NULL && i == (size_t) listener) {
+ return handle_connection (event, cinfos, cinfo);
+ } else {
+ for(j = 0; j < cinfos->size; j++) {
+ if(i == (size_t) cinfos->cinfos[j]->fd ) {
+ return handle_message (event, cinfos, cinfos->cinfos[j], switchdb);
+ }
+ }
+ }
+ }
+ }
- struct ipc_connection_info *pc = cinfos->cinfos[j];
+ return IPC_ERROR_NONE;
+}
- // no treatment of the socket if external socket
- if (pc->type == IPC_CONNECTION_TYPE_EXTERNAL) {
- IPC_EVENT_SET (event, IPC_EVENT_TYPE_EXTRA_SOCKET, NULL, pc);
- return IPC_ERROR_NONE;
- }
-
- // listen to what they have to say (disconnection or message)
- // then add a client to `event`, the ipc_event structure
- enum ipc_errors ret;
- struct ipc_message *m = NULL;
- m = malloc (sizeof(struct ipc_message));
- if (m == NULL) {
- return IPC_ERROR_NOT_ENOUGH_MEMORY;
- }
- memset (m, 0, sizeof (struct ipc_message));
-
- // current talking client
- ret = ipc_read (pc, m);
- if (ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT) {
- handle_err ("ipc_wait_event", "ipc_read");
- ipc_message_empty (m);
- free (m);
-
- // if there is a problem, just remove the client
- ret = ipc_close (pc);
- if (ret != IPC_ERROR_NONE) {
- handle_err( "ipc_wait_event", "ipc_close");
- }
-
- ret = ipc_del (cinfos, pc);
- if (ret != IPC_ERROR_NONE) {
- handle_err( "ipc_wait_event", "ipc_del");
- }
-
- IPC_EVENT_SET(event, IPC_EVENT_TYPE_ERROR, NULL, pc);
- return ret;
- }
-
- // disconnection: close the client then delete it from cinfos
- if (ret == IPC_ERROR_CLOSED_RECIPIENT) {
- ret = ipc_close (pc);
- if (ret != IPC_ERROR_NONE) {
- handle_err( "ipc_wait_event", "ipc_close");
- }
-
- ret = ipc_del (cinfos, pc);
- if (ret != IPC_ERROR_NONE) {
- handle_err( "ipc_wait_event", "ipc_del");
- }
- ipc_message_empty (m);
- free (m);
-
- IPC_EVENT_SET(event, IPC_EVENT_TYPE_DISCONNECTION, NULL, pc);
-
- // warning: do not forget to free the ipc_client structure
- return IPC_ERROR_NONE;
- }
-
- IPC_EVENT_SET (event, IPC_EVENT_TYPE_MESSAGE, m, pc);
- return IPC_ERROR_NONE;
- }
- }
- }
- }
- }
-
- return IPC_ERROR_NONE;
+enum ipc_errors ipc_wait_event (struct ipc_connection_infos *cinfos
+ , struct ipc_connection_info *cinfo // NULL for clients
+ , struct ipc_event *event)
+{
+ return ipc_wait_event_networkd (cinfos, cinfo, event, NULL);
}
// store and remove only pointers on allocated structures
enum ipc_errors ipc_add (struct ipc_connection_infos *cinfos, struct ipc_connection_info *p)
{
- assert(cinfos != NULL);
- assert(p != NULL);
-
- if (cinfos == NULL) {
- return IPC_ERROR_ADD__NO_PARAM_CLIENTS;
- }
-
- if (p == NULL) {
- return IPC_ERROR_ADD__NO_PARAM_CLIENT;
- }
+ T_R ((cinfos == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENTS);
+ T_R ((p == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENT);
cinfos->size++;
- if (cinfos->size == 1 && cinfos->cinfos == NULL) {
- // first allocation
- cinfos->cinfos = malloc (sizeof(struct ipc_connection_info));
- }
- else {
- cinfos->cinfos = realloc(cinfos->cinfos, sizeof(struct ipc_connection_info) * cinfos->size);
- }
-
-
- if (cinfos->cinfos == NULL) {
- return IPC_ERROR_ADD__EMPTY_LIST;
+ if (cinfos->size == 1 && cinfos->cinfos == NULL) {
+ // first allocation
+ SECURE_BUFFER_HEAP_ALLOCATION_R (cinfos->cinfos, sizeof(struct ipc_connection_info), , IPC_ERROR_ADD__MALLOC);
}
+ else {
+ cinfos->cinfos = realloc(cinfos->cinfos, sizeof(struct ipc_connection_info) * cinfos->size);
+ }
+
+ T_R ((cinfos->cinfos == NULL), IPC_ERROR_ADD__EMPTY_LIST);
cinfos->cinfos[cinfos->size - 1] = p;
return IPC_ERROR_NONE;
@@ -380,25 +468,14 @@ enum ipc_errors ipc_add (struct ipc_connection_infos *cinfos, struct ipc_connect
enum ipc_errors ipc_del (struct ipc_connection_infos *cinfos, struct ipc_connection_info *p)
{
- assert(cinfos != NULL);
- assert(p != NULL);
+ T_R ((cinfos == NULL), IPC_ERROR_DEL__NO_CLIENTS_PARAM);
+ T_R ((p == NULL), IPC_ERROR_DEL__NO_CLIENT_PARAM);
+ T_R ((cinfos->cinfos == NULL), IPC_ERROR_DEL__EMPTY_LIST);
- if (cinfos == NULL) {
- return IPC_ERROR_DEL__NO_CLIENTS_PARAM;
- }
-
- if (p == NULL) {
- return IPC_ERROR_DEL__NO_CLIENT_PARAM;
- }
-
- if (cinfos->cinfos == NULL) {
- return IPC_ERROR_DEL__EMPTY_LIST;
- }
-
- int32_t i;
+ size_t i;
for (i = 0; i < cinfos->size; i++) {
if (cinfos->cinfos[i] == p) {
- // TODO: possible memory leak if the ipc_connection_info is not free'ed
+ // TODO: possible memory leak if the ipc_connection_info is not free'ed
cinfos->cinfos[i] = cinfos->cinfos[cinfos->size-1];
cinfos->size--;
if (cinfos->size == 0) {
@@ -419,12 +496,25 @@ enum ipc_errors ipc_del (struct ipc_connection_infos *cinfos, struct ipc_connect
return IPC_ERROR_DEL__CANNOT_FIND_CLIENT;
}
+void ipc_connections_close (struct ipc_connection_infos *cinfos)
+{
+ if (cinfos->cinfos != NULL) {
+ for (size_t i = 0; i < cinfos->size ; i++) {
+ ipc_close (cinfos->cinfos[i]);
+ free (cinfos->cinfos[i]);
+ }
+ free (cinfos->cinfos);
+ cinfos->cinfos = NULL;
+ }
+ cinfos->size = 0;
+}
+
void ipc_connections_free (struct ipc_connection_infos *cinfos)
{
if (cinfos->cinfos != NULL) {
- for (size_t i = 0; i < cinfos->size ; i++) {
- free (cinfos->cinfos[i]);
- }
+ for (size_t i = 0; i < cinfos->size ; i++) {
+ free (cinfos->cinfos[i]);
+ }
free (cinfos->cinfos);
cinfos->cinfos = NULL;
}
@@ -433,15 +523,11 @@ void ipc_connections_free (struct ipc_connection_infos *cinfos)
struct ipc_connection_info * ipc_connection_copy (const struct ipc_connection_info *p)
{
- if (p == NULL)
- return NULL;
+ T_R ((p == NULL), NULL);
- struct ipc_connection_info * copy = malloc (sizeof(struct ipc_connection_info));
-
- if (copy == NULL)
- return NULL;
-
- memset (copy, 0, sizeof (struct ipc_connection_info));
+ struct ipc_connection_info * copy = NULL;
+
+ SECURE_BUFFER_HEAP_ALLOCATION_R (copy, sizeof(struct ipc_connection_info), , NULL);
memcpy (copy, p, sizeof (struct ipc_connection_info));
return copy;
@@ -454,64 +540,49 @@ int8_t ipc_connection_eq (const struct ipc_connection_info *p1, const struct ipc
// create the client service structure
enum ipc_errors ipc_connection_gen (struct ipc_connection_info *cinfo
- , uint32_t index, uint32_t version, int fd, char type)
+ , uint32_t index, uint32_t version, int fd, char type)
{
- if (cinfo == NULL) {
- return IPC_ERROR_CONNECTION_GEN__NO_CINFO;
- }
+ T_R ((cinfo == NULL), IPC_ERROR_CONNECTION_GEN__NO_CINFO);
- cinfo->type = type;
+ cinfo->type = type;
cinfo->version = version;
cinfo->index = index;
- cinfo->fd = fd;
+ cinfo->fd = fd;
- return IPC_ERROR_NONE;
+ return IPC_ERROR_NONE;
}
// add an arbitrary file descriptor to read
enum ipc_errors ipc_add_fd (struct ipc_connection_infos *cinfos, int fd)
{
- if (cinfos == NULL) {
- return IPC_ERROR_ADD_FD__NO_PARAM_CINFOS;
- }
+ T_R ((cinfos == NULL), IPC_ERROR_ADD_FD__NO_PARAM_CINFOS);
- struct ipc_connection_info *cinfo = NULL;
+ struct ipc_connection_info *cinfo = NULL;
- cinfo = malloc (sizeof(struct ipc_connection_info));
- if (cinfo == NULL) {
- return IPC_ERROR_NOT_ENOUGH_MEMORY;
- }
- memset (cinfo, 0, sizeof(struct ipc_connection_info));
+ SECURE_BUFFER_HEAP_ALLOCATION_R (cinfo, sizeof(struct ipc_connection_info), , IPC_ERROR_NOT_ENOUGH_MEMORY);
- enum ipc_errors ret;
- ipc_connection_gen (cinfo, 0, 0, fd, IPC_CONNECTION_TYPE_EXTERNAL);
+ ipc_connection_gen (cinfo, 0, 0, fd, IPC_CONNECTION_TYPE_EXTERNAL);
- return ipc_add (cinfos, cinfo);
+ return ipc_add (cinfos, cinfo);
}
// remove a connection from its file descriptor
enum ipc_errors ipc_del_fd (struct ipc_connection_infos *cinfos, int fd)
{
- assert(cinfos != NULL);
- if (cinfos == NULL) {
- return IPC_ERROR_DEL_FD__NO_PARAM_CINFOS;
- }
+ T_R ((cinfos == NULL), IPC_ERROR_DEL_FD__NO_PARAM_CINFOS);
+ T_R ((cinfos->cinfos == NULL), IPC_ERROR_DEL_FD__EMPTY_LIST);
- if (cinfos->cinfos == NULL) {
- return IPC_ERROR_DEL_FD__EMPTY_LIST;
- }
-
- int32_t i;
+ size_t i;
for (i = 0; i < cinfos->size; i++) {
if (cinfos->cinfos[i]->fd == fd) {
- free (cinfos->cinfos[i]);
+ free (cinfos->cinfos[i]);
cinfos->size--;
if (cinfos->size == 0) {
- // free cinfos->cinfos
+ // free cinfos->cinfos
ipc_connections_free (cinfos);
}
else {
- cinfos->cinfos[i] = cinfos->cinfos[cinfos->size];
+ cinfos->cinfos[i] = cinfos->cinfos[cinfos->size];
cinfos->cinfos = realloc(cinfos->cinfos, sizeof(struct ipc_connection_info) * cinfos->size);
if (cinfos->cinfos == NULL) {
@@ -528,26 +599,16 @@ enum ipc_errors ipc_del_fd (struct ipc_connection_infos *cinfos, int fd)
void ipc_connection_print (struct ipc_connection_info *cinfo)
{
- if (cinfo == NULL) {
- return;
- }
+ T_R ((cinfo == NULL), );
- printf ("fd %d: index %d, version %d, type %c"
- , cinfo->fd, cinfo->index, cinfo->version, cinfo->type);
-
- if (cinfo->spath != NULL) {
- printf (", path %s\n", cinfo->spath);
- }
- else {
- printf ("\n");
- }
+ LOG_DEBUG ("fd %d: index %d, version %d, type %c, path %s"
+ , cinfo->fd, cinfo->index, cinfo->version, cinfo->type
+ , (cinfo->spath == NULL) ? "-" : cinfo->spath);
}
void ipc_connections_print (struct ipc_connection_infos *cinfos)
{
- int32_t i;
- for (i = 0; i < cinfos->size; i++) {
- printf("[%d] : ", i);
+ for (size_t i = 0; i < cinfos->size; i++) {
ipc_connection_print(cinfos->cinfos[i]);
}
}
diff --git a/src/error.c b/src/error.c
index 553ea97..5a4d14e 100644
--- a/src/error.c
+++ b/src/error.c
@@ -10,102 +10,113 @@ struct ipc_errors_verbose {
static struct ipc_errors_verbose ipc_errors_verbose [] = {
/* general errors */
- IPC_ERROR_NONE, "no error"
- , IPC_ERROR_NOT_ENOUGH_MEMORY, "not enough memory"
- , IPC_ERROR_CLOSED_RECIPIENT, "closed recipient"
+ { IPC_ERROR_NONE, "no error" }
+ , { IPC_ERROR_NOT_ENOUGH_MEMORY, "not enough memory" }
+ , { IPC_ERROR_CLOSED_RECIPIENT, "closed recipient" }
- , IPC_ERROR_SERVER_INIT__NO_ENVIRONMENT_PARAM, "ipc_server_init: no environment param"
- , IPC_ERROR_SERVER_INIT__NO_SERVICE_PARAM, "ipc_server_init: no service param"
- , IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM, "ipc_server_init: no server name param"
- , IPC_ERROR_SERVER_INIT__MALLOC, "ipc_server_init: error on malloc function"
+ , { IPC_ERROR_SERVER_INIT__NO_ENVIRONMENT_PARAM, "ipc_server_init: no environment param" }
+ , { IPC_ERROR_SERVER_INIT__NO_SERVICE_PARAM, "ipc_server_init: no service param" }
+ , { IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM, "ipc_server_init: no server name param" }
+ , { IPC_ERROR_SERVER_INIT__MALLOC, "ipc_server_init: error on malloc function" }
- , IPC_ERROR_CONNECTION__NO_SERVER, "ipc_connection: no server parameter"
- , IPC_ERROR_CONNECTION__NO_SERVICE_NAME, "ipc_connection: no service name parameter"
- , IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM, "ipc_connection: no environment param"
- , IPC_ERROR_USOCK_CONNECT__CONNECT, "ipc_connection: error on the connect function"
+ , { IPC_ERROR_CONNECTION__NO_SERVER, "ipc_connection: no server parameter" }
+ , { IPC_ERROR_CONNECTION__NO_SERVICE_NAME, "ipc_connection: no service name parameter" }
+ , { IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM, "ipc_connection: no environment param" }
+ , { IPC_ERROR_USOCK_CONNECT__CONNECT, "ipc_connection: error on the connect function" }
- , IPC_ERROR_CONNECTION_GEN__NO_CINFO, "ipc_connection_gen: no cinfo"
+ , { IPC_ERROR_CONNECTION_GEN__NO_CINFO, "ipc_connection_gen: no cinfo" }
- , IPC_ERROR_ACCEPT__NO_SERVICE_PARAM, "ipc_accept: no service param"
- , IPC_ERROR_ACCEPT__NO_CLIENT_PARAM, "ipc_accept: no client param"
- , IPC_ERROR_ACCEPT, "ipc_accept: error on accept function"
+ , { IPC_ERROR_ACCEPT__NO_SERVICE_PARAM, "ipc_accept: no service param" }
+ , { IPC_ERROR_ACCEPT__NO_CLIENT_PARAM, "ipc_accept: no client param" }
+ , { IPC_ERROR_ACCEPT, "ipc_accept: error on accept function" }
- , IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFO_PARAM, "ipc_handle_new_connection: no cinfo param"
- , IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM, "ipc_handle_new_connection: no cinfos param"
+ , { IPC_ERROR_RECEIVE_FD__RECVMSG, "ipc_receive_fd: recvmsg function" }
+ , { IPC_ERROR_RECEIVE_FD__NO_PARAM_FD, "ipc_receive_fd: no fd param" }
+ , { IPC_ERROR_PROVIDE_FD__SENDMSG, "ipc_provide_fd: sendmsg function" }
- , IPC_ERROR_WAIT_EVENT__SELECT, "ipc_wait_event: error on the select function"
- , IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM, "ipc_wait_event: no clients param"
- , IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM, "ipc_wait_event: no event param"
+ , { IPC_ERROR_WRITE__NO_MESSAGE_PARAM, "ipc_write: no message param" }
+ , { IPC_ERROR_WRITE__NOT_ENOUGH_DATA, "ipc_write: no enough data sent" }
+ , { IPC_ERROR_READ__NO_MESSAGE_PARAM, "ipc_read: no message param" }
- , IPC_ERROR_HANDLE_NEW_CONNECTION__MALLOC, "ipc_handle_new_connection: error on malloc function"
+ , { IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFO_PARAM, "ipc_handle_new_connection: no cinfo param" }
+ , { IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM, "ipc_handle_new_connection: no cinfos param" }
- , IPC_ERROR_ADD__EMPTY_LIST, "ipc_clients_add: empty list: realloc failed"
- , IPC_ERROR_ADD__NO_PARAM_CLIENTS, "ipc_clients_add: no param client list"
- , IPC_ERROR_ADD__NO_PARAM_CLIENT, "ipc_clients_add: no param client"
+ , { IPC_ERROR_WAIT_EVENT__SELECT, "ipc_wait_event: error on the select function" }
+ , { IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM, "ipc_wait_event: no clients param" }
+ , { IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM, "ipc_wait_event: no event param" }
- , IPC_ERROR_ADD_FD__NO_PARAM_CINFOS, "ipc_add_fd: no cinfos param"
- , IPC_ERROR_ADD_FD__EMPTY_LIST, "ipc_add_fd: empty list after realloc (memory problem)"
+ , { IPC_ERROR_CONTACT_NETWORKD__NO_SERVICE_NAME_PARAM, "ipc_contact_networkd: no service name param"}
+ , { IPC_ERROR_CONTACT_NETWORKD__NO_SERVER_PARAM, "ipc_contact_networkd: no server param"}
+ , { IPC_ERROR_CONTACT_NETWORKD__NETWORKD, "ipc_contact_networkd: cannot retrieve fd"}
- , IPC_ERROR_DEL_FD__NO_PARAM_CINFOS, "ipc_del_fd: no cinfos param"
- , IPC_ERROR_DEL_FD__EMPTIED_LIST, "ipc_del_fd: empty list after realloc (memory problem)"
- , IPC_ERROR_DEL_FD__EMPTY_LIST, "ipc_del_fd: empty list"
- , IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT, "ipc_del_fd: cannot find user"
+ , { IPC_ERROR_HANDLE_NEW_CONNECTION__MALLOC, "ipc_handle_new_connection: error on malloc function" }
+
+ , { IPC_ERROR_ADD__MALLOC, "ipc_add: first memory allocation failed" }
+ , { IPC_ERROR_ADD__EMPTY_LIST, "ipc_add: empty list: realloc failed" }
+ , { IPC_ERROR_ADD__NO_PARAM_CLIENTS, "ipc_add: no param client list" }
+ , { IPC_ERROR_ADD__NO_PARAM_CLIENT, "ipc_add: no param client" }
+
+ , { IPC_ERROR_ADD_FD__NO_PARAM_CINFOS, "ipc_add_fd: no cinfos param" }
+ , { IPC_ERROR_ADD_FD__EMPTY_LIST, "ipc_add_fd: empty list after realloc (memory problem)" }
+
+ , { IPC_ERROR_DEL_FD__NO_PARAM_CINFOS, "ipc_del_fd: no cinfos param" }
+ , { IPC_ERROR_DEL_FD__EMPTIED_LIST, "ipc_del_fd: empty list after realloc (memory problem)" }
+ , { IPC_ERROR_DEL_FD__EMPTY_LIST, "ipc_del_fd: empty list" }
+ , { IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT, "ipc_del_fd: cannot find user" }
+
+ , { IPC_ERROR_DEL__EMPTY_LIST, "ipc_del: empty list" }
+ , { IPC_ERROR_DEL__EMPTIED_LIST, "ipc_del: cannot realloc" }
+ , { IPC_ERROR_DEL__CANNOT_FIND_CLIENT, "ipc_del: cannot find client" }
+ , { IPC_ERROR_DEL__NO_CLIENTS_PARAM, "ipc_del: no clients param" }
+ , { IPC_ERROR_DEL__NO_CLIENT_PARAM, "ipc_del: no client param" }
- , IPC_ERROR_DEL__EMPTY_LIST, "ipc_clients_del: empty list"
- , IPC_ERROR_DEL__EMPTIED_LIST, "ipc_clients_del: cannot realloc"
- , IPC_ERROR_DEL__CANNOT_FIND_CLIENT, "ipc_clients_del: cannot find client"
- , IPC_ERROR_DEL__NO_CLIENTS_PARAM, "ipc_clients_del: no clients param"
- , IPC_ERROR_DEL__NO_CLIENT_PARAM, "ipc_clients_del: no client param"
-
/* unix socket */
- , IPC_ERROR_USOCK_SEND, "usock_send: cannot send message"
+ , { IPC_ERROR_USOCK_SEND, "usock_send: cannot send message" }
- , IPC_ERROR_USOCK_CONNECT__SOCKET, "usock_connect: error on socket function"
- , IPC_ERROR_USOCK_CONNECT__WRONG_FILE_DESCRIPTOR, "usock_connect: wrong file descriptor"
- , IPC_ERROR_USOCK_CONNECT__EMPTY_PATH, "usock_connect: empty path"
+ , { IPC_ERROR_USOCK_CONNECT__SOCKET, "usock_connect: error on socket function" }
+ , { IPC_ERROR_USOCK_CONNECT__WRONG_FILE_DESCRIPTOR, "usock_connect: wrong file descriptor" }
+ , { IPC_ERROR_USOCK_CONNECT__EMPTY_PATH, "usock_connect: empty path" }
- , IPC_ERROR_USOCK_CLOSE, "usock_close: close function"
+ , { IPC_ERROR_USOCK_CLOSE, "usock_close: close function" }
- , IPC_ERROR_USOCK_REMOVE__UNLINK, "usock_remove: unlink function"
- , IPC_ERROR_USOCK_REMOVE__NO_FILE, "usock_remove: file not found"
+ , { IPC_ERROR_USOCK_REMOVE__UNLINK, "usock_remove: unlink function" }
+ , { IPC_ERROR_USOCK_REMOVE__NO_FILE, "usock_remove: file not found" }
- , IPC_ERROR_USOCK_INIT__EMPTY_FILE_DESCRIPTOR, "usock_init: no file descriptor"
- , IPC_ERROR_USOCK_INIT__WRONG_FILE_DESCRIPTOR, "usock_init: wrong file descriptor"
- , IPC_ERROR_USOCK_INIT__EMPTY_PATH, "usock_init: empty path"
- , IPC_ERROR_USOCK_INIT__BIND, "usock_init: error on bind function"
- , IPC_ERROR_USOCK_INIT__LISTEN, "usock_init: error on listen function"
+ , { IPC_ERROR_USOCK_INIT__EMPTY_FILE_DESCRIPTOR, "usock_init: no file descriptor" }
+ , { IPC_ERROR_USOCK_INIT__WRONG_FILE_DESCRIPTOR, "usock_init: wrong file descriptor" }
+ , { IPC_ERROR_USOCK_INIT__EMPTY_PATH, "usock_init: empty path" }
+ , { IPC_ERROR_USOCK_INIT__BIND, "usock_init: error on bind function" }
+ , { IPC_ERROR_USOCK_INIT__LISTEN, "usock_init: error on listen function" }
- , IPC_ERROR_USOCK_ACCEPT__PATH_FILE_DESCRIPTOR, "ipc_usock_accept: no path file descriptor"
- , IPC_ERROR_USOCK_ACCEPT, "ipc_usock_accept: error on accept function"
+ , { IPC_ERROR_USOCK_ACCEPT__PATH_FILE_DESCRIPTOR, "ipc_usock_accept: no path file descriptor" }
+ , { IPC_ERROR_USOCK_ACCEPT, "ipc_usock_accept: error on accept function" }
- , IPC_ERROR_USOCK_RECV__NO_BUFFER, "ipc_usock_recv: no buffer in usock_recv"
- , IPC_ERROR_USOCK_RECV__NO_LENGTH, "ipc_usock_recv: no length in usock_recv"
- , IPC_ERROR_USOCK_RECV, "ipc_usock_recv: cannot receive message in usock_recv"
+ , { IPC_ERROR_USOCK_RECV__NO_BUFFER, "ipc_usock_recv: no buffer in usock_recv" }
+ , { IPC_ERROR_USOCK_RECV__NO_LENGTH, "ipc_usock_recv: no length in usock_recv" }
+ , { IPC_ERROR_USOCK_RECV, "ipc_usock_recv: cannot receive message in usock_recv" }
+ , { IPC_ERROR_USOCK_RECV__MESSAGE_SIZE, "ipc_usock_recv: message length > maximum allowed" }
/* message function errors */
- , IPC_ERROR_MESSAGE_NEW__NO_MESSAGE_PARAM, "ipc_message_new: no message param"
- , IPC_ERROR_MESSAGE_READ__NO_MESSAGE_PARAM, "ipc_message_read: no message param"
+ , { IPC_ERROR_MESSAGE_FORMAT_WRITE__MESSAGE_LENGTH, "ipc_message_write: message is longer than accepted" }
- , IPC_ERROR_MESSAGE_WRITE__NO_MESSAGE_PARAM, "ipc_message_write: no message param"
- , IPC_ERROR_MESSAGE_WRITE__NOT_ENOUGH_DATA, "ipc_message_write: no enough data sent"
+ , { IPC_ERROR_MESSAGE_FORMAT__NO_MESSAGE_PARAM, "ipc_message_format: no message param" }
+ , { IPC_ERROR_MESSAGE_FORMAT__INCONSISTENT_PARAMS, "ipc_message_format: inconsistent params" }
+ , { IPC_ERROR_MESSAGE_FORMAT__MESSAGE_SIZE, "ipc_message_format: length param > maximum allowed" }
+ , { IPC_ERROR_MESSAGE_FORMAT_READ__READ_MESSAGE_SIZE, "ipc_message_format: read message size > maximum allowed" }
- , IPC_ERROR_MESSAGE_FORMAT__NO_MESSAGE_PARAM, "ipc_message_format: no message param"
- , IPC_ERROR_MESSAGE_FORMAT__INCONSISTENT_PARAMS, "ipc_message_format: inconsistent params"
- , IPC_ERROR_MESSAGE_FORMAT__LENGTH, "ipc_message_format: length param > maximum allowed"
+ , { IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MESSAGE, "ipc_message_format_write: empty message" }
+ , { IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MSIZE, "ipc_message_format_write: empty message size" }
+ , { IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_BUFFER, "ipc_message_format_write: empty buffer" }
- , IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MESSAGE, "ipc_message_format_write: empty message"
- , IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MSIZE, "ipc_message_format_write: empty message size"
- , IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_BUFFER, "ipc_message_format_write: empty buffer"
+ , { IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_MESSAGE, "ipc_message_format_read: empty message" }
+ , { IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_BUFFER, "ipc_message_format_read: empty buffer" }
+ , { IPC_ERROR_MESSAGE_FORMAT_READ__MESSAGE_SIZE, "ipc_message_format_read: message size > maximum allowed" }
- , IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_MESSAGE, "ipc_message_format_read: empty message"
- , IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_BUFFER, "ipc_message_format_read: empty buffer"
- , IPC_ERROR_MESSAGE_FORMAT_READ__MESSAGE_SIZE, "ipc_message_format_read: message size > maximum allowed"
-
- , IPC_ERROR_MESSAGE_EMPTY__EMPTY_MESSAGE_LIST, "ipc_message_empty: empty message list"
+ , { IPC_ERROR_MESSAGE_EMPTY__EMPTY_MESSAGE_LIST, "ipc_message_empty: empty message list" }
};
const char * ipc_errors_get (enum ipc_errors e)
diff --git a/src/ipc.h b/src/ipc.h
index e43326b..8ad07bb 100644
--- a/src/ipc.h
+++ b/src/ipc.h
@@ -9,133 +9,206 @@
#include // error numbers
#include
+/***
+ * global defaults
+ **/
+
#define RUNDIR "/run/ipc/"
#define PATH_MAX 4096
#define IPC_HEADER_SIZE 6
#define IPC_MAX_MESSAGE_SIZE 8000000-IPC_HEADER_SIZE
-// #define IPC_MAX_MESSAGE_SIZE 100-IPC_HEADER_SIZE
-// #include "queue.h"
-
-#define SECURE_DECLARATION(t,v) t v; memset(&v,0,sizeof(t));
#define IPC_VERSION 1
+#if ! defined(IPC_WITHOUT_ERRORS) && ! defined(IPC_WITH_ERRORS)
+#define IPC_WITH_ERRORS 2
+#endif
+#define IPC_WITH_UNIX_SOCKETS
+
+#ifdef IPC_WITH_UNIX_SOCKETS
+#include "usocket.h"
+#endif
+
+/***
+ * grooming macros
+ **/
+
+#define SECURE_DECLARATION(t,v) t v; memset(&v,0,sizeof(t));
+#define SECURE_BUFFER_DECLARATION(type,name,size) type name[size]; memset(&name, 0, sizeof(type) * size);
+#define SECURE_BUFFER_HEAP_ALLOCATION(p,len,instr,r) { p = malloc (len); if (p == NULL) { instr; r; } ; memset(p, 0, len); }
+#define SECURE_BUFFER_HEAP_ALLOCATION_R(p,len,instr,r) SECURE_BUFFER_HEAP_ALLOCATION(p,len,instr, return r )
+#define SECURE_BUFFER_HEAP_ALLOCATION_Q(p,len,instr,r) SECURE_BUFFER_HEAP_ALLOCATION(p,len,instr, exit(r))
+
+#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
+// print error string
+#define PRINT_ERR(code) const char *estr = ipc_errors_get (code); LOG_ERROR ("%s", estr);
+#define PRINT_ERR_STR(code,err) { const char *estr = ipc_errors_get (code); LOG_ERROR ("%s - %s", err, estr); }
+#else
+#define PRINT_ERR(code)
+#define PRINT_ERR_STR(code,err)
+#endif
+
+// Test macros, requiring the variable `enum ipc_errors ret`
+
+// one macro to rule them all!
+// 1. function to test
+// 2. Test IPC error based (test itself)
+// 3. Print error (then ipc-error message)
+// 4. Instructions to exec on failure
+// 5. Return something
+#define TIPC_T_P_I_R(f, t, err, instr, r) { enum ipc_errors ret = f;\
+ if (t) {\
+ PRINT_ERR_STR(ret, err); \
+ instr;\
+ r;\
+ } }
+
+// P = print somehting with LOG_ERROR
+// NP = no LOG_ERROR print
+// R = return r param
+// RR = return "ret" variable
+// RV = return void
+// Q = quit
+// I = additionnal instructions before returning on error
+
+#define TIPC_P_I_R(f, t, err, instr, r) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, err, instr, return r)
+#define TIPC_P_I_Q(f, t, err, instr, r) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, err, instr, quit(r))
+#define TIPC_P_Q(f, err,r) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, err, ;, exit(r))
+#define TIPC_P_R(f, err,r) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, err, ;, return r)
+#define TIPC_P_RR(f, err) TIPC_P_R(f,err,ret)
+#define TIPC_F_RR(f, format) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, "", LOG_ERROR format ;, return ret)
+#define TIPC_F_Q(f, format, r) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, "", LOG_ERROR format ;, exit(r))
+#define TIPC_F_R(f, format, r) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, "", LOG_ERROR format ;, return r)
+#define TIPC_P_RV(f, err) TIPC_P_R(f,err,;)
+#define TIPC_P(f, err) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, err, ;, ;)
+#define TIPC_T_I_P_Q(f,t,instr,err,r) TIPC_T_P_I_R(f, t, err, instr, exit(r))
+#define TIPC_T_I_RR(f,t,instr) TIPC_T_P_I_R(f, t, "", instr, return ret)
+#define TIPC_I_RR(f,instr) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, "", instr, return ret)
+#define TIPC_RR(f) TIPC_T_P_I_R(f, ret != IPC_ERROR_NONE, "", ;, return ret)
+#define TIPC_NP_RR(f) { enum ipc_errors ret = f; if (ret != IPC_ERROR_NONE) { return ret; } }
+
+// Tests macros, do not require `enum ipc_errors ret` variable
+// test => return error code
+#define T_R(t,r) if t { return r; }
+// test => perror, formatted message then return (for system functions)
+#define T_PERROR_F_R(t,m,fmt,r) if t { perror(m); LOG_ERROR fmt; return r; }
+// test => perror then return (for system functions)
+#define T_PERROR_R(t,m,r) if t { perror(m); return r; }
+// test => perror then exit (for system functions)
+#define T_PERROR_Q(t,m,r) if t { perror(m); exit(r); }
+
+
+// Switch cases macros
+// print on error
+#define ERROR_CASE(e,f,m) case e : { LOG_ERROR ("function %s: %s", f, m); } break;
+
+
+/***
+ * structures and enumerations
+ **/
enum msg_types {
- MSG_TYPE_SERVER_CLOSE = 0
- , MSG_TYPE_ERR
- , MSG_TYPE_DATA
+ MSG_TYPE_SERVER_CLOSE = 0
+ , MSG_TYPE_ERR = 1
+ , MSG_TYPE_DATA = 2
+ , MSG_TYPE_NETWORK_LOOKUP = 3
} message_types;
enum ipc_event_type {
- IPC_EVENT_TYPE_NOT_SET
- , IPC_EVENT_TYPE_ERROR
-
- , IPC_EVENT_TYPE_EXTRA_SOCKET
-
- , IPC_EVENT_TYPE_CONNECTION
- , IPC_EVENT_TYPE_DISCONNECTION
- , IPC_EVENT_TYPE_MESSAGE
+ IPC_EVENT_TYPE_NOT_SET = 0
+ , IPC_EVENT_TYPE_ERROR = 1
+ , IPC_EVENT_TYPE_EXTRA_SOCKET = 2
+ , IPC_EVENT_TYPE_SWITCH = 3
+ , IPC_EVENT_TYPE_CONNECTION = 4
+ , IPC_EVENT_TYPE_DISCONNECTION = 5
+ , IPC_EVENT_TYPE_MESSAGE = 6
+ , IPC_EVENT_TYPE_LOOKUP = 7
};
enum ipc_errors {
+
/* general errors */
- IPC_ERROR_NONE
- , IPC_ERROR_NOT_ENOUGH_MEMORY
- , IPC_ERROR_CLOSED_RECIPIENT
-
- , IPC_ERROR_SERVER_INIT__NO_ENVIRONMENT_PARAM
- , IPC_ERROR_SERVER_INIT__NO_SERVICE_PARAM
- , IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM
- , IPC_ERROR_SERVER_INIT__MALLOC
-
- , IPC_ERROR_CONNECTION__NO_SERVER
- , IPC_ERROR_CONNECTION__NO_SERVICE_NAME
- , IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM
-
- , IPC_ERROR_CONNECTION_GEN__NO_CINFO
-
- , IPC_ERROR_ACCEPT__NO_SERVICE_PARAM
- , IPC_ERROR_ACCEPT__NO_CLIENT_PARAM
- , IPC_ERROR_ACCEPT
-
- , IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFO_PARAM
- , IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM
-
- , IPC_ERROR_WAIT_EVENT__SELECT
- , IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM
- , IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM
-
- , IPC_ERROR_HANDLE_NEW_CONNECTION__MALLOC
-
- , IPC_ERROR_ADD__EMPTY_LIST
- , IPC_ERROR_ADD__NO_PARAM_CLIENTS
- , IPC_ERROR_ADD__NO_PARAM_CLIENT
-
- , IPC_ERROR_ADD_FD__NO_PARAM_CINFOS
- , IPC_ERROR_ADD_FD__EMPTY_LIST
-
- , IPC_ERROR_DEL_FD__NO_PARAM_CINFOS
- , IPC_ERROR_DEL_FD__EMPTIED_LIST
- , IPC_ERROR_DEL_FD__EMPTY_LIST
- , IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT
-
- , IPC_ERROR_DEL__EMPTY_LIST
- , IPC_ERROR_DEL__EMPTIED_LIST
- , IPC_ERROR_DEL__CANNOT_FIND_CLIENT
- , IPC_ERROR_DEL__NO_CLIENTS_PARAM
- , IPC_ERROR_DEL__NO_CLIENT_PARAM
+ IPC_ERROR_NONE = 0
+ , IPC_ERROR_NOT_ENOUGH_MEMORY = 1
+ , IPC_ERROR_CLOSED_RECIPIENT = 2
+ , IPC_ERROR_SERVICE_PATH__NO_PATH = 3
+ , IPC_ERROR_SERVICE_PATH__NO_SERVICE_NAME = 4
+ , IPC_ERROR_SERVER_INIT__NO_ENVIRONMENT_PARAM = 5
+ , IPC_ERROR_SERVER_INIT__NO_SERVICE_PARAM = 6
+ , IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM = 7
+ , IPC_ERROR_SERVER_INIT__MALLOC = 8
+ , IPC_ERROR_WRITE__NO_MESSAGE_PARAM = 9
+ , IPC_ERROR_WRITE__NOT_ENOUGH_DATA = 10
+ , IPC_ERROR_READ__NO_MESSAGE_PARAM = 11
+ , IPC_ERROR_CONNECTION__NO_SERVER = 12
+ , IPC_ERROR_CONNECTION__NO_SERVICE_NAME = 13
+ , IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM = 14
+ , IPC_ERROR_CONNECTION_GEN__NO_CINFO = 15
+ , IPC_ERROR_ACCEPT__NO_SERVICE_PARAM = 16
+ , IPC_ERROR_ACCEPT__NO_CLIENT_PARAM = 17
+ , IPC_ERROR_ACCEPT = 18
+ , IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFO_PARAM = 19
+ , IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM = 20
+ , IPC_ERROR_WAIT_EVENT__SELECT = 21
+ , IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM = 22
+ , IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM = 23
+ , IPC_ERROR_HANDLE_NEW_CONNECTION__MALLOC = 24
+ , IPC_ERROR_ADD__EMPTY_LIST = 25
+ , IPC_ERROR_ADD__NO_PARAM_CLIENTS = 26
+ , IPC_ERROR_ADD__NO_PARAM_CLIENT = 27
+ , IPC_ERROR_ADD__MALLOC = 28
+ , IPC_ERROR_ADD_FD__NO_PARAM_CINFOS = 29
+ , IPC_ERROR_ADD_FD__EMPTY_LIST = 30
+ , IPC_ERROR_DEL_FD__NO_PARAM_CINFOS = 31
+ , IPC_ERROR_DEL_FD__EMPTIED_LIST = 32
+ , IPC_ERROR_DEL_FD__EMPTY_LIST = 33
+ , IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT = 34
+ , IPC_ERROR_CONTACT_NETWORKD__NO_SERVICE_NAME_PARAM = 35
+ , IPC_ERROR_CONTACT_NETWORKD__NO_SERVER_PARAM = 36
+ , IPC_ERROR_CONTACT_NETWORKD__NETWORKD = 37
+ , IPC_ERROR_DEL__EMPTY_LIST = 38
+ , IPC_ERROR_DEL__EMPTIED_LIST = 39
+ , IPC_ERROR_DEL__CANNOT_FIND_CLIENT = 40
+ , IPC_ERROR_DEL__NO_CLIENTS_PARAM = 41
+ , IPC_ERROR_DEL__NO_CLIENT_PARAM = 42
-
/* unix socket */
-
- , IPC_ERROR_USOCK_SEND
-
- , IPC_ERROR_USOCK_CONNECT__SOCKET
- , IPC_ERROR_USOCK_CONNECT__WRONG_FILE_DESCRIPTOR
- , IPC_ERROR_USOCK_CONNECT__EMPTY_PATH
- , IPC_ERROR_USOCK_CONNECT__CONNECT
-
- , IPC_ERROR_USOCK_CLOSE
-
- , IPC_ERROR_USOCK_REMOVE__UNLINK
- , IPC_ERROR_USOCK_REMOVE__NO_FILE
-
- , IPC_ERROR_USOCK_INIT__EMPTY_FILE_DESCRIPTOR
- , IPC_ERROR_USOCK_INIT__WRONG_FILE_DESCRIPTOR
- , IPC_ERROR_USOCK_INIT__EMPTY_PATH
- , IPC_ERROR_USOCK_INIT__BIND
- , IPC_ERROR_USOCK_INIT__LISTEN
-
- , IPC_ERROR_USOCK_ACCEPT__PATH_FILE_DESCRIPTOR
- , IPC_ERROR_USOCK_ACCEPT
-
- , IPC_ERROR_USOCK_RECV__NO_BUFFER
- , IPC_ERROR_USOCK_RECV__NO_LENGTH
- , IPC_ERROR_USOCK_RECV
-
+ , IPC_ERROR_USOCK_SEND = 1
+ , IPC_ERROR_USOCK_CONNECT__SOCKET = 43
+ , IPC_ERROR_USOCK_CONNECT__WRONG_FILE_DESCRIPTOR = 44
+ , IPC_ERROR_USOCK_CONNECT__EMPTY_PATH = 45
+ , IPC_ERROR_USOCK_CONNECT__CONNECT = 46
+ , IPC_ERROR_USOCK_CLOSE = 47
+ , IPC_ERROR_USOCK_REMOVE__UNLINK = 48
+ , IPC_ERROR_USOCK_REMOVE__NO_FILE = 49
+ , IPC_ERROR_USOCK_INIT__EMPTY_FILE_DESCRIPTOR = 50
+ , IPC_ERROR_USOCK_INIT__WRONG_FILE_DESCRIPTOR = 51
+ , IPC_ERROR_USOCK_INIT__EMPTY_PATH = 52
+ , IPC_ERROR_USOCK_INIT__BIND = 53
+ , IPC_ERROR_USOCK_INIT__LISTEN = 54
+ , IPC_ERROR_USOCK_ACCEPT__PATH_FILE_DESCRIPTOR = 55
+ , IPC_ERROR_USOCK_ACCEPT = 56
+ , IPC_ERROR_USOCK_RECV__NO_BUFFER = 57
+ , IPC_ERROR_USOCK_RECV__NO_LENGTH = 58
+ , IPC_ERROR_USOCK_RECV = 59
+ , IPC_ERROR_USOCK_RECV__MESSAGE_SIZE = 60
+ , IPC_ERROR_RECEIVE_FD__NO_PARAM_FD = 61
+ , IPC_ERROR_RECEIVE_FD__RECVMSG = 62
+ , IPC_ERROR_PROVIDE_FD__SENDMSG = 63
/* message function errors */
-
- , IPC_ERROR_MESSAGE_NEW__NO_MESSAGE_PARAM
- , IPC_ERROR_MESSAGE_READ__NO_MESSAGE_PARAM
-
- , IPC_ERROR_MESSAGE_WRITE__NO_MESSAGE_PARAM
- , IPC_ERROR_MESSAGE_WRITE__NOT_ENOUGH_DATA
-
- , IPC_ERROR_MESSAGE_FORMAT__NO_MESSAGE_PARAM
- , IPC_ERROR_MESSAGE_FORMAT__INCONSISTENT_PARAMS
- , IPC_ERROR_MESSAGE_FORMAT__LENGTH
-
- , IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MESSAGE
- , IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MSIZE
- , IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_BUFFER
-
- , IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_MESSAGE
- , IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_BUFFER
- , IPC_ERROR_MESSAGE_FORMAT_READ__MESSAGE_SIZE
-
- , IPC_ERROR_MESSAGE_EMPTY__EMPTY_MESSAGE_LIST
+ , IPC_ERROR_MESSAGE_FORMAT_WRITE__MESSAGE_LENGTH = 64
+ , IPC_ERROR_MESSAGE_FORMAT__MESSAGE_SIZE = 65
+ , IPC_ERROR_MESSAGE_FORMAT__NO_MESSAGE_PARAM = 66
+ , IPC_ERROR_MESSAGE_FORMAT__INCONSISTENT_PARAMS = 67
+ , IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MESSAGE = 68
+ , IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MSIZE = 69
+ , IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_BUFFER = 70
+ , IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_MESSAGE = 71
+ , IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_BUFFER = 72
+ , IPC_ERROR_MESSAGE_FORMAT_READ__MESSAGE_SIZE = 73
+ , IPC_ERROR_MESSAGE_FORMAT_READ__READ_MESSAGE_SIZE = 74
+ , IPC_ERROR_MESSAGE_EMPTY__EMPTY_MESSAGE_LIST = 75
};
@@ -149,7 +222,7 @@ struct ipc_connection_info {
struct ipc_connection_infos {
struct ipc_connection_info ** cinfos;
- int32_t size;
+ size_t size;
};
@@ -167,27 +240,42 @@ struct ipc_event {
};
-/**
- * MACROS
+/***
+ * logging macros
**/
-// #define IPC_WITH_ERRORS 3
-
#ifdef IPC_WITH_ERRORS
#include "logger.h"
-#define handle_err(fun,msg)\
- do { log_error ("%s: file %s line %d %s", fun, __FILE__, __LINE__, msg); } while (0)
+// XXX: ##__VA_ARGS__ is a GNU extension to avoid requiring more arguments
+#define LOG_ERROR(format, ...) log_error ( __FILE__ ":%d:" format, __LINE__, ##__VA_ARGS__ )
+#define LOG_INFO(format, ...) log_info ( __FILE__ ":%d:" format, __LINE__, ##__VA_ARGS__ )
#else
-#define handle_err(fun,msg)
+#define LOG_ERROR(format, ...)
+#define LOG_INFO(format, ...)
#endif
+#if IPC_WITH_ERRORS > 2
+#define LOG_DEBUG(format, ...) log_debug ( __FILE__ ":%d:" format, __LINE__, ##__VA_ARGS__ )
+#else
+#define LOG_DEBUG(format, ...)
+#endif
+
+/***
+ * ipc event macros
+ **/
+
#define IPC_EVENT_SET(pevent,type_,message_,origin_) {\
pevent->type = type_; \
pevent->m = message_; \
pevent->origin = origin_; \
};
+enum ipc_connection_types {
+ IPC_CONNECTION_TYPE_IPC = 0
+ , IPC_CONNECTION_TYPE_EXTERNAL = 1
+};
+
#define IPC_EVENT_CLEAN(pevent) {\
pevent->type = IPC_EVENT_TYPE_NOT_SET;\
if (pevent->m != NULL) {\
@@ -197,21 +285,19 @@ struct ipc_event {
}\
};
-#define IPC_WITH_UNIX_SOCKETS
-#ifdef IPC_WITH_UNIX_SOCKETS
-#include "usocket.h"
-#endif
-
-#define LOG
+/***
+ * logging functions
+ **/
void log_error (const char* message, ...);
void log_info (const char* message, ...);
void log_debug (const char* message, ...);
+
/**
* main public functions
- */
+ **/
enum ipc_errors ipc_server_init (char **env, struct ipc_connection_info *srv, const char *sname);
enum ipc_errors ipc_connection (char **env, struct ipc_connection_info *srv, const char *sname);
@@ -243,40 +329,78 @@ int8_t ipc_connection_eq (const struct ipc_connection_info *p1, const struct ipc
enum ipc_errors ipc_connection_gen (struct ipc_connection_info *cinfo
, uint32_t index, uint32_t version, int fd, char type);
-void ipc_connection_print (struct ipc_connection_info *cinfo);
-void ipc_connections_print (struct ipc_connection_infos *cinfos);
+void ipc_connection_print (struct ipc_connection_info *cinfo);
+void ipc_connections_print (struct ipc_connection_infos *cinfos);
+void ipc_connections_close (struct ipc_connection_infos *cinfos);
// get explanation about an error
const char * ipc_errors_get (enum ipc_errors e);
-/**
+/***
* message functions
**/
-// used to create msg structure with a certain payload length (0 for no payload memory allocation)
-enum ipc_errors ipc_message_new (struct ipc_message **m, ssize_t paylen);
+uint32_t ipc_message_raw_serialize (char *buffer, char type, char user_type, char * message, uint32_t message_size);
+
// used to create msg structure from buffer
-enum ipc_errors ipc_message_format_read (struct ipc_message *m, const char *buf, ssize_t msize);
+enum ipc_errors ipc_message_format_read (struct ipc_message *m, const char *buf, size_t msize);
// used to create buffer from msg structure
-enum ipc_errors ipc_message_format_write (const struct ipc_message *m, char **buf, ssize_t *msize);
+enum ipc_errors ipc_message_format_write (const struct ipc_message *m, char **buf, size_t *msize);
-// read a structure msg from fd
-enum ipc_errors ipc_message_read (int32_t fd, struct ipc_message *m);
-// write a structure msg to fd
-enum ipc_errors ipc_message_write (int32_t fd, const struct ipc_message *m);
-
-enum ipc_errors ipc_message_format (struct ipc_message *m
- , char type, char utype, const char *payload, ssize_t length);
-enum ipc_errors ipc_message_format_data (struct ipc_message *m
- , char utype, const char *payload, ssize_t length);
+enum ipc_errors ipc_message_format (struct ipc_message *m, char type, char utype, const char *payload, size_t length);
+enum ipc_errors ipc_message_format_data (struct ipc_message *m, char utype, const char *payload, size_t length);
enum ipc_errors ipc_message_format_server_close (struct ipc_message *m);
-
enum ipc_errors ipc_message_empty (struct ipc_message *m);
+/***
+ * non public functions
+ **/
-// non public functions
-void service_path (char *path, const char *sname, int32_t index, int32_t version);
+
+enum ipc_errors ipc_accept (struct ipc_connection_info *srv, struct ipc_connection_info *p);
+enum ipc_errors ipc_contact_networkd (struct ipc_connection_info *srv, const char *sname);
+enum ipc_errors service_path (char *path, const char *sname, int32_t index, int32_t version);
+char * log_get_logfile_dir (char *buf, size_t size);
+void log_get_logfile_name (char *buf, size_t size);
+
+
+/***
+ * networkd enumerations, structures and functions
+ **/
+
+struct ipc_switching {
+ int orig;
+ int dest;
+};
+
+struct ipc_switchings {
+ struct ipc_switching *collection;
+ size_t size;
+};
+
+struct networkd {
+ int cpt;
+ struct ipc_connection_info *srv;
+ struct ipc_connection_infos *clients;
+ struct ipc_switchings * TCP_TO_IPC;
+};
+
+enum ipc_errors ipc_wait_event_networkd (struct ipc_connection_infos *cinfos
+ , struct ipc_connection_info *cinfo // NULL for clients
+ , struct ipc_event *event
+ , struct ipc_switchings *switchdb);
+
+
+void ipc_switching_add (struct ipc_switchings *is, int orig, int dest);
+int ipc_switching_del (struct ipc_switchings *is, int fd);
+int ipc_switching_get (struct ipc_switchings *is, int fd);
+void ipc_switching_free (struct ipc_switchings *is);
+void ipc_switching_print (struct ipc_switchings *is);
+
+
+enum ipc_errors ipc_receive_fd (int sock, int *fd);
+enum ipc_errors ipc_provide_fd (int sock, int fd);
#endif
diff --git a/src/logger.c b/src/logger.c
index 5fda936..1962a93 100644
--- a/src/logger.c
+++ b/src/logger.c
@@ -3,18 +3,86 @@
#include
#include
#include
+#include
+#include
+#include
+#include
+
+#include "ipc.h"
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_GNU_SOURCE)
+#else
+extern char *__progname;
+#endif
+
+char * log_get_logfile_dir (char *buf, size_t size)
+{
+ char * datadir = getenv ("XDG_DATA_HOME");
+ if (datadir == NULL) {
+ datadir = getenv ("HOME");
+ if (datadir == NULL) {
+ return buf + snprintf (buf, size, "./ipc/");
+ }
+ else {
+ return buf + snprintf (buf, size, "%s/.local/share/ipc/", datadir);
+ }
+ }
+ return buf + snprintf (buf, size, "%s/ipc/", datadir);
+}
+
+void log_get_logfile_name (char *buf, size_t size) {
+ char *logfile = getenv ("IPC_LOGFILE");
+ if (logfile == NULL) {
+ char *buf_after_dir;
+ buf_after_dir = log_get_logfile_dir (buf, size);
+ pid_t pid = getpid();
+
+#if defined(__APPLE__) || defined(__FreeBSD__)
+ const char * appname = getprogname();
+#elif defined(_GNU_SOURCE)
+ const char * appname = program_invocation_name;
+#elif defined(__linux__)
+ const char * appname = __progname;
+#else
+#error "cannot know the application name for this environment"
+#endif
+
+ snprintf (buf_after_dir, size - (buf_after_dir - buf), "%s-%d.log", appname, pid);
+ return;
+ }
+
+ snprintf (buf, size, "%s", logfile);
+}
void log_format (const char* tag, const char* message, va_list args) {
time_t now;
time(&now);
- char * date =ctime(&now);
- date[strlen(date) - 1] = '\0';
- printf("%s:%s: ", date, tag);
- vprintf(message, args);
+ struct tm *t = localtime (&now);
- printf("\n");
+ SECURE_BUFFER_DECLARATION (char, date, 200);
+
+ snprintf (date, 200, "%d-%02d-%02d_%02d-%02d-%02d"
+ , t->tm_year+1900, t->tm_mon +1, t->tm_mday
+ , t->tm_hour, t->tm_min, t->tm_sec);
+
+ SECURE_BUFFER_DECLARATION (char, logfile, BUFSIZ);
+ log_get_logfile_name (logfile, BUFSIZ);
+
+ FILE * logfd = fopen (logfile, "a");
+ if (logfd == NULL) {
+ fprintf (stderr, "something gone horribly wrong: cannot open logfile: %s\n", logfile);
+ return;
+ }
+
+ fprintf (logfd, "%s:%s:", date, tag);
+ vfprintf(logfd, message, args);
+ fprintf (logfd, "\n");
+
+ fflush (logfd);
+
+ fclose (logfd);
}
void log_error (const char* message, ...) {
diff --git a/src/message.c b/src/message.c
index 850ad52..8626555 100644
--- a/src/message.c
+++ b/src/message.c
@@ -9,70 +9,55 @@
#include "message.h"
#include "usocket.h"
-#include
+// #define IPC_WITH_ERRORS 3
+
+uint32_t ipc_message_raw_serialize (char *buffer, char type, char user_type, char * message, uint32_t message_size)
+{
+ uint32_t msize = 6 + message_size;
+ buffer[0] = type;
+
+ uint32_t msize_n = htonl (message_size);
+ uint32_t index = 1;
+
+ memcpy (buffer + index, &msize_n, sizeof (uint32_t));
+ index += sizeof (uint32_t);
+ buffer[index] = user_type;
+ index += 1;
+ memcpy (buffer + index, message, message_size);
+
+ return msize;
+}
-#define IPC_WITH_ERRORS 3
void ipc_message_print (const struct ipc_message *m)
{
- assert (m != NULL);
+ if (m == NULL) return;
+
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
- printf ("msg: type %d len %d\n", m->type, m->length);
+ LOG_INFO ("msg: type %d len %d\n", m->type, m->length);
#endif
}
-
-enum ipc_errors ipc_message_new (struct ipc_message **m, ssize_t paylen)
+enum ipc_errors ipc_message_format_read (struct ipc_message *m, const char *buf, size_t msize)
{
- m = malloc (sizeof(struct ipc_message));
- if (m == NULL) {
- return IPC_ERROR_MESSAGE_NEW__NO_MESSAGE_PARAM;
- }
-
- memset (*m, 0, sizeof (struct ipc_message));
-
- if (paylen != 0) {
- ((struct ipc_message *)m)->payload = malloc (paylen);
- if (((struct ipc_message *)m)->payload == NULL) {
- free (*m);
- return IPC_ERROR_NOT_ENOUGH_MEMORY;
- }
- }
-
- return IPC_ERROR_NONE;
-}
-
-enum ipc_errors ipc_message_format_read (struct ipc_message *m, const char *buf, ssize_t msize)
-{
- assert (m != NULL);
- assert (buf != NULL);
- assert (msize <= IPC_MAX_MESSAGE_SIZE);
-
- if (m == NULL) {
- return IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_MESSAGE;
- }
-
- if (buf == NULL) {
- return IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_BUFFER;
- }
-
- if (msize > IPC_MAX_MESSAGE_SIZE) {
- return IPC_ERROR_MESSAGE_FORMAT_READ__MESSAGE_SIZE;
- }
+ T_R ((m == NULL), IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_MESSAGE);
+ T_R ((buf == NULL), IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_BUFFER);
+ T_R ((msize > IPC_MAX_MESSAGE_SIZE), IPC_ERROR_MESSAGE_FORMAT_READ__MESSAGE_SIZE);
// message format:
// Type (1 B) | Length (4 B) | UserType (1 B) | Payload (Length B)
m->type = buf[0];
- size_t unformated_size = 0;
- memcpy (&unformated_size, buf+1, sizeof(size_t));
+ uint32_t unformated_size = 0;
+ memcpy (&unformated_size, buf+1, sizeof(uint32_t));
m->length = ntohl (unformated_size);
m->user_type = buf[1 + sizeof m->length];
- assert (m->length <= IPC_MAX_MESSAGE_SIZE);
+ T_R ((m->length > IPC_MAX_MESSAGE_SIZE), IPC_ERROR_MESSAGE_FORMAT_READ__READ_MESSAGE_SIZE);
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
- printf ("receiving msg:\ttype %d, paylen %u, total %lu\n", m->type, m->length, msize);
+ LOG_INFO ("receiving msg: type %d, paylen %u, total %lu", m->type, m->length, msize);
#endif
- assert (m->length == msize - IPC_HEADER_SIZE || m->length == 0);
+ T_R ((m->length != msize - IPC_HEADER_SIZE && m->length != 0)
+ , IPC_ERROR_MESSAGE_FORMAT_READ__READ_MESSAGE_SIZE);
if (m->payload != NULL) {
free (m->payload);
@@ -90,24 +75,12 @@ enum ipc_errors ipc_message_format_read (struct ipc_message *m, const char *buf,
return IPC_ERROR_NONE;
}
-enum ipc_errors ipc_message_format_write (const struct ipc_message *m, char **buf, ssize_t *msize)
+enum ipc_errors ipc_message_format_write (const struct ipc_message *m, char **buf, size_t *msize)
{
- assert (m != NULL);
- assert (buf != NULL);
- assert (msize != NULL);
- assert (m->length <= IPC_MAX_MESSAGE_SIZE);
-
- if (m == NULL) {
- return IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MESSAGE;
- }
-
- if (buf == NULL) {
- return IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_BUFFER;
- }
-
- if (msize == NULL) {
- return IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MSIZE;
- }
+ T_R ((m == NULL), IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MESSAGE);
+ T_R ((buf == NULL), IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_BUFFER);
+ T_R ((msize == NULL), IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MSIZE);
+ T_R ((m->length > IPC_MAX_MESSAGE_SIZE), IPC_ERROR_MESSAGE_FORMAT_WRITE__MESSAGE_LENGTH);
if (*buf == NULL) {
*buf = malloc (IPC_HEADER_SIZE + m->length);
@@ -115,10 +88,9 @@ enum ipc_errors ipc_message_format_write (const struct ipc_message *m, char **bu
}
char *buffer = *buf;
- uint32_t paylen = htonl(m->length);
+ uint32_t net_paylen = htonl(m->length);
buffer[0] = m->type;
- uint32_t net_paylen = htonl(m->length);
memcpy (buffer + 1, &net_paylen, sizeof(uint32_t));
buffer[1 + sizeof m->length] = m->user_type;
if (m->payload != NULL && m->length > 0) {
@@ -128,96 +100,21 @@ enum ipc_errors ipc_message_format_write (const struct ipc_message *m, char **bu
*msize = IPC_HEADER_SIZE + m->length;
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
- printf ("sending msg:\ttype %u, paylen %u, msize %lu\n", m->type, m->length, *msize);
+ LOG_INFO ("sending msg: type %u, paylen %u, msize %lu", m->type, m->length, *msize);
#endif
return IPC_ERROR_NONE;
}
-// IPC_ERROR_CLOSED_RECIPIENT on closed recipient
-enum ipc_errors ipc_message_read (int32_t fd, struct ipc_message *m)
-{
- assert (m != NULL);
-
- if (m == NULL) {
- return IPC_ERROR_MESSAGE_READ__NO_MESSAGE_PARAM;
- }
-
- char *buf = NULL;
- ssize_t msize = IPC_MAX_MESSAGE_SIZE;
-
- enum ipc_errors ret = usock_recv (fd, &buf, &msize);
- if (ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT) {
- handle_err ("msg_read", "usock_recv");
- return ret;
- }
-
- // closed recipient, buffer already freed
- if (ret == IPC_ERROR_CLOSED_RECIPIENT) {
- return IPC_ERROR_CLOSED_RECIPIENT;
- }
-
- if (buf != NULL) {
- ret = ipc_message_format_read (m, buf, msize);
- free (buf);
- }
- return ret; // propagates ipc_message_format return
-}
-
-enum ipc_errors ipc_message_write (int32_t fd, const struct ipc_message *m)
-{
- assert (m != NULL);
-
- if (m == NULL) {
- return IPC_ERROR_MESSAGE_WRITE__NO_MESSAGE_PARAM;
- }
-
- char *buf = NULL;
- ssize_t msize = 0;
- ipc_message_format_write (m, &buf, &msize);
-
- ssize_t nbytes_sent = 0;
- enum ipc_errors ret = usock_send (fd, buf, msize, &nbytes_sent);
- if (buf != NULL) {
- free (buf);
- }
-
- if (ret != IPC_ERROR_NONE) {
- handle_err ("msg_write", "usock_send");
- return ret;
- }
-
- // what was sent != what should have been sent
- if (nbytes_sent != msize) {
- handle_err ("msg_write", "usock_send did not send enough data");
- return IPC_ERROR_MESSAGE_WRITE__NOT_ENOUGH_DATA;
- }
-
- return IPC_ERROR_NONE;
-}
-
// MSG FORMAT
enum ipc_errors ipc_message_format (struct ipc_message *m
- , char type, char utype, const char *payload, ssize_t length)
+ , char type, char utype, const char *payload, size_t length)
{
- assert (m != NULL);
- assert (length <= IPC_MAX_MESSAGE_SIZE);
- assert ((length == 0 && payload == NULL) || (length > 0 && payload != NULL));
-
- if (m == NULL) {
- return IPC_ERROR_MESSAGE_FORMAT__NO_MESSAGE_PARAM;
- }
-
- if ((length == 0 && payload != NULL) || (length > 0 && payload == NULL)) {
- return IPC_ERROR_MESSAGE_FORMAT__INCONSISTENT_PARAMS;
- }
-
- if (length > IPC_MAX_MESSAGE_SIZE) {
- handle_err ("msg_format_con", "msgsize > BUFSIZ");
- printf ("msg to format: %ld B)\n", length);
- return IPC_ERROR_MESSAGE_FORMAT__LENGTH;
- }
+ T_R ((m == NULL), IPC_ERROR_MESSAGE_FORMAT__NO_MESSAGE_PARAM);
+ T_R ((length > IPC_MAX_MESSAGE_SIZE), IPC_ERROR_MESSAGE_FORMAT__MESSAGE_SIZE);
+ T_R (((length == 0 && payload != NULL) || (length > 0 && payload == NULL))
+ , IPC_ERROR_MESSAGE_FORMAT__INCONSISTENT_PARAMS);
m->type = type;
m->user_type = utype;
@@ -228,11 +125,7 @@ enum ipc_errors ipc_message_format (struct ipc_message *m
free (m->payload);
}
- m->payload = malloc (length);
- if (m->payload == NULL) {
- return IPC_ERROR_NOT_ENOUGH_MEMORY;
- }
- memset (m->payload, 0, length);
+ SECURE_BUFFER_HEAP_ALLOCATION_R (m->payload, length, , IPC_ERROR_NOT_ENOUGH_MEMORY);
}
if (payload != NULL) {
@@ -241,7 +134,7 @@ enum ipc_errors ipc_message_format (struct ipc_message *m
return IPC_ERROR_NONE;
}
-enum ipc_errors ipc_message_format_data (struct ipc_message *m, char utype, const char *payload, ssize_t length)
+enum ipc_errors ipc_message_format_data (struct ipc_message *m, char utype, const char *payload, size_t length)
{
return ipc_message_format (m, MSG_TYPE_DATA, utype, payload, length);
}
@@ -253,11 +146,7 @@ enum ipc_errors ipc_message_format_server_close (struct ipc_message *m)
enum ipc_errors ipc_message_empty (struct ipc_message *m)
{
- assert (m != NULL);
-
- if (m == NULL) {
- return IPC_ERROR_MESSAGE_EMPTY__EMPTY_MESSAGE_LIST;
- }
+ T_R ((m == NULL), IPC_ERROR_MESSAGE_EMPTY__EMPTY_MESSAGE_LIST);
if (m->payload != NULL) {
free (m->payload);
diff --git a/src/network.c b/src/network.c
new file mode 100644
index 0000000..943f3f7
--- /dev/null
+++ b/src/network.c
@@ -0,0 +1,163 @@
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "ipc.h"
+
+/**
+ * TODO:
+ * describe a protocol to get this working into networkd
+ * asking networkd for a fd with an URI
+ * URI should contain: who (the service name), where (destination), how (protocol)
+ * networkd initiates a communication with the requested service
+ * networkd sends the fd
+ * get a networkd working with this
+ */
+
+
+
+enum ipc_errors ipc_receive_fd (int sock, int *fd)
+{
+ T_R ((fd == NULL), IPC_ERROR_RECEIVE_FD__NO_PARAM_FD);
+ *fd = -1;
+
+ SECURE_DECLARATION (struct msghdr, msg);
+ SECURE_BUFFER_DECLARATION (char, c_buffer, 256);
+
+ /* On Mac OS X, the struct iovec is needed, even if it points to minimal data */
+ char m_buffer[1];
+ struct iovec io = { .iov_base = m_buffer, .iov_len = sizeof(m_buffer) };
+ msg.msg_iov = &io;
+ msg.msg_iovlen = 1;
+
+ msg.msg_control = c_buffer;
+ msg.msg_controllen = sizeof(c_buffer);
+
+ T_PERROR_R ((recvmsg(sock, &msg, 0) <= 0), "recvmsg", IPC_ERROR_RECEIVE_FD__RECVMSG);
+
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+
+ memmove(fd, CMSG_DATA(cmsg), sizeof(*fd));
+
+ return IPC_ERROR_NONE;
+}
+
+enum ipc_errors ipc_provide_fd (int sock, int fd)
+{
+ SECURE_DECLARATION (struct msghdr, msg);
+ SECURE_BUFFER_DECLARATION (char, buf, CMSG_SPACE(sizeof(fd)));
+
+ /* On Mac OS X, the struct iovec is needed, even if it points to minimal data */
+ struct iovec io = { .iov_base = "", .iov_len = 1 };
+
+ msg.msg_iov = &io;
+ msg.msg_iovlen = 1;
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+
+ struct cmsghdr * cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+
+ memmove(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ T_PERROR_R ((sendmsg(sock, &msg, 0) < 0), "sendmsg", IPC_ERROR_PROVIDE_FD__SENDMSG);
+
+ return IPC_ERROR_NONE;
+}
+
+void ipc_switching_add (struct ipc_switchings *is, int orig, int dest)
+{
+ is->collection = realloc(is->collection, sizeof(struct ipc_switching) * (is->size+1));
+ if (is->collection == NULL) {
+ LOG_ERROR ("error realloc");
+ exit (EXIT_FAILURE);
+ }
+
+ is->size++;
+
+ is->collection[is->size-1].orig = orig;
+ is->collection[is->size-1].dest = dest;
+}
+
+int ipc_switching_del (struct ipc_switchings *is, int fd)
+{
+ for (size_t i = 0; i < is->size; i++) {
+ if (is->collection[i].orig == fd || is->collection[i].dest == fd) {
+ int ret;
+
+ if (fd == is->collection[i].orig) {
+ ret = is->collection[i].dest;
+ }
+ else {
+ ret = is->collection[i].orig;
+ }
+
+ is->collection[i].orig = is->collection[is->size-1].orig;
+ is->collection[i].dest = is->collection[is->size-1].dest;
+
+ size_t s = (is->size - 1) > 0 ? (is->size - 1) : 1;
+
+ is->collection = realloc(is->collection, sizeof(struct ipc_switching) * s);
+ if (is->collection == NULL) {
+ LOG_ERROR ("error realloc");
+ exit (EXIT_FAILURE);
+ }
+
+ is->size--;
+ return ret;
+ }
+ }
+
+ return -1;
+}
+
+int ipc_switching_get (struct ipc_switchings *is, int fd)
+{
+ for (size_t i = 0; i < is->size; i++) {
+ if (is->collection[i].orig == fd) {
+ return is->collection[i].dest;
+ }
+ else if (is->collection[i].dest == fd) {
+ return is->collection[i].orig;
+ }
+ }
+
+ return -1;
+}
+
+void ipc_switching_free (struct ipc_switchings *is)
+{
+ if (is == NULL)
+ return;
+
+ if (is->collection != NULL) {
+ free (is->collection);
+ is->collection = NULL;
+ }
+ is->size = 0;
+}
+
+void ipc_switching_print (struct ipc_switchings *is)
+{
+ for (size_t i = 0; i < is->size; i++) {
+ LOG_DEBUG ("client %d - %d", is->collection[i].orig, is->collection[i].dest);
+ }
+}
diff --git a/src/usocket.c b/src/usocket.c
index 33eb794..8f65ea1 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -9,59 +9,45 @@
#include
#include
#include
-#include
#include
#include "usocket.h"
#include "utils.h"
-#define IPC_DEBUG
-
-#undef handle_err
-#define handle_err(a,b) fprintf (stderr, "FUNCTION %s LINE %d ERROR %s\n", a, __LINE__, b);
+// #define IPC_DEBUG 3
/**
* TODO: non blocking read
*/
-enum ipc_errors usock_send (const int32_t fd, const char *buf, ssize_t len, ssize_t *sent)
+enum ipc_errors usock_send (const int32_t fd, const char *buf, size_t len, size_t *sent)
{
ssize_t ret = 0;
ret = send (fd, buf, len, MSG_NOSIGNAL);
- if (ret <= 0) {
- handle_err ("usock_send", "send ret <= 0");
- return IPC_ERROR_USOCK_SEND;
- }
+ T_R ((ret <= 0), IPC_ERROR_USOCK_SEND);
*sent = ret;
return IPC_ERROR_NONE;
}
// *len is changed to the total message size read (header + payload)
-enum ipc_errors usock_recv (const int32_t fd, char **buf, ssize_t *len)
+enum ipc_errors usock_recv (const int32_t fd, char **buf, size_t *len)
{
- assert(buf != NULL);
- assert(len != NULL);
+ T_R ((buf == NULL), IPC_ERROR_USOCK_RECV__NO_BUFFER);
+ T_R ((len == NULL), IPC_ERROR_USOCK_RECV__NO_LENGTH);
int32_t ret_recv = 0;
- if (buf == NULL) {
- handle_err ("usock_recv", "buf == NULL");
- return IPC_ERROR_USOCK_RECV__NO_BUFFER;
- }
-
- if (len == NULL) {
- handle_err ("usock_recv", "len == NULL");
- return IPC_ERROR_USOCK_RECV__NO_LENGTH;
- }
+ if (*len == 0)
+ *len = IPC_MAX_MESSAGE_SIZE;
if (*buf == NULL) {
// do not allocate too much memory
if (*len > IPC_MAX_MESSAGE_SIZE) {
- handle_err ("usock_recv", "len > IPC_MAX_MESSAGE_SIZE");
+ LOG_ERROR ("usock_recv: len > IPC_MAX_MESSAGE_SIZE");
*len = IPC_MAX_MESSAGE_SIZE;
}
- *buf = malloc (*len + IPC_HEADER_SIZE);
+ SECURE_BUFFER_HEAP_ALLOCATION (*buf,*len + IPC_HEADER_SIZE, , return (IPC_ERROR_NOT_ENOUGH_MEMORY));
}
uint32_t msize = 0;
@@ -69,99 +55,78 @@ enum ipc_errors usock_recv (const int32_t fd, char **buf, ssize_t *len)
do {
ret_recv = recv (fd, *buf, *len, 0);
+#ifdef IPC_DEBUG
+ if (ret_recv > 0) {
+ print_hexa ("msg recv", (uint8_t *)*buf, ret_recv);
+ fflush(stdout);
+ }
+#endif
+
if (ret_recv > 0) {
if (msize == 0) {
memcpy (&msize, *buf + 1, sizeof msize);
}
- else {
- printf ("pas la première boucle, msize == %u\n", msize);
- }
msize = ntohl (msize);
if (msize >= IPC_MAX_MESSAGE_SIZE) {
#ifdef IPC_DEBUG
- printf ("lecture bien passée : %d octets\n", ret_recv);
print_hexa ("msg recv", (uint8_t *)*buf, ret_recv);
fflush(stdout);
#endif
}
- assert (msize < IPC_MAX_MESSAGE_SIZE);
+ T_R ((msize > IPC_MAX_MESSAGE_SIZE), IPC_ERROR_USOCK_RECV__MESSAGE_SIZE);
msize_read += ret_recv - IPC_HEADER_SIZE;
-
}
else if (ret_recv < 0) {
- if (*buf != NULL)
+ if (*buf != NULL) {
free (*buf);
+ *buf = NULL;
+ }
*len = 0;
switch (errno) {
// The receive buffer pointer(s) point outside the process's address space.
- case EFAULT:
- handle_err ("usock_recv", "critical error: use of unallocated memory, quitting...");
- fprintf (stderr, "ERROR WHILE RECEIVING: EFAULT\n");
- break;
+ ERROR_CASE (EFAULT, "usock_recv", "critical error: use of unallocated memory, quitting...");
// Invalid argument passed.
- case EINVAL:
- handle_err ("usock_recv", "critical error: invalid arguments to read(2), quitting...");
- fprintf (stderr, "ERROR WHILE RECEIVING: EINVAL\n");
- break;
+ ERROR_CASE (EINVAL, "usock_recv", "critical error: invalid arguments to read(2), quitting...");
// Could not allocate memory for recvmsg().
- case ENOMEM:
- handle_err ("usock_recv", "critical error: cannot allocate memory, quitting...");
- fprintf (stderr, "ERROR WHILE RECEIVING: ENOMEM\n");
- break;
+ ERROR_CASE (ENOMEM, "usock_recv", "critical error: cannot allocate memory, quitting...");
// The argument sockfd is an invalid descriptor.
- case EBADF:
- handle_err ("usock_recv", "critical error: invalid descriptor, quitting...");
- fprintf (stderr, "ERROR WHILE RECEIVING: EBADF\n");
- break;
+ ERROR_CASE (EBADF, "usock_recv", "critical error: invalid descriptor, quitting...");
// The file descriptor sockfd does not refer to a socket.
- case ENOTSOCK:
- handle_err ("usock_recv", "critical error: fd is not a socket, quitting...");
- fprintf (stderr, "ERROR WHILE RECEIVING: ENOTSOCK\n");
- break;
+ ERROR_CASE (ENOTSOCK, "usock_recv", "critical error: fd is not a socket, quitting...");
// The socket is associated with a connection-oriented protocol and has not
// been connected (see connect(2) and accept(2)).
- case ENOTCONN:
- handle_err ("usock_recv", "critical error: read(2) on a non connected socket, quitting...");
- fprintf (stderr, "ERROR WHILE RECEIVING: ENOTCONN\n");
- break;
+ ERROR_CASE (ENOTCONN, "usock_recv", "critical error: read(2) on a non connected socket, quitting...");
- case EAGAIN:
- fprintf (stderr, "ERROR WHILE RECEIVING: EAGAIN / EWOULDBLOCK\n");
- break;
+ ERROR_CASE (EAGAIN, "usock_recv", "ERROR WHILE RECEIVING: EAGAIN / EWOULDBLOCK");
// A remote host refused to allow the network connection
// (typically because it is not running the requested service).
- case ECONNREFUSED:
- fprintf (stderr, "ERROR WHILE RECEIVING: ECONNREFUSED\n");
- break;
+ ERROR_CASE (ECONNREFUSED, "usock_recv", "ERROR WHILE RECEIVING: ECONNREFUSED");
// The receive was interrupted by delivery of a signal before
// any data were available; see signal(7).
- case EINTR:
- handle_err ("usock_recv", "unsupported error");
- break;
+ ERROR_CASE (EINTR, "usock_recv", "unsupported error");
default:
- printf ("usock_recv unsupported error : %d\n", errno);
- handle_err ("usock_recv", "unsupported error");
+ LOG_ERROR ("usock_recv: unsupported error");
}
- handle_err ("usock_recv", "recv < 0");
- perror("recv");
-
+ LOG_ERROR ("usock_recv: recv < 0");
return IPC_ERROR_USOCK_RECV;
}
+#if 0
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
- printf ("fragmentation: message size read %u, should read %u\n", msize_read, msize);
+ LOG_ERROR ("fragmentation: message size read %u, should read %u", msize_read, msize);
+#endif
#endif
} while (msize > msize_read);
@@ -173,6 +138,7 @@ enum ipc_errors usock_recv (const int32_t fd, char **buf, ssize_t *len)
free (*buf);
*buf = NULL;
}
+ *len = 0;
return IPC_ERROR_CLOSED_RECIPIENT;
}
@@ -183,41 +149,24 @@ enum ipc_errors usock_recv (const int32_t fd, char **buf, ssize_t *len)
enum ipc_errors usock_connect (int32_t *fd, const char *path)
{
- assert (fd != NULL);
- assert (path != NULL);
+ T_R ((fd == NULL), IPC_ERROR_USOCK_CONNECT__WRONG_FILE_DESCRIPTOR);
+ T_R ((path == NULL), IPC_ERROR_USOCK_CONNECT__EMPTY_PATH);
- if (fd == NULL) {
- handle_err ("usock_connect", "fd == NULL");
- return IPC_ERROR_USOCK_CONNECT__WRONG_FILE_DESCRIPTOR;
- }
-
- if (path == NULL) {
- handle_err ("usock_connect", "path == NULL");
- return IPC_ERROR_USOCK_CONNECT__EMPTY_PATH;
- }
+ SECURE_DECLARATION (struct sockaddr_un, my_addr);
+ my_addr.sun_family = AF_UNIX;
int32_t sfd;
- struct sockaddr_un my_addr;
- socklen_t peer_addr_size;
+ socklen_t peer_addr_size = sizeof(struct sockaddr_un);
- sfd = socket (AF_UNIX, SOCK_STREAM, 0);
- if (sfd == -1) {
- handle_err ("usock_connect", "sfd == -1");
- return IPC_ERROR_USOCK_CONNECT__SOCKET;
- }
-
- // clear structure
- memset(&my_addr, 0, sizeof(struct sockaddr_un));
-
- my_addr.sun_family = AF_UNIX;
+ T_PERROR_R (((sfd = socket (AF_UNIX, SOCK_STREAM, 0)) == -1), "socket", IPC_ERROR_USOCK_CONNECT__SOCKET);
strncpy(my_addr.sun_path, path, (strlen (path) < PATH_MAX) ? strlen(path) : PATH_MAX);
- peer_addr_size = sizeof(struct sockaddr_un);
- if(connect(sfd, (struct sockaddr *) &my_addr, peer_addr_size) == -1) {
- handle_err ("usock_connect", "connect == -1");
- perror("connect");
- return IPC_ERROR_USOCK_CONNECT__CONNECT;
- }
+ /** TODO: massive series of tests */
+ T_PERROR_F_R (
+ /** test */ (connect(sfd, (struct sockaddr *) &my_addr, peer_addr_size) == -1)
+ , /** perror */ "connect"
+ , /** log error */ ("unix socket connection to the path %s not possible", path)
+ , /** return value */ IPC_ERROR_USOCK_CONNECT__CONNECT);
*fd = sfd;
@@ -226,52 +175,26 @@ enum ipc_errors usock_connect (int32_t *fd, const char *path)
enum ipc_errors usock_init (int32_t *fd, const char *path)
{
- assert (fd != NULL);
- assert (path != NULL);
-
- if (fd == NULL) {
- handle_err ("usock_init", "fd == NULL");
- return IPC_ERROR_USOCK_INIT__EMPTY_FILE_DESCRIPTOR;
- }
-
- if (path == NULL) {
- handle_err ("usock_init", "path == NULL");
- return IPC_ERROR_USOCK_INIT__EMPTY_PATH;
- }
-
- int32_t sfd;
- struct sockaddr_un my_addr;
- socklen_t peer_addr_size;
-
- sfd = socket (AF_UNIX, SOCK_STREAM, 0);
- if (sfd == -1) {
- handle_err ("usock_init", "sfd == -1");
- return IPC_ERROR_USOCK_INIT__WRONG_FILE_DESCRIPTOR;
- }
-
- // clear structure
- memset(&my_addr, 0, sizeof(struct sockaddr_un));
+ T_R ((fd == NULL), IPC_ERROR_USOCK_INIT__EMPTY_FILE_DESCRIPTOR);
+ T_R ((path == NULL), IPC_ERROR_USOCK_INIT__EMPTY_PATH);
+ SECURE_DECLARATION (struct sockaddr_un, my_addr);
my_addr.sun_family = AF_UNIX;
strncpy(my_addr.sun_path, path, strlen (path));
+ int32_t sfd;
+ socklen_t peer_addr_size;
+
+ T_PERROR_R (((sfd = socket (AF_UNIX, SOCK_STREAM, 0)) == -1), "socket", IPC_ERROR_USOCK_INIT__WRONG_FILE_DESCRIPTOR);
+
// delete the unix socket if already created
// ignore otherwise
usock_remove (path);
peer_addr_size = sizeof(struct sockaddr_un);
- if (bind (sfd, (struct sockaddr *) &my_addr, peer_addr_size) == -1) {
- handle_err ("usock_init", "bind == -1");
- perror("bind");
- return IPC_ERROR_USOCK_INIT__BIND;
- }
-
- if (listen (sfd, LISTEN_BACKLOG) == -1) {
- handle_err ("usock_init", "listen == -1");
- perror("listen");
- return IPC_ERROR_USOCK_INIT__LISTEN;
- }
+ T_PERROR_R ((bind (sfd, (struct sockaddr *) &my_addr, peer_addr_size) == -1), "bind", IPC_ERROR_USOCK_INIT__BIND);
+ T_PERROR_R ((listen (sfd, LISTEN_BACKLOG) == -1), "listen", IPC_ERROR_USOCK_INIT__LISTEN);
*fd = sfd;
@@ -280,54 +203,29 @@ enum ipc_errors usock_init (int32_t *fd, const char *path)
enum ipc_errors usock_accept (int32_t fd, int32_t *pfd)
{
- assert (pfd != NULL);
+ T_R ((pfd == NULL), IPC_ERROR_USOCK_ACCEPT__PATH_FILE_DESCRIPTOR);
- if (pfd == NULL) {
- handle_err ("usock_accept", "pfd == NULL");
- return IPC_ERROR_USOCK_ACCEPT__PATH_FILE_DESCRIPTOR;
- }
-
- struct sockaddr_un peer_addr;
- memset (&peer_addr, 0, sizeof (struct sockaddr_un));
+ SECURE_DECLARATION (struct sockaddr_un, peer_addr);
socklen_t peer_addr_size = 0;
- *pfd = accept (fd, (struct sockaddr *) &peer_addr, &peer_addr_size);
- if (*pfd < 0) {
- handle_err ("usock_accept", "accept < 0");
- perror("listen");
- return IPC_ERROR_USOCK_ACCEPT;
- }
+ T_PERROR_R (((*pfd = accept (fd, (struct sockaddr *) &peer_addr, &peer_addr_size)) < 0), "accept", IPC_ERROR_USOCK_ACCEPT);
return IPC_ERROR_NONE;
}
enum ipc_errors usock_close (int32_t fd)
{
- int32_t ret = 0;
-
- ret = close (fd);
- if (ret < 0) {
- handle_err ("usock_close", "close ret < 0");
- perror ("closing");
- return IPC_ERROR_USOCK_CLOSE;
- }
+ T_PERROR_R ((close (fd) < 0), "close", IPC_ERROR_USOCK_CLOSE);
return IPC_ERROR_NONE;
}
enum ipc_errors usock_remove (const char *path)
{
- struct stat file_state;
- memset (&file_state, 0, sizeof (struct stat));
+ SECURE_DECLARATION(struct stat, file_state);
// if file exists, remove it
- int ret = stat (path, &file_state);
- if (ret == 0) {
- ret = unlink (path);
- if (ret != 0) {
- return IPC_ERROR_USOCK_REMOVE__UNLINK;
- }
- return IPC_ERROR_NONE;
- }
+ T_R ((stat (path, &file_state) != 0), IPC_ERROR_USOCK_REMOVE__NO_FILE);
+ T_R ((unlink (path) != 0), IPC_ERROR_USOCK_REMOVE__UNLINK);
- return IPC_ERROR_USOCK_REMOVE__NO_FILE;
+ return IPC_ERROR_NONE;
}
diff --git a/src/usocket.h b/src/usocket.h
index 79bb3c2..df06027 100644
--- a/src/usocket.h
+++ b/src/usocket.h
@@ -7,12 +7,12 @@
// input: len = max buf size
// output: *sent = nb received bytes
-enum ipc_errors usock_send (const int32_t fd, const char *buf, ssize_t len, ssize_t *sent);
+enum ipc_errors usock_send (const int32_t fd, const char *buf, size_t len, size_t *sent);
// allocation of *len bytes on *buf == NULL
//
// output: *len = nb sent bytes
-enum ipc_errors usock_recv (int32_t fd, char **buf, ssize_t *len);
+enum ipc_errors usock_recv (int32_t fd, char **buf, size_t *len);
enum ipc_errors usock_close (int32_t fd);
diff --git a/src/utils.c b/src/utils.c
index d6c5f37..bd4d2fe 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,22 +1,36 @@
#include "utils.h"
+#include "ipc.h"
void print_hexa (const char *prefix, uint8_t *payload, size_t size)
{
- if (! payload)
+ if (payload == NULL)
return ;
+ SECURE_BUFFER_DECLARATION (char, buffer, BUFSIZ);
+
+ char *cur = buffer, * const end = buffer + sizeof buffer;
+
size_t i;
- for(i = 0; i < size; i++)
- {
- if(! (i % 4))
- printf("\n%s (%ld) ", prefix, size);
- printf("%2x ", payload[i]);
+ size_t linenum = 0;
+ for(i = 0; i < size; i++) {
+ if (i == 0) {
+ cur += snprintf(cur, end-cur, "\033[32m[%2ld/%2ld]\033[00m \033[36m%s\033[00m (%ld) ", linenum +1, (size / 16) +1, prefix, size);
+ linenum ++;
+ }
+ else if(! (i % 16)) {
+ LOG_DEBUG ("%s", buffer);
+ memset (buffer, 0, BUFSIZ);
+ cur = buffer;
+ cur += snprintf(cur, end-cur, "\033[32m[%2ld/%2ld]\033[00m \033[36m%s\033[00m (%ld) ", linenum +1, (size / 16) +1, prefix, size);
+ linenum ++;
+ }
+ else if (! (i % 4)) {
+ cur += snprintf(cur, end-cur, " ");
+ }
+ cur += snprintf(cur, end-cur, "%2x ", payload[i]);
}
- printf("\n");
-}
-
-void mprint_hexa (char *prefix, uint8_t *buf, size_t length)
-{
- print_hexa (prefix, buf, length);
+ if ((i % 16)) {
+ LOG_DEBUG ("%s", buffer);
+ }
}
diff --git a/src/utils.h b/src/utils.h
index 352b78f..6d3c0e3 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -8,6 +8,5 @@
#include
void print_hexa (const char *prefix, uint8_t *payload, size_t size);
-void mprint_hexa (char *prefix, uint8_t *buf, size_t length);
#endif
From a0d0c6be3047713304521a1c653766a67c6adecd Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Sat, 27 Jul 2019 15:47:50 +0200
Subject: [PATCH 2/5] some documentation (WIP)
---
README.md | 11 +++++++++++
man/libipc.7.md | 6 ------
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index cb7d402..1dccfcc 100644
--- a/README.md
+++ b/README.md
@@ -5,3 +5,14 @@ libipc - Simple, easy-to-use IPC library
See the introductory [man page](man/libipc.7.md).
+# Compilation
+
+`make`
+
+
+# logging system
+
+Logs are in one of the following directories: `$XDG_DATA_HOME/ipc/` or `$HOME/.local/share/ipc/`.
+The log file can be indicated with the `IPC_LOGFILE` environment variable, too.
+
+To remove logs: `make LDFLAGS=-DIPC_WITHOUT_ERRORS`
diff --git a/man/libipc.7.md b/man/libipc.7.md
index 136c8eb..6114e57 100644
--- a/man/libipc.7.md
+++ b/man/libipc.7.md
@@ -47,17 +47,11 @@ It provides both client and server code.
## Message functions
-// create msg structure with a certain payload length (0 for no payload memory allocation)\
-*enum ipc_errors* **ipc_message_new** (*struct ipc_message* \*\*m, *ssize_t* paylen);\
// create msg structure from buffer\
*enum ipc_errors* **ipc_message_format_read** (*struct ipc_message* \*m, *const char* \*buf, *ssize_t* msize);\
// create buffer from msg structure\
*enum ipc_errors* **ipc_message_format_write** (*const struct ipc_message* \*m, *char* \*\*buf, *ssize_t* \*msize);\
-// read a structure msg from fd\
-*enum ipc_errors* **ipc_message_read** (*int32_t* fd, *struct ipc_message* \*m);\
-// write a structure msg to fd\
-*enum ipc_errors* **ipc_message_write** (*int32_t* fd, *const struct ipc_message* \*m);\
*enum ipc_errors* **ipc_message_format** (*struct ipc_message* \*m, *char* type, *const char* \*payload, *ssize_t* length);\
*enum ipc_errors* **ipc_message_format_data** (*struct ipc_message* \*m, *const char* \*payload, *ssize_t* length);\
*enum ipc_errors* **ipc_message_format_server_close** (*struct ipc_message* \*m);\
From 1e5e475bcb2559d3f8923c89e9e97984f598626a Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Sat, 27 Jul 2019 15:48:10 +0200
Subject: [PATCH 3/5] examples and utils
---
drop/build.sh | 23 ++
drop/print-bytes.c | 27 ++
drop/to-pascal.pl | 9 +
examples/build.sh | 20 +-
examples/fd-exchange-providing.c | 31 ++
examples/fd-exchange-receiving.c | 37 +++
examples/pong.c | 113 +++-----
examples/pongd.c | 12 +-
examples/simple-tcp-client.c | 96 ++-----
examples/simple-tcpd.c | 378 +++++++------------------
examples/test-ask-for-fd-to-networkd.c | 46 +++
examples/test-networkd-provide-fd.c | 41 +++
examples/tests-logs.c | 16 ++
examples/wsserver.c | 118 ++++++++
14 files changed, 546 insertions(+), 421 deletions(-)
create mode 100755 drop/build.sh
create mode 100644 drop/print-bytes.c
create mode 100644 drop/to-pascal.pl
create mode 100644 examples/fd-exchange-providing.c
create mode 100644 examples/fd-exchange-receiving.c
create mode 100644 examples/test-ask-for-fd-to-networkd.c
create mode 100644 examples/test-networkd-provide-fd.c
create mode 100644 examples/tests-logs.c
create mode 100644 examples/wsserver.c
diff --git a/drop/build.sh b/drop/build.sh
new file mode 100755
index 0000000..a77e6d2
--- /dev/null
+++ b/drop/build.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+nontapmsg() {
+ echo $*
+}
+
+if [ $# -eq 0 ] ; then
+ SRC="*.c"
+else
+ SRC="$*"
+fi
+
+for i in $SRC
+do
+ BIN=$(echo ${i} | sed "s/.c$/.bin/")
+ if [ ! -f ${BIN} ] || [ $(stat -c "%X" ${BIN}) -lt $(stat -c "%X" ${i}) ]
+ then
+ nontapmsg "compiling ${BIN}"
+ # gcc $BIN.c ./lib/*.o -o $BIN -I../src -I ./lib/ -L../ -L./lib/ -lipc -Wall -g -Wextra
+ gcc -Wall -g -Wextra "${i}" -o "${BIN}" -I../src -L../ ../src/ipc.h -lipc
+ touch "${BIN}"
+ fi
+done
diff --git a/drop/print-bytes.c b/drop/print-bytes.c
new file mode 100644
index 0000000..4dcda06
--- /dev/null
+++ b/drop/print-bytes.c
@@ -0,0 +1,27 @@
+#include
+#include
+#include
+#include
+#include
+
+#include "../src/ipc.h"
+
+int main(int argc, char * argv[])
+{
+ SECURE_BUFFER_DECLARATION (char, buffer, 4096);
+ uint32_t msize = 0;
+ char *message = "coucou";
+
+ if (argc == 2) {
+ message = argv[1];
+ }
+
+ msize = ipc_message_raw_serialize (buffer, 2, 42, message, strlen(message));
+ write (1, buffer, msize);
+ fflush (stdout);
+
+ // to wait for a response
+ sleep (1);
+
+ return EXIT_SUCCESS;
+}
diff --git a/drop/to-pascal.pl b/drop/to-pascal.pl
new file mode 100644
index 0000000..61a18da
--- /dev/null
+++ b/drop/to-pascal.pl
@@ -0,0 +1,9 @@
+#!/usr/bin/perl -w
+use v5.14;
+
+while(<>) {
+ chomp;
+ my @wl = split "_\+";
+ my @wl2 = map { ucfirst lc } @wl;
+ say join "", @wl2;
+}
diff --git a/examples/build.sh b/examples/build.sh
index 8c14e3e..a77e6d2 100755
--- a/examples/build.sh
+++ b/examples/build.sh
@@ -4,10 +4,20 @@ nontapmsg() {
echo $*
}
-for i in *.c
+if [ $# -eq 0 ] ; then
+ SRC="*.c"
+else
+ SRC="$*"
+fi
+
+for i in $SRC
do
- f=`echo $i | sed "s/.c$//"`
- nontapmsg "compiling $f"
- # gcc $f.c ./lib/*.o -o $f -I../src -I ./lib/ -L../ -L./lib/ -lipc -Wall -g -Wextra
- gcc -Wall -g -Wextra $f.c -o $f -I../src -L../ ../src/ipc.h -lipc
+ BIN=$(echo ${i} | sed "s/.c$/.bin/")
+ if [ ! -f ${BIN} ] || [ $(stat -c "%X" ${BIN}) -lt $(stat -c "%X" ${i}) ]
+ then
+ nontapmsg "compiling ${BIN}"
+ # gcc $BIN.c ./lib/*.o -o $BIN -I../src -I ./lib/ -L../ -L./lib/ -lipc -Wall -g -Wextra
+ gcc -Wall -g -Wextra "${i}" -o "${BIN}" -I../src -L../ ../src/ipc.h -lipc
+ touch "${BIN}"
+ fi
done
diff --git a/examples/fd-exchange-providing.c b/examples/fd-exchange-providing.c
new file mode 100644
index 0000000..799a1d1
--- /dev/null
+++ b/examples/fd-exchange-providing.c
@@ -0,0 +1,31 @@
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "../src/ipc.h"
+#include "../src/usocket.h"
+
+// This program opens a file then provide it to another running program.
+// see examples/fd-exchange-receiving.c
+
+int main(int argc, char * argv[])
+{
+ if (argc != 2) {
+ fprintf (stderr, "usage: %s file", argv[0]);
+ exit (EXIT_FAILURE);
+ }
+
+ int sock = 0;
+ int fd = 0;
+
+ T_PERROR_R (((fd = open (argv[1], O_CREAT | O_RDWR)) < 0), "cannot open the file", EXIT_FAILURE);
+
+ TIPC_P_Q (usock_connect (&sock, "SOCKET_FD_EXCHANGE_TEST"), "trying to connect to the unix socket", EXIT_FAILURE);
+ TIPC_P_Q (ipc_provide_fd (sock, fd), "cannot send the file descriptor", EXIT_FAILURE);
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/fd-exchange-receiving.c b/examples/fd-exchange-receiving.c
new file mode 100644
index 0000000..1436651
--- /dev/null
+++ b/examples/fd-exchange-receiving.c
@@ -0,0 +1,37 @@
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "../src/ipc.h"
+#include "../src/usocket.h"
+
+// This program receives an open file descriptor from another running program.
+// see examples/fd-exchange-providing.c
+
+int main(int argc, char * argv[])
+{
+ if (argc != 1) {
+ fprintf (stderr, "usage: %s", argv[0]);
+ exit (EXIT_FAILURE);
+ }
+
+ int usock = 0;
+ int usockclient = 0;
+ int fd = 0;
+
+ TIPC_P_Q (usock_init (&usock, "SOCKET_FD_EXCHANGE_TEST"), "trying to connect to the unix socket", EXIT_FAILURE);
+ TIPC_P_Q (usock_accept (usock, &usockclient), "cannot accept a client from the unix socket", EXIT_FAILURE);
+ TIPC_P_Q (ipc_receive_fd (usockclient, &fd), "cannot receive the file descriptor", EXIT_FAILURE);
+
+ T_PERROR_R ((write (fd, "coucou\n", 7) < 0), "cannot write a message in the file", EXIT_FAILURE);
+ T_PERROR_R ((close (fd) < 0), "cannot close the file descriptor", EXIT_FAILURE);
+
+ TIPC_P_Q (usock_close (usock), "cannot close the unix socket", EXIT_FAILURE);
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/pong.c b/examples/pong.c
index eea4b60..f15e565 100644
--- a/examples/pong.c
+++ b/examples/pong.c
@@ -13,115 +13,79 @@
fprintf(stderr, "error while %s: %s\n", msg, err);\
}
+void chomp (char *str, ssize_t len) {
+ if (str[len -1] == '\n') {
+ str[len -1] = '\0';
+ }
+ if (str[len -2] == '\n') {
+ str[len -2] = '\0';
+ }
+}
+
struct ipc_connection_info *srv;
void non_interactive (char *env[])
{
- struct ipc_message m;
- memset (&m, 0, sizeof (struct ipc_message));
-
- enum ipc_errors ret;
+ SECURE_DECLARATION (struct ipc_message, m);
// init service
- ret = ipc_connection (env, srv, SERVICE_NAME);
- if (ret != IPC_ERROR_NONE) {
- handle_err("main", "ipc_application_connection < 0");
- PRINTERR(ret, "application connection");
- exit (EXIT_FAILURE);
- }
+ TIPC_P_Q (ipc_connection (env, srv, SERVICE_NAME), "application connection", EXIT_FAILURE);
+ TIPC_P_Q (ipc_message_format_data (&m, 42, MSG, (ssize_t) strlen(MSG) +1), "message format data", EXIT_FAILURE);
printf ("msg to send (%ld): %.*s\n", (ssize_t) strlen(MSG) +1, (int) strlen(MSG), MSG);
- ret = ipc_message_format_data (&m, 42, MSG, (ssize_t) strlen(MSG) +1);
- if (ret != IPC_ERROR_NONE) {
- PRINTERR(ret, "message format data");
- exit (EXIT_FAILURE);
- }
-
- // printf ("msg to send in the client: ");
- // ipc_message_print (&m);
- ret = ipc_write (srv, &m);
- if (ret != IPC_ERROR_NONE) {
- handle_err("main", "application_write");
- PRINTERR(ret, "application write");
- exit (EXIT_FAILURE);
- }
+ TIPC_P_Q (ipc_write (srv, &m), "application write", EXIT_FAILURE);
ipc_message_empty (&m);
-
- ret = ipc_read (srv, &m);
- if (ret != IPC_ERROR_NONE) {
- handle_err("main", "application_read");
- PRINTERR(ret, "application read");
- exit (EXIT_FAILURE);
- }
+ TIPC_P_Q (ipc_read (srv, &m), "application read", EXIT_FAILURE);
printf ("msg recv (type: %u): %s\n", m.user_type, m.payload);
ipc_message_empty (&m);
- ret = ipc_close (srv);
- if (ret != IPC_ERROR_NONE) {
- handle_err("main", "application_close");
- PRINTERR(ret, "application close");
- exit (EXIT_FAILURE);
- }
+ TIPC_P_Q (ipc_close (srv), "application close", EXIT_FAILURE);
}
void interactive (char *env[])
{
- enum ipc_errors ret;
-
// init service
- ret = ipc_connection (env, srv, SERVICE_NAME);
- if (ret != IPC_ERROR_NONE) {
- handle_err ("main", "ipc_application_connection < 0");
- PRINTERR(ret, "application connection");
- exit (EXIT_FAILURE);
- }
+ TIPC_P_Q (ipc_connection (env, srv, SERVICE_NAME), "application connection", EXIT_FAILURE);
- struct ipc_event event;
- memset (&event, 0, sizeof (struct ipc_event));
+ SECURE_DECLARATION (struct ipc_event, event);
+ SECURE_DECLARATION (struct ipc_connection_infos, services);
- struct ipc_connection_infos services;
- memset (&services, 0, sizeof (struct ipc_connection_infos));
ipc_add (&services, srv);
-
ipc_add_fd (&services, 0); // add STDIN
- ipc_connections_print(&services);
+ ipc_connections_print (&services);
while (1) {
printf ("msg to send: ");
fflush (stdout);
- ret = ipc_wait_event (&services, NULL, &event);
- if (ret != IPC_ERROR_NONE) {
- PRINTERR(ret, "wait event");
- exit (EXIT_FAILURE);
- }
+ TIPC_P_Q (ipc_wait_event (&services, NULL, &event), "wait event", EXIT_FAILURE);
switch (event.type) {
case IPC_EVENT_TYPE_EXTRA_SOCKET:
{
// structure not read, should read the message here
-
ssize_t len;
char buf[4096];
memset(buf, 0, 4096);
len = read (event.origin->fd, buf, 4096);
- buf[100] = '\0';
+ buf[len -1] = '\0';
+ chomp (buf, len);
+
+#if 0
+ printf ("\n");
+ printf ("message to send: %.*s\n", (int) len, buf);
+#endif
// in case we want to quit the program
if ( len == 0
|| strncmp (buf, "quit", 4) == 0
|| strncmp (buf, "exit", 4) == 0) {
- ret = ipc_close (srv);
- if (ret != IPC_ERROR_NONE) {
- handle_err("main", "ipc_close");
- PRINTERR(ret, "application close");
- exit (EXIT_FAILURE);
- }
+ TIPC_P_Q (ipc_close (srv), "application close", EXIT_FAILURE);
ipc_connections_free (&services);
@@ -130,15 +94,18 @@ void interactive (char *env[])
// send the message read on STDIN
struct ipc_message *m = NULL;
- m = malloc (sizeof (struct ipc_message));
- memset (m, 0, sizeof (struct ipc_message));
+ SECURE_BUFFER_HEAP_ALLOCATION_R (m, sizeof (struct ipc_message), , );
- ret = ipc_write (srv, m);
- if (ret != IPC_ERROR_NONE) {
- handle_err("main", "ipc_write");
- PRINTERR(ret, "ipc_write");
- exit (EXIT_FAILURE);
- }
+ TIPC_P_Q (ipc_message_format_data (m, 42, buf, len), "message format", EXIT_FAILURE);
+
+#if 0
+ printf ("\n");
+ printf ("right before sending a message\n");
+#endif
+ TIPC_P_Q (ipc_write (srv, m), "ipc_write", EXIT_FAILURE);
+#if 0
+ printf ("right after sending a message\n");
+#endif
ipc_message_empty (m);
free (m);
@@ -147,7 +114,7 @@ void interactive (char *env[])
case IPC_EVENT_TYPE_MESSAGE:
{
struct ipc_message *m = event.m;
- printf ("msg recv: %.*s", m->length, m->payload);
+ printf ("\rmsg recv: %.*s\n", m->length, m->payload);
};
break;
case IPC_EVENT_TYPE_DISCONNECTION:
diff --git a/examples/pongd.c b/examples/pongd.c
index eba67fb..1fe47b6 100644
--- a/examples/pongd.c
+++ b/examples/pongd.c
@@ -71,16 +71,20 @@ void main_loop ()
case IPC_EVENT_TYPE_MESSAGE:
{
struct ipc_message *m = event.m;
- if (m->length > 0) {
#ifdef PONGD_VERBOSE
- printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload);
-#endif
+ if (m->length > 0) {
+ printf ("message received (type %d, user type %d, size %u bytes): %.*s\n", m->type, m->user_type, m->length, m->length, m->payload);
}
+ else {
+ printf ("message with a 0-byte size :(\n");
+ }
+#endif
ret = ipc_write (event.origin, m);
if (ret != IPC_ERROR_NONE) {
PRINTERR(ret,"server write");
}
+ printf ("message sent\n");
};
break;
case IPC_EVENT_TYPE_ERROR:
@@ -110,7 +114,7 @@ void exit_program(int signal)
printf("Quitting, signal: %d\n", signal);
// free remaining clients
- for (int i = 0; i < clients->size ; i++) {
+ for (size_t i = 0; i < clients->size ; i++) {
struct ipc_connection_info *cli = clients->cinfos[i];
if (cli != NULL) {
free (cli);
diff --git a/examples/simple-tcp-client.c b/examples/simple-tcp-client.c
index 1cf0693..f017d84 100644
--- a/examples/simple-tcp-client.c
+++ b/examples/simple-tcp-client.c
@@ -23,18 +23,14 @@
*/
-int connection(int port)
+int connection(char *ipstr, int port)
{
int sockfd;
- struct sockaddr_in server;
+ SECURE_DECLARATION (struct sockaddr_in, server);
socklen_t addrlen;
// socket factory
- if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
- {
- perror("socket");
- exit(EXIT_FAILURE);
- }
+ T_PERROR_Q (((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1), "socket creation", EXIT_FAILURE);
// init remote addr structure and other params
server.sin_family = AF_INET;
@@ -42,19 +38,11 @@ int connection(int port)
addrlen = sizeof(struct sockaddr_in);
// get addr from command line and convert it
- if(inet_pton(AF_INET, "127.0.0.1", &server.sin_addr) <= 0)
- {
- perror("inet_pton");
- close(sockfd);
- exit(EXIT_FAILURE);
- }
+ T_PERROR_Q ((inet_pton(AF_INET, ipstr, &server.sin_addr) <= 0), "inet_pton", EXIT_FAILURE);
printf("Trying to connect to the remote host\n");
- if(connect(sockfd, (struct sockaddr *) &server, addrlen) == -1)
- {
- perror("connect");
- exit(EXIT_FAILURE);
- }
+
+ T_PERROR_Q ((connect(sockfd, (struct sockaddr *) &server, addrlen) == -1), "connection", EXIT_FAILURE);
printf("Connection OK\n");
@@ -63,70 +51,37 @@ int connection(int port)
void send_receive (int sockfd) {
- unsigned char buf[BUFSIZ];
- memset (buf, 0, BUFSIZ);
+ SECURE_BUFFER_DECLARATION (unsigned char, buf, BUFSIZ);
+ int paylen;
// first, send service name "pong"
// send string
- if(send(sockfd, "pong", 4, 0) == -1) {
- perror("send pong");
- close(sockfd);
- exit(EXIT_FAILURE);
- }
+ T_PERROR_Q ((send(sockfd, "pong", 4, 0) == -1), "sending a message", EXIT_FAILURE);
printf ("message 'pong' sent\n");
+ T_PERROR_Q (((paylen = recv(sockfd, buf, BUFSIZ, 0)) <= 0), "cannot connect to networkd", EXIT_FAILURE);
+ print_hexa ("should be 'OK'", buf, paylen);
memset (buf, 0, BUFSIZ);
- int paylen;
- paylen = recv(sockfd, buf, BUFSIZ, 0);
- if (paylen <= 0) {
- printf ("cannot connect to networkd\n");
- exit (EXIT_FAILURE);
- }
- printf ("should receive 'OK': %*.s\n", paylen, buf);
-
- memset (buf, 0, BUFSIZ);
-
- buf[0] = MSG_TYPE_DATA;
-
- // uint32_t v = htonl(6);
- // memcpy (buf+1, &v, sizeof (uint32_t));
-
- uint32_t v = 6;
- uint32_t net_paylen = htonl (v);
- memcpy (buf+1, &net_paylen, sizeof (uint32_t));
-
- buf[5] = 0;
- memcpy (buf+6, "coucou", 6);
-
- print_hexa ("SENT MESSAGE", buf, 12);
-
// 2 | 6 | 0 | "coucou"
// 1 B | 4 B | 1 | 6 B
-
- if(send(sockfd, buf, 12, 0) == -1) {
- perror("send coucou");
- close(sockfd);
- exit(EXIT_FAILURE);
- }
+ ipc_message_raw_serialize ((char *) buf, MSG_TYPE_DATA, 42, "coucou", 6);
+ print_hexa ("WAITING 10 seconds then message to send", buf, 12);
+ // sleep (1);
+ T_PERROR_Q ((send(sockfd, buf, 12, 0) == -1), "sending a message", EXIT_FAILURE);
printf ("message 'coucou' sent\n");
-
memset (buf, 0, BUFSIZ);
- paylen = recv (sockfd, buf, BUFSIZ, 0);
- if(paylen < 0) {
- perror("recv a message");
- close(sockfd);
- exit(EXIT_FAILURE);
- }
- if (paylen > 0) {
- print_hexa ("RECEIVED MESSAGE", buf, paylen);
- }
- else {
+ // receiving a message
+ T_PERROR_Q ( ((paylen = recv (sockfd, buf, BUFSIZ, 0)) < 0), "receiving a message", EXIT_FAILURE);
+
+ if (paylen == 0) {
fprintf (stderr, "error: disconnection from the server\n");
exit (EXIT_FAILURE);
}
+ print_hexa ("RECEIVED MESSAGE", buf, paylen);
+
#if 0
// send string
if(sendto(sockfd, , ), 0) == -1)
@@ -141,12 +96,17 @@ void send_receive (int sockfd) {
int main(int argc, char * argv[])
{
+ char *ipstr = "127.0.0.1";
int port = 9000;
- if (argc > 1) {
+ if (argc == 2) {
port = atoi (argv[1]);
}
+ else if (argc == 3) {
+ ipstr = argv[1];
+ port = atoi (argv[2]);
+ }
- int sockfd = connection (port);
+ int sockfd = connection (ipstr, port);
send_receive (sockfd);
diff --git a/examples/simple-tcpd.c b/examples/simple-tcpd.c
index 691f36e..317facd 100644
--- a/examples/simple-tcpd.c
+++ b/examples/simple-tcpd.c
@@ -7,12 +7,16 @@
#include
#include
-#define NTAB(t) ((int) (sizeof (t) / sizeof (t)[0]))
-#define SECURE_BUFFER_DECLARATION(type,name,size) type name[size]; memset(&name, 0, sizeof(type) * size);
-// print error string
-#define PRINT_ERR_STR(code) const char *estr = ipc_errors_get (code); fprintf (stderr, "%s", estr);
-// Test Print Quit
-#define T_P_Q(f,err,q) { ret = f; if (ret != IPC_ERROR_NONE) { fprintf (stderr, err); PRINT_ERR_STR(ret); exit (q); } }
+#define CLOG_DEBUG(a, ...) LOG_DEBUG (""); LOG_DEBUG("\033[36m" a "\033[00m", #__VA_ARGS__); LOG_DEBUG ("")
+
+void chomp (char *str, size_t len) {
+ if (str[len -1] == '\n') {
+ str[len -1] = '\0';
+ }
+ if (str[len -2] == '\n') {
+ str[len -2] = '\0';
+ }
+}
/*
*
@@ -30,8 +34,14 @@
if reading on sock_tcp
sock_client = accept
ipc_add_fd sock_client
- elif reading on sock_client
- TODO (first draft): print messages
+ elif
+ if socket bind to another (client to service or service to client)
+ reading on fd ; writing on related fd
+ else
+ connection from the client:
+ 1. client sends service name
+ 2. networkd establishes a connection to the service
+ 3. ack
else
lolwat shouldn't happen :(
elif reading on usual socket
@@ -40,223 +50,89 @@
#define SERVICE_NAME "simpletcp"
-#define PRINTERR(ret,msg) {\
- const char * err = ipc_errors_get (ret);\
- fprintf(stderr, "error while %s: %s\n", msg, err);\
-}
-
-struct ipc_switching {
- int orig;
- int dest;
-};
-
-struct ipc_switchings {
- struct ipc_switching *collection;
- size_t size;
-};
-
-struct networkd {
- int cpt;
- struct ipc_connection_info *srv;
- struct ipc_connection_infos *clients;
- struct ipc_switchings * TCP_TO_IPC;
- struct ipc_switchings * IPC_TO_TCP;
-};
-
struct networkd * ctx;
-
-void ipc_switching_add (struct ipc_switchings *is, int orig, int dest)
+void handle_disconnection (int fd)
{
- is->collection = realloc(is->collection, sizeof(struct ipc_switching) * (is->size+1));
- if (is->collection == NULL) {
- printf ("error realloc\n");
- exit (EXIT_FAILURE);
+ // disconnection
+ LOG_DEBUG ("CLOSE CONNECTION %d", fd);
+
+ int delfd;
+
+ delfd = ipc_switching_del (ctx->TCP_TO_IPC, fd);
+ if (delfd >= 0) {
+ LOG_DEBUG ("CLOSE RELATED CONNECTION %d", delfd);
+ close (delfd);
+ ipc_del_fd (ctx->clients, delfd);
}
- is->size++;
+ close (fd);
+ ipc_del_fd (ctx->clients, fd);
- is->collection[is->size-1].orig = orig;
- is->collection[is->size-1].dest = dest;
+ printf ("\n\n");
+ // printf ("TCP_TO_IPC\n");
+ ipc_switching_print (ctx->TCP_TO_IPC);
+
+ printf ("\n\n");
}
-int ipc_switching_del (struct ipc_switchings *is, int orig)
+void tcp_connection (char **env, int fd)
{
- for (size_t i = 0; i < is->size; i++) {
- if (is->collection[i].orig == orig) {
- is->collection[i].orig = is->collection[is->size-1].orig;
- int ret = is->collection[i].dest;
- is->collection[i].dest = is->collection[is->size-1].dest;
+ SECURE_BUFFER_DECLARATION(char, buf, BUFSIZ);
- size_t s = (is->size - 1) > 0 ? (is->size - 1) : 1;
-
- is->collection = realloc(is->collection, sizeof(struct ipc_switching) * s);
- if (is->collection == NULL) {
- printf ("error realloc\n");
- exit (EXIT_FAILURE);
- }
-
- is->size--;
- return ret;
- }
+ ssize_t len = recv (fd, buf, BUFSIZ, 0);
+ if (len <= 0) {
+ handle_disconnection (fd);
+ return ;
}
- return -1;
-}
-
-int ipc_switching_get (struct ipc_switchings *is, int orig) {
- for (size_t i = 0; i < is->size; i++) {
- if (is->collection[i].orig == orig) {
- return is->collection[i].dest;
- }
- }
-
- return -1;
-}
-
-void ipc_switching_print (struct ipc_switchings *is) {
- printf ("print!\n");
- for (size_t i = 0; i < is->size; i++)
- {
- printf ("client %d - %d\n", is->collection[i].orig, is->collection[i].dest);
- }
-}
-
-void tcp_connection (char **env, int fd, char * buf, int len)
-{
- printf ("tcp client %d is not already connected to a service\n", fd);
buf[len] = '\0';
- // for testing purposes
- size_t last_char = strlen ((const char*)buf) -1;
- if (buf[last_char] == '\n') {
- buf[last_char] = '\0';
- }
-
- printf ("read something: where to connect %s\n", buf);
- printf ("sending ok\n");
+ // XXX: for testing purposes
+ chomp (buf, len);
+ LOG_DEBUG ("SHOULD CONNECT TO %s", buf);
// TODO: tests
- if (send (fd, "OK", 2, 0) <= 0) {
- fprintf (stderr, "error: cannot send message\n");
- perror("send");
- exit (EXIT_FAILURE);
- }
-
+ T_PERROR_Q ( (send (fd, "OK", 2, 0) <= 0), "sending a message", EXIT_FAILURE);
SECURE_DECLARATION (struct ipc_connection_info, tcp_to_ipc_ci);
- enum ipc_errors ret = 0;
- T_P_Q (ipc_connection (env, &tcp_to_ipc_ci, buf), "cannot connect to the service\n", EXIT_FAILURE);
+ TIPC_F_Q (ipc_connection (env, &tcp_to_ipc_ci, buf), ("cannot connect to the service [%s]", buf), EXIT_FAILURE);
ipc_switching_add (ctx->TCP_TO_IPC, fd, tcp_to_ipc_ci.fd);
- ipc_switching_add (ctx->IPC_TO_TCP, tcp_to_ipc_ci.fd, fd);
ipc_add_fd (ctx->clients, tcp_to_ipc_ci.fd);
+
+ LOG_DEBUG ("CONNECTION TO SERVICE client %d -> %d", fd, tcp_to_ipc_ci.fd);
}
-void handle_extra_socket (struct ipc_event event, int sockfd, char **env)
+int accept_new_client (int serverfd)
{
SECURE_DECLARATION (struct sockaddr_in, client);
socklen_t addrlen = 0;
- printf ("something comes from somewhere: fd %d\n", event.origin->fd);
+ int sock_fd_client;
+ T_PERROR_Q (((sock_fd_client = accept(serverfd, (struct sockaddr *) &client, &addrlen)) == -1), "accept new client", EXIT_FAILURE);
- // NEW CLIENT
- if (event.origin->fd == sockfd) {
- int sock_fd_client;
- if((sock_fd_client = accept(sockfd, (struct sockaddr *) &client, &addrlen)) == -1) {
- perror("accept");
- close(sockfd);
- exit(EXIT_FAILURE);
- }
- printf ("after accept\n");
- // adding a client
- ipc_add_fd (ctx->clients, sock_fd_client);
- printf ("after ipc_add_fd, TCP client: %d\n", sock_fd_client);
- }
- // CLIENT IS TALKING
- else {
- SECURE_BUFFER_DECLARATION(char, buf, 4096);
+ // adding a client
+ ipc_add_fd (ctx->clients, sock_fd_client);
- ssize_t len = recv (event.origin->fd, buf, 4096, 0);
- if (len > 0) {
-
- print_hexa ("RECEIVED", (unsigned char*) buf, len);
-
- // TODO: check if the message comes from an external IPC
- int fd = ipc_switching_get (ctx->IPC_TO_TCP, event.origin->fd);
-
- if (fd >= 0) {
- printf ("SWITCH: ipc service %d sent a message for %d\n", event.origin->fd, fd);
- int sent_len = send (fd, buf, len, 0);
- if (sent_len < 0) {
- perror ("write to ipc");
- }
- else if (sent_len != len) {
- fprintf (stderr, "write NOT ENOUGH to tcp client\n");
- }
- }
- else {
- fd = ipc_switching_get (ctx->TCP_TO_IPC, event.origin->fd);
- if (fd >= 0) {
- printf ("SWITCH: client %d sent a message for %d\n", event.origin->fd, fd);
- int sent_len = send (fd, buf, len, 0);
- if (sent_len < 0) {
- perror ("write to ipc");
- }
- else if (sent_len != len) {
- fprintf (stderr, "write NOT ENOUGH to ipc\n");
- }
- }
- else {
- tcp_connection (env, event.origin->fd, buf, len);
- }
- }
- }
- else if (len == 0) {
- // disconnection
- printf ("close connection\n");
-
- int delfd = ipc_switching_del (ctx->TCP_TO_IPC, event.origin->fd);
- if (delfd >= 0) {
- close (delfd);
- ipc_del_fd (ctx->clients, delfd);
- }
-
- delfd = ipc_switching_del (ctx->IPC_TO_TCP, event.origin->fd);
- if (delfd >= 0) {
- close (delfd);
- ipc_del_fd (ctx->clients, delfd);
- }
-
- close (event.origin->fd);
- ipc_del_fd (ctx->clients, event.origin->fd);
- }
- }
+ return sock_fd_client;
}
-
void main_loop (int argc, char **argv, char **env)
{
argc = argc; // FIXME: useless
- int sockfd;
+ int serverfd;
- struct sockaddr_in my_addr;
+ SECURE_DECLARATION (struct sockaddr_in, my_addr);
socklen_t addrlen;
// socket factory
- if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
- {
- perror("socket");
- exit(EXIT_FAILURE);
- }
+ T_PERROR_R (((serverfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1), "socket", );
int yes = 1;
- if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
- perror ("setsockopt");
- }
-
+ T_PERROR_R ((setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1), "setsockopt", );
// init local addr structure and other params
my_addr.sin_family = AF_INET;
@@ -265,57 +141,51 @@ void main_loop (int argc, char **argv, char **env)
addrlen = sizeof(struct sockaddr_in);
// bind addr structure with socket
- if(bind(sockfd, (struct sockaddr *) &my_addr, addrlen) == -1)
- {
- perror("bind");
- close(sockfd);
- exit(EXIT_FAILURE);
- }
+ T_PERROR_R ((bind(serverfd, (struct sockaddr *) &my_addr, addrlen) == -1), "bind", );
// set the socket in passive mode (only used for accept())
// and set the list size for pending connection
- if(listen(sockfd, 5) == -1)
- {
- perror("listen");
- close(sockfd);
- exit(EXIT_FAILURE);
- }
+ T_PERROR_R ((listen(serverfd, 5) == -1), "listen", );
printf("Waiting for incomming connection\n");
+ SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->clients, sizeof (struct ipc_connection_infos), , EXIT_FAILURE);
+ SECURE_DECLARATION (struct ipc_event, event);
- enum ipc_errors ret = 0;
-
- ctx->clients = malloc (sizeof (struct ipc_connection_infos));
- memset(ctx->clients, 0, sizeof(struct ipc_connection_infos));
-
- struct ipc_event event;
- memset(&event, 0, sizeof (struct ipc_event));
- printf ("adding sockfd to ctx->clients\n");
- ipc_add_fd (ctx->clients, sockfd);
+ printf ("adding serverfd to ctx->clients\n");
+ ipc_add_fd (ctx->clients, serverfd);
while(1) {
- // ipc_service_poll_event provides one event at a time
+ // ipc_wait_event provides one event at a time
// warning: event->m is free'ed if not NULL
- // printf ("before wait event\n"); // TODO remove
- ret = ipc_wait_event (ctx->clients, ctx->srv, &event);
- // printf ("after wait event\n"); // TODO remove
- if (ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT) {
- PRINTERR(ret,"wait event");
-
- // the application will shut down, and close the service
- ret = ipc_server_close (ctx->srv);
- if (ret != IPC_ERROR_NONE) {
- PRINTERR(ret,"server close");
- }
- exit (EXIT_FAILURE);
- }
+ TIPC_T_P_I_R (
+ /* function to test */ ipc_wait_event_networkd (ctx->clients, ctx->srv, &event, ctx->TCP_TO_IPC)
+ , /* error condition */ ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT
+ , /* to say on error */ "wait event"
+ , /* to do on error */ LOG_ERROR ("\033[31m error happened\033[00m"); TIPC_P (ipc_server_close (ctx->srv), "server close")
+ , /* return function */ return );
switch (event.type) {
+ case IPC_EVENT_TYPE_SWITCH:
+ {
+ printf ("switch happened\n");
+ }
+ break;
+
case IPC_EVENT_TYPE_EXTRA_SOCKET:
{
- handle_extra_socket (event, sockfd, env);
+ // NEW CLIENT
+ if (event.origin->fd == serverfd) {
+ int sock_fd_client = accept_new_client (serverfd);
+ ctx->cpt++;
+ printf ("TCP connection: %d clients connected\n", ctx->cpt);
+ printf ("new TCP client has the fd %d\n", sock_fd_client);
+ }
+ // CLIENT IS TALKING
+ else {
+ tcp_connection (env, event.origin->fd);
+ }
}
break;
@@ -326,13 +196,15 @@ void main_loop (int argc, char **argv, char **env)
printf ("new client has the fd %d\n", (event.origin)->fd);
};
break;
+
case IPC_EVENT_TYPE_DISCONNECTION:
{
ctx->cpt--;
printf ("disconnection: %d clients remaining\n", ctx->cpt);
// free the ipc_client structure
- free (event.origin);
+ // if (event.origin != NULL)
+ // free (event.origin);
};
break;
case IPC_EVENT_TYPE_MESSAGE:
@@ -342,24 +214,14 @@ void main_loop (int argc, char **argv, char **env)
printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload);
}
- ret = ipc_write (event.origin, m);
-
- if (ret != IPC_ERROR_NONE) {
- handle_err( "handle_new_msg", "server_write < 0");
- PRINTERR(ret,"server write");
- }
+ TIPC_P (ipc_write (event.origin, m), "server write");
};
break;
case IPC_EVENT_TYPE_ERROR:
- {
- fprintf (stderr, "a problem happened with client %d\n"
- , (event.origin)->fd);
- };
+ fprintf (stderr, "a problem happened with client %d\n", (event.origin)->fd);
break;
default :
- {
- fprintf (stderr, "there must be a problem, event not set\n");
- };
+ fprintf (stderr, "there must be a problem, event not set\n");
}
}
@@ -373,7 +235,7 @@ void exit_program(int signal)
printf("Quitting, signal: %d\n", signal);
// free remaining clients
- for (int i = 0; i < ctx->clients->size ; i++) {
+ for (size_t i = 0; i < ctx->clients->size ; i++) {
struct ipc_connection_info *cli = ctx->clients->cinfos[i];
if (cli != NULL) {
free (cli);
@@ -382,20 +244,15 @@ void exit_program(int signal)
}
ipc_connections_free (ctx->clients);
- free (ctx->clients);
-
// the application will shut down, and close the service
- enum ipc_errors ret = ipc_server_close (ctx->srv);
- if (ret != IPC_ERROR_NONE) {
- PRINTERR(ret,"server close");
- }
- free (ctx->srv);
+ TIPC_P (ipc_server_close (ctx->srv), "server close");
+ // free, free everything!
+ free (ctx->clients);
+ free (ctx->srv);
free (ctx->TCP_TO_IPC->collection);
free (ctx->TCP_TO_IPC);
- free (ctx->IPC_TO_TCP->collection);
- free (ctx->IPC_TO_TCP);
free (ctx);
exit(EXIT_SUCCESS);
@@ -412,39 +269,18 @@ int main(int argc, char * argv[], char **env)
if(argc != 2)
{
printf("USAGE: %s port_num\n", argv[0]);
- exit(-1);
+ exit(EXIT_FAILURE);
}
printf ("pid = %d\n", getpid ());
- ctx = malloc (sizeof (struct networkd));
- memset (ctx, 0, sizeof (struct networkd));
+ SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx, sizeof (struct networkd), , EXIT_FAILURE);
+ SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->TCP_TO_IPC, sizeof(struct ipc_switchings), , EXIT_FAILURE);
+ SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->TCP_TO_IPC->collection, sizeof(struct ipc_switching), , EXIT_FAILURE);
+ SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->srv, sizeof (struct ipc_connection_info), , EXIT_FAILURE);
-
- ctx->TCP_TO_IPC = malloc(sizeof(struct ipc_switchings));
- memset (ctx->TCP_TO_IPC, 0, sizeof(struct ipc_switchings));
- ctx->TCP_TO_IPC->collection = malloc(sizeof(struct ipc_switching));
- ctx->IPC_TO_TCP = malloc(sizeof(struct ipc_switchings));
- memset (ctx->IPC_TO_TCP, 0, sizeof(struct ipc_switchings));
- ctx->IPC_TO_TCP->collection = malloc(sizeof(struct ipc_switching));
-
- ctx->srv = malloc (sizeof (struct ipc_connection_info));
- if (ctx->srv == NULL) {
- exit (EXIT_FAILURE);
- }
- memset (ctx->srv, 0, sizeof (struct ipc_connection_info));
- ctx->srv->type = '\0';
- ctx->srv->index = 0;
- ctx->srv->version = 0;
- ctx->srv->fd = 0;
- ctx->srv->spath = NULL;
-
- enum ipc_errors ret = ipc_server_init (env, ctx->srv, SERVICE_NAME);
- if (ret != IPC_ERROR_NONE) {
- PRINTERR(ret,"server init");
- return EXIT_FAILURE;
- }
- printf ("Listening on %s.\n", ctx->srv->spath);
+ TIPC_P_R (ipc_server_init (env, ctx->srv, SERVICE_NAME), "server init", EXIT_FAILURE);
+ printf ("Listening on [%s].\n", ctx->srv->spath);
printf("MAIN: server created\n" );
diff --git a/examples/test-ask-for-fd-to-networkd.c b/examples/test-ask-for-fd-to-networkd.c
new file mode 100644
index 0000000..80fd9ad
--- /dev/null
+++ b/examples/test-ask-for-fd-to-networkd.c
@@ -0,0 +1,46 @@
+#include
+#include
+#include
+
+#include "../src/ipc.h"
+
+#define DEFAULT_IPC_NETWORK "IPC_NETWORK=\"pong local:lolwat\""
+
+int main(int argc, char * argv[])
+{
+
+ (void) argc;
+ (void) argv;
+
+ enum ipc_errors ret;
+ SECURE_DECLARATION (struct ipc_connection_info, srv);
+
+ if (argc != 2) {
+ fprintf (stderr, "usage: %s service_name\n", argv[0]);
+ exit (1);
+ }
+
+ char *service_name = argv[1];
+
+ // ask for a local service "pong"
+ // inform the network service that it's now named "lolwat"
+ char *ipc_network = getenv("IPC_NETWORK");
+ if (ipc_network == NULL) {
+ ipc_network = DEFAULT_IPC_NETWORK;
+ }
+
+ ret = ipc_contact_networkd (&srv, service_name, ipc_network);
+
+ printf ("ret = %d\n", ret);
+
+ if (ret == 0 && srv.fd != 0) {
+ printf ("Success\n");
+ }
+ else {
+ printf ("Ow. :(\n");
+ }
+
+ usock_close (srv.fd);
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/test-networkd-provide-fd.c b/examples/test-networkd-provide-fd.c
new file mode 100644
index 0000000..6074d30
--- /dev/null
+++ b/examples/test-networkd-provide-fd.c
@@ -0,0 +1,41 @@
+#include
+#include
+#include
+
+#include "../src/ipc.h"
+
+
+int main(int argc, char * argv[], char *env[])
+{
+
+ (void) argc;
+ (void) argv;
+
+ enum ipc_errors ret;
+ SECURE_DECLARATION (struct ipc_connection_info, srv);
+ SECURE_DECLARATION (struct ipc_connection_info, client);
+ SECURE_DECLARATION (struct ipc_connection_info, contacted_service);
+
+
+ // service start
+ TIPC_P_RR (ipc_server_init (env, &srv, "network"), "Networkd cannot be initialized");
+
+ printf ("service initialized, waiting for a client\n");
+
+ // accept a new client
+ TIPC_P_RR (ipc_accept (&srv, &client), "cannot accept the client during handle_new_connection");
+
+ // TODO: read a message to know the requested service
+ SECURE_DECLARATION (struct ipc_message, msg);
+ ret = ipc_read (&client, &msg);
+ printf ("received message: %s\n", msg.payload);
+
+ /** TODO: contact the service */
+ printf ("WARNING: currently this program only ask for pong service %d\n", ret);
+ TIPC_P_RR (ipc_connection (env, &contacted_service, "pong"), "cannot connect to the requested service");
+
+ ipc_provide_fd (client.fd, contacted_service.fd);
+
+ TIPC_P_RR (ipc_server_close (&srv), "Networkd cannot be stopped!!");
+ return EXIT_SUCCESS;
+}
diff --git a/examples/tests-logs.c b/examples/tests-logs.c
new file mode 100644
index 0000000..3a57c04
--- /dev/null
+++ b/examples/tests-logs.c
@@ -0,0 +1,16 @@
+#include
+#include
+#include
+
+#include "../src/ipc.h"
+
+int main(void)
+{
+ SECURE_BUFFER_DECLARATION (char, buffer, BUFSIZ);
+
+ log_get_logfile_name (buffer, BUFSIZ);
+
+ printf ("log: %s\n", buffer);
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/wsserver.c b/examples/wsserver.c
new file mode 100644
index 0000000..7e9c343
--- /dev/null
+++ b/examples/wsserver.c
@@ -0,0 +1,118 @@
+#include
+#include
+#include
+#include
+#include
+
+#include "../src/ipc.h"
+#include "../src/utils.h"
+
+#define WEBSOCKETD_BULLSHIT
+
+void chomp (char *str, ssize_t len) {
+ if (str[len -1] == '\n') {
+ str[len -1] = '\0';
+ }
+ if (str[len -2] == '\n') {
+ str[len -2] = '\0';
+ }
+}
+
+struct ipc_connection_info *srv;
+
+void interactive (char *env[])
+{
+ SECURE_BUFFER_DECLARATION (char, service_name, 100);
+
+ char *sn = getenv("PATH_TRANSLATED");
+
+ if (sn != NULL) {
+ memcpy (service_name, sn, strlen(sn));
+ }
+ else {
+ fprintf (stderr, "cannot see PATH_TRANSLATED variable\n");
+ exit (EXIT_FAILURE);
+ }
+
+ // init service
+ TIPC_P_Q (ipc_connection (env, srv, service_name), "application connection", EXIT_FAILURE);
+
+ SECURE_DECLARATION (struct ipc_event, event);
+ SECURE_DECLARATION (struct ipc_connection_infos, services);
+
+ ipc_add (&services, srv);
+ ipc_add_fd (&services, 0); // add STDIN
+
+ while (1) {
+ TIPC_P_Q (ipc_wait_event (&services, NULL, &event), "wait event", EXIT_FAILURE);
+
+ switch (event.type) {
+ case IPC_EVENT_TYPE_EXTRA_SOCKET:
+ {
+ // structure not read, should read the message here
+ SECURE_BUFFER_DECLARATION (char, buf, 4096);
+ ssize_t len;
+
+ len = read (event.origin->fd, buf, 4096);
+
+ // in case we want to quit the program
+ if ( len == 0
+ || strncmp (buf, "quit", 4) == 0
+ || strncmp (buf, "exit", 4) == 0) {
+
+ TIPC_P_Q (ipc_close (srv), "application close", EXIT_FAILURE);
+
+ ipc_connections_free (&services);
+
+ exit (EXIT_SUCCESS);
+ }
+
+ // send the message read on STDIN
+ ssize_t len_sent = write (srv->fd, buf, len);
+ if (len_sent != len) {
+ fprintf (stderr, "cannot send the message %lu-byte message, sent %lu bytes"
+ , len, len_sent);
+ exit (EXIT_FAILURE);
+ }
+ }
+ break;
+ case IPC_EVENT_TYPE_MESSAGE:
+ {
+ struct ipc_message *m = event.m;
+ SECURE_BUFFER_DECLARATION (char, buf, 4096);
+ uint32_t size;
+ size = ipc_message_raw_serialize (buf, m->type, m->user_type, m->payload, m->length);
+
+ write (1, buf, size);
+#ifdef WEBSOCKETD_BULLSHIT
+ printf ("\n");
+#endif
+ fflush (stdout);
+ };
+ break;
+ ERROR_CASE (IPC_EVENT_TYPE_DISCONNECTION, "main loop", "disconnection: should not happen");
+ ERROR_CASE (IPC_EVENT_TYPE_NOT_SET , "main loop", "not set: should not happen");
+ ERROR_CASE (IPC_EVENT_TYPE_CONNECTION , "main loop", "connection: should not happen");
+ // ERROR_CASE (IPC_EVENT_TYPE_ERROR , "main loop", "error");
+ default :
+ fprintf (stderr, "event type error: should not happen, event type %d\n", event.type);
+ }
+ }
+}
+
+int main (int argc, char *argv[], char *env[])
+{
+ argc = argc; // warnings
+ argv = argv; // warnings
+
+ srv = malloc (sizeof (struct ipc_connection_info));
+ memset (srv, 0, sizeof (struct ipc_connection_info));
+
+ // index and version should be filled
+ srv->index = 0;
+ srv->version = 0;
+
+ interactive (env);
+
+ return EXIT_SUCCESS;
+}
From c783168198c48a085783b54f12a3ecd6a750889f Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Sat, 27 Jul 2019 15:48:56 +0200
Subject: [PATCH 4/5] tests (WIP)
---
tests/build.sh | 12 ++
tests/func_01_connection_establishment.c | 31 ++++
tests/func_01_connection_establishmentd.c | 56 ++++++
tests/func_02_pong.c | 147 ++++++++++++++++
tests/func_02_pongd.c | 163 ++++++++++++++++++
.../func_03_multiple-communications-client.c | 97 +++++++++++
.../func_03_multiple-communications-server.c | 84 +++++++++
tests/func_04_empty_message.c | 72 ++++++++
tests/unit_01_service-path.c | 34 ++++
tests/unit_02_usock-remove.c | 26 +++
tests/unit_03_connection-add-remove.c | 15 ++
11 files changed, 737 insertions(+)
create mode 100755 tests/build.sh
create mode 100644 tests/func_01_connection_establishment.c
create mode 100644 tests/func_01_connection_establishmentd.c
create mode 100644 tests/func_02_pong.c
create mode 100644 tests/func_02_pongd.c
create mode 100644 tests/func_03_multiple-communications-client.c
create mode 100644 tests/func_03_multiple-communications-server.c
create mode 100644 tests/func_04_empty_message.c
create mode 100644 tests/unit_01_service-path.c
create mode 100644 tests/unit_02_usock-remove.c
create mode 100644 tests/unit_03_connection-add-remove.c
diff --git a/tests/build.sh b/tests/build.sh
new file mode 100755
index 0000000..72b2e2f
--- /dev/null
+++ b/tests/build.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+nontapmsg() {
+ echo $*
+}
+
+for i in *.c
+do
+ f=`echo $i | sed "s/.c$//"`
+ nontapmsg "compiling $f"
+ gcc $f.c -Wall -Wextra -Wno-unused-parameter -g -o $f.bin -I../src -L../ -lipc
+done
diff --git a/tests/func_01_connection_establishment.c b/tests/func_01_connection_establishment.c
new file mode 100644
index 0000000..21730e6
--- /dev/null
+++ b/tests/func_01_connection_establishment.c
@@ -0,0 +1,31 @@
+#include "../src/ipc.h"
+
+#include
+#include
+#include
+
+#define SERVICE_NAME "pong"
+
+int main(int argc, char * argv[], char **env)
+{
+ enum ipc_errors ret;
+ SECURE_DECLARATION(struct ipc_connection_info,service);
+ SECURE_DECLARATION(struct ipc_event, event);
+
+ ret = ipc_connection (env, &service, SERVICE_NAME);
+ if (ret != IPC_ERROR_NONE) {
+ return EXIT_FAILURE;
+ }
+
+ // ret = ipc_wait_event (services, struct ipc_event *event);
+ // if (ret != IPC_ERROR_NONE) {
+ // return EXIT_FAILURE;
+ // }
+
+ ret = ipc_close (&service);
+ if (ret != IPC_ERROR_NONE) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/func_01_connection_establishmentd.c b/tests/func_01_connection_establishmentd.c
new file mode 100644
index 0000000..0968964
--- /dev/null
+++ b/tests/func_01_connection_establishmentd.c
@@ -0,0 +1,56 @@
+#include "../src/ipc.h"
+
+#include
+#include
+#include
+
+#define SERVICE_NAME "pong"
+
+int main(int argc, char * argv[], char **env)
+{
+ enum ipc_errors ret;
+ SECURE_DECLARATION(struct ipc_connection_info,srv);
+
+ printf ("func 01 - server init...\n");
+ ret = ipc_server_init (env, &srv, SERVICE_NAME);
+ if (ret != IPC_ERROR_NONE) {
+ return EXIT_FAILURE;
+ }
+ printf ("func 01 - server init ok\n");
+
+ SECURE_DECLARATION(struct ipc_connection_infos, clients);
+ SECURE_DECLARATION(struct ipc_event,event);
+
+ printf ("func 01 - service polling...\n");
+ // listen only for a single client
+ ret = ipc_wait_event (&clients, &srv, &event);
+
+ switch (event.type) {
+ case IPC_EVENT_TYPE_CONNECTION :
+ {
+ printf ("ok - connection establishment\n");
+ break;
+ }
+ case IPC_EVENT_TYPE_NOT_SET :
+ case IPC_EVENT_TYPE_ERROR :
+ case IPC_EVENT_TYPE_EXTRA_SOCKET :
+ case IPC_EVENT_TYPE_DISCONNECTION :
+ case IPC_EVENT_TYPE_MESSAGE :
+ default :
+ printf ("not ok - should not happen\n");
+ exit (EXIT_FAILURE);
+ break;
+ }
+
+ printf ("func 01 - closing clients...\n");
+ ipc_connections_free (&clients);
+ printf ("func 01 - closing server...\n");
+ ret = ipc_server_close(&srv);
+ if (ret != IPC_ERROR_NONE)
+ {
+ const char * error_explanation = ipc_errors_get (ret);
+ printf ("ipc_server_close: %s\n", error_explanation);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/func_02_pong.c b/tests/func_02_pong.c
new file mode 100644
index 0000000..96c5712
--- /dev/null
+++ b/tests/func_02_pong.c
@@ -0,0 +1,147 @@
+#include
+#include
+#include
+#include
+
+#include "../src/ipc.h"
+
+#define MSG "coucou"
+#define SERVICE_NAME "pong"
+
+#define PRINTERR(ret,msg) {\
+ const char * err = ipc_errors_get (ret);\
+ fprintf(stderr, "error while %s: %s\n", msg, err);\
+}
+
+void non_interactive (char *env[])
+{
+ enum ipc_errors ret;
+ struct ipc_message m;
+ memset (&m, 0, sizeof (struct ipc_message));
+ SECURE_DECLARATION(struct ipc_connection_info, srv);
+
+ // init service
+ ret = ipc_connection (env, &srv, SERVICE_NAME);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret, "application connection");
+ exit (EXIT_FAILURE);
+ }
+
+ printf ("msg to send (%ld): %.*s\n", (ssize_t) strlen(MSG) +1, (int) strlen(MSG), MSG);
+ ret = ipc_message_format_data (&m, /* type */ 'a', MSG, (ssize_t) strlen(MSG) +1);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret, "message format data");
+ exit (EXIT_FAILURE);
+ }
+
+ // printf ("msg to send in the client: ");
+ // ipc_message_print (&m);
+ ret = ipc_write (&srv, &m);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret, "application write");
+ exit (EXIT_FAILURE);
+ }
+ ipc_message_empty (&m);
+
+ ret = ipc_read (&srv, &m);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret, "application read");
+ exit (EXIT_FAILURE);
+ }
+
+ printf ("msg recv: %s\n", m.payload);
+ ipc_message_empty (&m);
+
+ ret = ipc_close (&srv);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret, "application close");
+ exit (EXIT_FAILURE);
+ }
+}
+
+void interactive (char *env[])
+{
+ enum ipc_errors ret;
+ SECURE_DECLARATION(struct ipc_connection_info, srv);
+
+ // index and version should be filled
+ srv.index = 0;
+ srv.version = 0;
+
+ // init service
+ ret = ipc_connection (env, &srv, SERVICE_NAME);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret, "application connection");
+ exit (EXIT_FAILURE);
+ }
+
+ SECURE_DECLARATION(struct ipc_event, event);
+ SECURE_DECLARATION(struct ipc_connection_infos, services);
+
+ ipc_add (&services, &srv);
+
+ while (1) {
+ printf ("msg to send: ");
+ fflush (stdout);
+ ret = ipc_wait_event (&services, NULL, &event);
+
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret, "application peek event");
+ exit (EXIT_FAILURE);
+ }
+
+ switch (event.type) {
+ case IPC_EVENT_TYPE_EXTRA_SOCKET:
+ {
+ struct ipc_message *m = event.m;
+ if ( m->length == 0 || strncmp (m->payload, "exit", 4) == 0) {
+
+ ipc_message_empty (m);
+ free (m);
+
+ ipc_connections_free (&services);
+
+ ret = ipc_close (&srv);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret, "application close");
+ exit (EXIT_FAILURE);
+ }
+
+ exit (EXIT_SUCCESS);
+ }
+
+ ret = ipc_write (&srv, m);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret, "application write");
+ exit (EXIT_FAILURE);
+ }
+ }
+ break;
+ case IPC_EVENT_TYPE_MESSAGE:
+ {
+ struct ipc_message *m = event.m;
+ printf ("msg recv: %.*s", m->length, m->payload);
+ };
+ break;
+ case IPC_EVENT_TYPE_DISCONNECTION:
+ case IPC_EVENT_TYPE_NOT_SET:
+ case IPC_EVENT_TYPE_CONNECTION:
+ case IPC_EVENT_TYPE_ERROR:
+ default :
+ fprintf (stderr, "should not happen, event type %d\n", event.type);
+ }
+ }
+}
+
+int main (int argc, char *argv[], char *env[])
+{
+ argc = argc; // warnings
+ argv = argv; // warnings
+
+ if (argc == 1)
+ non_interactive (env);
+ else
+ interactive (env);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/func_02_pongd.c b/tests/func_02_pongd.c
new file mode 100644
index 0000000..9252258
--- /dev/null
+++ b/tests/func_02_pongd.c
@@ -0,0 +1,163 @@
+#include "../src/ipc.h"
+#include
+
+#include
+#include
+#include
+
+#define PONGD_SERVICE_NAME "pong"
+
+#define PRINTERR(ret,msg) {\
+ const char * err = ipc_errors_get (ret);\
+ fprintf(stderr, "error while %s: %s\n", msg, err);\
+}
+
+int cpt = 0;
+
+struct ipc_connection_info *srv = 0;
+struct ipc_connection_infos *clients;
+
+
+void main_loop ()
+{
+ enum ipc_errors ret = 0;
+
+ clients = malloc (sizeof (struct ipc_connection_infos));
+ memset(clients, 0, sizeof(struct ipc_connection_infos));
+
+ SECURE_DECLARATION(struct ipc_event,event);
+
+ while(1) {
+ // ipc_wait_event provides one event at a time
+ // warning: event->m is free'ed if not NULL
+ ret = ipc_wait_event (clients, srv, &event);
+ if (ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT) {
+ PRINTERR(ret,"service poll event");
+
+ // the application will shut down, and close the service
+ ret = ipc_server_close (srv);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret,"server close");
+ }
+ exit (EXIT_FAILURE);
+ }
+
+ switch (event.type) {
+ case IPC_EVENT_TYPE_CONNECTION:
+ {
+ cpt++;
+ printf ("connection: %d clients connected\n", cpt);
+ printf ("new client has the fd %d\n", ((struct ipc_connection_info*) event.origin)->fd);
+ };
+ break;
+ case IPC_EVENT_TYPE_DISCONNECTION:
+ {
+ cpt--;
+ printf ("disconnection: %d clients remaining\n", cpt);
+
+ // free the ipc_connection_info structure
+ free (event.origin);
+ };
+ break;
+ case IPC_EVENT_TYPE_MESSAGE:
+ {
+ struct ipc_message *m = event.m;
+ if (m->length > 0) {
+ printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload);
+ }
+
+ ret = ipc_write (event.origin, m);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret,"server write");
+ }
+ };
+ break;
+ case IPC_EVENT_TYPE_ERROR:
+ {
+ fprintf (stderr, "a problem happened with client %d\n"
+ , ((struct ipc_connection_info*) event.origin)->fd);
+ };
+ break;
+ default :
+ {
+ fprintf (stderr, "there must be a problem, event not set\n");
+ };
+ }
+ }
+
+ // should never go there
+ exit (1);
+}
+
+
+void exit_program(int signal)
+{
+ printf("Quitting, signal: %d\n", signal);
+
+ // free remaining clients
+ for (int i = 0; i < clients->size ; i++) {
+ struct ipc_connection_info *cli = clients->cinfos[i];
+ if (cli != NULL) {
+ free (cli);
+ }
+ clients->cinfos[i] = NULL;
+ }
+
+ ipc_connections_free (clients);
+ free (clients);
+
+
+ // the application will shut down, and close the service
+ enum ipc_errors ret = ipc_server_close (srv);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret,"server close");
+ }
+ free (srv);
+
+ exit(EXIT_SUCCESS);
+}
+
+/*
+ * service ping-pong: send back everything sent by the clients
+ * stop the program on SIG{TERM,INT,ALRM,USR{1,2},HUP} signals
+ */
+
+int main(int argc, char * argv[], char **env)
+{
+ argc = argc; // warnings
+ argv = argv; // warnings
+
+ printf ("pid = %d\n", getpid ());
+
+ srv = malloc (sizeof (struct ipc_connection_info));
+ if (srv == NULL) {
+ exit (1);
+ }
+ memset (srv, 0, sizeof (struct ipc_connection_info));
+ srv->index = 0;
+ srv->version = 0;
+
+ // unlink("/tmp/ipc/pongd-0-0");
+
+ enum ipc_errors ret = ipc_server_init (env, srv, PONGD_SERVICE_NAME);
+ if (ret != IPC_ERROR_NONE) {
+ PRINTERR(ret,"server init");
+ return EXIT_FAILURE;
+ }
+ printf ("Listening on %s.\n", srv->spath);
+
+ printf("MAIN: server created\n" );
+
+ signal (SIGHUP, exit_program);
+ signal (SIGALRM, exit_program);
+ signal (SIGUSR1, exit_program);
+ signal (SIGUSR2, exit_program);
+ signal (SIGTERM, exit_program);
+ signal (SIGINT, exit_program);
+
+ // the service will loop until the end of time, or a signal
+ main_loop ();
+
+ // main_loop should not return
+ return EXIT_FAILURE;
+}
diff --git a/tests/func_03_multiple-communications-client.c b/tests/func_03_multiple-communications-client.c
new file mode 100644
index 0000000..cfbff4e
--- /dev/null
+++ b/tests/func_03_multiple-communications-client.c
@@ -0,0 +1,97 @@
+#include "../src/ipc.h"
+
+#include
+#include
+#include
+
+#define SERVICE_NAME "pong"
+#define SECURE_MALLOC(p, s, wat) p = malloc (s); if (p == NULL) { wat; }
+
+void connection (char **env, struct ipc_connection_info *ci)
+{
+ enum ipc_errors ret = ipc_connection (env, ci, SERVICE_NAME);
+ if (ret != IPC_ERROR_NONE) {
+ fprintf (stderr, "cannot connect to the server\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+void closing (struct ipc_connection_info *ci)
+{
+ enum ipc_errors ret = ipc_close (ci);
+ if (ret != IPC_ERROR_NONE) {
+ fprintf (stderr, "cannot close server\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+// test the behavior of the server when the client never read its messages
+
+void send_message (struct ipc_connection_info *ci)
+{
+ SECURE_DECLARATION (struct ipc_message, m);
+ SECURE_MALLOC (m.payload, 5, exit(EXIT_FAILURE));
+ memcpy (m.payload, "salut", 5);
+ m.type = MSG_TYPE_DATA;
+ m.user_type = 42;
+ m.length = 5;
+
+ ipc_write (ci, &m);
+
+ ipc_message_empty (&m);
+}
+
+
+void read_message (struct ipc_connection_info *ci)
+{
+#if 0
+ SECURE_DECLARATION(struct ipc_event, event);
+ SECURE_DECLARATION(struct ipc_connection_infos, clients);
+
+ ipc_add (&clients, ci);
+
+ ipc_wait_event (&clients, NULL, &event);
+
+ switch (event.type) {
+ case IPC_EVENT_TYPE_MESSAGE : {
+ printf ("received message: %*.s\n", m.length, ((struct ipc_message*) event.m)->payload);
+ }
+ break;
+ case IPC_EVENT_TYPE_CONNECTION :
+ case IPC_EVENT_TYPE_DISCONNECTION :
+ case IPC_EVENT_TYPE_NOT_SET :
+ case IPC_EVENT_TYPE_ERROR :
+ case IPC_EVENT_TYPE_EXTRA_SOCKET :
+ default :
+ printf ("not ok - should not happen\n");
+ exit (EXIT_FAILURE);
+ break;
+ }
+
+ ipc_connections_free (&clients);
+#else
+ SECURE_DECLARATION (struct ipc_message, m);
+
+ ipc_read (ci, &m);
+ printf ("received message: %*.s\n", m.length, m.payload);
+ free (m.payload);
+#endif
+}
+
+int main(int argc, char * argv[], char **env)
+{
+ SECURE_DECLARATION(struct ipc_connection_info,srv1);
+ SECURE_DECLARATION(struct ipc_connection_info,srv2);
+ SECURE_DECLARATION(struct ipc_event, event);
+
+ connection (env, &srv1);
+ connection (env, &srv2);
+ send_message (&srv1);
+ read_message (&srv1);
+ closing (&srv1);
+ send_message (&srv2);
+ read_message (&srv2);
+ closing (&srv2);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/func_03_multiple-communications-server.c b/tests/func_03_multiple-communications-server.c
new file mode 100644
index 0000000..56dabe5
--- /dev/null
+++ b/tests/func_03_multiple-communications-server.c
@@ -0,0 +1,84 @@
+#include "../src/ipc.h"
+
+#include
+#include
+#include
+#include
+
+#define SERVICE_NAME "pong"
+
+int main_loop(int argc, char * argv[], char **env)
+{
+ enum ipc_errors ret;
+ SECURE_DECLARATION (struct ipc_connection_info, srv);
+
+ printf ("func 03 - server init...\n");
+ ret = ipc_server_init (env, &srv, SERVICE_NAME);
+ if (ret != IPC_ERROR_NONE) {
+ exit(EXIT_FAILURE);
+ }
+ printf ("func 03 - server init ok\n");
+
+ SECURE_DECLARATION (struct ipc_connection_infos, clients);
+ SECURE_DECLARATION (struct ipc_event, event);
+
+ printf ("func 01 - service polling...\n");
+ // listen only for a single client
+ while (1) {
+ ret = ipc_wait_event (&clients, &srv, &event);
+
+ switch (event.type) {
+ case IPC_EVENT_TYPE_CONNECTION : {
+ printf ("connection establishment: %d \n", event.origin->fd);
+ }
+ break;
+ case IPC_EVENT_TYPE_DISCONNECTION : {
+ printf ("client %d disconnecting\n", event.origin->fd);
+ };
+ break;
+ case IPC_EVENT_TYPE_MESSAGE : {
+ printf ("received message: %s\n", ((struct ipc_message*) event.m)->payload);
+ ipc_write (event.origin, (struct ipc_message*) event.m);
+ }
+ break;
+ case IPC_EVENT_TYPE_NOT_SET :
+ case IPC_EVENT_TYPE_ERROR :
+ case IPC_EVENT_TYPE_EXTRA_SOCKET :
+ default :
+ printf ("not ok - should not happen\n");
+ exit (EXIT_FAILURE);
+ break;
+ }
+ }
+
+ printf ("func 03 - closing clients...\n");
+ ipc_connections_free (&clients);
+ printf ("func 03 - closing server...\n");
+ ret = ipc_server_close(&srv);
+ if (ret != IPC_ERROR_NONE)
+ {
+ const char * error_explanation = ipc_errors_get (ret);
+ printf ("ipc_server_close: %s\n", error_explanation);
+ }
+
+ return 0;
+}
+
+void exit_program(int signal)
+{
+ printf("Quitting, signal: %d\n", signal);
+ exit(EXIT_SUCCESS);
+}
+
+
+int main(int argc, char * argv[], char **env)
+{
+ signal (SIGHUP, exit_program);
+ signal (SIGALRM, exit_program);
+ signal (SIGUSR1, exit_program);
+ signal (SIGUSR2, exit_program);
+ signal (SIGTERM, exit_program);
+ signal (SIGINT, exit_program);
+ main_loop (argc, argv, env);
+ return EXIT_SUCCESS;
+}
diff --git a/tests/func_04_empty_message.c b/tests/func_04_empty_message.c
new file mode 100644
index 0000000..cd0d55c
--- /dev/null
+++ b/tests/func_04_empty_message.c
@@ -0,0 +1,72 @@
+#include "../src/ipc.h"
+
+#include
+#include
+#include
+
+#define SERVICE_NAME "pong"
+#define SECURE_MALLOC(p, s, wat) p = malloc (s); if (p == NULL) { wat; }
+
+void connection (char **env, struct ipc_connection_info *ci)
+{
+ enum ipc_errors ret = ipc_connection (env, ci, SERVICE_NAME);
+ if (ret != IPC_ERROR_NONE) {
+ fprintf (stderr, "cannot connect to the server\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+void closing (struct ipc_connection_info *ci)
+{
+ enum ipc_errors ret = ipc_close (ci);
+ if (ret != IPC_ERROR_NONE) {
+ fprintf (stderr, "cannot close server\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+// test the behavior of the server when the client never read its messages
+
+void send_message (struct ipc_connection_info *ci)
+{
+ SECURE_DECLARATION (struct ipc_message, m);
+ SECURE_MALLOC (m.payload, 1, exit(EXIT_FAILURE));
+ memcpy (m.payload, "", 0);
+ m.type = MSG_TYPE_DATA;
+ m.user_type = 42;
+ m.length = 0;
+
+ ipc_write (ci, &m);
+
+ ipc_message_empty (&m);
+}
+
+
+void read_message (struct ipc_connection_info *ci)
+{
+ SECURE_DECLARATION (struct ipc_message, m);
+
+ ipc_read (ci, &m);
+ if (m.length > 0) {
+ printf ("received message: %*.s\n", m.length, m.payload);
+ }
+ else {
+ printf ("received empty message as intended : %d bytes\n", m.length);
+ if (m.payload == NULL) {
+ printf ("message payload is NULL\n");
+ }
+ }
+ free (m.payload);
+}
+
+int main(int argc, char * argv[], char **env)
+{
+ SECURE_DECLARATION(struct ipc_connection_info,srv1);
+
+ connection (env, &srv1);
+ send_message (&srv1);
+ read_message (&srv1);
+ closing (&srv1);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/unit_01_service-path.c b/tests/unit_01_service-path.c
new file mode 100644
index 0000000..cf2d531
--- /dev/null
+++ b/tests/unit_01_service-path.c
@@ -0,0 +1,34 @@
+#include "../src/ipc.h"
+
+#include
+#include
+#include
+
+#define SERVICE_NAME "example"
+#define VERSION 0
+#define INDEX 0
+
+int main(int argc, char * argv[])
+{
+ char path[PATH_MAX];
+ char * sname = SERVICE_NAME;
+ int32_t index = INDEX;
+ int32_t version = VERSION;
+
+ if (argc == 4) {
+ sname = argv[1];
+ index = atoi(argv[2]);
+ version = atoi(argv[3]);
+ }
+ else if (argc != 1) {
+ fprintf (stderr, "usage: %s [service-name index version]\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ service_path (path, sname, index, version);
+
+ // printf ("servicename: %s, index: %d, version: %d\n", sname, index, version);
+ printf ("%s\n", path);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/unit_02_usock-remove.c b/tests/unit_02_usock-remove.c
new file mode 100644
index 0000000..168d91f
--- /dev/null
+++ b/tests/unit_02_usock-remove.c
@@ -0,0 +1,26 @@
+#include "../src/ipc.h"
+#include "../src/usocket.h"
+
+#include
+#include
+#include
+
+#define FILE_TO_REMOVE "/tmp/FILE_TO_REMOVE"
+
+int main(int argc, char * argv[])
+{
+ char * ftr = FILE_TO_REMOVE;
+
+ if (argc == 2) {
+ ftr = argv[1];
+ }
+ else if (argc > 2) {
+ fprintf (stderr, "usage: %s [file-to-remove]\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ enum ipc_errors ret = usock_remove (ftr);
+ if (ret == IPC_ERROR_NONE)
+ return 0;
+ return 1;
+}
diff --git a/tests/unit_03_connection-add-remove.c b/tests/unit_03_connection-add-remove.c
new file mode 100644
index 0000000..17968aa
--- /dev/null
+++ b/tests/unit_03_connection-add-remove.c
@@ -0,0 +1,15 @@
+#include "../src/ipc.h"
+
+#include
+#include
+#include
+
+/***
+ * TODO
+ */
+
+// int main(int argc, char * argv[])
+int main(void)
+{
+ return EXIT_SUCCESS;
+}
From aa93e8a88c0d841ef480bc6894caafc521cda4c7 Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Sat, 27 Jul 2019 15:53:19 +0200
Subject: [PATCH 5/5] IPC version => 2
---
src/ipc.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ipc.h b/src/ipc.h
index 8ad07bb..6ca0701 100644
--- a/src/ipc.h
+++ b/src/ipc.h
@@ -18,7 +18,7 @@
#define IPC_HEADER_SIZE 6
#define IPC_MAX_MESSAGE_SIZE 8000000-IPC_HEADER_SIZE
-#define IPC_VERSION 1
+#define IPC_VERSION 2
#if ! defined(IPC_WITHOUT_ERRORS) && ! defined(IPC_WITH_ERRORS)
#define IPC_WITH_ERRORS 2