libipc version 0.2
parent
b9054b557e
commit
b528040d11
53
Makefile
53
Makefile
|
@ -11,7 +11,7 @@ MANDIR := $(SHAREDIR)/man
|
|||
CC := cc
|
||||
AR := ar
|
||||
RANLIB := ranlib
|
||||
CFLAGS := -g
|
||||
CFLAGS := -Wall -Wextra -g
|
||||
LDFLAGS :=
|
||||
|
||||
Q := @
|
||||
|
@ -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'
|
||||
|
@ -105,7 +105,7 @@ libipc.a.uninstall:
|
|||
|
||||
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:
|
||||
|
||||
|
@ -117,7 +117,7 @@ src/communication.o.uninstall:
|
|||
|
||||
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:
|
||||
|
||||
|
@ -129,7 +129,7 @@ src/error.o.uninstall:
|
|||
|
||||
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:
|
||||
|
||||
|
@ -141,7 +141,7 @@ src/logger.o.uninstall:
|
|||
|
||||
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/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 \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
#include "ipc.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h> // error numbers
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ipc.h"
|
||||
#include "utils.h"
|
||||
|
||||
// FOR THE PURPOSE OF SOME EXPERIMENT
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -29,12 +29,13 @@ void service_path (char *path, const char *sname, int32_t index, int32_t version
|
|||
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,25 +49,26 @@ 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;
|
||||
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) {
|
||||
|
@ -75,54 +77,93 @@ enum ipc_errors ipc_server_init (char **env, struct ipc_connection_info *srv, co
|
|||
}
|
||||
|
||||
size_t s = strlen (buf);
|
||||
srv->spath = malloc (s+1);
|
||||
if (srv->spath == NULL) {
|
||||
return IPC_ERROR_SERVER_INIT__MALLOC;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
enum ipc_errors ret = usock_init (&srv->fd, srv->spath);
|
||||
if (ret != IPC_ERROR_NONE) {
|
||||
handle_err ("ipc_server_init", "usock_init");
|
||||
return ret;
|
||||
}
|
||||
TIPC_F_RR (usock_init (&srv->fd, srv->spath), ("cannot init server %s", srv->spath) );
|
||||
|
||||
return IPC_ERROR_NONE;
|
||||
}
|
||||
|
||||
enum ipc_errors ipc_connection (char **env, struct ipc_connection_info *srv, const char *sname)
|
||||
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)
|
||||
{
|
||||
// TODO: loop over environment variables
|
||||
// any IPC_NETWORK_* should be shared with the network service
|
||||
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;
|
||||
}
|
||||
|
||||
// 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/"
|
||||
env = env;
|
||||
if (env == NULL)
|
||||
return IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM;
|
||||
// ex: IPC_NETWORK="audio tor://some.example.com/audio ;pong tls://pong.example.com/pong"
|
||||
|
||||
assert (srv != NULL);
|
||||
assert (sname != NULL);
|
||||
// printf ("IPC_NETWORK: %s\n", networkvar);
|
||||
|
||||
if (srv == NULL) {
|
||||
return IPC_ERROR_CONNECTION__NO_SERVER;
|
||||
}
|
||||
|
||||
if (sname == NULL) {
|
||||
return IPC_ERROR_CONNECTION__NO_SERVICE_NAME;
|
||||
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
|
||||
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, "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);
|
||||
}
|
||||
|
||||
enum ipc_errors ret = usock_connect (&srv->fd, buf);
|
||||
if (ret != IPC_ERROR_NONE) {
|
||||
handle_err ("ipc_connection", "usock_connect ret");
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum ipc_errors ipc_connection (char **env, struct ipc_connection_info *srv, const char *sname)
|
||||
{
|
||||
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);
|
||||
|
||||
TIPC_P (ipc_contact_networkd (srv, sname), "error during networkd connection");
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
return IPC_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
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;
|
||||
}
|
||||
T_R ((srv == NULL), IPC_ERROR_ACCEPT__NO_SERVICE_PARAM);
|
||||
T_R ((p == NULL), IPC_ERROR_ACCEPT__NO_CLIENT_PARAM);
|
||||
|
||||
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)
|
||||
{
|
||||
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));
|
||||
|
||||
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;
|
||||
}
|
||||
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");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (event == NULL) {
|
||||
return IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
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);
|
||||
|
||||
int32_t i, j;
|
||||
size_t i, j;
|
||||
/* master file descriptor list */
|
||||
fd_set master;
|
||||
fd_set readf;
|
||||
|
@ -254,89 +419,16 @@ enum ipc_errors ipc_wait_event (struct ipc_connection_infos *cinfos
|
|||
}
|
||||
|
||||
readf = master;
|
||||
if(select(fdmax+1, &readf, NULL, NULL, NULL) == -1) {
|
||||
perror("select");
|
||||
return IPC_ERROR_WAIT_EVENT__SELECT;
|
||||
}
|
||||
T_PERROR_R ((select(fdmax+1, &readf, NULL, NULL, NULL) == -1), "select", IPC_ERROR_WAIT_EVENT__SELECT);
|
||||
|
||||
for (i = 0; i <= fdmax; i++) {
|
||||
for (i = 0; i <= (size_t) 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;
|
||||
if (cinfo != NULL && i == (size_t) listener) {
|
||||
return handle_connection (event, cinfos, cinfo);
|
||||
} else {
|
||||
for(j = 0; j < cinfos->size; j++) {
|
||||
if(i == cinfos->cinfos[j]->fd ) {
|
||||
|
||||
struct ipc_connection_info *pc = cinfos->cinfos[j];
|
||||
|
||||
// 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;
|
||||
if(i == (size_t) cinfos->cinfos[j]->fd ) {
|
||||
return handle_message (event, cinfos, cinfos->cinfos[j], switchdb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -346,33 +438,29 @@ enum ipc_errors ipc_wait_event (struct ipc_connection_infos *cinfos
|
|||
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));
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
if (cinfos->cinfos == NULL) {
|
||||
return IPC_ERROR_ADD__EMPTY_LIST;
|
||||
}
|
||||
T_R ((cinfos->cinfos == NULL), IPC_ERROR_ADD__EMPTY_LIST);
|
||||
|
||||
cinfos->cinfos[cinfos->size - 1] = p;
|
||||
return IPC_ERROR_NONE;
|
||||
|
@ -380,22 +468,11 @@ 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
|
||||
|
@ -419,6 +496,19 @@ 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) {
|
||||
|
@ -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));
|
||||
struct ipc_connection_info * copy = NULL;
|
||||
|
||||
if (copy == NULL)
|
||||
return NULL;
|
||||
|
||||
memset (copy, 0, sizeof (struct ipc_connection_info));
|
||||
SECURE_BUFFER_HEAP_ALLOCATION_R (copy, sizeof(struct ipc_connection_info), , NULL);
|
||||
memcpy (copy, p, sizeof (struct ipc_connection_info));
|
||||
|
||||
return copy;
|
||||
|
@ -456,9 +542,7 @@ 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)
|
||||
{
|
||||
if (cinfo == NULL) {
|
||||
return IPC_ERROR_CONNECTION_GEN__NO_CINFO;
|
||||
}
|
||||
T_R ((cinfo == NULL), IPC_ERROR_CONNECTION_GEN__NO_CINFO);
|
||||
|
||||
cinfo->type = type;
|
||||
cinfo->version = version;
|
||||
|
@ -471,19 +555,12 @@ enum ipc_errors ipc_connection_gen (struct ipc_connection_info *cinfo
|
|||
// 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;
|
||||
|
||||
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);
|
||||
|
||||
return ipc_add (cinfos, cinfo);
|
||||
|
@ -492,16 +569,10 @@ enum ipc_errors ipc_add_fd (struct ipc_connection_infos *cinfos, int fd)
|
|||
// 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]);
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
145
src/error.c
145
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_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"
|
||||
, { 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" }
|
||||
|
||||
|
||||
/* 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)
|
||||
|
|
400
src/ipc.h
400
src/ipc.h
|
@ -9,133 +9,206 @@
|
|||
#include <errno.h> // error numbers
|
||||
#include <time.h>
|
||||
|
||||
/***
|
||||
* 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_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);
|
||||
|
@ -245,38 +331,76 @@ enum ipc_errors ipc_connection_gen (struct ipc_connection_info *cinfo
|
|||
|
||||
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
|
||||
|
|
78
src/logger.c
78
src/logger.c
|
@ -3,18 +3,86 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#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, ...) {
|
||||
|
|
203
src/message.c
203
src/message.c
|
@ -9,70 +9,55 @@
|
|||
#include "message.h"
|
||||
#include "usocket.h"
|
||||
|
||||
#include <assert.h>
|
||||
// #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);
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
234
src/usocket.c
234
src/usocket.c
|
@ -9,59 +9,45 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
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_NONE;
|
||||
}
|
||||
|
||||
return IPC_ERROR_USOCK_REMOVE__NO_FILE;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
36
src/utils.c
36
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 ++;
|
||||
}
|
||||
printf("\n");
|
||||
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]);
|
||||
}
|
||||
|
||||
|
||||
void mprint_hexa (char *prefix, uint8_t *buf, size_t length)
|
||||
{
|
||||
print_hexa (prefix, buf, length);
|
||||
if ((i % 16)) {
|
||||
LOG_DEBUG ("%s", buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,5 @@
|
|||
#include <stdint.h>
|
||||
|
||||
void print_hexa (const char *prefix, uint8_t *payload, size_t size);
|
||||
void mprint_hexa (char *prefix, uint8_t *buf, size_t length);
|
||||
|
||||
#endif
|
||||
|
|
Reference in New Issue