Compare commits
49 Commits
Author | SHA1 | Date |
---|---|---|
Karchnu | 282cc59c18 | |
Karchnu | 045b1433f5 | |
Karchnu | 2813bd2695 | |
Karchnu | 02c25c150d | |
Karchnu | ff21ff42cb | |
Karchnu | c897edf9e7 | |
Karchnu | 58aab88dbf | |
Karchnu | 553a550d97 | |
Karchnu | 0a8680a7e8 | |
Karchnu | 8ccefcc40f | |
Karchnu | 74fea778f7 | |
Karchnu | 12427217c6 | |
Karchnu | 90a51a7ed7 | |
Karchnu | 98a1389376 | |
Karchnu | ff9d6ed2b8 | |
Karchnu | 47408ef653 | |
Karchnu | 4c45fb7d12 | |
Karchnu | 8439cc0f18 | |
Karchnu | f1790cf314 | |
Karchnu | 6243b818f1 | |
Karchnu | bef3b28656 | |
Karchnu | 9a83993795 | |
Karchnu | e8cd339622 | |
Karchnu | df373aea6a | |
Karchnu | fe87f31c34 | |
Karchnu | e98b544539 | |
Karchnu | 1377e6fd28 | |
Karchnu | 36cdda36e0 | |
Karchnu | fbb7394f31 | |
Karchnu | f89ab91917 | |
Karchnu | 3b1aaf36c2 | |
Karchnu | 0f46858e78 | |
Karchnu | b6f32819e5 | |
Karchnu | 2bba5cb232 | |
Karchnu | 71db43802e | |
Karchnu | a5877101eb | |
Karchnu | f4ffd7386f | |
Karchnu | 292cca45e0 | |
Karchnu | a6ca358847 | |
Karchnu | 2a8e9a3707 | |
Karchnu | 9cdf868755 | |
Karchnu | 9429be80b3 | |
Karchnu | 0cd6f5bebd | |
Karchnu | 89d8881a40 | |
Karchnu | 1dc5b4bcbe | |
Karchnu | 44992e940c | |
Karchnu | 05d483a712 | |
Karchnu | 91793c45cc | |
Karchnu | 85b54b0db6 |
44
Makefile
44
Makefile
|
@ -45,9 +45,9 @@ man/libipc.7.uninstall:
|
||||||
@echo '[01;37m RM > [01;37m$(MANDIR)/man7/libipc.7[00m'
|
@echo '[01;37m RM > [01;37m$(MANDIR)/man7/libipc.7[00m'
|
||||||
$(Q)rm -f '$(DESTDIR)$(MANDIR)/man7/libipc.7'
|
$(Q)rm -f '$(DESTDIR)$(MANDIR)/man7/libipc.7'
|
||||||
|
|
||||||
libipc.so: src/communication.o src/error.o src/fs.o src/message.o src/network.o src/print.o src/usocket.o src/utils.o src/fs.h src/ipc.h src/message.h src/usocket.h src/utils.h
|
libipc.so: src/communication.o src/context.o src/error.o src/fs.o src/message.o src/network.o src/print.o src/service_path.o src/usocket.o src/utils.o src/fs.h src/ipc.h src/message.h src/usocket.h src/utils.h
|
||||||
@echo '[01;32m LD > [01;37mlibipc.so[00m'
|
@echo '[01;32m LD > [01;37mlibipc.so[00m'
|
||||||
$(Q)$(CC) -o libipc.so -shared $(LDFLAGS) src/communication.o src/error.o src/fs.o src/message.o src/network.o src/print.o src/usocket.o src/utils.o
|
$(Q)$(CC) -o libipc.so -shared $(LDFLAGS) src/communication.o src/context.o src/error.o src/fs.o src/message.o src/network.o src/print.o src/service_path.o src/usocket.o src/utils.o
|
||||||
|
|
||||||
libipc.so.install: libipc.so
|
libipc.so.install: libipc.so
|
||||||
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.so.0.6.0[00m'
|
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.so.0.6.0[00m'
|
||||||
|
@ -74,9 +74,9 @@ libipc.so.uninstall:
|
||||||
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so[00m'
|
@echo '[01;37m RM > [01;37m$(LIBDIR)/libipc.so[00m'
|
||||||
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so'
|
$(Q)rm -f '$(DESTDIR)$(LIBDIR)/libipc.so'
|
||||||
|
|
||||||
libipc.a: src/communication.o src/error.o src/fs.o src/message.o src/network.o src/print.o src/usocket.o src/utils.o src/fs.h src/ipc.h src/message.h src/usocket.h src/utils.h
|
libipc.a: src/communication.o src/context.o src/error.o src/fs.o src/message.o src/network.o src/print.o src/service_path.o src/usocket.o src/utils.o src/fs.h src/ipc.h src/message.h src/usocket.h src/utils.h
|
||||||
@echo '[01;32m LD > [01;37mlibipc.a[00m'
|
@echo '[01;32m LD > [01;37mlibipc.a[00m'
|
||||||
$(Q)$(AR) rc 'libipc.a' src/communication.o src/error.o src/fs.o src/message.o src/network.o src/print.o src/usocket.o src/utils.o
|
$(Q)$(AR) rc 'libipc.a' src/communication.o src/context.o src/error.o src/fs.o src/message.o src/network.o src/print.o src/service_path.o src/usocket.o src/utils.o
|
||||||
|
|
||||||
libipc.a.install: libipc.a
|
libipc.a.install: libipc.a
|
||||||
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.a[00m'
|
@echo '[01;31m IN > [01;37m$(LIBDIR)/libipc.a[00m'
|
||||||
|
@ -103,6 +103,18 @@ src/communication.o.clean:
|
||||||
|
|
||||||
src/communication.o.uninstall:
|
src/communication.o.uninstall:
|
||||||
|
|
||||||
|
src/context.o: src/context.c src/ipc.h
|
||||||
|
@echo '[01;34m CC > [01;37msrc/context.o[00m'
|
||||||
|
$(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/context.c -fPIC -std=c11 -o src/context.o
|
||||||
|
|
||||||
|
src/context.o.install:
|
||||||
|
|
||||||
|
src/context.o.clean:
|
||||||
|
@echo '[01;37m RM > [01;37msrc/context.o[00m'
|
||||||
|
$(Q)rm -f src/context.o
|
||||||
|
|
||||||
|
src/context.o.uninstall:
|
||||||
|
|
||||||
src/error.o: src/error.c src/ipc.h
|
src/error.o: src/error.c src/ipc.h
|
||||||
@echo '[01;34m CC > [01;37msrc/error.o[00m'
|
@echo '[01;34m CC > [01;37msrc/error.o[00m'
|
||||||
$(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/error.c -fPIC -std=c11 -o src/error.o
|
$(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/error.c -fPIC -std=c11 -o src/error.o
|
||||||
|
@ -163,6 +175,18 @@ src/print.o.clean:
|
||||||
|
|
||||||
src/print.o.uninstall:
|
src/print.o.uninstall:
|
||||||
|
|
||||||
|
src/service_path.o: src/service_path.c src/ipc.h
|
||||||
|
@echo '[01;34m CC > [01;37msrc/service_path.o[00m'
|
||||||
|
$(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/service_path.c -fPIC -std=c11 -o src/service_path.o
|
||||||
|
|
||||||
|
src/service_path.o.install:
|
||||||
|
|
||||||
|
src/service_path.o.clean:
|
||||||
|
@echo '[01;37m RM > [01;37msrc/service_path.o[00m'
|
||||||
|
$(Q)rm -f src/service_path.o
|
||||||
|
|
||||||
|
src/service_path.o.uninstall:
|
||||||
|
|
||||||
src/usocket.o: src/usocket.c src/usocket.h src/utils.h src/fs.h
|
src/usocket.o: src/usocket.c src/usocket.h src/utils.h src/fs.h
|
||||||
@echo '[01;34m CC > [01;37msrc/usocket.o[00m'
|
@echo '[01;34m CC > [01;37msrc/usocket.o[00m'
|
||||||
$(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/usocket.c -fPIC -std=c11 -o src/usocket.o
|
$(Q)$(CC) $(CFLAGS) -fPIC -std=c11 -c src/usocket.c -fPIC -std=c11 -o src/usocket.o
|
||||||
|
@ -209,13 +233,13 @@ $(DESTDIR)$(INCLUDEDIR):
|
||||||
$(DESTDIR)$(MANDIR):
|
$(DESTDIR)$(MANDIR):
|
||||||
@echo '[01;35m DIR > [01;37m$(MANDIR)[00m'
|
@echo '[01;35m DIR > [01;37m$(MANDIR)[00m'
|
||||||
$(Q)mkdir -p $(DESTDIR)$(MANDIR)
|
$(Q)mkdir -p $(DESTDIR)$(MANDIR)
|
||||||
install: libipc.install man/libipc.7.install libipc.so.install libipc.a.install src/communication.o.install src/error.o.install src/fs.o.install src/message.o.install src/network.o.install src/print.o.install src/usocket.o.install src/utils.o.install src/communication.o.install src/error.o.install src/fs.o.install src/message.o.install src/network.o.install src/print.o.install src/usocket.o.install src/utils.o.install
|
install: libipc.install man/libipc.7.install libipc.so.install libipc.a.install src/communication.o.install src/context.o.install src/error.o.install src/fs.o.install src/message.o.install src/network.o.install src/print.o.install src/service_path.o.install src/usocket.o.install src/utils.o.install src/communication.o.install src/context.o.install src/error.o.install src/fs.o.install src/message.o.install src/network.o.install src/print.o.install src/service_path.o.install src/usocket.o.install src/utils.o.install
|
||||||
@:
|
@:
|
||||||
|
|
||||||
uninstall: libipc.uninstall man/libipc.7.uninstall libipc.so.uninstall libipc.a.uninstall src/communication.o.uninstall src/error.o.uninstall src/fs.o.uninstall src/message.o.uninstall src/network.o.uninstall src/print.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall src/communication.o.uninstall src/error.o.uninstall src/fs.o.uninstall src/message.o.uninstall src/network.o.uninstall src/print.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall
|
uninstall: libipc.uninstall man/libipc.7.uninstall libipc.so.uninstall libipc.a.uninstall src/communication.o.uninstall src/context.o.uninstall src/error.o.uninstall src/fs.o.uninstall src/message.o.uninstall src/network.o.uninstall src/print.o.uninstall src/service_path.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall src/communication.o.uninstall src/context.o.uninstall src/error.o.uninstall src/fs.o.uninstall src/message.o.uninstall src/network.o.uninstall src/print.o.uninstall src/service_path.o.uninstall src/usocket.o.uninstall src/utils.o.uninstall
|
||||||
@:
|
@:
|
||||||
|
|
||||||
clean: libipc.clean man/libipc.7.clean libipc.so.clean libipc.a.clean src/communication.o.clean src/error.o.clean src/fs.o.clean src/message.o.clean src/network.o.clean src/print.o.clean src/usocket.o.clean src/utils.o.clean src/communication.o.clean src/error.o.clean src/fs.o.clean src/message.o.clean src/network.o.clean src/print.o.clean src/usocket.o.clean src/utils.o.clean
|
clean: libipc.clean man/libipc.7.clean libipc.so.clean libipc.a.clean src/communication.o.clean src/context.o.clean src/error.o.clean src/fs.o.clean src/message.o.clean src/network.o.clean src/print.o.clean src/service_path.o.clean src/usocket.o.clean src/utils.o.clean src/communication.o.clean src/context.o.clean src/error.o.clean src/fs.o.clean src/message.o.clean src/network.o.clean src/print.o.clean src/service_path.o.clean src/usocket.o.clean src/utils.o.clean
|
||||||
distclean: clean
|
distclean: clean
|
||||||
dist: dist-gz dist-xz dist-bz2
|
dist: dist-gz dist-xz dist-bz2
|
||||||
$(Q)rm -- $(PACKAGE)-$(VERSION)
|
$(Q)rm -- $(PACKAGE)-$(VERSION)
|
||||||
|
@ -235,11 +259,13 @@ $(PACKAGE)-$(VERSION).tar.gz: distdir
|
||||||
$(PACKAGE)-$(VERSION)/Makefile \
|
$(PACKAGE)-$(VERSION)/Makefile \
|
||||||
$(PACKAGE)-$(VERSION)/project.zsh \
|
$(PACKAGE)-$(VERSION)/project.zsh \
|
||||||
$(PACKAGE)-$(VERSION)/src/communication.c \
|
$(PACKAGE)-$(VERSION)/src/communication.c \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/context.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/error.c \
|
$(PACKAGE)-$(VERSION)/src/error.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/fs.c \
|
$(PACKAGE)-$(VERSION)/src/fs.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/message.c \
|
$(PACKAGE)-$(VERSION)/src/message.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/network.c \
|
$(PACKAGE)-$(VERSION)/src/network.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/print.c \
|
$(PACKAGE)-$(VERSION)/src/print.c \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/service_path.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/usocket.c \
|
$(PACKAGE)-$(VERSION)/src/usocket.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/utils.c \
|
$(PACKAGE)-$(VERSION)/src/utils.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/ipc.h \
|
$(PACKAGE)-$(VERSION)/src/ipc.h \
|
||||||
|
@ -259,11 +285,13 @@ $(PACKAGE)-$(VERSION).tar.xz: distdir
|
||||||
$(PACKAGE)-$(VERSION)/Makefile \
|
$(PACKAGE)-$(VERSION)/Makefile \
|
||||||
$(PACKAGE)-$(VERSION)/project.zsh \
|
$(PACKAGE)-$(VERSION)/project.zsh \
|
||||||
$(PACKAGE)-$(VERSION)/src/communication.c \
|
$(PACKAGE)-$(VERSION)/src/communication.c \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/context.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/error.c \
|
$(PACKAGE)-$(VERSION)/src/error.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/fs.c \
|
$(PACKAGE)-$(VERSION)/src/fs.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/message.c \
|
$(PACKAGE)-$(VERSION)/src/message.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/network.c \
|
$(PACKAGE)-$(VERSION)/src/network.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/print.c \
|
$(PACKAGE)-$(VERSION)/src/print.c \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/service_path.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/usocket.c \
|
$(PACKAGE)-$(VERSION)/src/usocket.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/utils.c \
|
$(PACKAGE)-$(VERSION)/src/utils.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/ipc.h \
|
$(PACKAGE)-$(VERSION)/src/ipc.h \
|
||||||
|
@ -283,11 +311,13 @@ $(PACKAGE)-$(VERSION).tar.bz2: distdir
|
||||||
$(PACKAGE)-$(VERSION)/Makefile \
|
$(PACKAGE)-$(VERSION)/Makefile \
|
||||||
$(PACKAGE)-$(VERSION)/project.zsh \
|
$(PACKAGE)-$(VERSION)/project.zsh \
|
||||||
$(PACKAGE)-$(VERSION)/src/communication.c \
|
$(PACKAGE)-$(VERSION)/src/communication.c \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/context.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/error.c \
|
$(PACKAGE)-$(VERSION)/src/error.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/fs.c \
|
$(PACKAGE)-$(VERSION)/src/fs.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/message.c \
|
$(PACKAGE)-$(VERSION)/src/message.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/network.c \
|
$(PACKAGE)-$(VERSION)/src/network.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/print.c \
|
$(PACKAGE)-$(VERSION)/src/print.c \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/service_path.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/usocket.c \
|
$(PACKAGE)-$(VERSION)/src/usocket.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/utils.c \
|
$(PACKAGE)-$(VERSION)/src/utils.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/ipc.h \
|
$(PACKAGE)-$(VERSION)/src/ipc.h \
|
||||||
|
|
29
README.md
29
README.md
|
@ -16,3 +16,32 @@ Logs are in one of the following directories: `$XDG_DATA_HOME/ipc/` or `$HOME/.l
|
||||||
The log file can be indicated with the `IPC_LOGFILE` environment variable, too.
|
The log file can be indicated with the `IPC_LOGFILE` environment variable, too.
|
||||||
|
|
||||||
To remove logs: `make LDFLAGS=-DIPC_WITHOUT_ERRORS`
|
To remove logs: `make LDFLAGS=-DIPC_WITHOUT_ERRORS`
|
||||||
|
|
||||||
|
# Since 0.7
|
||||||
|
|
||||||
|
- `libipc` have callbacks to use along with switching capabilities, making easier to implement proxies for different communication protocols
|
||||||
|
|
||||||
|
# Planning for 0.8
|
||||||
|
|
||||||
|
For performance improvements within `libipc`:
|
||||||
|
|
||||||
|
- `libipc` shouldn't use realloc for each event (new client, new message, etc.) but by batch of a few thousand elements
|
||||||
|
- `libipc` should use better internal structures, unrequiring the use of loops (over the whole list of messages or connections) for each action
|
||||||
|
|
||||||
|
# Planning for 0.9
|
||||||
|
|
||||||
|
- `libipc` should use `libevent` for performance improvments
|
||||||
|
- `libipc` should be thread-safe
|
||||||
|
|
||||||
|
# Planning for 1.0
|
||||||
|
|
||||||
|
- `libipc` *may* be written in Zig
|
||||||
|
- `libipc` should have usable bindings in several languages
|
||||||
|
|
||||||
|
|
||||||
|
# Implementation design
|
||||||
|
|
||||||
|
## Memory management
|
||||||
|
|
||||||
|
1. Prefer stack over mallocs.
|
||||||
|
2. Basic functions (such as *usock_*) should not handle memory allocation.
|
||||||
|
|
|
@ -23,14 +23,14 @@ void chomp (char *str, ssize_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_connection_info *srv;
|
struct ipc_ctx *ctx = NULL;
|
||||||
|
|
||||||
void non_interactive (int verbosity, size_t nb_msg, char *msg_str, char *env[])
|
void non_interactive (int verbosity, size_t nb_msg, char *msg_str)
|
||||||
{
|
{
|
||||||
SECURE_DECLARATION (struct ipc_message, m);
|
SECURE_DECLARATION (struct ipc_message, m);
|
||||||
|
|
||||||
// init service
|
// init service
|
||||||
TEST_IPC_QUIT_ON_ERROR (ipc_connection (env, srv, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_QUIT_ON_ERROR (ipc_connection (ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
if (verbosity > 1) {
|
if (verbosity > 1) {
|
||||||
printf ("msg to send (%ld): %.*s\n", (ssize_t) strlen (MSG) + 1, (int)strlen (MSG), MSG);
|
printf ("msg to send (%ld): %.*s\n", (ssize_t) strlen (MSG) + 1, (int)strlen (MSG), MSG);
|
||||||
|
@ -38,9 +38,9 @@ void non_interactive (int verbosity, size_t nb_msg, char *msg_str, char *env[])
|
||||||
|
|
||||||
for (size_t i = 0 ; i < nb_msg ; i++) {
|
for (size_t i = 0 ; i < nb_msg ; i++) {
|
||||||
TEST_IPC_QUIT_ON_ERROR (ipc_message_format_data (&m, 42, msg_str, (ssize_t) strlen (msg_str) + 1), EXIT_FAILURE);
|
TEST_IPC_QUIT_ON_ERROR (ipc_message_format_data (&m, 42, msg_str, (ssize_t) strlen (msg_str) + 1), EXIT_FAILURE);
|
||||||
TEST_IPC_QUIT_ON_ERROR (ipc_write (srv, &m), EXIT_FAILURE);
|
TEST_IPC_QUIT_ON_ERROR (ipc_write_fd (ctx->pollfd[0].fd, &m), EXIT_FAILURE);
|
||||||
ipc_message_empty (&m);
|
ipc_message_empty (&m);
|
||||||
TEST_IPC_QUIT_ON_ERROR (ipc_read (srv, &m), EXIT_FAILURE);
|
TEST_IPC_QUIT_ON_ERROR (ipc_read (ctx, 0 /* read from the only valid index */, &m), EXIT_FAILURE);
|
||||||
|
|
||||||
if (verbosity > 1) {
|
if (verbosity > 1) {
|
||||||
printf ("msg recv (type: %u): %s\n", m.user_type, m.payload);
|
printf ("msg recv (type: %u): %s\n", m.user_type, m.payload);
|
||||||
|
@ -48,30 +48,28 @@ void non_interactive (int verbosity, size_t nb_msg, char *msg_str, char *env[])
|
||||||
ipc_message_empty (&m);
|
ipc_message_empty (&m);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_IPC_QUIT_ON_ERROR (ipc_close (srv), EXIT_FAILURE);
|
TEST_IPC_QUIT_ON_ERROR (ipc_close_all (ctx), EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void interactive (char *env[])
|
void interactive ()
|
||||||
{
|
{
|
||||||
// init service
|
// init service
|
||||||
TEST_IPC_QUIT_ON_ERROR (ipc_connection (env, srv, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_QUIT_ON_ERROR (ipc_connection (ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_error, ret);
|
SECURE_DECLARATION (struct ipc_error, ret);
|
||||||
SECURE_DECLARATION (struct ipc_event, event);
|
SECURE_DECLARATION (struct ipc_event, event);
|
||||||
SECURE_DECLARATION (struct ipc_connection_infos, services);
|
|
||||||
|
|
||||||
ipc_add (&services, srv);
|
ipc_add_fd (ctx, 0); // add STDIN
|
||||||
ipc_add_fd (&services, 0); // add STDIN
|
|
||||||
|
|
||||||
ipc_connections_print (&services);
|
ipc_ctx_print (ctx);
|
||||||
|
|
||||||
long timer = 10;
|
int timer = 10000;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
printf ("msg to send: ");
|
printf ("msg to send: ");
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
|
|
||||||
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (&services, NULL, &event, &timer), EXIT_FAILURE);
|
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (ctx, &event, &timer), EXIT_FAILURE);
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_EXTRA_SOCKET:
|
case IPC_EVENT_TYPE_EXTRA_SOCKET:
|
||||||
{
|
{
|
||||||
|
@ -80,7 +78,7 @@ void interactive (char *env[])
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
memset (buf, 0, 4096);
|
memset (buf, 0, 4096);
|
||||||
|
|
||||||
len = read (event.origin->fd, buf, 4096);
|
len = read (event.origin, buf, 4096);
|
||||||
|
|
||||||
buf[len - 1] = '\0';
|
buf[len - 1] = '\0';
|
||||||
chomp (buf, len);
|
chomp (buf, len);
|
||||||
|
@ -93,13 +91,13 @@ void interactive (char *env[])
|
||||||
// in case we want to quit the program
|
// in case we want to quit the program
|
||||||
if (len == 0 || strncmp (buf, "quit", 4) == 0 || strncmp (buf, "exit", 4) == 0) {
|
if (len == 0 || strncmp (buf, "quit", 4) == 0 || strncmp (buf, "exit", 4) == 0) {
|
||||||
|
|
||||||
struct ipc_error ret = ipc_close (srv);
|
struct ipc_error ret = ipc_close_all (ctx);
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
fprintf (stderr, "%s", ret.error_message);
|
fprintf (stderr, "%s", ret.error_message);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ipc_connections_free (&services);
|
ipc_ctx_free (ctx);
|
||||||
|
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -116,7 +114,7 @@ void interactive (char *env[])
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf ("right before sending a message\n");
|
printf ("right before sending a message\n");
|
||||||
#endif
|
#endif
|
||||||
ret = ipc_write (srv, m);
|
ret = ipc_write (ctx, m);
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
fprintf (stderr, "%s", ret.error_message);
|
fprintf (stderr, "%s", ret.error_message);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
|
@ -145,24 +143,17 @@ void interactive (char *env[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char *argv[], char *env[])
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
printf("usage: %s [verbosity #messages message]", argv[0]);
|
printf("usage: %s [verbosity #messages message]", argv[0]);
|
||||||
|
|
||||||
// $0:
|
ctx = malloc (sizeof (struct ipc_ctx));
|
||||||
argv = argv; // warnings
|
memset (ctx, 0, sizeof (struct ipc_ctx));
|
||||||
|
|
||||||
srv = malloc (sizeof (struct ipc_connection_info));
|
|
||||||
memset (srv, 0, sizeof (struct ipc_connection_info));
|
|
||||||
|
|
||||||
// index and version should be filled
|
|
||||||
srv->index = 0;
|
|
||||||
srv->version = 0;
|
|
||||||
|
|
||||||
if (argc == 4)
|
if (argc == 4)
|
||||||
non_interactive (atoi(argv[1]), (size_t) atoi(argv[2]), argv[3], env);
|
non_interactive (atoi(argv[1]), (size_t) atoi(argv[2]), argv[3]);
|
||||||
else
|
else
|
||||||
interactive (env);
|
interactive ();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
100
examples/pongd.c
100
examples/pongd.c
|
@ -12,36 +12,47 @@
|
||||||
fprintf(stderr, "error while %s: %s\n", msg, ret.error_message);\
|
fprintf(stderr, "error while %s: %s\n", msg, ret.error_message);\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipc_ctx:
|
||||||
|
* cinfos: array of ipc_connection_info
|
||||||
|
* pollfd: array of `pollfd` structure
|
||||||
|
* Both arrays share the same indices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Overview of the main loop:
|
||||||
|
* 1. "ctx" pointer declaration (struct ipc_ctx).
|
||||||
|
* 1. ipc_server_init (ctx, SERVICE_NAME)
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
int cpt = 0;
|
int cpt = 0;
|
||||||
|
|
||||||
int verbosity = 1;
|
int verbosity = 1;
|
||||||
|
|
||||||
struct ipc_connection_info *srv = NULL;
|
struct ipc_ctx *ctx = NULL;
|
||||||
struct ipc_connection_infos *clients = NULL;
|
|
||||||
|
|
||||||
void main_loop ()
|
void main_loop ()
|
||||||
{
|
{
|
||||||
double base_timer = 0;
|
int base_timer = 10000;
|
||||||
double timer = base_timer;
|
int timer = base_timer;
|
||||||
SECURE_DECLARATION (struct ipc_error, ret);
|
SECURE_DECLARATION (struct ipc_error, ret);
|
||||||
|
|
||||||
clients = malloc (sizeof (struct ipc_connection_infos));
|
|
||||||
memset (clients, 0, sizeof (struct ipc_connection_infos));
|
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_event, event);
|
SECURE_DECLARATION (struct ipc_event, event);
|
||||||
event.type = IPC_EVENT_TYPE_NOT_SET;
|
event.type = IPC_EVENT_TYPE_NOT_SET;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// ipc_service_poll_event provides one event at a time
|
// ipc_wait_event provides one event at a time
|
||||||
// warning: event->m is free'ed if not NULL
|
// warning: event->m is free'ed if not NULL
|
||||||
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (clients, srv, &event, &timer), EXIT_FAILURE);
|
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (ctx, &event, &timer), EXIT_FAILURE);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_CONNECTION:
|
case IPC_EVENT_TYPE_CONNECTION:
|
||||||
{
|
{
|
||||||
cpt++;
|
cpt++;
|
||||||
if (verbosity > 1) {
|
if (verbosity > 1) {
|
||||||
printf ("connection: %d clients connected, new client is %d\n", cpt, (event.origin)->fd);
|
printf ("connection: %d ctx connected, new client is %d\n", cpt, event.origin);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
@ -49,11 +60,8 @@ void main_loop ()
|
||||||
{
|
{
|
||||||
cpt--;
|
cpt--;
|
||||||
if (verbosity > 1) {
|
if (verbosity > 1) {
|
||||||
printf ("disconnection: %d clients remaining\n", cpt);
|
printf ("disconnection: %d ctx remaining\n", cpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// free the ipc_client structure
|
|
||||||
free (event.origin);
|
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_MESSAGE:
|
case IPC_EVENT_TYPE_MESSAGE:
|
||||||
|
@ -68,13 +76,10 @@ void main_loop ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ipc_write (event.origin, m);
|
ret = ipc_write (ctx, m);
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
PRINTERR (ret, "server write");
|
PRINTERR (ret, "server write");
|
||||||
}
|
}
|
||||||
if (verbosity > 1) {
|
|
||||||
printf ("message sent\n");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_TIMER:{
|
case IPC_EVENT_TYPE_TIMER:{
|
||||||
|
@ -86,13 +91,17 @@ void main_loop ()
|
||||||
case IPC_EVENT_TYPE_ERROR:
|
case IPC_EVENT_TYPE_ERROR:
|
||||||
{
|
{
|
||||||
cpt--;
|
cpt--;
|
||||||
fprintf (stderr, "a problem happened with client %d (now disconnected)", (event.origin)->fd);
|
fprintf (stderr, "a problem happened with client %d (now disconnected)", event.origin);
|
||||||
fprintf (stderr, ", %d clients remaining\n", cpt);
|
fprintf (stderr, ", %d ctx remaining\n", cpt);
|
||||||
|
|
||||||
// free the ipc_client structure
|
|
||||||
free (event.origin);
|
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case IPC_EVENT_TYPE_TX:
|
||||||
|
{
|
||||||
|
if (verbosity > 1) {
|
||||||
|
printf ("a message was sent\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
fprintf (stderr, "there must be a problem, event not set\n");
|
fprintf (stderr, "there must be a problem, event not set\n");
|
||||||
|
@ -108,70 +117,49 @@ void exit_program (int signal)
|
||||||
{
|
{
|
||||||
printf ("Quitting, signal: %d\n", signal);
|
printf ("Quitting, signal: %d\n", signal);
|
||||||
|
|
||||||
// free remaining clients
|
|
||||||
for (size_t i = 0; i < clients->size; i++) {
|
|
||||||
struct ipc_connection_info *cli = clients->cinfos[i];
|
|
||||||
if (cli != NULL) {
|
|
||||||
free (cli);
|
|
||||||
}
|
|
||||||
clients->cinfos[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipc_connections_free (clients);
|
|
||||||
free (clients);
|
|
||||||
|
|
||||||
// the application will shut down, and close the service
|
// the application will shut down, and close the service
|
||||||
struct ipc_error ret = ipc_server_close (srv);
|
struct ipc_error ret = ipc_close_all (ctx);
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
PRINTERR (ret, "server close");
|
PRINTERR (ret, "server close");
|
||||||
}
|
}
|
||||||
free (srv);
|
|
||||||
|
ipc_ctx_free (ctx);
|
||||||
|
free (ctx);
|
||||||
|
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* service ping-pong: send back everything sent by the clients
|
* service ping-pong: send back everything sent by the ctx
|
||||||
* stop the program on SIG{TERM,INT,ALRM,USR{1,2},HUP} signals
|
* stop the program on SIG{TERM,INT,ALRM,USR{1,2},HUP} signals
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int main (int argc, char *argv[], char **env)
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
argc = argc; // warnings
|
|
||||||
argv = argv; // warnings
|
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
verbosity = atoi(argv[1]);
|
verbosity = atoi(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("pid = %d\n", getpid ());
|
printf ("pid = %d\n", getpid ());
|
||||||
|
|
||||||
srv = malloc (sizeof (struct ipc_connection_info));
|
ctx = malloc (sizeof (struct ipc_ctx));
|
||||||
if (srv == NULL) {
|
memset (ctx, 0, sizeof (struct ipc_ctx));
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
memset (srv, 0, sizeof (struct ipc_connection_info));
|
|
||||||
srv->type = '\0';
|
|
||||||
srv->index = 0;
|
|
||||||
srv->version = 0;
|
|
||||||
srv->fd = 0;
|
|
||||||
srv->spath = NULL;
|
|
||||||
|
|
||||||
struct ipc_error ret = ipc_server_init (env, srv, PONGD_SERVICE_NAME);
|
struct ipc_error ret = ipc_server_init (ctx, PONGD_SERVICE_NAME);
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
PRINTERR (ret, "server init");
|
PRINTERR (ret, "server init");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
printf ("Listening on %s.\n", srv->spath);
|
printf ("Listening on %s.\n", ctx->cinfos[0].spath);
|
||||||
|
|
||||||
printf ("MAIN: server created\n");
|
printf ("MAIN: server created\n");
|
||||||
|
|
||||||
signal (SIGHUP, exit_program);
|
signal (SIGHUP, exit_program);
|
||||||
signal (SIGALRM, exit_program);
|
signal (SIGALRM, exit_program);
|
||||||
signal (SIGUSR1, exit_program);
|
signal (SIGUSR1, exit_program);
|
||||||
signal (SIGUSR2, exit_program);
|
signal (SIGUSR2, exit_program);
|
||||||
signal (SIGTERM, exit_program);
|
signal (SIGTERM, exit_program);
|
||||||
signal (SIGINT, exit_program);
|
signal (SIGINT, exit_program);
|
||||||
|
|
||||||
// the service will loop until the end of time, or a signal
|
// the service will loop until the end of time, or a signal
|
||||||
main_loop ();
|
main_loop ();
|
||||||
|
|
|
@ -23,52 +23,51 @@ void chomp (char *str, ssize_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_connection_info *srv;
|
struct ipc_ctx *ctx = NULL;
|
||||||
|
|
||||||
void non_interactive (char *env[])
|
void non_interactive ()
|
||||||
{
|
{
|
||||||
SECURE_DECLARATION (struct ipc_message, m);
|
SECURE_DECLARATION (struct ipc_message, m);
|
||||||
|
|
||||||
// init service
|
// init service
|
||||||
TEST_IPC_Q (ipc_connection (env, srv, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_connection (ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
TEST_IPC_Q (ipc_message_format_data (&m, 42, MSG, (ssize_t) strlen (MSG) + 1), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_message_format_data (&m, 42, MSG, (ssize_t) strlen (MSG) + 1), EXIT_FAILURE);
|
||||||
|
|
||||||
printf ("msg to send (%ld): %.*s\n", (ssize_t) strlen (MSG) + 1, (int)strlen (MSG), MSG);
|
printf ("msg to send (%ld): %.*s\n", (ssize_t) strlen (MSG) + 1, (int)strlen (MSG), MSG);
|
||||||
TEST_IPC_Q (ipc_write (srv, &m), EXIT_FAILURE);
|
// ipc_write fd: write a message without fd availability check.
|
||||||
|
TEST_IPC_Q (ipc_write_fd (ctx->pollfd[0].fd, &m), EXIT_FAILURE);
|
||||||
ipc_message_empty (&m);
|
ipc_message_empty (&m);
|
||||||
TEST_IPC_Q (ipc_read (srv, &m), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_read (ctx, 0 /* only valid index */, &m), EXIT_FAILURE);
|
||||||
|
|
||||||
printf ("msg recv (type: %u): %s\n", m.user_type, m.payload);
|
printf ("msg recv (type: %u): %s\n", m.user_type, m.payload);
|
||||||
ipc_message_empty (&m);
|
ipc_message_empty (&m);
|
||||||
|
|
||||||
TEST_IPC_Q (ipc_close (srv), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_close_all (ctx), EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void interactive (char *env[])
|
void interactive ()
|
||||||
{
|
{
|
||||||
// init service
|
// init service
|
||||||
TEST_IPC_Q (ipc_connection (env, srv, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_connection (ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_event, event);
|
SECURE_DECLARATION (struct ipc_event, event);
|
||||||
SECURE_DECLARATION (struct ipc_connection_infos, services);
|
|
||||||
|
|
||||||
ipc_add (&services, srv);
|
ipc_add_fd (ctx, 0); // add STDIN
|
||||||
ipc_add_fd (&services, 0); // add STDIN
|
|
||||||
|
|
||||||
ipc_connections_print (&services);
|
ipc_ctx_print (ctx);
|
||||||
|
|
||||||
long timer = 10;
|
int timer = 10000;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
printf ("msg to send: ");
|
printf ("msg to send: ");
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
|
|
||||||
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (&services, NULL, &event, &timer), EXIT_FAILURE);
|
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (ctx, &event, &timer), EXIT_FAILURE);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_TIMER:{
|
case IPC_EVENT_TYPE_TIMER:{
|
||||||
printf ("time up!\n");
|
printf ("time up!\n");
|
||||||
timer = 10;
|
timer = 10000;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_EXTRA_SOCKET:
|
case IPC_EVENT_TYPE_EXTRA_SOCKET:
|
||||||
|
@ -78,7 +77,7 @@ void interactive (char *env[])
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
memset (buf, 0, 4096);
|
memset (buf, 0, 4096);
|
||||||
|
|
||||||
len = read (event.origin->fd, buf, 4096);
|
len = read (event.origin, buf, 4096);
|
||||||
|
|
||||||
buf[len - 1] = '\0';
|
buf[len - 1] = '\0';
|
||||||
chomp (buf, len);
|
chomp (buf, len);
|
||||||
|
@ -91,9 +90,9 @@ void interactive (char *env[])
|
||||||
// in case we want to quit the program
|
// in case we want to quit the program
|
||||||
if (len == 0 || strncmp (buf, "quit", 4) == 0 || strncmp (buf, "exit", 4) == 0) {
|
if (len == 0 || strncmp (buf, "quit", 4) == 0 || strncmp (buf, "exit", 4) == 0) {
|
||||||
|
|
||||||
TEST_IPC_Q (ipc_close (srv), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_close_all (ctx), EXIT_FAILURE);
|
||||||
|
|
||||||
ipc_connections_free (&services);
|
ipc_ctx_free (ctx);
|
||||||
|
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -107,6 +106,7 @@ void interactive (char *env[])
|
||||||
len = strlen (buf);
|
len = strlen (buf);
|
||||||
printf ("message %lu, buffer %.*s\n", i, (int)len, buf);
|
printf ("message %lu, buffer %.*s\n", i, (int)len, buf);
|
||||||
TEST_IPC_Q (ipc_message_format_data (m, 42, buf, len), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_message_format_data (m, 42, buf, len), EXIT_FAILURE);
|
||||||
|
m->fd = ctx->pollfd[0].fd;
|
||||||
|
|
||||||
printf ("message from structure: %.*s\n", m->length, m->payload);
|
printf ("message from structure: %.*s\n", m->length, m->payload);
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ void interactive (char *env[])
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf ("right before sending a message\n");
|
printf ("right before sending a message\n");
|
||||||
#endif
|
#endif
|
||||||
TEST_IPC_Q (ipc_write (srv, m), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_write (ctx, m), EXIT_FAILURE);
|
||||||
#if 0
|
#if 0
|
||||||
printf ("right after sending a message\n");
|
printf ("right after sending a message\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -125,6 +125,11 @@ void interactive (char *env[])
|
||||||
free (m);
|
free (m);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case IPC_EVENT_TYPE_TX:
|
||||||
|
{
|
||||||
|
printf ("a message was sent\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case IPC_EVENT_TYPE_MESSAGE:
|
case IPC_EVENT_TYPE_MESSAGE:
|
||||||
{
|
{
|
||||||
struct ipc_message *m = event.m;
|
struct ipc_message *m = event.m;
|
||||||
|
@ -141,22 +146,18 @@ void interactive (char *env[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char *argv[], char *env[])
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
argc = argc; // warnings
|
// Compilers fuckery.
|
||||||
argv = argv; // warnings
|
argv = argv;
|
||||||
|
|
||||||
srv = malloc (sizeof (struct ipc_connection_info));
|
ctx = malloc (sizeof (struct ipc_ctx));
|
||||||
memset (srv, 0, sizeof (struct ipc_connection_info));
|
memset (ctx, 0, sizeof (struct ipc_ctx));
|
||||||
|
|
||||||
// index and version should be filled
|
|
||||||
srv->index = 0;
|
|
||||||
srv->version = 0;
|
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
non_interactive (env);
|
non_interactive ();
|
||||||
else
|
else
|
||||||
interactive (env);
|
interactive ();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,9 @@ void send_receive (int sockfd)
|
||||||
// 2 | 6 | 0 | "coucou"
|
// 2 | 6 | 0 | "coucou"
|
||||||
// 1 B | 4 B | 1 | 6 B
|
// 1 B | 4 B | 1 | 6 B
|
||||||
ipc_message_raw_serialize ((char *)buf, MSG_TYPE_DATA, 42, "coucou", 6);
|
ipc_message_raw_serialize ((char *)buf, MSG_TYPE_DATA, 42, "coucou", 6);
|
||||||
print_hexa ("WAITING 10 seconds then message to send", buf, 12);
|
printf("\n");
|
||||||
|
print_hexa ("message to send", buf, 12);
|
||||||
|
printf("\n");
|
||||||
// sleep (1);
|
// sleep (1);
|
||||||
T_PERROR_Q ((send (sockfd, buf, 12, 0) == -1), "sending a message", EXIT_FAILURE);
|
T_PERROR_Q ((send (sockfd, buf, 12, 0) == -1), "sending a message", EXIT_FAILURE);
|
||||||
printf ("message 'coucou' sent\n");
|
printf ("message 'coucou' sent\n");
|
||||||
|
@ -72,6 +74,7 @@ void send_receive (int sockfd)
|
||||||
|
|
||||||
// receiving a message
|
// receiving a message
|
||||||
T_PERROR_Q (((paylen = recv (sockfd, buf, BUFSIZ, 0)) < 0), "receiving a message", EXIT_FAILURE);
|
T_PERROR_Q (((paylen = recv (sockfd, buf, BUFSIZ, 0)) < 0), "receiving a message", EXIT_FAILURE);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
if (paylen == 0) {
|
if (paylen == 0) {
|
||||||
fprintf (stderr, "error: disconnection from the server\n");
|
fprintf (stderr, "error: disconnection from the server\n");
|
||||||
|
@ -96,7 +99,7 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
send_receive (sockfd);
|
send_receive (sockfd);
|
||||||
|
|
||||||
printf ("Disconnection\n");
|
printf ("\nDisconnection\n");
|
||||||
|
|
||||||
// close the socket
|
// close the socket
|
||||||
close (sockfd);
|
close (sockfd);
|
||||||
|
|
|
@ -42,7 +42,7 @@ void chomp (char *str, size_t len)
|
||||||
else
|
else
|
||||||
connection from the client:
|
connection from the client:
|
||||||
1. client sends service name
|
1. client sends service name
|
||||||
2. networkd establishes a connection to the service
|
2. ipcd establishes a connection to the service
|
||||||
3. ack
|
3. ack
|
||||||
else
|
else
|
||||||
lolwat shouldn't happen :(
|
lolwat shouldn't happen :(
|
||||||
|
@ -52,26 +52,26 @@ void chomp (char *str, size_t len)
|
||||||
|
|
||||||
#define SERVICE_NAME "simpletcp"
|
#define SERVICE_NAME "simpletcp"
|
||||||
|
|
||||||
struct networkd *ctx;
|
struct ipc_ctx *ctx = NULL;
|
||||||
|
|
||||||
void handle_disconnection (int fd)
|
void handle_disconnection (int fd)
|
||||||
{
|
{
|
||||||
int delfd;
|
int delfd;
|
||||||
|
|
||||||
delfd = ipc_switching_del (ctx->TCP_TO_IPC, fd);
|
delfd = ipc_switching_del (&ctx->switchdb, fd);
|
||||||
if (delfd >= 0) {
|
if (delfd >= 0) {
|
||||||
close (delfd);
|
close (delfd);
|
||||||
ipc_del_fd (ctx->clients, delfd);
|
ipc_del_fd (ctx, delfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
ipc_del_fd (ctx->clients, fd);
|
ipc_del_fd (ctx, fd);
|
||||||
|
|
||||||
// printf ("TCP_TO_IPC\n");
|
// printf ("ctx.switchdb\n");
|
||||||
ipc_switching_print (ctx->TCP_TO_IPC);
|
ipc_switching_print (&ctx->switchdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_connection (char **env, int fd)
|
void tcp_connection (int fd)
|
||||||
{
|
{
|
||||||
SECURE_BUFFER_DECLARATION (char, buf, BUFSIZ);
|
SECURE_BUFFER_DECLARATION (char, buf, BUFSIZ);
|
||||||
|
|
||||||
|
@ -89,16 +89,15 @@ void tcp_connection (char **env, int fd)
|
||||||
// TODO: tests
|
// TODO: tests
|
||||||
T_PERROR_Q ((send (fd, "OK", 2, 0) <= 0), "sending a message", EXIT_FAILURE);
|
T_PERROR_Q ((send (fd, "OK", 2, 0) <= 0), "sending a message", EXIT_FAILURE);
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_connection_info, tcp_to_ipc_ci);
|
printf ("connection to %s\n", buf);
|
||||||
|
struct ipc_error ret = ipc_connection_switched (ctx, buf);
|
||||||
struct ipc_error ret = ipc_connection (env, &tcp_to_ipc_ci, buf);
|
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
fprintf (stderr, "%s\n", ret.error_message);
|
fprintf (stderr, "%s\n", ret.error_message);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ipc_switching_add (ctx->TCP_TO_IPC, fd, tcp_to_ipc_ci.fd);
|
ipc_switching_add (&ctx->switchdb, fd, ctx->pollfd[ctx->size-1].fd);
|
||||||
ipc_add_fd (ctx->clients, tcp_to_ipc_ci.fd);
|
ipc_ctx_fd_type (ctx, fd, IPC_CONNECTION_TYPE_SWITCHED);
|
||||||
}
|
}
|
||||||
|
|
||||||
int accept_new_client (int serverfd)
|
int accept_new_client (int serverfd)
|
||||||
|
@ -111,13 +110,14 @@ int accept_new_client (int serverfd)
|
||||||
accept (serverfd, (struct sockaddr *)&client, &addrlen)) == -1), "accept new client",
|
accept (serverfd, (struct sockaddr *)&client, &addrlen)) == -1), "accept new client",
|
||||||
EXIT_FAILURE);
|
EXIT_FAILURE);
|
||||||
|
|
||||||
// adding a client
|
// adding a client, for now not switched:
|
||||||
ipc_add_fd (ctx->clients, sock_fd_client);
|
// tcpd should handle the first message (getting the service name)
|
||||||
|
ipc_add_fd (ctx, sock_fd_client);
|
||||||
|
|
||||||
return sock_fd_client;
|
return sock_fd_client;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main_loop (int argc, char **argv, char **env)
|
void main_loop (int argc, char **argv)
|
||||||
{
|
{
|
||||||
argc = argc; // FIXME: useless
|
argc = argc; // FIXME: useless
|
||||||
int serverfd;
|
int serverfd;
|
||||||
|
@ -155,80 +155,89 @@ void main_loop (int argc, char **argv, char **env)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->clients, sizeof (struct ipc_connection_infos),, EXIT_FAILURE);
|
|
||||||
SECURE_DECLARATION (struct ipc_event, event);
|
SECURE_DECLARATION (struct ipc_event, event);
|
||||||
|
|
||||||
ipc_add_fd (ctx->clients, serverfd);
|
ipc_add_fd (ctx, serverfd);
|
||||||
|
|
||||||
|
int cpt = 0;
|
||||||
|
|
||||||
|
int timer = 10000;
|
||||||
while (1) {
|
while (1) {
|
||||||
// ipc_wait_event provides one event at a time
|
// ipc_wait_event provides one event at a time
|
||||||
// warning: event->m is free'ed if not NULL
|
// warning: event->m is free'ed if not NULL
|
||||||
long timer = 10;
|
|
||||||
|
|
||||||
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event_networkd (ctx->clients, ctx->srv, &event, ctx->TCP_TO_IPC, &timer)
|
ipc_ctx_print (ctx);
|
||||||
, EXIT_FAILURE);
|
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (ctx, &event, &timer), EXIT_FAILURE);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_TIMER:{
|
case IPC_EVENT_TYPE_TIMER:{
|
||||||
printf ("timed out!\n");
|
printf ("timed out!\n");
|
||||||
|
timer = 10000;
|
||||||
timer = 10;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPC_EVENT_TYPE_SWITCH:{
|
case IPC_EVENT_TYPE_SWITCH:{
|
||||||
printf ("switch happened\n");
|
printf ("switch happened, from %d\n", event.origin);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPC_EVENT_TYPE_EXTRA_SOCKET:
|
case IPC_EVENT_TYPE_EXTRA_SOCKET:
|
||||||
{
|
{
|
||||||
// NEW CLIENT
|
// NEW CLIENT
|
||||||
if (event.origin->fd == serverfd) {
|
if (event.origin == serverfd) {
|
||||||
int sock_fd_client = accept_new_client (serverfd);
|
int sock_fd_client = accept_new_client (serverfd);
|
||||||
ctx->cpt++;
|
cpt++;
|
||||||
printf ("TCP connection: %d clients connected\n", ctx->cpt);
|
printf ("TCP connection: %d ctx connected\n", cpt);
|
||||||
printf ("new TCP client has the fd %d\n", sock_fd_client);
|
printf ("new TCP client has the fd %d\n", sock_fd_client);
|
||||||
}
|
}
|
||||||
// CLIENT IS TALKING
|
// CLIENT IS TALKING
|
||||||
else {
|
else {
|
||||||
tcp_connection (env, event.origin->fd);
|
// Test: if the socket already is in the switch, this means we can just switch the packet.
|
||||||
|
// Is the socket in the switch db?
|
||||||
|
tcp_connection (event.origin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPC_EVENT_TYPE_CONNECTION:
|
case IPC_EVENT_TYPE_CONNECTION:
|
||||||
{
|
{
|
||||||
ctx->cpt++;
|
cpt++;
|
||||||
printf ("connection: %d clients connected\n", ctx->cpt);
|
printf ("connection: %d ctx connected\n", cpt);
|
||||||
printf ("new client has the fd %d\n", (event.origin)->fd);
|
printf ("new client has the fd %d\n", event.origin);
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPC_EVENT_TYPE_DISCONNECTION:
|
case IPC_EVENT_TYPE_DISCONNECTION:
|
||||||
{
|
{
|
||||||
ctx->cpt--;
|
cpt--;
|
||||||
printf ("disconnection: %d clients remaining\n", ctx->cpt);
|
printf ("disconnection: %d ctx remaining\n", cpt);
|
||||||
|
|
||||||
// free the ipc_client structure
|
|
||||||
// if (event.origin != NULL)
|
|
||||||
// free (event.origin);
|
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPC_EVENT_TYPE_MESSAGE:
|
case IPC_EVENT_TYPE_MESSAGE:
|
||||||
{
|
{
|
||||||
struct ipc_message *m = event.m;
|
struct ipc_message *m = event.m;
|
||||||
if (m->length > 0) {
|
if (m->length > 0) {
|
||||||
printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload);
|
printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload);
|
||||||
}
|
}
|
||||||
|
// m->fd = 3;
|
||||||
TEST_IPC_P (ipc_write (event.origin, m), "server write");
|
TEST_IPC_P (ipc_write (ctx, m), "server write");
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_ERROR:
|
|
||||||
fprintf (stderr, "a problem happened with client %d\n", (event.origin)->fd);
|
case IPC_EVENT_TYPE_TX:
|
||||||
|
{
|
||||||
|
printf ("a message was sent\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IPC_EVENT_TYPE_ERROR:
|
||||||
|
fprintf (stderr, "a problem happened with client %d\n", event.origin);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf (stderr, "there must be a problem, event not set\n");
|
fprintf (stderr, "there must be a problem, event not set: %d\n", event.type);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,36 +249,22 @@ void exit_program (int signal)
|
||||||
{
|
{
|
||||||
printf ("Quitting, signal: %d\n", signal);
|
printf ("Quitting, signal: %d\n", signal);
|
||||||
|
|
||||||
// free remaining clients
|
// Close then free remaining ctx.
|
||||||
for (size_t i = 0; i < ctx->clients->size; i++) {
|
ipc_close_all (ctx);
|
||||||
struct ipc_connection_info *cli = ctx->clients->cinfos[i];
|
ipc_ctx_free (ctx);
|
||||||
if (cli != NULL) {
|
|
||||||
free (cli);
|
|
||||||
}
|
|
||||||
ctx->clients->cinfos[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipc_connections_free (ctx->clients);
|
|
||||||
|
|
||||||
// the application will shut down, and close the service
|
|
||||||
TEST_IPC_P (ipc_server_close (ctx->srv), "server close");
|
|
||||||
|
|
||||||
// free, free everything!
|
// free, free everything!
|
||||||
free (ctx->clients);
|
|
||||||
free (ctx->srv);
|
|
||||||
free (ctx->TCP_TO_IPC->collection);
|
|
||||||
free (ctx->TCP_TO_IPC);
|
|
||||||
free (ctx);
|
free (ctx);
|
||||||
|
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* service ping-pong: send back everything sent by the clients
|
* service ping-pong: send back everything sent by the ctx
|
||||||
* stop the program on SIG{TERM,INT,ALRM,USR{1,2},HUP} signals
|
* stop the program on SIG{TERM,INT,ALRM,USR{1,2},HUP} signals
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int main (int argc, char *argv[], char **env)
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// check the number of args on command line
|
// check the number of args on command line
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
|
@ -279,17 +274,15 @@ int main (int argc, char *argv[], char **env)
|
||||||
|
|
||||||
printf ("pid = %d\n", getpid ());
|
printf ("pid = %d\n", getpid ());
|
||||||
|
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx, sizeof (struct networkd) ,, EXIT_FAILURE);
|
ctx = malloc (sizeof (struct ipc_ctx));
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->TCP_TO_IPC, sizeof (struct ipc_switchings) ,, EXIT_FAILURE);
|
memset(ctx, 0, sizeof (struct ipc_ctx));
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->TCP_TO_IPC->collection, sizeof (struct ipc_switching) ,, EXIT_FAILURE);
|
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->srv, sizeof (struct ipc_connection_info),, EXIT_FAILURE);
|
|
||||||
|
|
||||||
struct ipc_error ret = ipc_server_init (env, ctx->srv, SERVICE_NAME);
|
struct ipc_error ret = ipc_server_init (ctx, SERVICE_NAME);
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
fprintf (stderr, "%s\n", ret.error_message);
|
fprintf (stderr, "%s\n", ret.error_message);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
printf ("Listening on [%s].\n", ctx->srv->spath);
|
printf ("Listening on [%s].\n", ctx->cinfos[0].spath);
|
||||||
|
|
||||||
printf ("MAIN: server created\n");
|
printf ("MAIN: server created\n");
|
||||||
|
|
||||||
|
@ -301,7 +294,7 @@ int main (int argc, char *argv[], char **env)
|
||||||
signal (SIGINT , exit_program);
|
signal (SIGINT , exit_program);
|
||||||
|
|
||||||
// the service will loop until the end of time, or a signal
|
// the service will loop until the end of time, or a signal
|
||||||
main_loop (argc, argv, env);
|
main_loop (argc, argv);
|
||||||
|
|
||||||
// main_loop should not return
|
// main_loop should not return
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
|
@ -6,30 +6,27 @@
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_error, ret);
|
|
||||||
SECURE_DECLARATION (struct ipc_connection_info, srv);
|
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
fprintf (stderr, "usage: %s service_name\n", argv[0]);
|
fprintf (stderr, "usage: %s service_name\n", argv[0]);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECURE_DECLARATION (struct ipc_error, ret);
|
||||||
|
int fd = 0;
|
||||||
|
|
||||||
char *service_name = argv[1];
|
char *service_name = argv[1];
|
||||||
|
|
||||||
ret = ipc_contact_networkd (&srv, service_name);
|
ret = ipc_contact_ipcd (&fd, service_name);
|
||||||
|
|
||||||
printf ("ret = %d\n", ret.error_code);
|
printf ("ret = %d\n", ret.error_code);
|
||||||
|
|
||||||
if (ret.error_code == IPC_ERROR_NONE && srv.fd != 0) {
|
if (ret.error_code == IPC_ERROR_NONE && fd > 0) {
|
||||||
printf ("Success\n");
|
printf ("Success\n");
|
||||||
} else {
|
} else {
|
||||||
printf ("Ow. :(\n");
|
printf ("Ow. :(\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
usock_close (srv.fd);
|
usock_close (fd);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,35 +4,32 @@
|
||||||
|
|
||||||
#include "../src/ipc.h"
|
#include "../src/ipc.h"
|
||||||
|
|
||||||
int main (int argc, char *argv[], char *env[])
|
int main (void)
|
||||||
{
|
{
|
||||||
(void)argc;
|
|
||||||
(void)argv;
|
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_error, ret);
|
SECURE_DECLARATION (struct ipc_error, ret);
|
||||||
SECURE_DECLARATION (struct ipc_connection_info, srv);
|
SECURE_DECLARATION (struct ipc_ctx, ctx);
|
||||||
SECURE_DECLARATION (struct ipc_connection_info, client);
|
SECURE_DECLARATION (struct ipc_event, event);
|
||||||
SECURE_DECLARATION (struct ipc_connection_info, contacted_service);
|
|
||||||
|
|
||||||
// service start
|
// service start
|
||||||
TEST_IPC_Q (ipc_server_init (env, &srv, "network"), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_server_init (&ctx, "ipcd"), EXIT_FAILURE);
|
||||||
|
|
||||||
printf ("service initialized, waiting for a client\n");
|
printf ("service initialized, waiting for a client\n");
|
||||||
|
|
||||||
// accept a new client
|
// accept a new client
|
||||||
TEST_IPC_Q (ipc_accept (&srv, &client), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_accept_add (&event, &ctx, 0 /* the only valid index right now */), EXIT_FAILURE);
|
||||||
|
int client_fd = ctx.pollfd[ctx.size-1].fd;
|
||||||
|
|
||||||
// TODO: read a message to know the requested service
|
// TODO: read a message to know the requested service
|
||||||
SECURE_DECLARATION (struct ipc_message, msg);
|
SECURE_DECLARATION (struct ipc_message, msg);
|
||||||
TEST_IPC_Q (ipc_read (&client, &msg), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_read (&ctx, 1 /* 1 = our client */, &msg), EXIT_FAILURE);
|
||||||
printf ("received message: %s\n", msg.payload);
|
printf ("received message: %s\n", msg.payload);
|
||||||
|
|
||||||
/** TODO: contact the service */
|
/** TODO: contact the service */
|
||||||
printf ("WARNING: currently this program only ask for pong service %d\n", ret.error_code);
|
printf ("WARNING: currently this program only ask for pong service %d\n", ret.error_code);
|
||||||
TEST_IPC_Q (ipc_connection (env, &contacted_service, "pong"), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_connection (&ctx, "pong"), EXIT_FAILURE);
|
||||||
|
|
||||||
ipc_provide_fd (client.fd, contacted_service.fd);
|
ipc_provide_fd (client_fd, ctx.pollfd[ctx.size-1].fd);
|
||||||
|
|
||||||
TEST_IPC_Q (ipc_server_close (&srv), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_close_all (&ctx), EXIT_FAILURE);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,13 @@ void chomp (char *str, ssize_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_connection_info *srv;
|
struct ipc_ctx *ctx;
|
||||||
|
|
||||||
void interactive (char *env[])
|
void interactive ()
|
||||||
{
|
{
|
||||||
long timer = 10;
|
int timer = 10000; // 10 seconds
|
||||||
|
|
||||||
|
SECURE_DECLARATION (struct ipc_event, event);
|
||||||
SECURE_BUFFER_DECLARATION (char, service_name, 100);
|
SECURE_BUFFER_DECLARATION (char, service_name, 100);
|
||||||
|
|
||||||
char *sn = getenv ("PATH_TRANSLATED");
|
char *sn = getenv ("PATH_TRANSLATED");
|
||||||
|
@ -37,21 +38,17 @@ void interactive (char *env[])
|
||||||
}
|
}
|
||||||
|
|
||||||
// init service
|
// init service
|
||||||
TEST_IPC_Q (ipc_connection (env, srv, service_name), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_connection (ctx, service_name), EXIT_FAILURE);
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_event, event);
|
ipc_add_fd (ctx, 0); // add STDIN
|
||||||
SECURE_DECLARATION (struct ipc_connection_infos, services);
|
|
||||||
|
|
||||||
ipc_add (&services, srv);
|
|
||||||
ipc_add_fd (&services, 0); // add STDIN
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (&services, NULL, &event, &timer), EXIT_FAILURE);
|
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (ctx, &event, &timer), EXIT_FAILURE);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_TIMER:{
|
case IPC_EVENT_TYPE_TIMER:{
|
||||||
fprintf (stderr, "time up!\n");
|
fprintf (stderr, "time up!\n");
|
||||||
timer = 10;
|
timer = 10000;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_EXTRA_SOCKET:
|
case IPC_EVENT_TYPE_EXTRA_SOCKET:
|
||||||
|
@ -60,19 +57,19 @@ void interactive (char *env[])
|
||||||
SECURE_BUFFER_DECLARATION (char, buf, 4096);
|
SECURE_BUFFER_DECLARATION (char, buf, 4096);
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
len = read (event.origin->fd, buf, 4096);
|
len = read (event.origin, buf, 4096);
|
||||||
|
|
||||||
// in case we want to quit the program
|
// in case we want to quit the program
|
||||||
if (len == 0 || strncmp (buf, "quit", 4) == 0 || strncmp (buf, "exit", 4) == 0) {
|
if (len == 0 || strncmp (buf, "quit", 4) == 0 || strncmp (buf, "exit", 4) == 0) {
|
||||||
|
|
||||||
TEST_IPC_Q (ipc_close (srv), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_close_all (ctx), EXIT_FAILURE);
|
||||||
|
|
||||||
ipc_connections_free (&services);
|
ipc_ctx_free (ctx);
|
||||||
|
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
// send the message read on STDIN
|
// send the message read on STDIN
|
||||||
ssize_t len_sent = write (srv->fd, buf, len);
|
ssize_t len_sent = write (ctx->pollfd[0].fd, buf, len);
|
||||||
if (len_sent != len) {
|
if (len_sent != len) {
|
||||||
fprintf (stderr, "cannot send the message %lu-byte message, sent %lu bytes",
|
fprintf (stderr, "cannot send the message %lu-byte message, sent %lu bytes",
|
||||||
len, len_sent);
|
len, len_sent);
|
||||||
|
@ -94,6 +91,10 @@ void interactive (char *env[])
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case IPC_EVENT_TYPE_TX: {
|
||||||
|
printf ("Message sent\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
ERROR_CASE (IPC_EVENT_TYPE_DISCONNECTION, "main loop", "disconnection: should not happen");
|
ERROR_CASE (IPC_EVENT_TYPE_DISCONNECTION, "main loop", "disconnection: should not happen");
|
||||||
ERROR_CASE (IPC_EVENT_TYPE_NOT_SET , "main loop", "not set: should not happen");
|
ERROR_CASE (IPC_EVENT_TYPE_NOT_SET , "main loop", "not set: should not happen");
|
||||||
ERROR_CASE (IPC_EVENT_TYPE_CONNECTION , "main loop", "connection: should not happen");
|
ERROR_CASE (IPC_EVENT_TYPE_CONNECTION , "main loop", "connection: should not happen");
|
||||||
|
@ -104,19 +105,12 @@ void interactive (char *env[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char *argv[], char *env[])
|
int main (void)
|
||||||
{
|
{
|
||||||
argc = argc; // warnings
|
ctx = malloc (sizeof (struct ipc_ctx));
|
||||||
argv = argv; // warnings
|
memset (ctx, 0, sizeof (struct ipc_ctx));
|
||||||
|
|
||||||
srv = malloc (sizeof (struct ipc_connection_info));
|
interactive ();
|
||||||
memset (srv, 0, sizeof (struct ipc_connection_info));
|
|
||||||
|
|
||||||
// index and version should be filled
|
|
||||||
srv->index = 0;
|
|
||||||
srv->version = 0;
|
|
||||||
|
|
||||||
interactive (env);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,17 +34,17 @@ _enum ipc_errors_ **ipc_accept** (*struct ipc_connection_info* \*srv, *struct ip
|
||||||
|
|
||||||
_enum ipc_errors_ **ipc_read** (*const struct ipc_connection_info* \*, *struct ipc_message* \*m);++
|
_enum ipc_errors_ **ipc_read** (*const struct ipc_connection_info* \*, *struct ipc_message* \*m);++
|
||||||
_enum ipc_errors_ **ipc_write** (*const struct ipc_connection_info* \*, *const struct ipc_message* \*m);++
|
_enum ipc_errors_ **ipc_write** (*const struct ipc_connection_info* \*, *const struct ipc_message* \*m);++
|
||||||
_enum ipc_errors_ **ipc_wait_event** (*struct ipc_connection_infos* \*clients, *struct ipc_connection_info* \*srv, *struct ipc_event* \*event);
|
_enum ipc_errors_ **ipc_wait_event** (*struct ipc_ctx* \*clients, *struct ipc_connection_info* \*srv, *struct ipc_event* \*event);
|
||||||
|
|
||||||
|
|
||||||
// store and remove only pointers on allocated structures
|
// store and remove only pointers on allocated structures
|
||||||
|
|
||||||
_enum ipc_errors_ **ipc_add** (*struct ipc_connection_infos* \*cinfos, *struct ipc_connection_info* \*cinfo);++
|
_enum ipc_errors_ **ipc_add** (*struct ipc_ctx* \*cinfos, *struct ipc_connection_info* \*cinfo);++
|
||||||
_enum ipc_errors_ **ipc_del** (*struct ipc_connection_infos* \*cinfos, *struct ipc_connection_info* \*cinfo);
|
_enum ipc_errors_ **ipc_del** (*struct ipc_ctx* \*cinfos, *struct ipc_connection_info* \*cinfo);
|
||||||
|
|
||||||
// add an arbitrary file descriptor to read
|
// add an arbitrary file descriptor to read
|
||||||
|
|
||||||
_enum ipc_errors_ **ipc_add_fd** (*struct ipc_connection_infos* \*cinfos, *int* fd);
|
_enum ipc_errors_ **ipc_add_fd** (*struct ipc_ctx* \*cinfos, *int* fd);
|
||||||
|
|
||||||
|
|
||||||
## Message functions
|
## Message functions
|
||||||
|
@ -75,7 +75,7 @@ _enum ipc_errors_ **ipc_message_empty** (*struct ipc_message* \*m);
|
||||||
char *spath; // max size: PATH_MAX, used to store unix socket path
|
char *spath; // max size: PATH_MAX, used to store unix socket path
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipc_connection_infos {
|
struct ipc_ctx {
|
||||||
struct ipc_connection_info ** cinfos;
|
struct ipc_connection_info ** cinfos;
|
||||||
int32_t size;
|
int32_t size;
|
||||||
};
|
};
|
||||||
|
@ -106,7 +106,7 @@ _enum ipc_errors_ **ipc_message_empty** (*struct ipc_message* \*m);
|
||||||
|
|
||||||
Function **ipc_wait_event** returns an *event type* structure.\
|
Function **ipc_wait_event** returns an *event type* structure.\
|
||||||
The event may be a (dis)connection, received data or an error.\
|
The event may be a (dis)connection, received data or an error.\
|
||||||
It also can be *IPC_EVENT_TYPE_EXTRA_SOCKET* since an arbitrary file descriptor can be added to the *ipc_connection_infos* structure with **ipc_add_fd**.
|
It also can be *IPC_EVENT_TYPE_EXTRA_SOCKET* since an arbitrary file descriptor can be added to the *ipc_ctx* structure with **ipc_add_fd**.
|
||||||
|
|
||||||
```
|
```
|
||||||
enum ipc_event_type {
|
enum ipc_event_type {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
package=libipc # Package name.
|
package=libipc # Package name.
|
||||||
version=0.6.0 # Package version.
|
version=0.7.0 # Package version.
|
||||||
|
|
||||||
# Our targets are the library and its documentation.
|
# Our targets are the library and its documentation.
|
||||||
targets=(libipc man/libipc.7)
|
targets=(libipc man/libipc.7)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -13,86 +14,53 @@
|
||||||
// print structures
|
// print structures
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
|
|
||||||
struct ipc_error service_path (char *path, const char *sname, int32_t index, int32_t version)
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
int fd_is_valid(int fd)
|
||||||
{
|
{
|
||||||
T_R ((path == NULL), IPC_ERROR_SERVICE_PATH__NO_PATH);
|
return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
|
||||||
T_R ((sname == NULL), IPC_ERROR_SERVICE_PATH__NO_SERVICE_NAME);
|
|
||||||
|
|
||||||
memset (path, 0, PATH_MAX);
|
|
||||||
|
|
||||||
char *rundir = getenv ("IPC_RUNDIR");
|
|
||||||
if (rundir == NULL)
|
|
||||||
rundir = RUNDIR;
|
|
||||||
|
|
||||||
snprintf (path, PATH_MAX - 1, "%s/%s-%d-%d", rundir, sname, index, version);
|
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t get_max_fd (struct ipc_connection_infos *cinfos)
|
|
||||||
|
struct ipc_error ipc_server_init (struct ipc_ctx *ctx, const char *sname)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
int32_t max = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < cinfos->size; i++) {
|
|
||||||
if (cinfos->cinfos[i]->fd > max) {
|
|
||||||
max = cinfos->cinfos[i]->fd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ipc_error ipc_server_init (char **env, struct ipc_connection_info *srv, const char *sname)
|
|
||||||
{
|
|
||||||
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);
|
T_R ((sname == NULL), IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM);
|
||||||
|
|
||||||
#if 0
|
// Declaration and instanciation of the new connection (ipc_connection_info + pollfd).
|
||||||
// For server init, no need for networkd evaluation
|
SECURE_DECLARATION (struct ipc_connection_info, srv);
|
||||||
|
srv.type = IPC_CONNECTION_TYPE_SERVER;
|
||||||
|
SECURE_DECLARATION(struct pollfd, pollfd);
|
||||||
|
pollfd.events = POLLIN;
|
||||||
|
|
||||||
// TODO: loop over environment variables
|
// Get the service path.
|
||||||
// any IPC_NETWORK_* should be shared with the network service
|
|
||||||
// in order to route requests over any chosen protocol stack
|
|
||||||
// ex: IPC_NETWORK_AUDIO="tor://some.example.com/"
|
|
||||||
for (size_t i = 0; env[i] != NULL; i++) {
|
|
||||||
// TODO: check for every IPC_NETWORK_* environment variable
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// gets the service path
|
|
||||||
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
||||||
TEST_IPC_RR (service_path (buf, sname, srv->index, srv->version), "cannot get server path");
|
TEST_IPC_RR (service_path (buf, sname), "cannot get server path");
|
||||||
|
|
||||||
// gets the service path
|
|
||||||
if (srv->spath != NULL) {
|
|
||||||
free (srv->spath);
|
|
||||||
srv->spath = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t s = strlen (buf);
|
size_t s = strlen (buf);
|
||||||
|
if (s > PATH_MAX)
|
||||||
|
s = PATH_MAX;
|
||||||
|
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
|
||||||
|
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_R (srv->spath, s + 1,, IPC_ERROR_SERVER_INIT__MALLOC);
|
// Socket initialisation for the service.
|
||||||
memcpy (srv->spath, buf, s);
|
TEST_IPC_RETURN_ON_ERROR (usock_init (&pollfd.fd, srv.spath));
|
||||||
srv->spath[s] = '\0'; // to be sure
|
|
||||||
|
|
||||||
TEST_IPC_RETURN_ON_ERROR (usock_init (&srv->fd, srv->spath));
|
// Add the server to the listened file descriptors.
|
||||||
|
// ipc_add allocate memory then copy the data of srv and pollfd in ctx.
|
||||||
|
TEST_IPC_RR (ipc_add (ctx, &srv, &pollfd), "cannot add the server in the context");
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_write_fd (int fd, const struct ipc_message *m);
|
// when ipcd is not working properly (or do not retrieve the service): srv->fd = 0
|
||||||
|
struct ipc_error ipc_contact_ipcd (int *pfd, const char *sname)
|
||||||
// when networkd is not working properly (or do not retrieve the service): srv->fd = 0
|
|
||||||
struct ipc_error ipc_contact_networkd (struct ipc_connection_info *srv, const char *sname)
|
|
||||||
{
|
{
|
||||||
T_R ((srv == NULL), IPC_ERROR_CONTACT_NETWORKD__NO_SERVER_PARAM);
|
T_R ((pfd == NULL), IPC_ERROR_CONTACT_IPCD__NO_FD_PARAM);
|
||||||
T_R ((sname == NULL), IPC_ERROR_CONTACT_NETWORKD__NO_SERVICE_NAME_PARAM);
|
T_R ((sname == NULL), IPC_ERROR_CONTACT_IPCD__NO_SERVICE_NAME_PARAM);
|
||||||
|
|
||||||
char *networkvar = getenv ("IPC_NETWORK");
|
char *ipcd_var = getenv ("IPC_NETWORK");
|
||||||
if (networkvar == NULL) {
|
if (ipcd_var == NULL) {
|
||||||
srv->fd = 0;
|
*pfd = 0;
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
// TODO: is there another, more interesting way to do this?
|
// TODO: is there another, more interesting way to do this?
|
||||||
|
@ -100,488 +68,524 @@ struct ipc_error ipc_contact_networkd (struct ipc_connection_info *srv, const ch
|
||||||
// in order to route requests over any chosen protocol stack
|
// in order to route requests over any chosen protocol stack
|
||||||
// ex: IPC_NETWORK="audio tor://some.example.com/audio ;pong tls://pong.example.com/pong"
|
// ex: IPC_NETWORK="audio tor://some.example.com/audio ;pong tls://pong.example.com/pong"
|
||||||
|
|
||||||
// printf ("IPC_NETWORK: %s\n", networkvar);
|
|
||||||
|
|
||||||
SECURE_BUFFER_DECLARATION (char, columnthensname, BUFSIZ);
|
SECURE_BUFFER_DECLARATION (char, columnthensname, BUFSIZ);
|
||||||
columnthensname[0] = ';';
|
columnthensname[0] = ';';
|
||||||
memcpy (columnthensname + 1, sname, strlen (sname));
|
memcpy (columnthensname + 1, sname, strlen (sname));
|
||||||
|
|
||||||
if (strncmp (networkvar, sname, strlen (sname)) != 0 && strstr (networkvar, columnthensname) == NULL) {
|
if (strncmp (ipcd_var, sname, strlen (sname)) != 0 && strstr (ipcd_var, columnthensname) == NULL) {
|
||||||
// printf ("sname %s not found\n", sname);
|
*pfd = 0;
|
||||||
srv->fd = 0;
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
// printf ("(;)sname %s found\n", sname);
|
|
||||||
|
|
||||||
// gets the service path
|
// Get the service path.
|
||||||
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
||||||
TEST_IPC_RR (service_path (buf, "network", 0, 0), "cannot get network service path");
|
TEST_IPC_RR (service_path (buf, "network"), "cannot get network service path");
|
||||||
|
|
||||||
int networkdfd = 0;
|
int ipcd_fd = 0;
|
||||||
|
|
||||||
TEST_IPC_RETURN_ON_ERROR (usock_connect (&networkdfd, buf));
|
TEST_IPC_RETURN_ON_ERROR (usock_connect (&ipcd_fd, buf));
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_message, msg);
|
SECURE_DECLARATION (struct ipc_message, msg);
|
||||||
msg.type = MSG_TYPE_NETWORK_LOOKUP;
|
msg.type = MSG_TYPE_NETWORK_LOOKUP;
|
||||||
msg.user_type = MSG_TYPE_NETWORK_LOOKUP;
|
msg.user_type = MSG_TYPE_NETWORK_LOOKUP;
|
||||||
|
|
||||||
SECURE_BUFFER_DECLARATION (char, content, BUFSIZ);
|
SECURE_BUFFER_DECLARATION (char, content, BUFSIZ);
|
||||||
snprintf (content, BUFSIZ, "%s;%s", sname, networkvar);
|
snprintf (content, BUFSIZ, "%s;%s", sname, ipcd_var);
|
||||||
|
|
||||||
msg.length = strlen (content);
|
msg.length = strlen (content);
|
||||||
msg.payload = content;
|
msg.payload = content;
|
||||||
|
|
||||||
TEST_IPC_RR (ipc_write_fd (networkdfd, &msg), "cannot send a message to networkd");
|
TEST_IPC_RR (ipc_write_fd (ipcd_fd, &msg), "cannot send a message to networkd");
|
||||||
|
|
||||||
struct ipc_error ret = ipc_receive_fd (networkdfd, &srv->fd);
|
struct ipc_error ret = ipc_receive_fd (ipcd_fd, pfd);
|
||||||
if (ret.error_code == IPC_ERROR_NONE) {
|
if (ret.error_code == IPC_ERROR_NONE) {
|
||||||
usock_close (networkdfd);
|
usock_close (ipcd_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_connection (char **env, struct ipc_connection_info *srv, const char *sname)
|
// Create context, contact ipcd, connects to the service.
|
||||||
|
struct ipc_error ipc_connection_ (struct ipc_ctx *ctx, const char *sname, enum ipc_connection_type type, int *serverfd)
|
||||||
{
|
{
|
||||||
T_R ((env == NULL), IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM);
|
T_R ((ctx == NULL), IPC_ERROR_CONNECTION__NO_CTX);
|
||||||
T_R ((srv == NULL), IPC_ERROR_CONNECTION__NO_SERVER);
|
|
||||||
T_R ((sname == NULL), IPC_ERROR_CONNECTION__NO_SERVICE_NAME);
|
T_R ((sname == NULL), IPC_ERROR_CONNECTION__NO_SERVICE_NAME);
|
||||||
|
|
||||||
TEST_IPC_P (ipc_contact_networkd (srv, sname), "error during networkd connection");
|
SECURE_DECLARATION(struct ipc_connection_info, srv);
|
||||||
|
srv.type = type;
|
||||||
|
SECURE_DECLARATION(struct pollfd, pollfd);
|
||||||
|
pollfd.events = POLLIN;
|
||||||
|
|
||||||
// if networkd did not initiate the connection
|
TEST_IPC_P (ipc_contact_ipcd (&pollfd.fd, sname), "error during networkd connection");
|
||||||
if (srv->fd <= 0) {
|
|
||||||
|
// if ipcd did not initiate the connection
|
||||||
|
if (pollfd.fd <= 0) {
|
||||||
// gets the service path
|
// gets the service path
|
||||||
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
||||||
TEST_IPC_RR (service_path (buf, sname, srv->index, srv->version), "cannot get server path");
|
TEST_IPC_RR (service_path (buf, sname), "cannot get server path");
|
||||||
TEST_IPC_RETURN_ON_ERROR (usock_connect (&srv->fd, buf));
|
TEST_IPC_RETURN_ON_ERROR (usock_connect (&pollfd.fd, buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the server to the listened file descriptors.
|
||||||
|
TEST_IPC_RR (ipc_add (ctx, &srv, &pollfd), "cannot add the server in the context");
|
||||||
|
|
||||||
|
if (serverfd != NULL) {
|
||||||
|
*serverfd = pollfd.fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_server_close (struct ipc_connection_info *srv)
|
int ipc_ctx_fd_type (struct ipc_ctx *ctx, int fd, enum ipc_connection_type type)
|
||||||
{
|
{
|
||||||
usock_close (srv->fd);
|
if (ctx == NULL) {
|
||||||
struct ipc_error ret = usock_remove (srv->spath);
|
return -1;
|
||||||
if (srv->spath != NULL) {
|
|
||||||
free (srv->spath);
|
|
||||||
srv->spath = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ctx->size; i++) {
|
||||||
|
if (ctx->pollfd[i].fd == fd) {
|
||||||
|
ctx->cinfos[i].type = type;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipc_error ipc_connection (struct ipc_ctx *ctx, const char *sname)
|
||||||
|
{
|
||||||
|
// Data received on the socket = messages, not new clients, and not switched (no callbacks).
|
||||||
|
return ipc_connection_ (ctx, sname, IPC_CONNECTION_TYPE_IPC, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipc_error ipc_connection_switched (struct ipc_ctx *ctx, const char *sname, int clientfd, int *serverfd)
|
||||||
|
{
|
||||||
|
int sfd = 0;
|
||||||
|
// Data received are for switched fd (callbacks should be used).
|
||||||
|
struct ipc_error ret = ipc_connection_ (ctx
|
||||||
|
, sname
|
||||||
|
, IPC_CONNECTION_TYPE_SWITCHED
|
||||||
|
, &sfd);
|
||||||
|
|
||||||
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverfd != NULL) {
|
||||||
|
*serverfd = sfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipc_add_fd_switched (ctx, clientfd);
|
||||||
|
// ipc_ctx_fd_type (ctx, clientfd, IPC_CONNECTION_TYPE_SWITCHED);
|
||||||
|
ipc_ctx_switching_add (ctx, clientfd, sfd);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_close (struct ipc_connection_info *p)
|
struct ipc_error ipc_close_all (struct ipc_ctx *ctx)
|
||||||
{
|
{
|
||||||
return usock_close (p->fd);
|
T_R ((ctx == NULL), IPC_ERROR_CLOSE_ALL__NO_CTX_PARAM);
|
||||||
|
|
||||||
|
for (size_t i = 0 ; i < ctx->size ; i++) {
|
||||||
|
TEST_IPC_P (ipc_close (ctx, i), "cannot close a connection in handle_message");
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_accept (struct ipc_connection_info *srv, struct ipc_connection_info *p)
|
struct ipc_error ipc_close (struct ipc_ctx *ctx, uint32_t index)
|
||||||
{
|
{
|
||||||
T_R ((srv == NULL), IPC_ERROR_ACCEPT__NO_SERVICE_PARAM);
|
T_R ((ctx == NULL), IPC_ERROR_CLOSE__NO_CTX_PARAM);
|
||||||
T_R ((p == NULL), IPC_ERROR_ACCEPT__NO_CLIENT_PARAM);
|
|
||||||
|
|
||||||
TEST_IPC_RR (usock_accept (srv->fd, &p->fd), "cannot accept IPC connection");
|
SECURE_DECLARATION (struct ipc_error, ret);
|
||||||
p->type = IPC_CONNECTION_TYPE_IPC;
|
int fd = ctx->pollfd[index].fd;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (fd_is_valid (fd)) {
|
||||||
|
printf ("ipc_close: fd is valid ==> %d\n", fd);
|
||||||
|
|
||||||
|
if (ctx->cinfos[index].type == IPC_CONNECTION_TYPE_EXTERNAL) {
|
||||||
|
printf ("=== === === external fd: not closing %d\n", fd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = usock_close (fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf ("!!!!!!!!!!! !! !! !! IPC_CLOSE: fd is not valid!! ==> %d\n", fd);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Closing the file descriptor only if it is not an external connection,
|
||||||
|
// this should be handled by the libipc user application.
|
||||||
|
if (ctx->cinfos[index].type != IPC_CONNECTION_TYPE_EXTERNAL) {
|
||||||
|
ret = usock_close (fd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Verify that the close was OK.
|
||||||
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->cinfos[index].type == IPC_CONNECTION_TYPE_SERVER) {
|
||||||
|
ret = usock_remove (ctx->cinfos[index].spath);
|
||||||
|
if (ctx->cinfos[index].spath != NULL) {
|
||||||
|
free (ctx->cinfos[index].spath);
|
||||||
|
ctx->cinfos[index].spath = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New connection from a client.
|
||||||
|
struct ipc_error ipc_accept_add (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM);
|
||||||
|
T_R ((index >= ctx->size), IPC_ERROR_HANDLE_NEW_CONNECTION__INCONSISTENT_INDEX);
|
||||||
|
|
||||||
|
// Memory reallocation.
|
||||||
|
ipc_ctx_new_alloc (ctx);
|
||||||
|
|
||||||
|
int server_fd = ctx->pollfd[index].fd;
|
||||||
|
int *client_fd = &ctx->pollfd[ctx->size -1].fd;
|
||||||
|
|
||||||
|
TEST_IPC_RR (usock_accept (server_fd, client_fd), "cannot accept IPC connection");
|
||||||
|
ctx->pollfd[ctx->size -1].events = POLLIN; // Tell to poll(2) to watch for incoming data from this fd.
|
||||||
|
ctx->cinfos[ctx->size -1].type = IPC_CONNECTION_TYPE_IPC;
|
||||||
|
|
||||||
|
// Set the event structure.
|
||||||
|
uint32_t client_index = ctx->size - 1;
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_CONNECTION, client_index, *client_fd, NULL);
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// receive then format in an ipc_message structure
|
// receive then format in an ipc_message structure
|
||||||
struct ipc_error ipc_read (const struct ipc_connection_info *p, struct ipc_message *m)
|
struct ipc_error ipc_read (const struct ipc_ctx *ctx, uint32_t index, struct ipc_message *m)
|
||||||
{
|
{
|
||||||
T_R ((m == NULL), IPC_ERROR_READ__NO_MESSAGE_PARAM);
|
T_R ((m == NULL), IPC_ERROR_READ__NO_MESSAGE_PARAM);
|
||||||
|
|
||||||
char *buf = NULL;
|
|
||||||
size_t msize = IPC_MAX_MESSAGE_SIZE;
|
size_t msize = IPC_MAX_MESSAGE_SIZE;
|
||||||
|
SECURE_BUFFER_DECLARATION (char, buf, msize);
|
||||||
|
char *pbuf = buf;
|
||||||
|
|
||||||
// on error or closed recipient, the buffer already freed
|
// On error or closed recipient, the buffer already freed.
|
||||||
TEST_IPC_RETURN_ON_ERROR (usock_recv (p->fd, &buf, &msize));
|
TEST_IPC_RETURN_ON_ERROR (usock_recv (ctx->pollfd[index].fd, &pbuf, &msize));
|
||||||
TEST_IPC_RETURN_ON_ERROR_FREE (ipc_message_format_read (m, buf, msize), buf);
|
TEST_IPC_RETURN_ON_ERROR (ipc_message_format_read (m, buf, msize));
|
||||||
|
|
||||||
free (buf);
|
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR; // propagates ipc_message_format return
|
IPC_RETURN_NO_ERROR; // propagates ipc_message_format return
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_write_fd (int fd, const struct ipc_message *m)
|
struct ipc_error 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;
|
size_t msize = 0;
|
||||||
ipc_message_format_write (m, &buf, &msize);
|
SECURE_BUFFER_DECLARATION (char, buf, IPC_MAX_MESSAGE_SIZE);
|
||||||
|
char *pbuf = buf;
|
||||||
|
|
||||||
|
ipc_message_format_write (m, &pbuf, &msize);
|
||||||
|
|
||||||
size_t nbytes_sent = 0;
|
size_t nbytes_sent = 0;
|
||||||
TEST_IPC_RETURN_ON_ERROR_FREE (usock_send (fd, buf, msize, &nbytes_sent), buf);
|
TEST_IPC_RETURN_ON_ERROR (usock_send (fd, buf, msize, &nbytes_sent));
|
||||||
|
|
||||||
if (buf != NULL) {
|
|
||||||
free (buf);
|
|
||||||
}
|
|
||||||
// what was sent != what should have been sent
|
// what was sent != what should have been sent
|
||||||
T_R ((nbytes_sent != msize), IPC_ERROR_WRITE__NOT_ENOUGH_DATA);
|
T_R ((nbytes_sent != msize), IPC_ERROR_WRITE_FD__NOT_ENOUGH_DATA);
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_write (const struct ipc_connection_info *p, const struct ipc_message *m)
|
// Put the message in the list of messages to send.
|
||||||
|
struct ipc_error ipc_write (struct ipc_ctx *ctx, const struct ipc_message *m)
|
||||||
{
|
{
|
||||||
return ipc_write_fd (p->fd, m);
|
int found = 0;
|
||||||
}
|
for (size_t i = 0; i < ctx->size; i++) {
|
||||||
|
if (ctx->pollfd[i].fd == m->fd) {
|
||||||
struct ipc_error handle_new_connection (struct ipc_connection_info *cinfo, struct ipc_connection_infos *cinfos
|
ctx->pollfd[i].events |= POLLOUT;
|
||||||
, struct ipc_connection_info **new_client)
|
found = 1;
|
||||||
{
|
|
||||||
T_R ((cinfo == NULL), IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFO_PARAM);
|
|
||||||
T_R ((cinfos == NULL), 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);
|
|
||||||
|
|
||||||
TEST_IPC_RR (ipc_accept (cinfo, *new_client), "cannot accept the client during handle_new_connection");
|
|
||||||
TEST_IPC_RR (ipc_add (cinfos, *new_client), "cannot add the new accepted client");
|
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// new connection from a client
|
|
||||||
struct ipc_error handle_connection (struct ipc_event *event, struct ipc_connection_infos *cinfos
|
|
||||||
, struct ipc_connection_info *cinfo)
|
|
||||||
{
|
|
||||||
// connection
|
|
||||||
struct ipc_connection_info *new_client = NULL;
|
|
||||||
|
|
||||||
TEST_IPC_RR (handle_new_connection (cinfo, cinfos, &new_client), "cannot add new client");
|
|
||||||
|
|
||||||
IPC_EVENT_SET (event, IPC_EVENT_TYPE_CONNECTION, NULL, new_client);
|
|
||||||
IPC_RETURN_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// new message
|
|
||||||
struct ipc_error 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;
|
|
||||||
|
|
||||||
TEST_IPC_T_P_I_R (
|
|
||||||
/* function to test */ usock_recv (talkingfd, &buf, &msize)
|
|
||||||
, /* error condition */ ret.error_code != IPC_ERROR_NONE
|
|
||||||
&& ret.error_code != IPC_ERROR_CLOSED_RECIPIENT
|
|
||||||
, /* 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;
|
|
||||||
TEST_IPC_RETURN_ON_ERROR_FREE (usock_send (correspondingfd, buf, msize, &nbytes_sent), 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);
|
|
||||||
IPC_RETURN_NO_ERROR; // 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);
|
|
||||||
IPC_RETURN_NO_ERROR;
|
|
||||||
} 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 0
|
|
||||||
if (delfd >= 0) {
|
|
||||||
LOG_DEBUG ("disconnection of %d (and related fd %d)", talkingfd, delfd);
|
|
||||||
} else {
|
|
||||||
LOG_DEBUG ("disconnection of %d", talkingfd);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IPC_EVENT_SET (event, IPC_EVENT_TYPE_DISCONNECTION, NULL, pc);
|
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_CLOSED_RECIPIENT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no treatment of the socket if external socket
|
|
||||||
if (pc->type == IPC_CONNECTION_TYPE_EXTERNAL) {
|
T_R ((found == 0), IPC_ERROR_WRITE__FD_NOT_FOUND);
|
||||||
IPC_EVENT_SET (event, IPC_EVENT_TYPE_EXTRA_SOCKET, NULL, pc);
|
|
||||||
|
// Performs a deep copy of the structure.
|
||||||
|
return ipc_messages_add (&ctx->tx, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory then add a new connection to the context.
|
||||||
|
*/
|
||||||
|
struct ipc_error ipc_add (struct ipc_ctx *ctx, struct ipc_connection_info *p, struct pollfd *pollfd)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENTS);
|
||||||
|
T_R ((p == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENT);
|
||||||
|
T_R ((pollfd == NULL), IPC_ERROR_ADD__NO_PARAM_POLLFD);
|
||||||
|
|
||||||
|
// Memory reallocation.
|
||||||
|
ipc_ctx_new_alloc (ctx);
|
||||||
|
|
||||||
|
T_R ((ctx->size <= 0), IPC_ERROR_ADD__NOT_ENOUGH_MEMORY);
|
||||||
|
|
||||||
|
ctx->cinfos[ctx->size - 1] = *p;
|
||||||
|
ctx->pollfd[ctx->size - 1] = *pollfd;
|
||||||
|
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipc_error ipc_del (struct ipc_ctx *ctx, uint32_t index)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_DEL__NO_CLIENTS_PARAM);
|
||||||
|
T_R ((ctx->cinfos == NULL || ctx->pollfd == NULL), IPC_ERROR_DEL__EMPTY_LIST);
|
||||||
|
T_R ((index >= ctx->size), IPC_ERROR_DEL__CANNOT_FIND_CLIENT);
|
||||||
|
|
||||||
|
if (ctx->cinfos[index].spath != NULL) {
|
||||||
|
free (ctx->cinfos[index].spath);
|
||||||
|
ctx->cinfos[index].spath = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->size--;
|
||||||
|
|
||||||
|
if (ctx->size == 0) {
|
||||||
|
// free ctx->cinfos and ctx->pollfd
|
||||||
|
ipc_ctx_free (ctx);
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
// listen to what they have to say (disconnection or message)
|
|
||||||
// then add a client to `event`, the ipc_event structure
|
|
||||||
SECURE_DECLARATION (struct ipc_error, ret);
|
|
||||||
struct ipc_message *m = NULL;
|
|
||||||
|
|
||||||
|
// The last element in the array replaces the removed one.
|
||||||
|
ctx->cinfos[index] = ctx->cinfos[ctx->size];
|
||||||
|
ctx->pollfd[index] = ctx->pollfd[ctx->size];
|
||||||
|
|
||||||
|
// Reallocation of the arrays. TODO: should be optimised someday.
|
||||||
|
ctx->cinfos = realloc (ctx->cinfos, sizeof (struct ipc_connection_info) * ctx->size);
|
||||||
|
ctx->pollfd = realloc (ctx->pollfd, sizeof (struct pollfd ) * ctx->size);
|
||||||
|
|
||||||
|
if (ctx->cinfos == NULL || ctx->pollfd == NULL) {
|
||||||
|
IPC_RETURN_ERROR (IPC_ERROR_DEL__EMPTIED_LIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipc_error ipc_add_fd_ (struct ipc_ctx *ctx, int fd, enum ipc_connection_type type)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_ADD_FD__NO_PARAM_CINFOS);
|
||||||
|
|
||||||
|
SECURE_DECLARATION (struct ipc_connection_info, cinfo);
|
||||||
|
cinfo.type = type;
|
||||||
|
|
||||||
|
SECURE_DECLARATION (struct pollfd, pollfd);
|
||||||
|
pollfd.fd = fd;
|
||||||
|
pollfd.events = POLLIN;
|
||||||
|
|
||||||
|
return ipc_add (ctx, &cinfo, &pollfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a switched file descriptor to read
|
||||||
|
struct ipc_error ipc_add_fd_switched (struct ipc_ctx *ctx, int fd)
|
||||||
|
{
|
||||||
|
return ipc_add_fd_ (ctx, fd, IPC_CONNECTION_TYPE_SWITCHED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add an arbitrary file descriptor to read
|
||||||
|
struct ipc_error ipc_add_fd (struct ipc_ctx *ctx, int fd)
|
||||||
|
{
|
||||||
|
return ipc_add_fd_ (ctx, fd, IPC_CONNECTION_TYPE_EXTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove a connection from its file descriptor
|
||||||
|
struct ipc_error ipc_del_fd (struct ipc_ctx *ctx, int fd)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_DEL_FD__NO_PARAM_CINFOS);
|
||||||
|
T_R ((ctx->cinfos == NULL || ctx->pollfd == NULL), IPC_ERROR_DEL_FD__EMPTY_LIST);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ctx->size; i++) {
|
||||||
|
if (ctx->pollfd[i].fd == fd) {
|
||||||
|
return ipc_del (ctx, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_RETURN_ERROR (IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipc_error handle_writing_message (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index)
|
||||||
|
{
|
||||||
|
int txfd = ctx->pollfd[index].fd;
|
||||||
|
int mfd;
|
||||||
|
struct ipc_message *m;
|
||||||
|
for (size_t i = 0; ctx->tx.size ; i++) {
|
||||||
|
m = &ctx->tx.messages[i];
|
||||||
|
mfd = m->fd;
|
||||||
|
if (txfd == mfd) {
|
||||||
|
TEST_IPC_RR (ipc_write_fd (txfd, m), "cannot send a message to the client");
|
||||||
|
|
||||||
|
// Freeing the message structure.
|
||||||
|
ipc_message_empty (m);
|
||||||
|
// Removing the message from the context.
|
||||||
|
ipc_messages_del (&ctx->tx, i); // remove the message indexed by i
|
||||||
|
|
||||||
|
break; // The message has been sent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_TX, index, ctx->pollfd[index].fd, NULL);
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipc_error handle_new_message (struct ipc_event *event, struct ipc_ctx *ctx, int index)
|
||||||
|
{
|
||||||
|
SECURE_DECLARATION (struct ipc_error, ret);
|
||||||
|
|
||||||
|
// Listen to what they have to say (disconnection or message)
|
||||||
|
// then add a client to `event`, the ipc_event structure.
|
||||||
|
struct ipc_message *m = NULL;
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_R (m, sizeof (struct ipc_message),, IPC_ERROR_HANDLE_MESSAGE__NOT_ENOUGH_MEMORY);
|
SECURE_BUFFER_HEAP_ALLOCATION_R (m, sizeof (struct ipc_message),, IPC_ERROR_HANDLE_MESSAGE__NOT_ENOUGH_MEMORY);
|
||||||
|
|
||||||
// current talking client
|
// current talking client
|
||||||
ret = ipc_read (pc, m);
|
ret = ipc_read (ctx, index, m);
|
||||||
if (ret.error_code != IPC_ERROR_NONE && ret.error_code != IPC_ERROR_CLOSED_RECIPIENT) {
|
if (ret.error_code != IPC_ERROR_NONE && ret.error_code != IPC_ERROR_CLOSED_RECIPIENT) {
|
||||||
struct ipc_error rvalue = ret; // store the final return value
|
struct ipc_error rvalue = ret; // store the final return value
|
||||||
ipc_message_empty (m);
|
ipc_message_empty (m);
|
||||||
free (m);
|
free (m);
|
||||||
|
|
||||||
// if there is a problem, just remove the client
|
// if there is a problem, just remove the client
|
||||||
TEST_IPC_P (ipc_close (pc), "cannot close a connection in handle_message");
|
TEST_IPC_P (ipc_close (ctx, index), "cannot close a connection in handle_message");
|
||||||
TEST_IPC_P (ipc_del (cinfos, pc), "cannot delete a connection in handle_message");
|
TEST_IPC_P (ipc_del (ctx, index), "cannot delete a connection in handle_message");
|
||||||
|
|
||||||
IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, NULL, pc);
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, index, ctx->pollfd[index].fd, NULL);
|
||||||
return rvalue;
|
return rvalue;
|
||||||
}
|
}
|
||||||
// disconnection: close the client then delete it from cinfos
|
|
||||||
|
// disconnection: close the client then delete it from ctx
|
||||||
if (ret.error_code == IPC_ERROR_CLOSED_RECIPIENT) {
|
if (ret.error_code == IPC_ERROR_CLOSED_RECIPIENT) {
|
||||||
TEST_IPC_P (ipc_close (pc), "cannot close a connection on closed recipient in handle_message");
|
|
||||||
TEST_IPC_P (ipc_del (cinfos, pc), "cannot delete a connection on closed recipient in handle_message");
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_DISCONNECTION, index, ctx->pollfd[index].fd, NULL);
|
||||||
|
|
||||||
|
TEST_IPC_P (ipc_close (ctx, index), "cannot close a connection on closed recipient in handle_message");
|
||||||
|
TEST_IPC_P (ipc_del (ctx, index), "cannot delete a connection on closed recipient in handle_message");
|
||||||
|
|
||||||
ipc_message_empty (m);
|
ipc_message_empty (m);
|
||||||
free (m);
|
free (m);
|
||||||
|
|
||||||
IPC_EVENT_SET (event, IPC_EVENT_TYPE_DISCONNECTION, NULL, pc);
|
|
||||||
|
|
||||||
// warning: do not forget to free the ipc_client structure
|
// warning: do not forget to free the ipc_client structure
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC_EVENT_SET (event, IPC_EVENT_TYPE_MESSAGE, m, pc);
|
// The message carries the fd it was received on.
|
||||||
|
m->fd = ctx->pollfd[index].fd;
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_MESSAGE, index, ctx->pollfd[index].fd, m);
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_wait_event_networkd (struct ipc_connection_infos *cinfos
|
struct ipc_error
|
||||||
, struct ipc_connection_info *cinfo // NULL for clients
|
handle_writing_switched_message (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index)
|
||||||
, struct ipc_event *event, struct ipc_switchings *switchdb
|
|
||||||
, double *timer)
|
|
||||||
{
|
{
|
||||||
T_R ((cinfos == NULL), IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM);
|
return fd_switching_write (event, ctx, index);
|
||||||
T_R ((event == NULL), IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM);
|
}
|
||||||
|
|
||||||
|
struct ipc_error
|
||||||
|
handle_switched_message(struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index)
|
||||||
|
{
|
||||||
|
return fd_switching_read (event, ctx, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* timer is in ms */
|
||||||
|
struct ipc_error ipc_wait_event (struct ipc_ctx *ctx, struct ipc_event *event, int *timer)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM);
|
||||||
|
T_R ((event == NULL), IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM);
|
||||||
|
|
||||||
IPC_EVENT_CLEAN (event);
|
IPC_EVENT_CLEAN (event);
|
||||||
|
|
||||||
size_t i, j;
|
int32_t n;
|
||||||
/* master file descriptor list */
|
|
||||||
fd_set master;
|
|
||||||
fd_set readf;
|
|
||||||
|
|
||||||
/* clear the master and temp sets */
|
for (size_t i = 0; i < ctx->tx.size; i++) {
|
||||||
FD_ZERO (&master);
|
for (size_t y = 0; y < ctx->size; y++) {
|
||||||
FD_ZERO (&readf);
|
if (ctx->pollfd[y].fd == ctx->tx.messages[i].fd) {
|
||||||
|
ctx->pollfd[y].events |= POLLOUT;
|
||||||
/* maximum file descriptor number */
|
break;
|
||||||
/* keep track of the biggest file descriptor */
|
|
||||||
int32_t fdmax = get_max_fd (cinfos);
|
|
||||||
|
|
||||||
/* listening socket descriptor */
|
|
||||||
int32_t listener;
|
|
||||||
if (cinfo != NULL) {
|
|
||||||
listener = cinfo->fd;
|
|
||||||
|
|
||||||
/* add the listener to the master set */
|
|
||||||
FD_SET (listener, &master);
|
|
||||||
|
|
||||||
/* if listener is max fd */
|
|
||||||
if (fdmax < listener)
|
|
||||||
fdmax = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < cinfos->size; i++) {
|
|
||||||
FD_SET (cinfos->cinfos[i]->fd, &master);
|
|
||||||
}
|
|
||||||
|
|
||||||
readf = master;
|
|
||||||
|
|
||||||
struct timeval *ptimeout = NULL;
|
|
||||||
SECURE_DECLARATION (struct timeval, timeout);
|
|
||||||
|
|
||||||
if (timer != NULL && *timer > 0.0) {
|
|
||||||
timeout.tv_sec = (long) *timer;
|
|
||||||
timeout.tv_usec = (long) ((long)((*timer) * 1000000) % 1000000);
|
|
||||||
ptimeout = &timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
T_PERROR_RIPC ((select (fdmax + 1, &readf, NULL, NULL, ptimeout) == -1), "select", IPC_ERROR_WAIT_EVENT__SELECT);
|
|
||||||
|
|
||||||
if (ptimeout != NULL) {
|
|
||||||
*timer = (double) timeout.tv_sec + (timeout.tv_usec / 1000000.0);
|
|
||||||
if (*timer == 0) {
|
|
||||||
IPC_EVENT_SET (event, IPC_EVENT_TYPE_TIMER, NULL, NULL);
|
|
||||||
IPC_RETURN_NO_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i <= (size_t) fdmax; i++) {
|
|
||||||
if (FD_ISSET (i, &readf)) {
|
|
||||||
if (cinfo != NULL && i == (size_t) listener) {
|
|
||||||
return handle_connection (event, cinfos, cinfo);
|
|
||||||
} else {
|
|
||||||
for (j = 0; j < cinfos->size; j++) {
|
|
||||||
if (i == (size_t) cinfos->cinfos[j]->fd) {
|
|
||||||
return handle_message (event, cinfos, cinfos->cinfos[j], switchdb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
struct timeval tv_1;
|
||||||
}
|
memset (&tv_1, 0, sizeof(struct timeval));
|
||||||
|
|
||||||
struct ipc_error ipc_wait_event (struct ipc_connection_infos *cinfos
|
struct timeval tv_2;
|
||||||
, struct ipc_connection_info *cinfo // NULL for clients
|
memset (&tv_2, 0, sizeof(struct timeval));
|
||||||
, struct ipc_event *event, double *timer)
|
|
||||||
{
|
|
||||||
return ipc_wait_event_networkd (cinfos, cinfo, event, NULL, timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// store and remove only pointers on allocated structures
|
gettimeofday(&tv_1, NULL);
|
||||||
struct ipc_error ipc_add (struct ipc_connection_infos *cinfos, struct ipc_connection_info *p)
|
|
||||||
{
|
|
||||||
T_R ((cinfos == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENTS);
|
|
||||||
T_R ((p == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENT);
|
|
||||||
|
|
||||||
cinfos->size++;
|
if ((n = poll(ctx->pollfd, ctx->size, *timer)) < 0) {
|
||||||
if (cinfos->size == 1 && cinfos->cinfos == NULL) {
|
IPC_RETURN_ERROR (IPC_ERROR_WAIT_EVENT__POLL);
|
||||||
// first allocation
|
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_R (cinfos->cinfos, sizeof (struct ipc_connection_info),,
|
|
||||||
IPC_ERROR_ADD__MALLOC);
|
|
||||||
} else {
|
|
||||||
cinfos->cinfos = realloc (cinfos->cinfos, sizeof (struct ipc_connection_info) * cinfos->size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
T_R ((cinfos->cinfos == NULL), IPC_ERROR_ADD__EMPTY_LIST);
|
gettimeofday(&tv_2, NULL);
|
||||||
|
|
||||||
cinfos->cinfos[cinfos->size - 1] = p;
|
int nb_sec_ms = (tv_2.tv_sec - tv_1.tv_sec) * 1000;
|
||||||
IPC_RETURN_NO_ERROR;
|
int nb_usec_ms = (tv_2.tv_usec - tv_1.tv_usec) / 1000;
|
||||||
}
|
int time_elapsed_ms = (nb_sec_ms + nb_usec_ms);
|
||||||
|
|
||||||
struct ipc_error ipc_del (struct ipc_connection_infos *cinfos, struct ipc_connection_info *p)
|
// Handle memory fuckery, 'cause low level programming is fun.
|
||||||
{
|
if (time_elapsed_ms >= *timer) {
|
||||||
T_R ((cinfos == NULL), IPC_ERROR_DEL__NO_CLIENTS_PARAM);
|
*timer = 0;
|
||||||
T_R ((p == NULL), IPC_ERROR_DEL__NO_CLIENT_PARAM);
|
}
|
||||||
T_R ((cinfos->cinfos == NULL), IPC_ERROR_DEL__EMPTY_LIST);
|
else {
|
||||||
|
*timer -= time_elapsed_ms;
|
||||||
|
}
|
||||||
|
|
||||||
size_t i;
|
// Timeout.
|
||||||
for (i = 0; i < cinfos->size; i++) {
|
if (n == 0) {
|
||||||
if (cinfos->cinfos[i] == p) {
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_TIMER, 0, 0, NULL);
|
||||||
// TODO: possible memory leak if the ipc_connection_info is not free'ed
|
IPC_RETURN_NO_ERROR;
|
||||||
cinfos->cinfos[i] = cinfos->cinfos[cinfos->size - 1];
|
}
|
||||||
cinfos->size--;
|
|
||||||
if (cinfos->size == 0) {
|
|
||||||
ipc_connections_free (cinfos);
|
|
||||||
} else {
|
|
||||||
cinfos->cinfos = realloc (cinfos->cinfos, sizeof (struct ipc_connection_info) * cinfos->size);
|
|
||||||
|
|
||||||
if (cinfos->cinfos == NULL) {
|
for (size_t i = 0; i <= ctx->size; i++) {
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_DEL__EMPTIED_LIST);
|
// Something to read or connection.
|
||||||
}
|
if (ctx->pollfd[i].revents & POLLIN) {
|
||||||
|
// In case there is something to read for the server socket: new client.
|
||||||
|
if (ctx->cinfos[i].type == IPC_CONNECTION_TYPE_SERVER) {
|
||||||
|
return ipc_accept_add (event, ctx, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
// fd is switched: using callbacks for IO operations.
|
||||||
|
if (ctx->cinfos[i].type == IPC_CONNECTION_TYPE_SWITCHED) {
|
||||||
|
#if 0
|
||||||
|
int fd_validity = fd_is_valid (ctx->pollfd[i].fd);
|
||||||
|
if (! fd_validity) {
|
||||||
|
printf ("switch happening in C: %d FD IS INVALID:::::::::: IM BROKEN INSIIIIIIIDE\n", ctx->pollfd[i].fd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return handle_switched_message (event, ctx, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No treatment of the socket if external socket: the libipc user should handle IO operations.
|
||||||
|
if (ctx->cinfos[i].type == IPC_CONNECTION_TYPE_EXTERNAL) {
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_EXTRA_SOCKET, i, ctx->pollfd[i].fd, NULL);
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle_new_message (event, ctx, i);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_DEL__CANNOT_FIND_CLIENT);
|
// Something can be sent.
|
||||||
}
|
if (ctx->pollfd[i].revents & POLLOUT) {
|
||||||
|
ctx->pollfd[i].events &= ~POLLOUT;
|
||||||
|
|
||||||
void ipc_connections_close (struct ipc_connection_infos *cinfos)
|
// fd is switched: using callbacks for IO operations.
|
||||||
{
|
if (ctx->cinfos[i].type == IPC_CONNECTION_TYPE_SWITCHED) {
|
||||||
if (cinfos->cinfos != NULL) {
|
return handle_writing_switched_message (event, ctx, i);
|
||||||
for (size_t i = 0; i < cinfos->size; i++) {
|
}
|
||||||
ipc_close (cinfos->cinfos[i]);
|
|
||||||
free (cinfos->cinfos[i]);
|
return handle_writing_message (event, ctx, i);
|
||||||
}
|
}
|
||||||
free (cinfos->cinfos);
|
|
||||||
cinfos->cinfos = NULL;
|
|
||||||
}
|
|
||||||
cinfos->size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ipc_connections_free (struct ipc_connection_infos *cinfos)
|
// Disconnection.
|
||||||
{
|
if (ctx->pollfd[i].revents & POLLHUP) {
|
||||||
if (cinfos->cinfos != NULL) {
|
/** IPC_EVENT_SET: event, type, index, fd, message */
|
||||||
for (size_t i = 0; i < cinfos->size; i++) {
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_DISCONNECTION, i, ctx->pollfd[i].fd, NULL);
|
||||||
free (cinfos->cinfos[i]);
|
return ipc_close (ctx, i);
|
||||||
}
|
}
|
||||||
free (cinfos->cinfos);
|
|
||||||
cinfos->cinfos = NULL;
|
|
||||||
}
|
|
||||||
cinfos->size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the client service structure
|
} /** for loop: end of the message handling */
|
||||||
struct ipc_error ipc_connection_gen (struct ipc_connection_info *cinfo
|
|
||||||
, uint32_t index, uint32_t version
|
|
||||||
, int fd, char type)
|
|
||||||
{
|
|
||||||
T_R ((cinfo == NULL), IPC_ERROR_CONNECTION_GEN__NO_CINFO);
|
|
||||||
|
|
||||||
cinfo->type = type;
|
|
||||||
cinfo->version = version;
|
|
||||||
cinfo->index = index;
|
|
||||||
cinfo->fd = fd;
|
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add an arbitrary file descriptor to read
|
|
||||||
struct ipc_error ipc_add_fd (struct ipc_connection_infos *cinfos, int fd)
|
|
||||||
{
|
|
||||||
T_R ((cinfos == NULL), IPC_ERROR_ADD_FD__NO_PARAM_CINFOS);
|
|
||||||
|
|
||||||
struct ipc_connection_info *cinfo = NULL;
|
|
||||||
|
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_R (cinfo, sizeof (struct ipc_connection_info),,
|
|
||||||
IPC_ERROR_ADD_FD__NOT_ENOUGH_MEMORY);
|
|
||||||
|
|
||||||
ipc_connection_gen (cinfo, 0, 0, fd, IPC_CONNECTION_TYPE_EXTERNAL);
|
|
||||||
|
|
||||||
return ipc_add (cinfos, cinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove a connection from its file descriptor
|
|
||||||
struct ipc_error ipc_del_fd (struct ipc_connection_infos *cinfos, int fd)
|
|
||||||
{
|
|
||||||
T_R ((cinfos == NULL), IPC_ERROR_DEL_FD__NO_PARAM_CINFOS);
|
|
||||||
T_R ((cinfos->cinfos == NULL), IPC_ERROR_DEL_FD__EMPTY_LIST);
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < cinfos->size; i++) {
|
|
||||||
if (cinfos->cinfos[i]->fd == fd) {
|
|
||||||
cinfos->cinfos[i]->fd = -1;
|
|
||||||
free (cinfos->cinfos[i]);
|
|
||||||
cinfos->size--;
|
|
||||||
if (cinfos->size == 0) {
|
|
||||||
// free cinfos->cinfos
|
|
||||||
ipc_connections_free (cinfos);
|
|
||||||
} else {
|
|
||||||
cinfos->cinfos[i] = cinfos->cinfos[cinfos->size];
|
|
||||||
cinfos->cinfos = realloc (cinfos->cinfos, sizeof (struct ipc_connection_info) * cinfos->size);
|
|
||||||
|
|
||||||
if (cinfos->cinfos == NULL) {
|
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_DEL_FD__EMPTIED_LIST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT);
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "ipc.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PERFORMANCE POINT:
|
||||||
|
* Realloc is performed at each new user. There is plenty of room for improvement,
|
||||||
|
* for example by managing allocations of thousands of structures at once.
|
||||||
|
* WARNING: Store and remove only pointers on allocated structures.
|
||||||
|
*/
|
||||||
|
struct ipc_error ipc_ctx_new_alloc (struct ipc_ctx *ctx)
|
||||||
|
{
|
||||||
|
ctx->size++;
|
||||||
|
|
||||||
|
// Memory could be not allocated, yet.
|
||||||
|
if (ctx->size == 1 && ctx->cinfos == NULL && ctx->pollfd == NULL) {
|
||||||
|
SECURE_BUFFER_HEAP_ALLOCATION_R (ctx->cinfos, sizeof (struct ipc_connection_info),,
|
||||||
|
IPC_ERROR_ADD__MALLOC);
|
||||||
|
SECURE_BUFFER_HEAP_ALLOCATION_R (ctx->pollfd, sizeof (struct pollfd),, IPC_ERROR_ADD__MALLOC_POLLFD);
|
||||||
|
} else {
|
||||||
|
ctx->cinfos = realloc (ctx->cinfos, sizeof (struct ipc_connection_info) * ctx->size);
|
||||||
|
ctx->pollfd = realloc (ctx->pollfd, sizeof (struct pollfd ) * ctx->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
T_R ((ctx->cinfos == NULL), IPC_ERROR_ADD__EMPTY_LIST);
|
||||||
|
T_R ((ctx->pollfd == NULL), IPC_ERROR_ADD__EMPTY_LIST);
|
||||||
|
|
||||||
|
// Clean the last entry.
|
||||||
|
memset (&ctx->cinfos[ctx->size -1], 0, sizeof (struct ipc_connection_info));
|
||||||
|
memset (&ctx->pollfd[ctx->size -1], 0, sizeof (struct pollfd));
|
||||||
|
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipc_ctx_free (struct ipc_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->cinfos != NULL) {
|
||||||
|
free (ctx->cinfos);
|
||||||
|
ctx->cinfos = NULL;
|
||||||
|
}
|
||||||
|
if (ctx->pollfd != NULL) {
|
||||||
|
free (ctx->pollfd);
|
||||||
|
ctx->pollfd = NULL;
|
||||||
|
}
|
||||||
|
ctx->size = 0;
|
||||||
|
|
||||||
|
ipc_switching_free(&ctx->switchdb);
|
||||||
|
|
||||||
|
ipc_messages_free (&ctx->tx);
|
||||||
|
}
|
36
src/error.c
36
src/error.c
|
@ -12,22 +12,15 @@ static struct ipc_errors_verbose ipc_errors_verbose[] = {
|
||||||
{IPC_ERROR_NONE, "no error"}
|
{IPC_ERROR_NONE, "no error"}
|
||||||
, {IPC_ERROR_CLOSED_RECIPIENT, "closed recipient"}
|
, {IPC_ERROR_CLOSED_RECIPIENT, "closed recipient"}
|
||||||
|
|
||||||
, {IPC_ERROR_SERVER_INIT__NO_DIR_CANNOT_CREATE_IT,
|
|
||||||
"ipc_server_init: no directory for ipc and cannot to create it"}
|
|
||||||
, {IPC_ERROR_SERVER_INIT__NON_WRITABLE_DIR, "ipc_server_init: non writable directory for ipc"}
|
|
||||||
|
|
||||||
, {IPC_ERROR_SERVER_INIT__NO_ENVIRONMENT_PARAM, "ipc_server_init: no environment param"}
|
, {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_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__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__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_SERVICE_NAME, "ipc_connection: no service name parameter"}
|
||||||
, {IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM, "ipc_connection: no environment param"}
|
, {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_USOCK_CONNECT__CONNECT, "ipc_connection: error on the connect function"}
|
||||||
|
|
||||||
, {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_SERVICE_PARAM, "ipc_accept: no service param"}
|
||||||
, {IPC_ERROR_ACCEPT__NO_CLIENT_PARAM , "ipc_accept: no client param"}
|
, {IPC_ERROR_ACCEPT__NO_CLIENT_PARAM , "ipc_accept: no client param"}
|
||||||
|
|
||||||
|
@ -36,7 +29,7 @@ static struct ipc_errors_verbose ipc_errors_verbose[] = {
|
||||||
, {IPC_ERROR_PROVIDE_FD__SENDMSG , "ipc_provide_fd: sendmsg function"}
|
, {IPC_ERROR_PROVIDE_FD__SENDMSG , "ipc_provide_fd: sendmsg function"}
|
||||||
|
|
||||||
, {IPC_ERROR_WRITE__NO_MESSAGE_PARAM, "ipc_write: no message 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_WRITE_FD__NOT_ENOUGH_DATA , "ipc_write: no enough data sent"}
|
||||||
, {IPC_ERROR_READ__NO_MESSAGE_PARAM , "ipc_read: no message param"}
|
, {IPC_ERROR_READ__NO_MESSAGE_PARAM , "ipc_read: no message param"}
|
||||||
|
|
||||||
, {IPC_ERROR_HANDLE_MESSAGE__NOT_ENOUGH_MEMORY , "handle_message: not enough memory"}
|
, {IPC_ERROR_HANDLE_MESSAGE__NOT_ENOUGH_MEMORY , "handle_message: not enough memory"}
|
||||||
|
@ -47,8 +40,8 @@ static struct ipc_errors_verbose ipc_errors_verbose[] = {
|
||||||
, {IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM, "ipc_wait_event: no clients param"}
|
, {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_WAIT_EVENT__NO_EVENT_PARAM , "ipc_wait_event: no event param"}
|
||||||
|
|
||||||
, {IPC_ERROR_CONTACT_NETWORKD__NO_SERVICE_NAME_PARAM, "ipc_contact_networkd: no service name param"}
|
, {IPC_ERROR_CONTACT_IPCD__NO_SERVICE_NAME_PARAM, "ipc_contact_ipcd: no service name param"}
|
||||||
, {IPC_ERROR_CONTACT_NETWORKD__NO_SERVER_PARAM , "ipc_contact_networkd: no server param"}
|
, {IPC_ERROR_CONTACT_IPCD__NO_SERVER_PARAM , "ipc_contact_ipcd: no server param"}
|
||||||
|
|
||||||
, {IPC_ERROR_HANDLE_NEW_CONNECTION__MALLOC, "ipc_handle_new_connection: error on malloc function"}
|
, {IPC_ERROR_HANDLE_NEW_CONNECTION__MALLOC, "ipc_handle_new_connection: error on malloc function"}
|
||||||
|
|
||||||
|
@ -127,6 +120,29 @@ static struct ipc_errors_verbose ipc_errors_verbose[] = {
|
||||||
|
|
||||||
, {IPC_ERROR_DIR_SETUP__DIRECTORY_NOT_WRITABLE, "directory_setup_: directory not writable"}
|
, {IPC_ERROR_DIR_SETUP__DIRECTORY_NOT_WRITABLE, "directory_setup_: directory not writable"}
|
||||||
, {IPC_ERROR_DIRECTORY_SETUP__PATH_PARAM , "directory_setup_: no path param"}
|
, {IPC_ERROR_DIRECTORY_SETUP__PATH_PARAM , "directory_setup_: no path param"}
|
||||||
|
|
||||||
|
, {IPC_ERROR_SERVER_INIT__NOT_ENOUGH_MEMORY, "IPC_ERROR_SERVER_INIT__NOT_ENOUGH_MEMORY"}
|
||||||
|
, {IPC_ERROR_CONNECTION__NOT_ENOUGH_MEMORY, "IPC_ERROR_CONNECTION__NOT_ENOUGH_MEMORY"}
|
||||||
|
, {IPC_ERROR_CTX_INIT__NO_CONTEXT_PARAM, "IPC_ERROR_CTX_INIT__NO_CONTEXT_PARAM"}
|
||||||
|
, {IPC_ERROR_CTX_INIT__CONTEXT_ALREADY_INIT, "IPC_ERROR_CTX_INIT__CONTEXT_ALREADY_INIT"}
|
||||||
|
, {IPC_ERROR_ADD__MALLOC_POLLFD, "IPC_ERROR_ADD__MALLOC_POLLFD"}
|
||||||
|
, {IPC_ERROR_ADD_MESSAGE_TO_SEND__EMPTY_LIST, "IPC_ERROR_ADD_MESSAGE_TO_SEND__EMPTY_LIST"}
|
||||||
|
, {IPC_ERROR_ADD_MESSAGE_TO_SEND__MALLOC, "IPC_ERROR_ADD_MESSAGE_TO_SEND__MALLOC"}
|
||||||
|
, {IPC_ERROR_ADD_MESSAGE_TO_SEND__NO_PARAM_MESSAGE, "IPC_ERROR_ADD_MESSAGE_TO_SEND__NO_PARAM_MESSAGE"}
|
||||||
|
, {IPC_ERROR_ADD_MESSAGE_TO_SEND__NO_PARAM_MESSAGES, "IPC_ERROR_ADD_MESSAGE_TO_SEND__NO_PARAM_MESSAGES"}
|
||||||
|
, {IPC_ERROR_CONNECTION__NO_CTX, "IPC_ERROR_CONNECTION__NO_CTX"}
|
||||||
|
, {IPC_ERROR_CTX_INIT__MALLOC_CTX, "IPC_ERROR_CTX_INIT__MALLOC_CTX"}
|
||||||
|
, {IPC_ERROR_CTX_INIT__MALLOC_POLLFD, "IPC_ERROR_CTX_INIT__MALLOC_POLLFD"}
|
||||||
|
, {IPC_ERROR_CONTACT_IPCD__NO_FD_PARAM, "IPC_ERROR_CONTACT_IPCD__NO_FD_PARAM"}
|
||||||
|
, {IPC_ERROR_HANDLE_NEW_CONNECTION__INCONSISTENT_INDEX, "IPC_ERROR_HANDLE_NEW_CONNECTION__INCONSISTENT_INDEX"}
|
||||||
|
, {IPC_ERROR_DEL_MESSAGE_TO_SEND__NO_PARAM_MESSAGES, "IPC_ERROR_DEL_MESSAGE_TO_SEND__NO_PARAM_MESSAGES"}
|
||||||
|
, {IPC_ERROR_MESSAGE_DEL__INDEX_ERROR, "IPC_ERROR_MESSAGE_DEL__INDEX_ERROR"}
|
||||||
|
, {IPC_ERROR_MESSAGE_DEL__EMPTY_LIST, "IPC_ERROR_MESSAGE_DEL__EMPTY_LIST"}
|
||||||
|
, {IPC_ERROR_ADD__NO_PARAM_POLLFD, "IPC_ERROR_ADD__NO_PARAM_POLLFD"}
|
||||||
|
, {IPC_ERROR_WRITE__FD_NOT_FOUND, "IPC_ERROR_WRITE__FD_NOT_FOUND"}
|
||||||
|
, {IPC_ERROR_FD_SWITCHING__NO_FD_RECORD, "IPC_ERROR_FD_SWITCHING__NO_FD_RECORD"}
|
||||||
|
, {IPC_ERROR_CLOSE_ALL__NO_CTX_PARAM, "IPC_ERROR_CLOSE_ALL__NO_CTX_PARAM" }
|
||||||
|
, {IPC_ERROR_CLOSE__NO_CTX_PARAM, "IPC_ERROR_CLOSE__NO_CTX_PARAM"}
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *ipc_errors_get (enum ipc_error_code e)
|
const char *ipc_errors_get (enum ipc_error_code e)
|
||||||
|
|
247
src/ipc.h
247
src/ipc.h
|
@ -9,6 +9,8 @@
|
||||||
#include <errno.h> // error numbers
|
#include <errno.h> // error numbers
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* global defaults
|
* global defaults
|
||||||
**/
|
**/
|
||||||
|
@ -73,13 +75,23 @@ enum msg_types {
|
||||||
enum ipc_event_type {
|
enum ipc_event_type {
|
||||||
IPC_EVENT_TYPE_NOT_SET = 0
|
IPC_EVENT_TYPE_NOT_SET = 0
|
||||||
, IPC_EVENT_TYPE_ERROR = 1
|
, IPC_EVENT_TYPE_ERROR = 1
|
||||||
, IPC_EVENT_TYPE_EXTRA_SOCKET = 2
|
, IPC_EVENT_TYPE_EXTRA_SOCKET = 2 // Message received from a non IPC socket.
|
||||||
, IPC_EVENT_TYPE_SWITCH = 3
|
, IPC_EVENT_TYPE_SWITCH = 3 // Message to send to a corresponding fd.
|
||||||
, IPC_EVENT_TYPE_CONNECTION = 4
|
, IPC_EVENT_TYPE_CONNECTION = 4 // New user.
|
||||||
, IPC_EVENT_TYPE_DISCONNECTION = 5
|
, IPC_EVENT_TYPE_DISCONNECTION = 5 // User disconnected.
|
||||||
, IPC_EVENT_TYPE_MESSAGE = 6
|
, IPC_EVENT_TYPE_MESSAGE = 6 // New message.
|
||||||
, IPC_EVENT_TYPE_LOOKUP = 7
|
, IPC_EVENT_TYPE_LOOKUP = 7 // Client asking for a service through ipcd.
|
||||||
, IPC_EVENT_TYPE_TIMER = 8
|
, IPC_EVENT_TYPE_TIMER = 8 // Timeout in the poll(2) function.
|
||||||
|
, IPC_EVENT_TYPE_TX = 9 // Message sent.
|
||||||
|
};
|
||||||
|
|
||||||
|
// For IO callbacks (switching).
|
||||||
|
enum ipccb {
|
||||||
|
IPC_CB_NO_ERROR = 0 // No error. A message was generated.
|
||||||
|
, IPC_CB_FD_CLOSING = 1 // The fd is closing.
|
||||||
|
, IPC_CB_FD_ERROR = 2 // Generic error.
|
||||||
|
, IPC_CB_PARSING_ERROR = 3 // The message was read but with errors.
|
||||||
|
, IPC_CB_IGNORE = 4 // The message should be ignored (protocol specific).
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,8 +100,6 @@ enum ipc_event_type {
|
||||||
*/
|
*/
|
||||||
enum ipc_error_code {
|
enum ipc_error_code {
|
||||||
IPC_ERROR_NONE = 0
|
IPC_ERROR_NONE = 0
|
||||||
, IPC_ERROR_SERVER_INIT__NON_WRITABLE_DIR = 1
|
|
||||||
, IPC_ERROR_SERVER_INIT__NO_DIR_CANNOT_CREATE_IT = 2
|
|
||||||
, IPC_ERROR_HANDLE_MESSAGE__NOT_ENOUGH_MEMORY = 3
|
, IPC_ERROR_HANDLE_MESSAGE__NOT_ENOUGH_MEMORY = 3
|
||||||
, IPC_ERROR_CLOSED_RECIPIENT = 4
|
, IPC_ERROR_CLOSED_RECIPIENT = 4
|
||||||
, IPC_ERROR_SERVICE_PATH__NO_PATH = 5
|
, IPC_ERROR_SERVICE_PATH__NO_PATH = 5
|
||||||
|
@ -99,12 +109,10 @@ enum ipc_error_code {
|
||||||
, IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM = 9
|
, IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM = 9
|
||||||
, IPC_ERROR_SERVER_INIT__MALLOC = 10
|
, IPC_ERROR_SERVER_INIT__MALLOC = 10
|
||||||
, IPC_ERROR_WRITE__NO_MESSAGE_PARAM = 11
|
, IPC_ERROR_WRITE__NO_MESSAGE_PARAM = 11
|
||||||
, IPC_ERROR_WRITE__NOT_ENOUGH_DATA = 12
|
, IPC_ERROR_WRITE_FD__NOT_ENOUGH_DATA = 12
|
||||||
, IPC_ERROR_READ__NO_MESSAGE_PARAM = 13
|
, IPC_ERROR_READ__NO_MESSAGE_PARAM = 13
|
||||||
, IPC_ERROR_CONNECTION__NO_SERVER = 14
|
|
||||||
, IPC_ERROR_CONNECTION__NO_SERVICE_NAME = 15
|
, IPC_ERROR_CONNECTION__NO_SERVICE_NAME = 15
|
||||||
, IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM = 16
|
, IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM = 16
|
||||||
, IPC_ERROR_CONNECTION_GEN__NO_CINFO = 17
|
|
||||||
, IPC_ERROR_ACCEPT__NO_SERVICE_PARAM = 18
|
, IPC_ERROR_ACCEPT__NO_SERVICE_PARAM = 18
|
||||||
, IPC_ERROR_ACCEPT__NO_CLIENT_PARAM = 19
|
, IPC_ERROR_ACCEPT__NO_CLIENT_PARAM = 19
|
||||||
, IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFO_PARAM = 20
|
, IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFO_PARAM = 20
|
||||||
|
@ -123,8 +131,8 @@ enum ipc_error_code {
|
||||||
, IPC_ERROR_DEL_FD__EMPTIED_LIST = 33
|
, IPC_ERROR_DEL_FD__EMPTIED_LIST = 33
|
||||||
, IPC_ERROR_DEL_FD__EMPTY_LIST = 34
|
, IPC_ERROR_DEL_FD__EMPTY_LIST = 34
|
||||||
, IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT = 35
|
, IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT = 35
|
||||||
, IPC_ERROR_CONTACT_NETWORKD__NO_SERVICE_NAME_PARAM = 36
|
, IPC_ERROR_CONTACT_IPCD__NO_SERVICE_NAME_PARAM = 36
|
||||||
, IPC_ERROR_CONTACT_NETWORKD__NO_SERVER_PARAM = 37
|
, IPC_ERROR_CONTACT_IPCD__NO_SERVER_PARAM = 37
|
||||||
, IPC_ERROR_DEL__EMPTY_LIST = 38
|
, IPC_ERROR_DEL__EMPTY_LIST = 38
|
||||||
, IPC_ERROR_DEL__EMPTIED_LIST = 39
|
, IPC_ERROR_DEL__EMPTIED_LIST = 39
|
||||||
, IPC_ERROR_DEL__CANNOT_FIND_CLIENT = 40
|
, IPC_ERROR_DEL__CANNOT_FIND_CLIENT = 40
|
||||||
|
@ -173,6 +181,31 @@ enum ipc_error_code {
|
||||||
, IPC_ERROR_DIR_SETUP__NOT_A_DIRECTORY = 83
|
, IPC_ERROR_DIR_SETUP__NOT_A_DIRECTORY = 83
|
||||||
, IPC_ERROR_DIR_SETUP__DIRECTORY_NOT_WRITABLE = 84
|
, IPC_ERROR_DIR_SETUP__DIRECTORY_NOT_WRITABLE = 84
|
||||||
, IPC_ERROR_DIRECTORY_SETUP__PATH_PARAM = 85
|
, IPC_ERROR_DIRECTORY_SETUP__PATH_PARAM = 85
|
||||||
|
|
||||||
|
, IPC_ERROR_SERVER_INIT__NOT_ENOUGH_MEMORY = 86
|
||||||
|
, IPC_ERROR_CONNECTION__NOT_ENOUGH_MEMORY = 87
|
||||||
|
, IPC_ERROR_CTX_INIT__NO_CONTEXT_PARAM = 88
|
||||||
|
, IPC_ERROR_CTX_INIT__CONTEXT_ALREADY_INIT = 89
|
||||||
|
, IPC_ERROR_ADD__MALLOC_POLLFD = 90
|
||||||
|
, IPC_ERROR_ADD_MESSAGE_TO_SEND__EMPTY_LIST = 91
|
||||||
|
, IPC_ERROR_ADD_MESSAGE_TO_SEND__MALLOC = 92
|
||||||
|
, IPC_ERROR_ADD_MESSAGE_TO_SEND__NO_PARAM_MESSAGE = 93
|
||||||
|
, IPC_ERROR_ADD_MESSAGE_TO_SEND__NO_PARAM_MESSAGES = 94
|
||||||
|
, IPC_ERROR_CONNECTION__NO_CTX = 95
|
||||||
|
, IPC_ERROR_CTX_INIT__MALLOC_CTX = 96
|
||||||
|
, IPC_ERROR_CTX_INIT__MALLOC_POLLFD = 97
|
||||||
|
, IPC_ERROR_CONTACT_IPCD__NO_FD_PARAM = 98
|
||||||
|
, IPC_ERROR_HANDLE_NEW_CONNECTION__INCONSISTENT_INDEX = 99
|
||||||
|
, IPC_ERROR_DEL_MESSAGE_TO_SEND__NO_PARAM_MESSAGES = 100
|
||||||
|
, IPC_ERROR_MESSAGE_DEL__INDEX_ERROR = 101
|
||||||
|
, IPC_ERROR_MESSAGE_DEL__EMPTY_LIST = 102
|
||||||
|
, IPC_ERROR_ADD__NO_PARAM_POLLFD = 103
|
||||||
|
, IPC_ERROR_WRITE__FD_NOT_FOUND = 104
|
||||||
|
, IPC_ERROR_ADD__NOT_ENOUGH_MEMORY = 105
|
||||||
|
, IPC_ERROR_WAIT_EVENT__POLL = 106
|
||||||
|
, IPC_ERROR_FD_SWITCHING__NO_FD_RECORD = 107
|
||||||
|
, IPC_ERROR_CLOSE_ALL__NO_CTX_PARAM = 108
|
||||||
|
, IPC_ERROR_CLOSE__NO_CTX_PARAM = 109
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipc_error {
|
struct ipc_error {
|
||||||
|
@ -186,45 +219,98 @@ struct ipc_error {
|
||||||
// with the error_message string in the ipc_error structure.
|
// with the error_message string in the ipc_error structure.
|
||||||
const char *ipc_errors_get (enum ipc_error_code e);
|
const char *ipc_errors_get (enum ipc_error_code e);
|
||||||
|
|
||||||
|
|
||||||
|
enum ipc_connection_type {
|
||||||
|
IPC_CONNECTION_TYPE_IPC = 0
|
||||||
|
, IPC_CONNECTION_TYPE_EXTERNAL = 1
|
||||||
|
/** Messages received = new connections. */
|
||||||
|
, IPC_CONNECTION_TYPE_SERVER = 2
|
||||||
|
/** IO operations should go through registered callbacks. */
|
||||||
|
, IPC_CONNECTION_TYPE_SWITCHED = 3
|
||||||
|
};
|
||||||
|
|
||||||
struct ipc_connection_info {
|
struct ipc_connection_info {
|
||||||
uint32_t version;
|
enum ipc_connection_type type;
|
||||||
uint32_t index;
|
|
||||||
int32_t fd;
|
|
||||||
char type; // server, client, arbitrary fd
|
|
||||||
char *spath; // max size: PATH_MAX
|
char *spath; // max size: PATH_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipc_connection_infos {
|
struct ipc_message {
|
||||||
struct ipc_connection_info **cinfos;
|
char type; // Internal message type.
|
||||||
|
char user_type; // User-defined message type.
|
||||||
|
int fd; // File descriptor concerned about this message.
|
||||||
|
uint32_t length; // Payload length.
|
||||||
|
char *payload;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipc_messages {
|
||||||
|
struct ipc_message *messages;
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipc_message {
|
struct ipc_switching {
|
||||||
char type;
|
int orig;
|
||||||
char user_type;
|
int dest;
|
||||||
uint32_t length;
|
enum ipccb (*orig_in) (int origin_fd, struct ipc_message *m);
|
||||||
char *payload;
|
enum ipccb (*orig_out) (int origin_fd, struct ipc_message *m);
|
||||||
|
enum ipccb (*dest_in) (int origin_fd, struct ipc_message *m);
|
||||||
|
enum ipccb (*dest_out) (int origin_fd, struct ipc_message *m);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipc_switchings {
|
||||||
|
struct ipc_switching *collection;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ipc_message_copy (struct ipc_message *m
|
||||||
|
, uint32_t fd
|
||||||
|
, uint8_t type
|
||||||
|
, uint8_t utype
|
||||||
|
, char *payload
|
||||||
|
, uint32_t paylen);
|
||||||
|
struct ipc_error ipc_messages_del (struct ipc_messages *messages, uint32_t index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context of the whole networking state.
|
||||||
|
*/
|
||||||
|
struct ipc_ctx {
|
||||||
|
/**
|
||||||
|
* Keep track of connections.
|
||||||
|
*/
|
||||||
|
struct ipc_connection_info *cinfos;
|
||||||
|
/**
|
||||||
|
* List of "pollfd" structures within cinfos, so we can pass it to poll(2).
|
||||||
|
*/
|
||||||
|
struct pollfd *pollfd;
|
||||||
|
/**
|
||||||
|
* Size of the connection list.
|
||||||
|
*/
|
||||||
|
size_t size;
|
||||||
|
/**
|
||||||
|
* List of messages to send, once the fd are available.
|
||||||
|
*/
|
||||||
|
struct ipc_messages tx;
|
||||||
|
/**
|
||||||
|
* Relations between fd.
|
||||||
|
*/
|
||||||
|
struct ipc_switchings switchdb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipc_event {
|
struct ipc_event {
|
||||||
enum ipc_event_type type;
|
enum ipc_event_type type;
|
||||||
struct ipc_connection_info *origin;
|
uint32_t index;
|
||||||
void *m; // message pointer
|
int origin;
|
||||||
|
void *m; // message pointer
|
||||||
};
|
};
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* ipc event macros
|
* ipc event macros
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define IPC_EVENT_SET(pevent,type_,message_,origin_) {\
|
#define IPC_EVENT_SET(pevent,type_,index_, origin_fd_,message_) {\
|
||||||
pevent->type = type_; \
|
pevent->type = type_; \
|
||||||
|
pevent->index = index_; \
|
||||||
|
pevent->origin = origin_fd_; \
|
||||||
pevent->m = message_; \
|
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) {\
|
#define IPC_EVENT_CLEAN(pevent) {\
|
||||||
|
@ -240,35 +326,32 @@ enum ipc_connection_types {
|
||||||
* main public functions
|
* main public functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
struct ipc_error ipc_server_init (char **env, struct ipc_connection_info *srv, const char *sname);
|
struct ipc_error ipc_wait_event (struct ipc_ctx *, struct ipc_event *, int *timer);
|
||||||
struct ipc_error ipc_connection (char **env, struct ipc_connection_info *srv, const char *sname);
|
|
||||||
|
|
||||||
struct ipc_error ipc_server_close (struct ipc_connection_info *srv);
|
struct ipc_error ipc_server_init (struct ipc_ctx *ctx, const char *sname);
|
||||||
struct ipc_error ipc_close (struct ipc_connection_info *p);
|
struct ipc_error ipc_connection (struct ipc_ctx *ctx, const char *sname);
|
||||||
|
struct ipc_error ipc_connection_switched (struct ipc_ctx *ctx, const char *sname, int clientfd, int *serverfd);
|
||||||
|
|
||||||
struct ipc_error ipc_read (const struct ipc_connection_info *, struct ipc_message *m);
|
struct ipc_error ipc_close (struct ipc_ctx *ctx, uint32_t index);
|
||||||
struct ipc_error ipc_write (const struct ipc_connection_info *, const struct ipc_message *m);
|
struct ipc_error ipc_close_all (struct ipc_ctx *ctx);
|
||||||
|
|
||||||
struct ipc_error ipc_wait_event (struct ipc_connection_infos *clients
|
void ipc_ctx_free (struct ipc_ctx *ctx);
|
||||||
, struct ipc_connection_info *srv
|
|
||||||
, struct ipc_event *event, double *timer);
|
struct ipc_error ipc_read (const struct ipc_ctx *, uint32_t index, struct ipc_message *m);
|
||||||
|
struct ipc_error ipc_write (struct ipc_ctx *, const struct ipc_message *m);
|
||||||
|
|
||||||
|
struct ipc_error fd_switching_read (struct ipc_event *event, struct ipc_ctx *ctx, int index);
|
||||||
|
struct ipc_error fd_switching_write (struct ipc_event *event, struct ipc_ctx *ctx, int index);
|
||||||
|
|
||||||
// store and remove only pointers on allocated structures
|
// store and remove only pointers on allocated structures
|
||||||
struct ipc_error ipc_add (struct ipc_connection_infos *, struct ipc_connection_info *);
|
struct ipc_error ipc_add (struct ipc_ctx *, struct ipc_connection_info *, struct pollfd *);
|
||||||
struct ipc_error ipc_del (struct ipc_connection_infos *, struct ipc_connection_info *);
|
struct ipc_error ipc_del (struct ipc_ctx *, uint32_t index);
|
||||||
|
|
||||||
// add an arbitrary file descriptor to read
|
// add an arbitrary file descriptor to read
|
||||||
struct ipc_error ipc_add_fd (struct ipc_connection_infos *cinfos, int fd);
|
struct ipc_error ipc_add_fd (struct ipc_ctx *ctx, int fd);
|
||||||
struct ipc_error ipc_del_fd (struct ipc_connection_infos *cinfos, int fd);
|
// add a switched file descriptor to read
|
||||||
|
struct ipc_error ipc_add_fd_switched (struct ipc_ctx *ctx, int fd);
|
||||||
void ipc_connections_free (struct ipc_connection_infos *);
|
struct ipc_error ipc_del_fd (struct ipc_ctx *ctx, int fd);
|
||||||
|
|
||||||
// create the client service structure
|
|
||||||
struct ipc_error ipc_connection_gen (struct ipc_connection_info *cinfo
|
|
||||||
, uint32_t index, uint32_t version
|
|
||||||
, int fd, char type);
|
|
||||||
|
|
||||||
void ipc_connections_close (struct ipc_connection_infos *cinfos);
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* message functions
|
* message functions
|
||||||
|
@ -286,6 +369,9 @@ struct ipc_error ipc_message_format_data (struct ipc_message *m, char utype, con
|
||||||
struct ipc_error ipc_message_format_server_close (struct ipc_message *m);
|
struct ipc_error ipc_message_format_server_close (struct ipc_message *m);
|
||||||
struct ipc_error ipc_message_empty (struct ipc_message *m);
|
struct ipc_error ipc_message_empty (struct ipc_message *m);
|
||||||
|
|
||||||
|
struct ipc_error ipc_messages_add (struct ipc_messages *, const struct ipc_message *);
|
||||||
|
void ipc_messages_free (struct ipc_messages *);
|
||||||
|
|
||||||
// Switch cases macros
|
// Switch cases macros
|
||||||
// print on error
|
// print on error
|
||||||
#define ERROR_CASE(e,f,m) case e : { fprintf (stderr, "function %s: %s", f, m); } break;
|
#define ERROR_CASE(e,f,m) case e : { fprintf (stderr, "function %s: %s", f, m); } break;
|
||||||
|
@ -294,42 +380,37 @@ struct ipc_error ipc_message_empty (struct ipc_message *m);
|
||||||
* non public functions
|
* non public functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
void ipc_connection_print (struct ipc_connection_info *cinfo);
|
struct ipc_error ipc_write_fd (int fd, const struct ipc_message *m);
|
||||||
void ipc_connections_print (struct ipc_connection_infos *cinfos);
|
struct ipc_error ipc_ctx_init (struct ipc_ctx **);
|
||||||
|
struct ipc_error ipc_ctx_new_alloc (struct ipc_ctx *ctx);
|
||||||
|
struct ipc_error service_path (char *path, const char *sname);
|
||||||
|
struct ipc_error handle_writing_message (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index);
|
||||||
|
|
||||||
struct ipc_error ipc_accept (struct ipc_connection_info *srv, struct ipc_connection_info *p);
|
void ipc_ctx_print (struct ipc_ctx *ctx);
|
||||||
struct ipc_error ipc_contact_networkd (struct ipc_connection_info *srv, const char *sname);
|
|
||||||
struct ipc_error service_path (char *path, const char *sname, int32_t index, int32_t version);
|
// Last parameter is the index for the server fd in the context structure.
|
||||||
|
struct ipc_error ipc_accept_add (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index);
|
||||||
|
struct ipc_error ipc_contact_ipcd (int *pfd, const char *sname);
|
||||||
|
struct ipc_error service_path (char *path, const char *sname);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* networkd enumerations, structures and functions
|
* ipcd enumerations, structures and functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
struct ipc_switching {
|
void ipc_ctx_switching_add (struct ipc_ctx *ctx, int orig, int dest);
|
||||||
int orig;
|
|
||||||
int dest;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ipc_switchings {
|
|
||||||
struct ipc_switching *collection;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct networkd {
|
|
||||||
int cpt;
|
|
||||||
struct ipc_connection_info *srv;
|
|
||||||
struct ipc_connection_infos *clients;
|
|
||||||
struct ipc_switchings *TCP_TO_IPC;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ipc_error ipc_wait_event_networkd (struct ipc_connection_infos *cinfos
|
|
||||||
, struct ipc_connection_info *cinfo // cinfo is NULL for clients
|
|
||||||
, struct ipc_event *event, struct ipc_switchings *switchdb, double *timer);
|
|
||||||
|
|
||||||
void ipc_switching_add (struct ipc_switchings *is, int orig, int dest);
|
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_del (struct ipc_switchings *is, int fd);
|
||||||
int ipc_switching_get (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_free (struct ipc_switchings *is);
|
||||||
|
void ipc_switching_callbacks_ (struct ipc_ctx *ctx, int fd
|
||||||
|
, enum ipccb (*cb_in )(int fd, struct ipc_message *m));
|
||||||
|
void ipc_switching_callbacks (
|
||||||
|
struct ipc_ctx *ctx
|
||||||
|
, int fd
|
||||||
|
, enum ipccb (*cb_in )(int fd, struct ipc_message *m)
|
||||||
|
, enum ipccb (*cb_out)(int fd, struct ipc_message *m));
|
||||||
|
|
||||||
|
int ipc_ctx_fd_type (struct ipc_ctx *ctx, int fd, enum ipc_connection_type type);
|
||||||
|
|
||||||
void ipc_switching_print (struct ipc_switchings *is);
|
void ipc_switching_print (struct ipc_switchings *is);
|
||||||
|
|
||||||
|
|
|
@ -145,3 +145,87 @@ struct ipc_error ipc_message_empty (struct ipc_message *m)
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store and remove only pointers on allocated structures
|
||||||
|
struct ipc_error ipc_messages_add (struct ipc_messages *messages, const struct ipc_message *message)
|
||||||
|
{
|
||||||
|
T_R ((messages == NULL), IPC_ERROR_ADD_MESSAGE_TO_SEND__NO_PARAM_MESSAGES);
|
||||||
|
T_R ((message == NULL), IPC_ERROR_ADD_MESSAGE_TO_SEND__NO_PARAM_MESSAGE);
|
||||||
|
|
||||||
|
messages->size++;
|
||||||
|
if (messages->size == 1 && messages->messages == NULL) {
|
||||||
|
// first allocation
|
||||||
|
SECURE_BUFFER_HEAP_ALLOCATION_R (messages->messages, sizeof (struct ipc_message),,
|
||||||
|
IPC_ERROR_ADD_MESSAGE_TO_SEND__MALLOC);
|
||||||
|
} else {
|
||||||
|
messages->messages = realloc (messages->messages, sizeof (struct ipc_message) * messages->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
T_R ((messages->messages == NULL), IPC_ERROR_ADD_MESSAGE_TO_SEND__EMPTY_LIST);
|
||||||
|
|
||||||
|
// DEEP COPY.
|
||||||
|
messages->messages[messages->size -1] = *message;
|
||||||
|
if (message->length > 0 && message->payload != NULL) {
|
||||||
|
messages->messages[messages->size -1].payload = malloc(message->length * sizeof (char));
|
||||||
|
strncpy(messages->messages[messages->size -1].payload, message->payload, message->length);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
messages->messages[messages->size -1].payload = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove only pointers on allocated structures.
|
||||||
|
struct ipc_error ipc_messages_del (struct ipc_messages *messages, uint32_t index)
|
||||||
|
{
|
||||||
|
T_R ((messages == NULL), IPC_ERROR_DEL_MESSAGE_TO_SEND__NO_PARAM_MESSAGES);
|
||||||
|
T_R ((messages->size == 0 || index >= messages->size), IPC_ERROR_MESSAGE_DEL__INDEX_ERROR);
|
||||||
|
|
||||||
|
// NOT A DEEP COPY.
|
||||||
|
messages->size--;
|
||||||
|
if (messages->size == 0) {
|
||||||
|
free (messages->messages);
|
||||||
|
messages->messages = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
messages->messages[index] = messages->messages[messages->size];
|
||||||
|
messages->messages = realloc (messages->messages, sizeof (struct ipc_message) * messages->size);
|
||||||
|
T_R ((messages->messages == NULL), IPC_ERROR_MESSAGE_DEL__EMPTY_LIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipc_message_copy (struct ipc_message *m
|
||||||
|
, uint32_t fd
|
||||||
|
, uint8_t type
|
||||||
|
, uint8_t utype
|
||||||
|
, char *payload
|
||||||
|
, uint32_t paylen)
|
||||||
|
{
|
||||||
|
// printf("starting the message copy\n");
|
||||||
|
m->fd = fd;
|
||||||
|
m->type = type;
|
||||||
|
m->user_type = utype;
|
||||||
|
m->length = paylen;
|
||||||
|
if (m->payload != NULL) {
|
||||||
|
free(m->payload);
|
||||||
|
}
|
||||||
|
// printf("BEFORE THE PAYLOAD COPY\n");
|
||||||
|
m->payload = malloc(sizeof(char) * paylen);
|
||||||
|
memcpy(m->payload, payload, paylen);
|
||||||
|
// printf("PAYLOAD COPY DONE\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipc_messages_free (struct ipc_messages *messages)
|
||||||
|
{
|
||||||
|
if (messages != NULL)
|
||||||
|
{
|
||||||
|
if (messages->messages != NULL)
|
||||||
|
{
|
||||||
|
free(messages->messages);
|
||||||
|
messages->messages = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
335
src/network.c
335
src/network.c
|
@ -20,12 +20,12 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO:
|
* TODO:
|
||||||
* describe a protocol to get this working into networkd
|
* describe a protocol to get this working into ipcd
|
||||||
* asking networkd for a fd with an URI
|
* asking ipcd for a fd with an URI
|
||||||
* URI should contain: who (the service name), where (destination), how (protocol)
|
* URI should contain: who (the service name), where (destination), how (protocol)
|
||||||
* networkd initiates a communication with the requested service
|
* ipcd initiates a communication with the requested service
|
||||||
* networkd sends the fd
|
* ipcd sends the fd
|
||||||
* get a networkd working with this
|
* get a ipcd working with this
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct ipc_error ipc_receive_fd (int sock, int *fd)
|
struct ipc_error ipc_receive_fd (int sock, int *fd)
|
||||||
|
@ -81,9 +81,25 @@ struct ipc_error ipc_provide_fd (int sock, int fd)
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ipc_ctx_switching_add (struct ipc_ctx *ctx, int orig, int dest)
|
||||||
|
{
|
||||||
|
ipc_switching_add (&ctx->switchdb, orig, dest);
|
||||||
|
}
|
||||||
|
|
||||||
void ipc_switching_add (struct ipc_switchings *is, int orig, int dest)
|
void ipc_switching_add (struct ipc_switchings *is, int orig, int dest)
|
||||||
{
|
{
|
||||||
is->collection = realloc (is->collection, sizeof (struct ipc_switching) * (is->size + 1));
|
// printf ("ipc_switching_add START: switchdb has %ld entries\n", is->size);
|
||||||
|
|
||||||
|
if (is->collection == NULL) {
|
||||||
|
// printf ("switchdb collection is null\n");
|
||||||
|
is->collection = malloc (sizeof (struct ipc_switching) * (is->size + 1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// printf ("switchdb collection isn't null\n");
|
||||||
|
is->collection = realloc (is->collection, sizeof (struct ipc_switching) * (is->size + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TODO: less brutal approach */
|
||||||
if (is->collection == NULL) {
|
if (is->collection == NULL) {
|
||||||
fprintf (stderr, __FILE__ " error realloc line %d", __LINE__);
|
fprintf (stderr, __FILE__ " error realloc line %d", __LINE__);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
|
@ -93,6 +109,13 @@ void ipc_switching_add (struct ipc_switchings *is, int orig, int dest)
|
||||||
|
|
||||||
is->collection[is->size - 1].orig = orig;
|
is->collection[is->size - 1].orig = orig;
|
||||||
is->collection[is->size - 1].dest = dest;
|
is->collection[is->size - 1].dest = dest;
|
||||||
|
|
||||||
|
is->collection[is->size - 1].orig_in = NULL;
|
||||||
|
is->collection[is->size - 1].dest_in = NULL;
|
||||||
|
is->collection[is->size - 1].orig_out = NULL;
|
||||||
|
is->collection[is->size - 1].dest_out = NULL;
|
||||||
|
|
||||||
|
// printf ("ipc_switching_add END: switchdb has %ld entries\n", is->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ipc_switching_del (struct ipc_switchings *is, int fd)
|
int ipc_switching_del (struct ipc_switchings *is, int fd)
|
||||||
|
@ -110,13 +133,12 @@ int ipc_switching_del (struct ipc_switchings *is, int fd)
|
||||||
is->collection[i].orig = is->collection[is->size - 1].orig;
|
is->collection[i].orig = is->collection[is->size - 1].orig;
|
||||||
is->collection[i].dest = is->collection[is->size - 1].dest;
|
is->collection[i].dest = is->collection[is->size - 1].dest;
|
||||||
|
|
||||||
size_t s = (is->size - 1) > 0 ? (is->size - 1) : 1;
|
if (is->size == 1) {
|
||||||
|
free(is->collection);
|
||||||
is->collection = realloc (is->collection, sizeof (struct ipc_switching) * s);
|
is->collection = NULL;
|
||||||
if (is->collection == NULL) {
|
}
|
||||||
/** TODO: not sure we want this behavior */
|
else {
|
||||||
fprintf (stderr, __FILE__ " error realloc line %d", __LINE__);
|
is->collection = realloc (is->collection, sizeof (struct ipc_switching) * (is->size-1));
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is->size--;
|
is->size--;
|
||||||
|
@ -127,6 +149,28 @@ int ipc_switching_del (struct ipc_switchings *is, int fd)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 = fd is origin
|
||||||
|
* 1 = fd is dest
|
||||||
|
* -1 = not found
|
||||||
|
*/
|
||||||
|
int ipc_switching_get_ (const struct ipc_switchings *is
|
||||||
|
, int fd
|
||||||
|
, struct ipc_switching **s)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < is->size; i++) {
|
||||||
|
if (is->collection[i].orig == fd) {
|
||||||
|
*s = &is->collection[i];
|
||||||
|
return 0;
|
||||||
|
} else if (is->collection[i].dest == fd) {
|
||||||
|
*s = &is->collection[i];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int ipc_switching_get (struct ipc_switchings *is, int fd)
|
int ipc_switching_get (struct ipc_switchings *is, int fd)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < is->size; i++) {
|
for (size_t i = 0; i < is->size; i++) {
|
||||||
|
@ -151,3 +195,268 @@ void ipc_switching_free (struct ipc_switchings *is)
|
||||||
}
|
}
|
||||||
is->size = 0;
|
is->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ipccb
|
||||||
|
default_cb_in(int fd, struct ipc_message *m)
|
||||||
|
{
|
||||||
|
// TODO: fix buffer size for switching messages
|
||||||
|
size_t msize = 4096;
|
||||||
|
char buf[msize];
|
||||||
|
char *pbuf = buf;
|
||||||
|
|
||||||
|
// By default, usock_read (a wrapper around read(2)) is used.
|
||||||
|
|
||||||
|
{ /** Some macros use "ret" as a variable name, so this is to be sure. */
|
||||||
|
struct ipc_error ret = usock_recv (fd, &pbuf, &msize);
|
||||||
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
|
if (ret.error_code == IPC_ERROR_CLOSED_RECIPIENT) {
|
||||||
|
return IPC_CB_FD_CLOSING;
|
||||||
|
}
|
||||||
|
return IPC_CB_FD_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** There is a message, send it to the corresponding fd **/
|
||||||
|
if (msize > 0) {
|
||||||
|
struct ipc_error ret = ipc_message_format_read (m, buf, msize);
|
||||||
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
|
return IPC_CB_PARSING_ERROR;
|
||||||
|
}
|
||||||
|
return IPC_CB_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default, if msize <= 0 the fd should be closed.
|
||||||
|
return IPC_CB_FD_CLOSING;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ipccb
|
||||||
|
default_cb_out(int fd, struct ipc_message *m)
|
||||||
|
{
|
||||||
|
size_t msize = 0;
|
||||||
|
SECURE_DECLARATION (struct ipc_error, ret);
|
||||||
|
SECURE_BUFFER_DECLARATION (char, buf, IPC_MAX_MESSAGE_SIZE);
|
||||||
|
char *pbuf = buf;
|
||||||
|
|
||||||
|
ipc_message_format_write (m, &pbuf, &msize);
|
||||||
|
|
||||||
|
size_t nbytes_sent = 0;
|
||||||
|
ret = usock_send (fd, buf, msize, &nbytes_sent);
|
||||||
|
|
||||||
|
// On error or if what was sent != what should have been sent.
|
||||||
|
if (ret.error_code != IPC_ERROR_NONE || nbytes_sent != msize) {
|
||||||
|
return IPC_CB_FD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPC_CB_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipc_switching_callbacks_ (struct ipc_ctx *ctx, int fd
|
||||||
|
, enum ipccb (*cb_in )(int fd, struct ipc_message *m))
|
||||||
|
{
|
||||||
|
ipc_switching_callbacks (ctx, fd, cb_in, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipc_switching_callbacks (
|
||||||
|
struct ipc_ctx *ctx
|
||||||
|
, int fd
|
||||||
|
, enum ipccb (*cb_in )(int fd, struct ipc_message *m)
|
||||||
|
, enum ipccb (*cb_out)(int fd, struct ipc_message *m))
|
||||||
|
{
|
||||||
|
struct ipc_switching *sw = NULL;
|
||||||
|
int is_valid = ipc_switching_get_ (&ctx->switchdb, fd, &sw);
|
||||||
|
if (is_valid == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sw->orig == fd) {
|
||||||
|
sw->orig_in = cb_in;
|
||||||
|
sw->orig_out = cb_out;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sw->dest_in = cb_in;
|
||||||
|
sw->dest_out = cb_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fd_switching_read allows to read a message from a switched fd.
|
||||||
|
*/
|
||||||
|
struct ipc_error fd_switching_read (struct ipc_event *event, struct ipc_ctx *ctx, int index)
|
||||||
|
{
|
||||||
|
// printf ("fd_switching_read\n");
|
||||||
|
|
||||||
|
// If the socket is associated to another one for ipcd:
|
||||||
|
// read and write automatically and provide a new IPC_EVENT_TYPE indicating the switch.
|
||||||
|
T_R ((ctx->switchdb.size == 0), IPC_ERROR_FD_SWITCHING__NO_FD_RECORD);
|
||||||
|
|
||||||
|
int talkingfd = ctx->pollfd[index].fd;
|
||||||
|
int dest_fd = -1;
|
||||||
|
struct ipc_switching *sw = NULL;
|
||||||
|
struct ipc_message m;
|
||||||
|
memset(&m, 0, sizeof (struct ipc_message));
|
||||||
|
|
||||||
|
enum ipccb r;
|
||||||
|
int is_valid = 0;
|
||||||
|
|
||||||
|
is_valid = ipc_switching_get_ (&ctx->switchdb, talkingfd, &sw);
|
||||||
|
|
||||||
|
T_R ((is_valid == -1), IPC_ERROR_FD_SWITCHING__NO_FD_RECORD);
|
||||||
|
|
||||||
|
if (sw->orig == talkingfd) {
|
||||||
|
dest_fd = sw->dest;
|
||||||
|
if (sw->orig_in == NULL) {
|
||||||
|
r = default_cb_in (talkingfd, &m);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = (*sw->orig_in)(talkingfd, &m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dest_fd = sw->orig;
|
||||||
|
if (sw->dest_in == NULL) {
|
||||||
|
r = default_cb_in (talkingfd, &m);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = (*sw->dest_in)(talkingfd, &m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message reception OK: reading the message and put it in the list of messages to send.
|
||||||
|
if (r == IPC_CB_NO_ERROR) {
|
||||||
|
// In case of message reception:
|
||||||
|
// 1. put the message in the list to be sent
|
||||||
|
m.fd = dest_fd;
|
||||||
|
ipc_write (ctx, &m);
|
||||||
|
// 2. delete the message (a deep copy has been made)
|
||||||
|
ipc_message_empty (&m);
|
||||||
|
// 3. set event IPC_EVENT_TYPE_SWITCH, inform ipcd of a successful reception.
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_SWITCH, index, ctx->pollfd[index].fd, NULL);
|
||||||
|
// 4. IPC_RETURN_NO_ERROR
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message reception OK: no message to transfer.
|
||||||
|
// This is applied to protocol-specific messages, for example when the client
|
||||||
|
// has to communicate with the proxy, not the service.
|
||||||
|
if (r == IPC_CB_IGNORE) {
|
||||||
|
printf ("IGNORING REQUEST\n");
|
||||||
|
// In case of message reception:
|
||||||
|
// 1. set event IPC_EVENT_TYPE_SWITCH, inform ipcd of a successful reception.
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_SWITCH, index, ctx->pollfd[index].fd, NULL);
|
||||||
|
// 2. IPC_RETURN_NO_ERROR
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: In any other case, the fd is, or should be closed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 1. close and remove both fd from switchdb
|
||||||
|
close (sw->dest);
|
||||||
|
ipc_del_fd (ctx, sw->dest);
|
||||||
|
// Should not close the client: it's the job of the libipc user application.
|
||||||
|
// XXX: this may be normal, but should be documented.
|
||||||
|
// close (talkingfd);
|
||||||
|
ipc_del_fd (ctx, talkingfd);
|
||||||
|
ipc_switching_del (&ctx->switchdb, talkingfd);
|
||||||
|
|
||||||
|
// 2. set event (either error or disconnection)
|
||||||
|
if (r == IPC_CB_FD_CLOSING) {
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_DISCONNECTION, index, talkingfd, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, index, talkingfd, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. return IPC_ERROR_CLOSED_RECIPIENT
|
||||||
|
IPC_RETURN_ERROR (IPC_ERROR_CLOSED_RECIPIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fd_switching_write allows to read a message from a switched fd.
|
||||||
|
*/
|
||||||
|
struct ipc_error fd_switching_write (struct ipc_event *event, struct ipc_ctx *ctx, int index)
|
||||||
|
{
|
||||||
|
// printf ("fd_switching_write\n");
|
||||||
|
|
||||||
|
// If the socket is associated to another one for ipcd:
|
||||||
|
// read and write automatically and provide a new IPC_EVENT_TYPE indicating the switch.
|
||||||
|
T_R ((ctx->switchdb.size == 0), IPC_ERROR_FD_SWITCHING__NO_FD_RECORD);
|
||||||
|
|
||||||
|
int output_fd = ctx->pollfd[index].fd;
|
||||||
|
struct ipc_switching *sw = NULL;
|
||||||
|
struct ipc_message *m = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
// search for the next message to send for output_fd fd.
|
||||||
|
for (i = 0; ctx->tx.size ; i++) {
|
||||||
|
if (ctx->tx.messages[i].fd == output_fd) {
|
||||||
|
m = &ctx->tx.messages[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case there is no message for the fd: the error will be catched.
|
||||||
|
|
||||||
|
enum ipccb r;
|
||||||
|
int is_valid = 0;
|
||||||
|
|
||||||
|
is_valid = ipc_switching_get_ (&ctx->switchdb, output_fd, &sw);
|
||||||
|
|
||||||
|
T_R ((is_valid == -1), IPC_ERROR_FD_SWITCHING__NO_FD_RECORD);
|
||||||
|
|
||||||
|
if (sw->orig == output_fd) {
|
||||||
|
if (sw->orig_in == NULL) {
|
||||||
|
r = default_cb_out (output_fd, m);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = (*sw->orig_out)(output_fd, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (sw->dest_in == NULL) {
|
||||||
|
r = default_cb_out (output_fd, m);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = (*sw->dest_out)(output_fd, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whether or not the message has been sent, it should be removed.
|
||||||
|
// Freeing the message structure.
|
||||||
|
ipc_message_empty (m);
|
||||||
|
// Removing the message from the context.
|
||||||
|
ipc_messages_del (&ctx->tx, i); // remove the message indexed by i
|
||||||
|
|
||||||
|
// Message reception OK: reading the message and put it in the list of messages to send.
|
||||||
|
if (r == IPC_CB_NO_ERROR) {
|
||||||
|
// 1. set event IPC_EVENT_TYPE_SWITCH, inform ipcd of a successful reception.
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_TX, index, output_fd, NULL);
|
||||||
|
// 2. IPC_RETURN_NO_ERROR
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: In any other case, the fd is, or should be closed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 1. close and remove both fd from switchdb
|
||||||
|
int delfd = ipc_switching_del (&ctx->switchdb, output_fd);
|
||||||
|
if (delfd >= 0) {
|
||||||
|
close (delfd);
|
||||||
|
ipc_del_fd (ctx, delfd);
|
||||||
|
}
|
||||||
|
close (output_fd);
|
||||||
|
ipc_del_fd (ctx, output_fd);
|
||||||
|
|
||||||
|
// 2. set event (either error or disconnection)
|
||||||
|
if (r == IPC_CB_FD_CLOSING) {
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_DISCONNECTION, index, output_fd, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, index, output_fd, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. return IPC_ERROR_CLOSED_RECIPIENT
|
||||||
|
IPC_RETURN_ERROR (IPC_ERROR_CLOSED_RECIPIENT);
|
||||||
|
}
|
||||||
|
|
55
src/print.c
55
src/print.c
|
@ -1,20 +1,51 @@
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
|
|
||||||
void ipc_connection_print (struct ipc_connection_info *cinfo)
|
void ipc_ctx_print (struct ipc_ctx *ctx)
|
||||||
{
|
{
|
||||||
T_R_NOTHING ((cinfo == NULL));
|
printf ("Context contains:\n");
|
||||||
|
for (size_t i = 0; i < ctx->size; i++) {
|
||||||
|
printf ("- fd %d\t", ctx->pollfd[i].fd);
|
||||||
|
|
||||||
#if 0
|
switch (ctx->cinfos[i].type) {
|
||||||
LOG_DEBUG ("fd %d: index %d, version %d, type %c, path %s"
|
case IPC_CONNECTION_TYPE_IPC: {
|
||||||
, cinfo->fd , cinfo->index, cinfo->version, cinfo->type
|
printf ("- ipc\n");
|
||||||
, (cinfo->spath == NULL) ? "-" : cinfo->spath);
|
break;
|
||||||
#endif
|
}
|
||||||
}
|
case IPC_CONNECTION_TYPE_EXTERNAL: {
|
||||||
|
printf ("- external\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IPC_CONNECTION_TYPE_SERVER: {
|
||||||
|
printf ("- external\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IPC_CONNECTION_TYPE_SWITCHED: {
|
||||||
|
printf ("- switched\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ipc_connections_print (struct ipc_connection_infos *cinfos)
|
if (ctx->switchdb.size > 0) {
|
||||||
{
|
printf ("Context.switchdb contains:\n");
|
||||||
for (size_t i = 0; i < cinfos->size; i++) {
|
for (size_t i = 0; i < ctx->switchdb.size; i++) {
|
||||||
ipc_connection_print (cinfos->cinfos[i]);
|
printf ("- %d <-> %d\n"
|
||||||
|
, ctx->switchdb.collection[i].orig
|
||||||
|
, ctx->switchdb.collection[i].dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf ("Context.switchdb is empty\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->tx.size > 0) {
|
||||||
|
printf ("Context.tx contains:\n");
|
||||||
|
for (size_t i = 0; i < ctx->tx.size; i++) {
|
||||||
|
printf ("- message to %d\n", ctx->tx.messages[i].fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf ("Context.tx is empty\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include "ipc.h"
|
||||||
|
|
||||||
|
struct ipc_error
|
||||||
|
service_path (char *path, const char *sname)
|
||||||
|
{
|
||||||
|
T_R ((path == NULL), IPC_ERROR_SERVICE_PATH__NO_PATH);
|
||||||
|
T_R ((sname == NULL), IPC_ERROR_SERVICE_PATH__NO_SERVICE_NAME);
|
||||||
|
|
||||||
|
memset (path, 0, PATH_MAX);
|
||||||
|
|
||||||
|
char *rundir = getenv ("IPC_RUNDIR");
|
||||||
|
if (rundir == NULL)
|
||||||
|
rundir = RUNDIR;
|
||||||
|
|
||||||
|
snprintf (path, PATH_MAX - 1, "%s/%s", rundir, sname);
|
||||||
|
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
|
@ -40,15 +40,6 @@ struct ipc_error usock_recv (const int32_t fd, char **buf, size_t * len)
|
||||||
if (*len == 0)
|
if (*len == 0)
|
||||||
*len = IPC_MAX_MESSAGE_SIZE;
|
*len = IPC_MAX_MESSAGE_SIZE;
|
||||||
|
|
||||||
if (*buf == NULL) {
|
|
||||||
// do not allocate too much memory
|
|
||||||
if (*len > IPC_MAX_MESSAGE_SIZE) {
|
|
||||||
*len = IPC_MAX_MESSAGE_SIZE;
|
|
||||||
}
|
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION (*buf, *len + IPC_HEADER_SIZE,,
|
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_USOCK_RECV__HEAP_ALLOCATION));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t msize = 0;
|
uint32_t msize = 0;
|
||||||
uint32_t msize_read = 0;
|
uint32_t msize_read = 0;
|
||||||
|
|
||||||
|
@ -76,10 +67,6 @@ struct ipc_error usock_recv (const int32_t fd, char **buf, size_t * len)
|
||||||
T_R ((msize > IPC_MAX_MESSAGE_SIZE), IPC_ERROR_USOCK_RECV__MESSAGE_SIZE);
|
T_R ((msize > IPC_MAX_MESSAGE_SIZE), IPC_ERROR_USOCK_RECV__MESSAGE_SIZE);
|
||||||
msize_read += ret_recv - IPC_HEADER_SIZE;
|
msize_read += ret_recv - IPC_HEADER_SIZE;
|
||||||
} else if (ret_recv < 0) {
|
} else if (ret_recv < 0) {
|
||||||
if (*buf != NULL) {
|
|
||||||
free (*buf);
|
|
||||||
*buf = NULL;
|
|
||||||
}
|
|
||||||
*len = 0;
|
*len = 0;
|
||||||
|
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
|
@ -130,10 +117,6 @@ struct ipc_error usock_recv (const int32_t fd, char **buf, size_t * len)
|
||||||
|
|
||||||
// 1 on none byte received, indicates a closed recipient
|
// 1 on none byte received, indicates a closed recipient
|
||||||
if (ret_recv == 0) {
|
if (ret_recv == 0) {
|
||||||
if (*buf != NULL) {
|
|
||||||
free (*buf);
|
|
||||||
*buf = NULL;
|
|
||||||
}
|
|
||||||
*len = 0;
|
*len = 0;
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_CLOSED_RECIPIENT);
|
IPC_RETURN_ERROR (IPC_ERROR_CLOSED_RECIPIENT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,28 +6,30 @@
|
||||||
|
|
||||||
#define SERVICE_NAME "pong"
|
#define SERVICE_NAME "pong"
|
||||||
|
|
||||||
int main(int argc, char * argv[], char **env)
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
argc = (int) argc;
|
argc = (int) argc;
|
||||||
argv = (char **) argv;
|
argv = (char **) argv;
|
||||||
|
|
||||||
SECURE_DECLARATION(struct ipc_error, ret);
|
SECURE_DECLARATION(struct ipc_error, ret);
|
||||||
SECURE_DECLARATION(struct ipc_connection_info,service);
|
SECURE_DECLARATION(struct ipc_ctx, ctx);
|
||||||
SECURE_DECLARATION(struct ipc_event, event);
|
SECURE_DECLARATION(struct ipc_event, event);
|
||||||
|
|
||||||
ret = ipc_connection (env, &service, SERVICE_NAME);
|
ret = ipc_connection (&ctx, SERVICE_NAME);
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
|
printf ("error: %s\n", ipc_errors_get(ret.error_code));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// long timer = 10;
|
// int timer = 10000; // 10 seconds
|
||||||
// ret = ipc_wait_event (services, struct ipc_event *event, &timer);
|
// ret = ipc_wait_event (services, struct ipc_event *event, &timer);
|
||||||
// if (ret.error_code != IPC_ERROR_NONE) {
|
// if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
// return EXIT_FAILURE;
|
// return EXIT_FAILURE;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
ret = ipc_close (&service);
|
ret = ipc_close_all (&ctx);
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
|
printf ("error: %s\n", ipc_errors_get(ret.error_code));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,31 +6,30 @@
|
||||||
|
|
||||||
#define SERVICE_NAME "pong"
|
#define SERVICE_NAME "pong"
|
||||||
|
|
||||||
int main(int argc, char * argv[], char **env)
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
argc = (int) argc;
|
argc = (int) argc;
|
||||||
argv = (char **) argv;
|
argv = (char **) argv;
|
||||||
|
|
||||||
SECURE_DECLARATION(struct ipc_connection_info,srv);
|
SECURE_DECLARATION(struct ipc_ctx, ctx);
|
||||||
long timer = 10;
|
int timer = 10000; // 10 seconds timer
|
||||||
|
|
||||||
printf ("func 01 - server init...\n");
|
printf ("func 01 - server init...\n");
|
||||||
TEST_IPC_Q(ipc_server_init (env, &srv, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_server_init (&ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
printf ("func 01 - server init ok\n");
|
printf ("func 01 - server init ok\n");
|
||||||
SECURE_DECLARATION(struct ipc_connection_infos, clients);
|
SECURE_DECLARATION(struct ipc_event, event);
|
||||||
SECURE_DECLARATION(struct ipc_event,event);
|
|
||||||
|
|
||||||
printf ("func 01 - service polling...\n");
|
printf ("func 01 - service polling...\n");
|
||||||
|
|
||||||
// listen only for a single client
|
// listen only for a single client
|
||||||
TEST_IPC_Q(ipc_wait_event (&clients, &srv, &event, &timer), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_wait_event (&ctx, &event, &timer), EXIT_FAILURE);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_TIMER : {
|
case IPC_EVENT_TYPE_TIMER : {
|
||||||
fprintf(stderr, "time up!\n");
|
fprintf(stderr, "time up!\n");
|
||||||
|
|
||||||
timer = 10;
|
timer = 10000;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_CONNECTION :
|
case IPC_EVENT_TYPE_CONNECTION :
|
||||||
|
@ -49,11 +48,11 @@ int main(int argc, char * argv[], char **env)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("func 01 - closing clients...\n");
|
|
||||||
ipc_connections_free (&clients);
|
|
||||||
|
|
||||||
printf ("func 01 - closing server...\n");
|
printf ("func 01 - closing server...\n");
|
||||||
TEST_IPC_Q(ipc_server_close(&srv), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_close_all(&ctx), EXIT_FAILURE);
|
||||||
|
|
||||||
|
printf ("func 01 - closing ctx...\n");
|
||||||
|
ipc_ctx_free (&ctx);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,48 +13,50 @@
|
||||||
fprintf(stderr, "error while %s: %s\n", msg, err);\
|
fprintf(stderr, "error while %s: %s\n", msg, err);\
|
||||||
}
|
}
|
||||||
|
|
||||||
void non_interactive (char *env[])
|
void non_interactive ()
|
||||||
{
|
{
|
||||||
struct ipc_message m;
|
SECURE_DECLARATION(struct ipc_message, m);
|
||||||
memset (&m, 0, sizeof (struct ipc_message));
|
SECURE_DECLARATION(struct ipc_ctx, ctx);
|
||||||
SECURE_DECLARATION(struct ipc_connection_info, srv);
|
|
||||||
|
|
||||||
// init service
|
// init service
|
||||||
TEST_IPC_Q(ipc_connection (env, &srv, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_connection (&ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
printf ("msg to send (%ld): %.*s\n", (ssize_t) strlen(MSG) +1, (int) strlen(MSG), MSG);
|
int server_fd = ctx.pollfd[0].fd;
|
||||||
|
|
||||||
|
printf ("msg for fd %d to send (%ld): %.*s\n"
|
||||||
|
, server_fd
|
||||||
|
, (ssize_t) strlen(MSG) +1, (int) strlen(MSG), MSG);
|
||||||
TEST_IPC_Q(ipc_message_format_data (&m, /* type */ 'a', MSG, (ssize_t) strlen(MSG) +1), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_message_format_data (&m, /* type */ 'a', MSG, (ssize_t) strlen(MSG) +1), EXIT_FAILURE);
|
||||||
TEST_IPC_Q(ipc_write (&srv, &m), EXIT_FAILURE);
|
|
||||||
TEST_IPC_Q(ipc_read (&srv, &m), EXIT_FAILURE);
|
m.fd = server_fd;
|
||||||
|
TEST_IPC_Q(ipc_write_fd (server_fd, &m), EXIT_FAILURE);
|
||||||
|
TEST_IPC_Q(ipc_read (&ctx, 0 /* only one option */, &m), EXIT_FAILURE);
|
||||||
|
|
||||||
printf ("msg recv: %s\n", m.payload);
|
printf ("msg recv: %s\n", m.payload);
|
||||||
ipc_message_empty (&m);
|
ipc_message_empty (&m);
|
||||||
|
|
||||||
TEST_IPC_Q(ipc_close (&srv), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_close_all (&ctx), EXIT_FAILURE);
|
||||||
|
ipc_ctx_free (&ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void interactive (char *env[])
|
#if 0
|
||||||
|
void interactive ()
|
||||||
{
|
{
|
||||||
SECURE_DECLARATION(struct ipc_connection_info, srv);
|
SECURE_DECLARATION(struct ipc_ctx, ctx);
|
||||||
|
|
||||||
// index and version should be filled
|
|
||||||
srv.index = 0;
|
|
||||||
srv.version = 0;
|
|
||||||
|
|
||||||
// init service
|
// init service
|
||||||
TEST_IPC_Q(ipc_connection (env, &srv, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_connection (&ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
|
int server_fd = ctx.pollfd[0].fd;
|
||||||
|
|
||||||
SECURE_DECLARATION(struct ipc_event, event);
|
SECURE_DECLARATION(struct ipc_event, event);
|
||||||
SECURE_DECLARATION(struct ipc_connection_infos, services);
|
|
||||||
|
|
||||||
TEST_IPC_Q(ipc_add (&services, &srv), EXIT_FAILURE);
|
|
||||||
|
|
||||||
long timer = 10;
|
long timer = 10;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
printf ("msg to send: ");
|
printf ("msg to send: ");
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
TEST_IPC_Q(ipc_wait_event (&services, NULL, &event, &timer), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_wait_event (&ctx, &event, &timer), EXIT_FAILURE);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_TIMER: {
|
case IPC_EVENT_TYPE_TIMER: {
|
||||||
|
@ -71,14 +73,16 @@ void interactive (char *env[])
|
||||||
ipc_message_empty (m);
|
ipc_message_empty (m);
|
||||||
free (m);
|
free (m);
|
||||||
|
|
||||||
ipc_connections_free (&services);
|
TEST_IPC_Q(ipc_close_all (&ctx), EXIT_FAILURE);
|
||||||
|
|
||||||
TEST_IPC_Q(ipc_close (&srv), EXIT_FAILURE);
|
ipc_ctx_free (&ctx);
|
||||||
|
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_IPC_Q(ipc_write (&srv, m), EXIT_FAILURE);
|
m->fd = server_fd;
|
||||||
|
|
||||||
|
TEST_IPC_Q(ipc_write (&ctx, m), EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_MESSAGE:
|
case IPC_EVENT_TYPE_MESSAGE:
|
||||||
|
@ -96,16 +100,19 @@ void interactive (char *env[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main (int argc, char *argv[], char *env[])
|
//int main (int argc, char *argv[])
|
||||||
|
int main (void)
|
||||||
{
|
{
|
||||||
argc = argc; // warnings
|
non_interactive ();
|
||||||
argv = argv; // warnings
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
non_interactive (env);
|
non_interactive ();
|
||||||
else
|
else
|
||||||
interactive (env);
|
interactive ();
|
||||||
|
#endif
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,71 +14,67 @@
|
||||||
|
|
||||||
int cpt = 0;
|
int cpt = 0;
|
||||||
|
|
||||||
struct ipc_connection_info *srv = 0;
|
struct ipc_ctx *ctx;
|
||||||
struct ipc_connection_infos *clients;
|
|
||||||
|
|
||||||
|
|
||||||
void main_loop ()
|
void main_loop ()
|
||||||
{
|
{
|
||||||
SECURE_DECLARATION(struct ipc_error, ret);
|
SECURE_DECLARATION(struct ipc_error, ret);
|
||||||
|
SECURE_DECLARATION(struct ipc_event, event);
|
||||||
|
|
||||||
clients = malloc (sizeof (struct ipc_connection_infos));
|
int timer = 10000;
|
||||||
memset(clients, 0, sizeof(struct ipc_connection_infos));
|
|
||||||
|
|
||||||
SECURE_DECLARATION(struct ipc_event,event);
|
|
||||||
|
|
||||||
long timer = 10;
|
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
// ipc_wait_event provides one event at a time
|
// ipc_wait_event provides one event at a time
|
||||||
// warning: event->m is free'ed if not NULL
|
// warning: event->m is free'ed if not NULL
|
||||||
ret = ipc_wait_event (clients, srv, &event, &timer);
|
ret = ipc_wait_event (ctx, &event, &timer);
|
||||||
if (ret.error_code != IPC_ERROR_NONE && ret.error_code != IPC_ERROR_CLOSED_RECIPIENT) {
|
if (ret.error_code != IPC_ERROR_NONE && ret.error_code != IPC_ERROR_CLOSED_RECIPIENT) {
|
||||||
PRINTERR(ret,"service poll event");
|
PRINTERR(ret,"service poll event");
|
||||||
|
|
||||||
// the application will shut down, and close the service
|
// the application will shut down, and close the service
|
||||||
TEST_IPC_Q(ipc_server_close (srv), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_close_all (ctx), EXIT_FAILURE);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_TIMER: {
|
case IPC_EVENT_TYPE_TIMER: {
|
||||||
fprintf(stderr, "time up!\n");
|
fprintf(stderr, "time up!\n");
|
||||||
timer = 10;
|
timer = 10000;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_CONNECTION: {
|
case IPC_EVENT_TYPE_CONNECTION: {
|
||||||
cpt++;
|
cpt++;
|
||||||
printf ("connection: %d clients connected\n", cpt);
|
// printf ("new connection (fd %d): %d ctx connected\n", event.origin, cpt);
|
||||||
printf ("new client has the fd %d\n", ((struct ipc_connection_info*) event.origin)->fd);
|
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_DISCONNECTION:
|
case IPC_EVENT_TYPE_DISCONNECTION:
|
||||||
{
|
{
|
||||||
cpt--;
|
cpt--;
|
||||||
printf ("disconnection: %d clients remaining\n", cpt);
|
// printf ("disconnection (fd %d): %d clients remaining\n", event.origin, cpt);
|
||||||
|
|
||||||
// free the ipc_connection_info structure
|
|
||||||
free (event.origin);
|
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_MESSAGE:
|
case IPC_EVENT_TYPE_MESSAGE:
|
||||||
{
|
{
|
||||||
struct ipc_message *m = event.m;
|
struct ipc_message *m = event.m;
|
||||||
if (m->length > 0) {
|
if (m->length > 0) {
|
||||||
printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload);
|
// printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ipc_write (event.origin, m);
|
m->fd = event.origin;
|
||||||
|
ret = ipc_write (ctx, m);
|
||||||
if (ret.error_code != IPC_ERROR_NONE) {
|
if (ret.error_code != IPC_ERROR_NONE) {
|
||||||
PRINTERR(ret,"server write");
|
PRINTERR(ret,"server write");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case IPC_EVENT_TYPE_TX:
|
||||||
|
{
|
||||||
|
// printf ("a message was sent\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case IPC_EVENT_TYPE_ERROR:
|
case IPC_EVENT_TYPE_ERROR:
|
||||||
{
|
{
|
||||||
fprintf (stderr, "a problem happened with client %d\n"
|
fprintf (stderr, "a problem happened with client %d\n", event.origin);
|
||||||
, ((struct ipc_connection_info*) event.origin)->fd);
|
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
|
@ -97,48 +93,34 @@ void exit_program(int signal)
|
||||||
{
|
{
|
||||||
printf("Quitting, signal: %d\n", signal);
|
printf("Quitting, signal: %d\n", signal);
|
||||||
|
|
||||||
// free remaining clients
|
|
||||||
for (size_t i = 0; i < clients->size ; i++) {
|
|
||||||
struct ipc_connection_info *cli = clients->cinfos[i];
|
|
||||||
if (cli != NULL) {
|
|
||||||
free (cli);
|
|
||||||
}
|
|
||||||
clients->cinfos[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipc_connections_free (clients);
|
|
||||||
free (clients);
|
|
||||||
|
|
||||||
|
|
||||||
// the application will shut down, and close the service
|
// the application will shut down, and close the service
|
||||||
TEST_IPC_Q(ipc_server_close (srv), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_close_all (ctx), EXIT_FAILURE);
|
||||||
free (srv);
|
|
||||||
|
// free remaining ctx
|
||||||
|
ipc_ctx_free (ctx);
|
||||||
|
free (ctx);
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* service ping-pong: send back everything sent by the clients
|
* service ping-pong: send back everything sent by the ctx
|
||||||
* stop the program on SIG{TERM,INT,ALRM,USR{1,2},HUP} signals
|
* stop the program on SIG{TERM,INT,ALRM,USR{1,2},HUP} signals
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int main(int argc, char * argv[], char **env)
|
int main(void)
|
||||||
{
|
{
|
||||||
argc = argc; // warnings
|
|
||||||
argv = argv; // warnings
|
|
||||||
|
|
||||||
printf ("pid = %d\n", getpid ());
|
printf ("pid = %d\n", getpid ());
|
||||||
|
|
||||||
srv = malloc (sizeof (struct ipc_connection_info));
|
ctx = malloc (sizeof (struct ipc_ctx));
|
||||||
if (srv == NULL) {
|
if (ctx == NULL) {
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
memset (srv, 0, sizeof (struct ipc_connection_info));
|
memset (ctx, 0, sizeof (struct ipc_ctx));
|
||||||
srv->index = 0;
|
|
||||||
srv->version = 0;
|
|
||||||
|
|
||||||
TEST_IPC_Q(ipc_server_init (env, srv, PONGD_SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_server_init (ctx, PONGD_SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
|
struct ipc_connection_info * srv = &ctx->cinfos[0];
|
||||||
printf ("Listening on %s.\n", srv->spath);
|
printf ("Listening on %s.\n", srv->spath);
|
||||||
|
|
||||||
printf("MAIN: server created\n" );
|
printf("MAIN: server created\n" );
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
// test the behavior of the server when the client never read its messages
|
// test the behavior of the server when the client never read its messages
|
||||||
|
|
||||||
void send_message (struct ipc_connection_info *ci)
|
void send_message (struct ipc_ctx *ctx)
|
||||||
{
|
{
|
||||||
SECURE_DECLARATION (struct ipc_message, m);
|
SECURE_DECLARATION (struct ipc_message, m);
|
||||||
SECURE_MALLOC (m.payload, 5, exit(EXIT_FAILURE));
|
SECURE_MALLOC (m.payload, 5, exit(EXIT_FAILURE));
|
||||||
|
@ -18,23 +18,24 @@ void send_message (struct ipc_connection_info *ci)
|
||||||
m.user_type = 42;
|
m.user_type = 42;
|
||||||
m.length = 5;
|
m.length = 5;
|
||||||
|
|
||||||
ipc_write (ci, &m);
|
ipc_write_fd (ctx->pollfd[0].fd /* only one connection */, &m);
|
||||||
|
|
||||||
ipc_message_empty (&m);
|
ipc_message_empty (&m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void read_message (struct ipc_connection_info *ci)
|
void read_message (struct ipc_ctx *ctx)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
SECURE_DECLARATION(struct ipc_event, event);
|
SECURE_DECLARATION(struct ipc_event, event);
|
||||||
SECURE_DECLARATION(struct ipc_connection_infos, clients);
|
SECURE_DECLARATION (struct ipc_message, m);
|
||||||
|
|
||||||
long timer = 10;
|
int timer = 10000;
|
||||||
|
|
||||||
TEST_IPC_Q(ipc_read (ci, &m), EXIT_FAILURE);
|
// ctx, index, message
|
||||||
|
TEST_IPC_Q(ipc_read (ctx, 0 /* only one server here */, &m), EXIT_FAILURE);
|
||||||
|
|
||||||
ipc_wait_event (&clients, NULL, &event, &timer);
|
ipc_wait_event (ctx, &event, &timer);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_MESSAGE : {
|
case IPC_EVENT_TYPE_MESSAGE : {
|
||||||
|
@ -52,37 +53,34 @@ void read_message (struct ipc_connection_info *ci)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ipc_connections_free (&clients);
|
ipc_ctx_free (ctx);
|
||||||
#else
|
#else
|
||||||
SECURE_DECLARATION (struct ipc_message, m);
|
SECURE_DECLARATION (struct ipc_message, m);
|
||||||
|
|
||||||
TEST_IPC_Q(ipc_read (ci, &m), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_read (ctx, 0 /* only one server here */, &m), EXIT_FAILURE);
|
||||||
printf ("received message: %*.s\n", m.length, m.payload);
|
printf ("received message: %*.s\n", m.length, m.payload);
|
||||||
free (m.payload);
|
free (m.payload);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[], char **env)
|
int main(void)
|
||||||
{
|
{
|
||||||
argc = argc;
|
SECURE_DECLARATION(struct ipc_ctx, ctx1);
|
||||||
argv = argv;
|
SECURE_DECLARATION(struct ipc_ctx, ctx2);
|
||||||
|
|
||||||
SECURE_DECLARATION(struct ipc_connection_info,srv1);
|
|
||||||
SECURE_DECLARATION(struct ipc_connection_info,srv2);
|
|
||||||
SECURE_DECLARATION(struct ipc_event, event);
|
SECURE_DECLARATION(struct ipc_event, event);
|
||||||
|
|
||||||
TEST_IPC_Q (ipc_connection (env, &srv1, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_connection (&ctx1, SERVICE_NAME), EXIT_FAILURE);
|
||||||
TEST_IPC_Q (ipc_connection (env, &srv2, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_connection (&ctx2, SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
send_message (&srv1);
|
send_message (&ctx1);
|
||||||
read_message (&srv1);
|
read_message (&ctx1);
|
||||||
|
|
||||||
TEST_IPC_Q (ipc_close (&srv1), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_close_all (&ctx1), EXIT_FAILURE);
|
||||||
|
|
||||||
send_message (&srv2);
|
send_message (&ctx2);
|
||||||
read_message (&srv2);
|
read_message (&ctx2);
|
||||||
|
|
||||||
TEST_IPC_Q (ipc_close (&srv2), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_close_all (&ctx2), EXIT_FAILURE);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,43 +7,46 @@
|
||||||
|
|
||||||
#define SERVICE_NAME "pong"
|
#define SERVICE_NAME "pong"
|
||||||
|
|
||||||
int main_loop(int argc, char * argv[], char **env)
|
int main_loop(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
argc = argc;
|
argc = argc;
|
||||||
argv = argv;
|
argv = argv;
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_connection_info, srv);
|
SECURE_DECLARATION (struct ipc_ctx, ctx);
|
||||||
long timer = 10;
|
int timer = 10000; // in ms
|
||||||
|
|
||||||
printf ("func 03 - server init...\n");
|
printf ("func 03 - server init...\n");
|
||||||
TEST_IPC_Q (ipc_server_init (env, &srv, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_server_init (&ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
printf ("func 03 - server init ok\n");
|
printf ("func 03 - server init ok\n");
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_connection_infos, clients);
|
|
||||||
SECURE_DECLARATION (struct ipc_event, event);
|
SECURE_DECLARATION (struct ipc_event, event);
|
||||||
|
|
||||||
printf ("func 01 - service polling...\n");
|
printf ("func 01 - service polling...\n");
|
||||||
// listen only for a single client
|
// listen only for a single client
|
||||||
while (1) {
|
while (1) {
|
||||||
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (&clients, &srv, &event, &timer), EXIT_FAILURE);
|
TEST_IPC_WAIT_EVENT_Q (ipc_wait_event (&ctx, &event, &timer), EXIT_FAILURE);
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case IPC_EVENT_TYPE_TIMER : {
|
case IPC_EVENT_TYPE_TIMER : {
|
||||||
fprintf (stderr, "time up!");
|
fprintf (stderr, "time up!\n");
|
||||||
timer = 10;
|
timer = 10000;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_CONNECTION : {
|
case IPC_EVENT_TYPE_CONNECTION : {
|
||||||
printf ("connection establishment: %d \n", event.origin->fd);
|
printf ("connection establishment: %d \n", event.origin);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_DISCONNECTION : {
|
case IPC_EVENT_TYPE_DISCONNECTION : {
|
||||||
printf ("client %d disconnecting\n", event.origin->fd);
|
printf ("client %d disconnecting\n", event.origin);
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_MESSAGE : {
|
case IPC_EVENT_TYPE_MESSAGE : {
|
||||||
printf ("received message: %s\n", ((struct ipc_message*) event.m)->payload);
|
printf ("received message: %s\n", ((struct ipc_message*) event.m)->payload);
|
||||||
ipc_write (event.origin, (struct ipc_message*) event.m);
|
ipc_write (&ctx, (struct ipc_message*) event.m);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPC_EVENT_TYPE_TX : {
|
||||||
|
printf ("message sent to fd %d\n", event.origin);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IPC_EVENT_TYPE_NOT_SET :
|
case IPC_EVENT_TYPE_NOT_SET :
|
||||||
|
@ -56,10 +59,11 @@ int main_loop(int argc, char * argv[], char **env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("func 03 - closing clients...\n");
|
|
||||||
ipc_connections_free (&clients);
|
|
||||||
printf ("func 03 - closing server...\n");
|
printf ("func 03 - closing server...\n");
|
||||||
TEST_IPC_Q (ipc_server_close(&srv), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_close_all(&ctx), EXIT_FAILURE);
|
||||||
|
|
||||||
|
printf ("func 03 - freeing the context\n");
|
||||||
|
ipc_ctx_free (&ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -71,7 +75,7 @@ void exit_program(int signal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char * argv[], char **env)
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
signal (SIGHUP, exit_program);
|
signal (SIGHUP, exit_program);
|
||||||
signal (SIGALRM, exit_program);
|
signal (SIGALRM, exit_program);
|
||||||
|
@ -79,6 +83,6 @@ int main(int argc, char * argv[], char **env)
|
||||||
signal (SIGUSR2, exit_program);
|
signal (SIGUSR2, exit_program);
|
||||||
signal (SIGTERM, exit_program);
|
signal (SIGTERM, exit_program);
|
||||||
signal (SIGINT, exit_program);
|
signal (SIGINT, exit_program);
|
||||||
main_loop (argc, argv, env);
|
main_loop (argc, argv);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
// test the behavior of the server when the client never read its messages
|
// test the behavior of the server when the client never read its messages
|
||||||
|
|
||||||
void send_message (struct ipc_connection_info *ci)
|
void send_message (struct ipc_ctx *ctx)
|
||||||
{
|
{
|
||||||
SECURE_DECLARATION (struct ipc_message, m);
|
SECURE_DECLARATION (struct ipc_message, m);
|
||||||
SECURE_MALLOC (m.payload, 1, exit(EXIT_FAILURE));
|
SECURE_MALLOC (m.payload, 1, exit(EXIT_FAILURE));
|
||||||
|
@ -17,18 +17,20 @@ void send_message (struct ipc_connection_info *ci)
|
||||||
m.type = MSG_TYPE_DATA;
|
m.type = MSG_TYPE_DATA;
|
||||||
m.user_type = 42;
|
m.user_type = 42;
|
||||||
m.length = 0;
|
m.length = 0;
|
||||||
|
m.fd = ctx->pollfd[0].fd;
|
||||||
|
|
||||||
ipc_write (ci, &m);
|
// ipc_write_fd = write now, without waiting the fd to become available
|
||||||
|
ipc_write_fd (ctx->pollfd[0].fd, &m);
|
||||||
|
|
||||||
ipc_message_empty (&m);
|
ipc_message_empty (&m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void read_message (struct ipc_connection_info *ci)
|
void read_message (struct ipc_ctx *ctx)
|
||||||
{
|
{
|
||||||
SECURE_DECLARATION (struct ipc_message, m);
|
SECURE_DECLARATION (struct ipc_message, m);
|
||||||
|
|
||||||
ipc_read (ci, &m);
|
ipc_read (ctx, 0 /* there is only one valid index */, &m);
|
||||||
if (m.length > 0) {
|
if (m.length > 0) {
|
||||||
printf ("received message: %*.s\n", m.length, m.payload);
|
printf ("received message: %*.s\n", m.length, m.payload);
|
||||||
}
|
}
|
||||||
|
@ -41,19 +43,16 @@ void read_message (struct ipc_connection_info *ci)
|
||||||
free (m.payload);
|
free (m.payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[], char **env)
|
int main(void)
|
||||||
{
|
{
|
||||||
argc = argc;
|
SECURE_DECLARATION(struct ipc_ctx, ctx);
|
||||||
argv = argv;
|
|
||||||
|
|
||||||
SECURE_DECLARATION(struct ipc_connection_info,srv1);
|
TEST_IPC_Q(ipc_connection (&ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
TEST_IPC_Q(ipc_connection (env, &srv1, SERVICE_NAME), EXIT_FAILURE);
|
send_message (&ctx);
|
||||||
|
read_message (&ctx);
|
||||||
|
|
||||||
send_message (&srv1);
|
TEST_IPC_Q(ipc_close_all (&ctx), EXIT_FAILURE);
|
||||||
read_message (&srv1);
|
|
||||||
|
|
||||||
TEST_IPC_Q(ipc_close (&srv1), EXIT_FAILURE);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#define _BSD_SOURCE
|
// #define _BSD_SOURCE
|
||||||
|
#define _DEFAULT_SOURCE
|
||||||
|
|
||||||
#include "../src/ipc.h"
|
#include "../src/ipc.h"
|
||||||
|
|
||||||
|
@ -12,9 +13,9 @@
|
||||||
#define DEFAULT_MSG "coucou"
|
#define DEFAULT_MSG "coucou"
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char * argv[], char **env)
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
SECURE_DECLARATION(struct ipc_connection_info,srv);
|
SECURE_DECLARATION(struct ipc_ctx, ctx);
|
||||||
SECURE_DECLARATION(struct ipc_event, event);
|
SECURE_DECLARATION(struct ipc_event, event);
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_message, write_m);
|
SECURE_DECLARATION (struct ipc_message, write_m);
|
||||||
|
@ -46,20 +47,21 @@ int main(int argc, char * argv[], char **env)
|
||||||
memcpy(message_str, DEFAULT_MSG, strlen(DEFAULT_MSG));
|
memcpy(message_str, DEFAULT_MSG, strlen(DEFAULT_MSG));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_IPC_Q (ipc_connection (env, &srv, SERVICE_NAME), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_connection (&ctx, SERVICE_NAME), EXIT_FAILURE);
|
||||||
|
|
||||||
SECURE_MALLOC (write_m.payload, strlen(message_str), exit(EXIT_FAILURE));
|
SECURE_MALLOC (write_m.payload, strlen(message_str), exit(EXIT_FAILURE));
|
||||||
memcpy (write_m.payload, message_str, strlen(message_str));
|
memcpy (write_m.payload, message_str, strlen(message_str));
|
||||||
write_m.type = MSG_TYPE_DATA;
|
write_m.type = MSG_TYPE_DATA;
|
||||||
write_m.user_type = 42;
|
write_m.user_type = 42;
|
||||||
|
write_m.fd = ctx.pollfd[0].fd;
|
||||||
write_m.length = strlen(message_str);
|
write_m.length = strlen(message_str);
|
||||||
|
|
||||||
gettimeofday(&tval_before, NULL);
|
gettimeofday(&tval_before, NULL);
|
||||||
for (size_t i = 0 ; i < nb_rounds ; i++) {
|
for (size_t i = 0 ; i < nb_rounds ; i++) {
|
||||||
ipc_write (&srv, &write_m);
|
ipc_write_fd (ctx.pollfd[0].fd, &write_m);
|
||||||
|
|
||||||
// reading
|
// reading
|
||||||
TEST_IPC_Q(ipc_read (&srv, &read_m), EXIT_FAILURE);
|
TEST_IPC_Q(ipc_read (&ctx, 0 /* only valid index */, &read_m), EXIT_FAILURE);
|
||||||
// printf ("received message (%d bytes): %*s\n", read_m.length, read_m.length, read_m.payload);
|
// printf ("received message (%d bytes): %*s\n", read_m.length, read_m.length, read_m.payload);
|
||||||
// ipc_message_empty (&read_m);
|
// ipc_message_empty (&read_m);
|
||||||
|
|
||||||
|
@ -71,7 +73,7 @@ int main(int argc, char * argv[], char **env)
|
||||||
printf("Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);
|
printf("Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);
|
||||||
|
|
||||||
// disconnection
|
// disconnection
|
||||||
TEST_IPC_Q (ipc_close (&srv), EXIT_FAILURE);
|
TEST_IPC_Q (ipc_close_all (&ctx), EXIT_FAILURE);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,27 +5,21 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define SERVICE_NAME "example"
|
#define SERVICE_NAME "example"
|
||||||
#define VERSION 0
|
|
||||||
#define INDEX 0
|
|
||||||
|
|
||||||
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
char * sname = SERVICE_NAME;
|
char * sname = SERVICE_NAME;
|
||||||
int32_t index = INDEX;
|
|
||||||
int32_t version = VERSION;
|
|
||||||
|
|
||||||
if (argc == 4) {
|
if (argc == 2) {
|
||||||
sname = argv[1];
|
sname = argv[1];
|
||||||
index = atoi(argv[2]);
|
|
||||||
version = atoi(argv[3]);
|
|
||||||
}
|
}
|
||||||
else if (argc != 1) {
|
else if (argc != 1) {
|
||||||
fprintf (stderr, "usage: %s [service-name index version]\n", argv[0]);
|
fprintf (stderr, "usage: %s [service-name index version]\n", argv[0]);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
service_path (path, sname, index, version);
|
service_path (path, sname);
|
||||||
|
|
||||||
// printf ("servicename: %s, index: %d, version: %d\n", sname, index, version);
|
// printf ("servicename: %s, index: %d, version: %d\n", sname, index, version);
|
||||||
printf ("%s\n", path);
|
printf ("%s\n", path);
|
||||||
|
|
Loading…
Reference in New Issue