From 1e5e475bcb2559d3f8923c89e9e97984f598626a Mon Sep 17 00:00:00 2001 From: Philippe PITTOLI Date: Sat, 27 Jul 2019 15:48:10 +0200 Subject: [PATCH] examples and utils --- drop/build.sh | 23 ++ drop/print-bytes.c | 27 ++ drop/to-pascal.pl | 9 + examples/build.sh | 20 +- examples/fd-exchange-providing.c | 31 ++ examples/fd-exchange-receiving.c | 37 +++ examples/pong.c | 113 +++----- examples/pongd.c | 12 +- examples/simple-tcp-client.c | 96 ++----- examples/simple-tcpd.c | 378 +++++++------------------ examples/test-ask-for-fd-to-networkd.c | 46 +++ examples/test-networkd-provide-fd.c | 41 +++ examples/tests-logs.c | 16 ++ examples/wsserver.c | 118 ++++++++ 14 files changed, 546 insertions(+), 421 deletions(-) create mode 100755 drop/build.sh create mode 100644 drop/print-bytes.c create mode 100644 drop/to-pascal.pl create mode 100644 examples/fd-exchange-providing.c create mode 100644 examples/fd-exchange-receiving.c create mode 100644 examples/test-ask-for-fd-to-networkd.c create mode 100644 examples/test-networkd-provide-fd.c create mode 100644 examples/tests-logs.c create mode 100644 examples/wsserver.c diff --git a/drop/build.sh b/drop/build.sh new file mode 100755 index 0000000..a77e6d2 --- /dev/null +++ b/drop/build.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +nontapmsg() { + echo $* +} + +if [ $# -eq 0 ] ; then + SRC="*.c" +else + SRC="$*" +fi + +for i in $SRC +do + BIN=$(echo ${i} | sed "s/.c$/.bin/") + if [ ! -f ${BIN} ] || [ $(stat -c "%X" ${BIN}) -lt $(stat -c "%X" ${i}) ] + then + nontapmsg "compiling ${BIN}" + # gcc $BIN.c ./lib/*.o -o $BIN -I../src -I ./lib/ -L../ -L./lib/ -lipc -Wall -g -Wextra + gcc -Wall -g -Wextra "${i}" -o "${BIN}" -I../src -L../ ../src/ipc.h -lipc + touch "${BIN}" + fi +done diff --git a/drop/print-bytes.c b/drop/print-bytes.c new file mode 100644 index 0000000..4dcda06 --- /dev/null +++ b/drop/print-bytes.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include + +#include "../src/ipc.h" + +int main(int argc, char * argv[]) +{ + SECURE_BUFFER_DECLARATION (char, buffer, 4096); + uint32_t msize = 0; + char *message = "coucou"; + + if (argc == 2) { + message = argv[1]; + } + + msize = ipc_message_raw_serialize (buffer, 2, 42, message, strlen(message)); + write (1, buffer, msize); + fflush (stdout); + + // to wait for a response + sleep (1); + + return EXIT_SUCCESS; +} diff --git a/drop/to-pascal.pl b/drop/to-pascal.pl new file mode 100644 index 0000000..61a18da --- /dev/null +++ b/drop/to-pascal.pl @@ -0,0 +1,9 @@ +#!/usr/bin/perl -w +use v5.14; + +while(<>) { + chomp; + my @wl = split "_\+"; + my @wl2 = map { ucfirst lc } @wl; + say join "", @wl2; +} diff --git a/examples/build.sh b/examples/build.sh index 8c14e3e..a77e6d2 100755 --- a/examples/build.sh +++ b/examples/build.sh @@ -4,10 +4,20 @@ nontapmsg() { echo $* } -for i in *.c +if [ $# -eq 0 ] ; then + SRC="*.c" +else + SRC="$*" +fi + +for i in $SRC do - f=`echo $i | sed "s/.c$//"` - nontapmsg "compiling $f" - # gcc $f.c ./lib/*.o -o $f -I../src -I ./lib/ -L../ -L./lib/ -lipc -Wall -g -Wextra - gcc -Wall -g -Wextra $f.c -o $f -I../src -L../ ../src/ipc.h -lipc + BIN=$(echo ${i} | sed "s/.c$/.bin/") + if [ ! -f ${BIN} ] || [ $(stat -c "%X" ${BIN}) -lt $(stat -c "%X" ${i}) ] + then + nontapmsg "compiling ${BIN}" + # gcc $BIN.c ./lib/*.o -o $BIN -I../src -I ./lib/ -L../ -L./lib/ -lipc -Wall -g -Wextra + gcc -Wall -g -Wextra "${i}" -o "${BIN}" -I../src -L../ ../src/ipc.h -lipc + touch "${BIN}" + fi done diff --git a/examples/fd-exchange-providing.c b/examples/fd-exchange-providing.c new file mode 100644 index 0000000..799a1d1 --- /dev/null +++ b/examples/fd-exchange-providing.c @@ -0,0 +1,31 @@ +#include +#include +#include + +#include +#include +#include + +#include "../src/ipc.h" +#include "../src/usocket.h" + +// This program opens a file then provide it to another running program. +// see examples/fd-exchange-receiving.c + +int main(int argc, char * argv[]) +{ + if (argc != 2) { + fprintf (stderr, "usage: %s file", argv[0]); + exit (EXIT_FAILURE); + } + + int sock = 0; + int fd = 0; + + T_PERROR_R (((fd = open (argv[1], O_CREAT | O_RDWR)) < 0), "cannot open the file", EXIT_FAILURE); + + TIPC_P_Q (usock_connect (&sock, "SOCKET_FD_EXCHANGE_TEST"), "trying to connect to the unix socket", EXIT_FAILURE); + TIPC_P_Q (ipc_provide_fd (sock, fd), "cannot send the file descriptor", EXIT_FAILURE); + + return EXIT_SUCCESS; +} diff --git a/examples/fd-exchange-receiving.c b/examples/fd-exchange-receiving.c new file mode 100644 index 0000000..1436651 --- /dev/null +++ b/examples/fd-exchange-receiving.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "../src/ipc.h" +#include "../src/usocket.h" + +// This program receives an open file descriptor from another running program. +// see examples/fd-exchange-providing.c + +int main(int argc, char * argv[]) +{ + if (argc != 1) { + fprintf (stderr, "usage: %s", argv[0]); + exit (EXIT_FAILURE); + } + + int usock = 0; + int usockclient = 0; + int fd = 0; + + TIPC_P_Q (usock_init (&usock, "SOCKET_FD_EXCHANGE_TEST"), "trying to connect to the unix socket", EXIT_FAILURE); + TIPC_P_Q (usock_accept (usock, &usockclient), "cannot accept a client from the unix socket", EXIT_FAILURE); + TIPC_P_Q (ipc_receive_fd (usockclient, &fd), "cannot receive the file descriptor", EXIT_FAILURE); + + T_PERROR_R ((write (fd, "coucou\n", 7) < 0), "cannot write a message in the file", EXIT_FAILURE); + T_PERROR_R ((close (fd) < 0), "cannot close the file descriptor", EXIT_FAILURE); + + TIPC_P_Q (usock_close (usock), "cannot close the unix socket", EXIT_FAILURE); + + return EXIT_SUCCESS; +} diff --git a/examples/pong.c b/examples/pong.c index eea4b60..f15e565 100644 --- a/examples/pong.c +++ b/examples/pong.c @@ -13,115 +13,79 @@ fprintf(stderr, "error while %s: %s\n", msg, err);\ } +void chomp (char *str, ssize_t len) { + if (str[len -1] == '\n') { + str[len -1] = '\0'; + } + if (str[len -2] == '\n') { + str[len -2] = '\0'; + } +} + struct ipc_connection_info *srv; void non_interactive (char *env[]) { - struct ipc_message m; - memset (&m, 0, sizeof (struct ipc_message)); - - enum ipc_errors ret; + SECURE_DECLARATION (struct ipc_message, m); // init service - ret = ipc_connection (env, srv, SERVICE_NAME); - if (ret != IPC_ERROR_NONE) { - handle_err("main", "ipc_application_connection < 0"); - PRINTERR(ret, "application connection"); - exit (EXIT_FAILURE); - } + TIPC_P_Q (ipc_connection (env, srv, SERVICE_NAME), "application connection", EXIT_FAILURE); + TIPC_P_Q (ipc_message_format_data (&m, 42, MSG, (ssize_t) strlen(MSG) +1), "message format data", EXIT_FAILURE); printf ("msg to send (%ld): %.*s\n", (ssize_t) strlen(MSG) +1, (int) strlen(MSG), MSG); - ret = ipc_message_format_data (&m, 42, MSG, (ssize_t) strlen(MSG) +1); - if (ret != IPC_ERROR_NONE) { - PRINTERR(ret, "message format data"); - exit (EXIT_FAILURE); - } - - // printf ("msg to send in the client: "); - // ipc_message_print (&m); - ret = ipc_write (srv, &m); - if (ret != IPC_ERROR_NONE) { - handle_err("main", "application_write"); - PRINTERR(ret, "application write"); - exit (EXIT_FAILURE); - } + TIPC_P_Q (ipc_write (srv, &m), "application write", EXIT_FAILURE); ipc_message_empty (&m); - - ret = ipc_read (srv, &m); - if (ret != IPC_ERROR_NONE) { - handle_err("main", "application_read"); - PRINTERR(ret, "application read"); - exit (EXIT_FAILURE); - } + TIPC_P_Q (ipc_read (srv, &m), "application read", EXIT_FAILURE); printf ("msg recv (type: %u): %s\n", m.user_type, m.payload); ipc_message_empty (&m); - ret = ipc_close (srv); - if (ret != IPC_ERROR_NONE) { - handle_err("main", "application_close"); - PRINTERR(ret, "application close"); - exit (EXIT_FAILURE); - } + TIPC_P_Q (ipc_close (srv), "application close", EXIT_FAILURE); } void interactive (char *env[]) { - enum ipc_errors ret; - // init service - ret = ipc_connection (env, srv, SERVICE_NAME); - if (ret != IPC_ERROR_NONE) { - handle_err ("main", "ipc_application_connection < 0"); - PRINTERR(ret, "application connection"); - exit (EXIT_FAILURE); - } + TIPC_P_Q (ipc_connection (env, srv, SERVICE_NAME), "application connection", EXIT_FAILURE); - struct ipc_event event; - memset (&event, 0, sizeof (struct ipc_event)); + SECURE_DECLARATION (struct ipc_event, event); + SECURE_DECLARATION (struct ipc_connection_infos, services); - struct ipc_connection_infos services; - memset (&services, 0, sizeof (struct ipc_connection_infos)); ipc_add (&services, srv); - ipc_add_fd (&services, 0); // add STDIN - ipc_connections_print(&services); + ipc_connections_print (&services); while (1) { printf ("msg to send: "); fflush (stdout); - ret = ipc_wait_event (&services, NULL, &event); - if (ret != IPC_ERROR_NONE) { - PRINTERR(ret, "wait event"); - exit (EXIT_FAILURE); - } + TIPC_P_Q (ipc_wait_event (&services, NULL, &event), "wait event", EXIT_FAILURE); switch (event.type) { case IPC_EVENT_TYPE_EXTRA_SOCKET: { // structure not read, should read the message here - ssize_t len; char buf[4096]; memset(buf, 0, 4096); len = read (event.origin->fd, buf, 4096); - buf[100] = '\0'; + buf[len -1] = '\0'; + chomp (buf, len); + +#if 0 + printf ("\n"); + printf ("message to send: %.*s\n", (int) len, buf); +#endif // in case we want to quit the program if ( len == 0 || strncmp (buf, "quit", 4) == 0 || strncmp (buf, "exit", 4) == 0) { - ret = ipc_close (srv); - if (ret != IPC_ERROR_NONE) { - handle_err("main", "ipc_close"); - PRINTERR(ret, "application close"); - exit (EXIT_FAILURE); - } + TIPC_P_Q (ipc_close (srv), "application close", EXIT_FAILURE); ipc_connections_free (&services); @@ -130,15 +94,18 @@ void interactive (char *env[]) // send the message read on STDIN struct ipc_message *m = NULL; - m = malloc (sizeof (struct ipc_message)); - memset (m, 0, sizeof (struct ipc_message)); + SECURE_BUFFER_HEAP_ALLOCATION_R (m, sizeof (struct ipc_message), , ); - ret = ipc_write (srv, m); - if (ret != IPC_ERROR_NONE) { - handle_err("main", "ipc_write"); - PRINTERR(ret, "ipc_write"); - exit (EXIT_FAILURE); - } + TIPC_P_Q (ipc_message_format_data (m, 42, buf, len), "message format", EXIT_FAILURE); + +#if 0 + printf ("\n"); + printf ("right before sending a message\n"); +#endif + TIPC_P_Q (ipc_write (srv, m), "ipc_write", EXIT_FAILURE); +#if 0 + printf ("right after sending a message\n"); +#endif ipc_message_empty (m); free (m); @@ -147,7 +114,7 @@ void interactive (char *env[]) case IPC_EVENT_TYPE_MESSAGE: { struct ipc_message *m = event.m; - printf ("msg recv: %.*s", m->length, m->payload); + printf ("\rmsg recv: %.*s\n", m->length, m->payload); }; break; case IPC_EVENT_TYPE_DISCONNECTION: diff --git a/examples/pongd.c b/examples/pongd.c index eba67fb..1fe47b6 100644 --- a/examples/pongd.c +++ b/examples/pongd.c @@ -71,16 +71,20 @@ void main_loop () case IPC_EVENT_TYPE_MESSAGE: { struct ipc_message *m = event.m; - if (m->length > 0) { #ifdef PONGD_VERBOSE - printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload); -#endif + if (m->length > 0) { + printf ("message received (type %d, user type %d, size %u bytes): %.*s\n", m->type, m->user_type, m->length, m->length, m->payload); } + else { + printf ("message with a 0-byte size :(\n"); + } +#endif ret = ipc_write (event.origin, m); if (ret != IPC_ERROR_NONE) { PRINTERR(ret,"server write"); } + printf ("message sent\n"); }; break; case IPC_EVENT_TYPE_ERROR: @@ -110,7 +114,7 @@ void exit_program(int signal) printf("Quitting, signal: %d\n", signal); // free remaining clients - for (int i = 0; i < clients->size ; i++) { + for (size_t i = 0; i < clients->size ; i++) { struct ipc_connection_info *cli = clients->cinfos[i]; if (cli != NULL) { free (cli); diff --git a/examples/simple-tcp-client.c b/examples/simple-tcp-client.c index 1cf0693..f017d84 100644 --- a/examples/simple-tcp-client.c +++ b/examples/simple-tcp-client.c @@ -23,18 +23,14 @@ */ -int connection(int port) +int connection(char *ipstr, int port) { int sockfd; - struct sockaddr_in server; + SECURE_DECLARATION (struct sockaddr_in, server); socklen_t addrlen; // socket factory - if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) - { - perror("socket"); - exit(EXIT_FAILURE); - } + T_PERROR_Q (((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1), "socket creation", EXIT_FAILURE); // init remote addr structure and other params server.sin_family = AF_INET; @@ -42,19 +38,11 @@ int connection(int port) addrlen = sizeof(struct sockaddr_in); // get addr from command line and convert it - if(inet_pton(AF_INET, "127.0.0.1", &server.sin_addr) <= 0) - { - perror("inet_pton"); - close(sockfd); - exit(EXIT_FAILURE); - } + T_PERROR_Q ((inet_pton(AF_INET, ipstr, &server.sin_addr) <= 0), "inet_pton", EXIT_FAILURE); printf("Trying to connect to the remote host\n"); - if(connect(sockfd, (struct sockaddr *) &server, addrlen) == -1) - { - perror("connect"); - exit(EXIT_FAILURE); - } + + T_PERROR_Q ((connect(sockfd, (struct sockaddr *) &server, addrlen) == -1), "connection", EXIT_FAILURE); printf("Connection OK\n"); @@ -63,70 +51,37 @@ int connection(int port) void send_receive (int sockfd) { - unsigned char buf[BUFSIZ]; - memset (buf, 0, BUFSIZ); + SECURE_BUFFER_DECLARATION (unsigned char, buf, BUFSIZ); + int paylen; // first, send service name "pong" // send string - if(send(sockfd, "pong", 4, 0) == -1) { - perror("send pong"); - close(sockfd); - exit(EXIT_FAILURE); - } + T_PERROR_Q ((send(sockfd, "pong", 4, 0) == -1), "sending a message", EXIT_FAILURE); printf ("message 'pong' sent\n"); + T_PERROR_Q (((paylen = recv(sockfd, buf, BUFSIZ, 0)) <= 0), "cannot connect to networkd", EXIT_FAILURE); + print_hexa ("should be 'OK'", buf, paylen); memset (buf, 0, BUFSIZ); - int paylen; - paylen = recv(sockfd, buf, BUFSIZ, 0); - if (paylen <= 0) { - printf ("cannot connect to networkd\n"); - exit (EXIT_FAILURE); - } - printf ("should receive 'OK': %*.s\n", paylen, buf); - - memset (buf, 0, BUFSIZ); - - buf[0] = MSG_TYPE_DATA; - - // uint32_t v = htonl(6); - // memcpy (buf+1, &v, sizeof (uint32_t)); - - uint32_t v = 6; - uint32_t net_paylen = htonl (v); - memcpy (buf+1, &net_paylen, sizeof (uint32_t)); - - buf[5] = 0; - memcpy (buf+6, "coucou", 6); - - print_hexa ("SENT MESSAGE", buf, 12); - // 2 | 6 | 0 | "coucou" // 1 B | 4 B | 1 | 6 B - - if(send(sockfd, buf, 12, 0) == -1) { - perror("send coucou"); - close(sockfd); - exit(EXIT_FAILURE); - } + ipc_message_raw_serialize ((char *) buf, MSG_TYPE_DATA, 42, "coucou", 6); + print_hexa ("WAITING 10 seconds then message to send", buf, 12); + // sleep (1); + T_PERROR_Q ((send(sockfd, buf, 12, 0) == -1), "sending a message", EXIT_FAILURE); printf ("message 'coucou' sent\n"); - memset (buf, 0, BUFSIZ); - paylen = recv (sockfd, buf, BUFSIZ, 0); - if(paylen < 0) { - perror("recv a message"); - close(sockfd); - exit(EXIT_FAILURE); - } - if (paylen > 0) { - print_hexa ("RECEIVED MESSAGE", buf, paylen); - } - else { + // receiving a message + T_PERROR_Q ( ((paylen = recv (sockfd, buf, BUFSIZ, 0)) < 0), "receiving a message", EXIT_FAILURE); + + if (paylen == 0) { fprintf (stderr, "error: disconnection from the server\n"); exit (EXIT_FAILURE); } + print_hexa ("RECEIVED MESSAGE", buf, paylen); + #if 0 // send string if(sendto(sockfd, , ), 0) == -1) @@ -141,12 +96,17 @@ void send_receive (int sockfd) { int main(int argc, char * argv[]) { + char *ipstr = "127.0.0.1"; int port = 9000; - if (argc > 1) { + if (argc == 2) { port = atoi (argv[1]); } + else if (argc == 3) { + ipstr = argv[1]; + port = atoi (argv[2]); + } - int sockfd = connection (port); + int sockfd = connection (ipstr, port); send_receive (sockfd); diff --git a/examples/simple-tcpd.c b/examples/simple-tcpd.c index 691f36e..317facd 100644 --- a/examples/simple-tcpd.c +++ b/examples/simple-tcpd.c @@ -7,12 +7,16 @@ #include #include -#define NTAB(t) ((int) (sizeof (t) / sizeof (t)[0])) -#define SECURE_BUFFER_DECLARATION(type,name,size) type name[size]; memset(&name, 0, sizeof(type) * size); -// print error string -#define PRINT_ERR_STR(code) const char *estr = ipc_errors_get (code); fprintf (stderr, "%s", estr); -// Test Print Quit -#define T_P_Q(f,err,q) { ret = f; if (ret != IPC_ERROR_NONE) { fprintf (stderr, err); PRINT_ERR_STR(ret); exit (q); } } +#define CLOG_DEBUG(a, ...) LOG_DEBUG (""); LOG_DEBUG("\033[36m" a "\033[00m", #__VA_ARGS__); LOG_DEBUG ("") + +void chomp (char *str, size_t len) { + if (str[len -1] == '\n') { + str[len -1] = '\0'; + } + if (str[len -2] == '\n') { + str[len -2] = '\0'; + } +} /* * @@ -30,8 +34,14 @@ if reading on sock_tcp sock_client = accept ipc_add_fd sock_client - elif reading on sock_client - TODO (first draft): print messages + elif + if socket bind to another (client to service or service to client) + reading on fd ; writing on related fd + else + connection from the client: + 1. client sends service name + 2. networkd establishes a connection to the service + 3. ack else lolwat shouldn't happen :( elif reading on usual socket @@ -40,223 +50,89 @@ #define SERVICE_NAME "simpletcp" -#define PRINTERR(ret,msg) {\ - const char * err = ipc_errors_get (ret);\ - fprintf(stderr, "error while %s: %s\n", msg, err);\ -} - -struct ipc_switching { - int orig; - int dest; -}; - -struct ipc_switchings { - struct ipc_switching *collection; - size_t size; -}; - -struct networkd { - int cpt; - struct ipc_connection_info *srv; - struct ipc_connection_infos *clients; - struct ipc_switchings * TCP_TO_IPC; - struct ipc_switchings * IPC_TO_TCP; -}; - struct networkd * ctx; - -void ipc_switching_add (struct ipc_switchings *is, int orig, int dest) +void handle_disconnection (int fd) { - is->collection = realloc(is->collection, sizeof(struct ipc_switching) * (is->size+1)); - if (is->collection == NULL) { - printf ("error realloc\n"); - exit (EXIT_FAILURE); + // disconnection + LOG_DEBUG ("CLOSE CONNECTION %d", fd); + + int delfd; + + delfd = ipc_switching_del (ctx->TCP_TO_IPC, fd); + if (delfd >= 0) { + LOG_DEBUG ("CLOSE RELATED CONNECTION %d", delfd); + close (delfd); + ipc_del_fd (ctx->clients, delfd); } - is->size++; + close (fd); + ipc_del_fd (ctx->clients, fd); - is->collection[is->size-1].orig = orig; - is->collection[is->size-1].dest = dest; + printf ("\n\n"); + // printf ("TCP_TO_IPC\n"); + ipc_switching_print (ctx->TCP_TO_IPC); + + printf ("\n\n"); } -int ipc_switching_del (struct ipc_switchings *is, int orig) +void tcp_connection (char **env, int fd) { - for (size_t i = 0; i < is->size; i++) { - if (is->collection[i].orig == orig) { - is->collection[i].orig = is->collection[is->size-1].orig; - int ret = is->collection[i].dest; - is->collection[i].dest = is->collection[is->size-1].dest; + SECURE_BUFFER_DECLARATION(char, buf, BUFSIZ); - size_t s = (is->size - 1) > 0 ? (is->size - 1) : 1; - - is->collection = realloc(is->collection, sizeof(struct ipc_switching) * s); - if (is->collection == NULL) { - printf ("error realloc\n"); - exit (EXIT_FAILURE); - } - - is->size--; - return ret; - } + ssize_t len = recv (fd, buf, BUFSIZ, 0); + if (len <= 0) { + handle_disconnection (fd); + return ; } - return -1; -} - -int ipc_switching_get (struct ipc_switchings *is, int orig) { - for (size_t i = 0; i < is->size; i++) { - if (is->collection[i].orig == orig) { - return is->collection[i].dest; - } - } - - return -1; -} - -void ipc_switching_print (struct ipc_switchings *is) { - printf ("print!\n"); - for (size_t i = 0; i < is->size; i++) - { - printf ("client %d - %d\n", is->collection[i].orig, is->collection[i].dest); - } -} - -void tcp_connection (char **env, int fd, char * buf, int len) -{ - printf ("tcp client %d is not already connected to a service\n", fd); buf[len] = '\0'; - // for testing purposes - size_t last_char = strlen ((const char*)buf) -1; - if (buf[last_char] == '\n') { - buf[last_char] = '\0'; - } - - printf ("read something: where to connect %s\n", buf); - printf ("sending ok\n"); + // XXX: for testing purposes + chomp (buf, len); + LOG_DEBUG ("SHOULD CONNECT TO %s", buf); // TODO: tests - if (send (fd, "OK", 2, 0) <= 0) { - fprintf (stderr, "error: cannot send message\n"); - perror("send"); - exit (EXIT_FAILURE); - } - + T_PERROR_Q ( (send (fd, "OK", 2, 0) <= 0), "sending a message", EXIT_FAILURE); SECURE_DECLARATION (struct ipc_connection_info, tcp_to_ipc_ci); - enum ipc_errors ret = 0; - T_P_Q (ipc_connection (env, &tcp_to_ipc_ci, buf), "cannot connect to the service\n", EXIT_FAILURE); + TIPC_F_Q (ipc_connection (env, &tcp_to_ipc_ci, buf), ("cannot connect to the service [%s]", buf), EXIT_FAILURE); ipc_switching_add (ctx->TCP_TO_IPC, fd, tcp_to_ipc_ci.fd); - ipc_switching_add (ctx->IPC_TO_TCP, tcp_to_ipc_ci.fd, fd); ipc_add_fd (ctx->clients, tcp_to_ipc_ci.fd); + + LOG_DEBUG ("CONNECTION TO SERVICE client %d -> %d", fd, tcp_to_ipc_ci.fd); } -void handle_extra_socket (struct ipc_event event, int sockfd, char **env) +int accept_new_client (int serverfd) { SECURE_DECLARATION (struct sockaddr_in, client); socklen_t addrlen = 0; - printf ("something comes from somewhere: fd %d\n", event.origin->fd); + int sock_fd_client; + T_PERROR_Q (((sock_fd_client = accept(serverfd, (struct sockaddr *) &client, &addrlen)) == -1), "accept new client", EXIT_FAILURE); - // NEW CLIENT - if (event.origin->fd == sockfd) { - int sock_fd_client; - if((sock_fd_client = accept(sockfd, (struct sockaddr *) &client, &addrlen)) == -1) { - perror("accept"); - close(sockfd); - exit(EXIT_FAILURE); - } - printf ("after accept\n"); - // adding a client - ipc_add_fd (ctx->clients, sock_fd_client); - printf ("after ipc_add_fd, TCP client: %d\n", sock_fd_client); - } - // CLIENT IS TALKING - else { - SECURE_BUFFER_DECLARATION(char, buf, 4096); + // adding a client + ipc_add_fd (ctx->clients, sock_fd_client); - ssize_t len = recv (event.origin->fd, buf, 4096, 0); - if (len > 0) { - - print_hexa ("RECEIVED", (unsigned char*) buf, len); - - // TODO: check if the message comes from an external IPC - int fd = ipc_switching_get (ctx->IPC_TO_TCP, event.origin->fd); - - if (fd >= 0) { - printf ("SWITCH: ipc service %d sent a message for %d\n", event.origin->fd, fd); - int sent_len = send (fd, buf, len, 0); - if (sent_len < 0) { - perror ("write to ipc"); - } - else if (sent_len != len) { - fprintf (stderr, "write NOT ENOUGH to tcp client\n"); - } - } - else { - fd = ipc_switching_get (ctx->TCP_TO_IPC, event.origin->fd); - if (fd >= 0) { - printf ("SWITCH: client %d sent a message for %d\n", event.origin->fd, fd); - int sent_len = send (fd, buf, len, 0); - if (sent_len < 0) { - perror ("write to ipc"); - } - else if (sent_len != len) { - fprintf (stderr, "write NOT ENOUGH to ipc\n"); - } - } - else { - tcp_connection (env, event.origin->fd, buf, len); - } - } - } - else if (len == 0) { - // disconnection - printf ("close connection\n"); - - int delfd = ipc_switching_del (ctx->TCP_TO_IPC, event.origin->fd); - if (delfd >= 0) { - close (delfd); - ipc_del_fd (ctx->clients, delfd); - } - - delfd = ipc_switching_del (ctx->IPC_TO_TCP, event.origin->fd); - if (delfd >= 0) { - close (delfd); - ipc_del_fd (ctx->clients, delfd); - } - - close (event.origin->fd); - ipc_del_fd (ctx->clients, event.origin->fd); - } - } + return sock_fd_client; } - void main_loop (int argc, char **argv, char **env) { argc = argc; // FIXME: useless - int sockfd; + int serverfd; - struct sockaddr_in my_addr; + SECURE_DECLARATION (struct sockaddr_in, my_addr); socklen_t addrlen; // socket factory - if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) - { - perror("socket"); - exit(EXIT_FAILURE); - } + T_PERROR_R (((serverfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1), "socket", ); int yes = 1; - if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { - perror ("setsockopt"); - } - + T_PERROR_R ((setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1), "setsockopt", ); // init local addr structure and other params my_addr.sin_family = AF_INET; @@ -265,57 +141,51 @@ void main_loop (int argc, char **argv, char **env) addrlen = sizeof(struct sockaddr_in); // bind addr structure with socket - if(bind(sockfd, (struct sockaddr *) &my_addr, addrlen) == -1) - { - perror("bind"); - close(sockfd); - exit(EXIT_FAILURE); - } + T_PERROR_R ((bind(serverfd, (struct sockaddr *) &my_addr, addrlen) == -1), "bind", ); // set the socket in passive mode (only used for accept()) // and set the list size for pending connection - if(listen(sockfd, 5) == -1) - { - perror("listen"); - close(sockfd); - exit(EXIT_FAILURE); - } + T_PERROR_R ((listen(serverfd, 5) == -1), "listen", ); printf("Waiting for incomming connection\n"); + SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->clients, sizeof (struct ipc_connection_infos), , EXIT_FAILURE); + SECURE_DECLARATION (struct ipc_event, event); - enum ipc_errors ret = 0; - - ctx->clients = malloc (sizeof (struct ipc_connection_infos)); - memset(ctx->clients, 0, sizeof(struct ipc_connection_infos)); - - struct ipc_event event; - memset(&event, 0, sizeof (struct ipc_event)); - printf ("adding sockfd to ctx->clients\n"); - ipc_add_fd (ctx->clients, sockfd); + printf ("adding serverfd to ctx->clients\n"); + ipc_add_fd (ctx->clients, serverfd); while(1) { - // ipc_service_poll_event provides one event at a time + // ipc_wait_event provides one event at a time // warning: event->m is free'ed if not NULL - // printf ("before wait event\n"); // TODO remove - ret = ipc_wait_event (ctx->clients, ctx->srv, &event); - // printf ("after wait event\n"); // TODO remove - if (ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT) { - PRINTERR(ret,"wait event"); - - // the application will shut down, and close the service - ret = ipc_server_close (ctx->srv); - if (ret != IPC_ERROR_NONE) { - PRINTERR(ret,"server close"); - } - exit (EXIT_FAILURE); - } + TIPC_T_P_I_R ( + /* function to test */ ipc_wait_event_networkd (ctx->clients, ctx->srv, &event, ctx->TCP_TO_IPC) + , /* error condition */ ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT + , /* to say on error */ "wait event" + , /* to do on error */ LOG_ERROR ("\033[31m error happened\033[00m"); TIPC_P (ipc_server_close (ctx->srv), "server close") + , /* return function */ return ); switch (event.type) { + case IPC_EVENT_TYPE_SWITCH: + { + printf ("switch happened\n"); + } + break; + case IPC_EVENT_TYPE_EXTRA_SOCKET: { - handle_extra_socket (event, sockfd, env); + // NEW CLIENT + if (event.origin->fd == serverfd) { + int sock_fd_client = accept_new_client (serverfd); + ctx->cpt++; + printf ("TCP connection: %d clients connected\n", ctx->cpt); + printf ("new TCP client has the fd %d\n", sock_fd_client); + } + // CLIENT IS TALKING + else { + tcp_connection (env, event.origin->fd); + } } break; @@ -326,13 +196,15 @@ void main_loop (int argc, char **argv, char **env) printf ("new client has the fd %d\n", (event.origin)->fd); }; break; + case IPC_EVENT_TYPE_DISCONNECTION: { ctx->cpt--; printf ("disconnection: %d clients remaining\n", ctx->cpt); // free the ipc_client structure - free (event.origin); + // if (event.origin != NULL) + // free (event.origin); }; break; case IPC_EVENT_TYPE_MESSAGE: @@ -342,24 +214,14 @@ void main_loop (int argc, char **argv, char **env) printf ("message received (type %d): %.*s\n", m->type, m->length, m->payload); } - ret = ipc_write (event.origin, m); - - if (ret != IPC_ERROR_NONE) { - handle_err( "handle_new_msg", "server_write < 0"); - PRINTERR(ret,"server write"); - } + TIPC_P (ipc_write (event.origin, m), "server write"); }; break; case IPC_EVENT_TYPE_ERROR: - { - fprintf (stderr, "a problem happened with client %d\n" - , (event.origin)->fd); - }; + fprintf (stderr, "a problem happened with client %d\n", (event.origin)->fd); break; default : - { - fprintf (stderr, "there must be a problem, event not set\n"); - }; + fprintf (stderr, "there must be a problem, event not set\n"); } } @@ -373,7 +235,7 @@ void exit_program(int signal) printf("Quitting, signal: %d\n", signal); // free remaining clients - for (int i = 0; i < ctx->clients->size ; i++) { + for (size_t i = 0; i < ctx->clients->size ; i++) { struct ipc_connection_info *cli = ctx->clients->cinfos[i]; if (cli != NULL) { free (cli); @@ -382,20 +244,15 @@ void exit_program(int signal) } ipc_connections_free (ctx->clients); - free (ctx->clients); - // the application will shut down, and close the service - enum ipc_errors ret = ipc_server_close (ctx->srv); - if (ret != IPC_ERROR_NONE) { - PRINTERR(ret,"server close"); - } - free (ctx->srv); + TIPC_P (ipc_server_close (ctx->srv), "server close"); + // free, free everything! + free (ctx->clients); + free (ctx->srv); free (ctx->TCP_TO_IPC->collection); free (ctx->TCP_TO_IPC); - free (ctx->IPC_TO_TCP->collection); - free (ctx->IPC_TO_TCP); free (ctx); exit(EXIT_SUCCESS); @@ -412,39 +269,18 @@ int main(int argc, char * argv[], char **env) if(argc != 2) { printf("USAGE: %s port_num\n", argv[0]); - exit(-1); + exit(EXIT_FAILURE); } printf ("pid = %d\n", getpid ()); - ctx = malloc (sizeof (struct networkd)); - memset (ctx, 0, sizeof (struct networkd)); + SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx, sizeof (struct networkd), , EXIT_FAILURE); + SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->TCP_TO_IPC, sizeof(struct ipc_switchings), , EXIT_FAILURE); + SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->TCP_TO_IPC->collection, sizeof(struct ipc_switching), , EXIT_FAILURE); + SECURE_BUFFER_HEAP_ALLOCATION_Q (ctx->srv, sizeof (struct ipc_connection_info), , EXIT_FAILURE); - - ctx->TCP_TO_IPC = malloc(sizeof(struct ipc_switchings)); - memset (ctx->TCP_TO_IPC, 0, sizeof(struct ipc_switchings)); - ctx->TCP_TO_IPC->collection = malloc(sizeof(struct ipc_switching)); - ctx->IPC_TO_TCP = malloc(sizeof(struct ipc_switchings)); - memset (ctx->IPC_TO_TCP, 0, sizeof(struct ipc_switchings)); - ctx->IPC_TO_TCP->collection = malloc(sizeof(struct ipc_switching)); - - ctx->srv = malloc (sizeof (struct ipc_connection_info)); - if (ctx->srv == NULL) { - exit (EXIT_FAILURE); - } - memset (ctx->srv, 0, sizeof (struct ipc_connection_info)); - ctx->srv->type = '\0'; - ctx->srv->index = 0; - ctx->srv->version = 0; - ctx->srv->fd = 0; - ctx->srv->spath = NULL; - - enum ipc_errors ret = ipc_server_init (env, ctx->srv, SERVICE_NAME); - if (ret != IPC_ERROR_NONE) { - PRINTERR(ret,"server init"); - return EXIT_FAILURE; - } - printf ("Listening on %s.\n", ctx->srv->spath); + TIPC_P_R (ipc_server_init (env, ctx->srv, SERVICE_NAME), "server init", EXIT_FAILURE); + printf ("Listening on [%s].\n", ctx->srv->spath); printf("MAIN: server created\n" ); diff --git a/examples/test-ask-for-fd-to-networkd.c b/examples/test-ask-for-fd-to-networkd.c new file mode 100644 index 0000000..80fd9ad --- /dev/null +++ b/examples/test-ask-for-fd-to-networkd.c @@ -0,0 +1,46 @@ +#include +#include +#include + +#include "../src/ipc.h" + +#define DEFAULT_IPC_NETWORK "IPC_NETWORK=\"pong local:lolwat\"" + +int main(int argc, char * argv[]) +{ + + (void) argc; + (void) argv; + + enum ipc_errors ret; + SECURE_DECLARATION (struct ipc_connection_info, srv); + + if (argc != 2) { + fprintf (stderr, "usage: %s service_name\n", argv[0]); + exit (1); + } + + char *service_name = argv[1]; + + // ask for a local service "pong" + // inform the network service that it's now named "lolwat" + char *ipc_network = getenv("IPC_NETWORK"); + if (ipc_network == NULL) { + ipc_network = DEFAULT_IPC_NETWORK; + } + + ret = ipc_contact_networkd (&srv, service_name, ipc_network); + + printf ("ret = %d\n", ret); + + if (ret == 0 && srv.fd != 0) { + printf ("Success\n"); + } + else { + printf ("Ow. :(\n"); + } + + usock_close (srv.fd); + + return EXIT_SUCCESS; +} diff --git a/examples/test-networkd-provide-fd.c b/examples/test-networkd-provide-fd.c new file mode 100644 index 0000000..6074d30 --- /dev/null +++ b/examples/test-networkd-provide-fd.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "../src/ipc.h" + + +int main(int argc, char * argv[], char *env[]) +{ + + (void) argc; + (void) argv; + + enum ipc_errors ret; + SECURE_DECLARATION (struct ipc_connection_info, srv); + SECURE_DECLARATION (struct ipc_connection_info, client); + SECURE_DECLARATION (struct ipc_connection_info, contacted_service); + + + // service start + TIPC_P_RR (ipc_server_init (env, &srv, "network"), "Networkd cannot be initialized"); + + printf ("service initialized, waiting for a client\n"); + + // accept a new client + TIPC_P_RR (ipc_accept (&srv, &client), "cannot accept the client during handle_new_connection"); + + // TODO: read a message to know the requested service + SECURE_DECLARATION (struct ipc_message, msg); + ret = ipc_read (&client, &msg); + printf ("received message: %s\n", msg.payload); + + /** TODO: contact the service */ + printf ("WARNING: currently this program only ask for pong service %d\n", ret); + TIPC_P_RR (ipc_connection (env, &contacted_service, "pong"), "cannot connect to the requested service"); + + ipc_provide_fd (client.fd, contacted_service.fd); + + TIPC_P_RR (ipc_server_close (&srv), "Networkd cannot be stopped!!"); + return EXIT_SUCCESS; +} diff --git a/examples/tests-logs.c b/examples/tests-logs.c new file mode 100644 index 0000000..3a57c04 --- /dev/null +++ b/examples/tests-logs.c @@ -0,0 +1,16 @@ +#include +#include +#include + +#include "../src/ipc.h" + +int main(void) +{ + SECURE_BUFFER_DECLARATION (char, buffer, BUFSIZ); + + log_get_logfile_name (buffer, BUFSIZ); + + printf ("log: %s\n", buffer); + + return EXIT_SUCCESS; +} diff --git a/examples/wsserver.c b/examples/wsserver.c new file mode 100644 index 0000000..7e9c343 --- /dev/null +++ b/examples/wsserver.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include + +#include "../src/ipc.h" +#include "../src/utils.h" + +#define WEBSOCKETD_BULLSHIT + +void chomp (char *str, ssize_t len) { + if (str[len -1] == '\n') { + str[len -1] = '\0'; + } + if (str[len -2] == '\n') { + str[len -2] = '\0'; + } +} + +struct ipc_connection_info *srv; + +void interactive (char *env[]) +{ + SECURE_BUFFER_DECLARATION (char, service_name, 100); + + char *sn = getenv("PATH_TRANSLATED"); + + if (sn != NULL) { + memcpy (service_name, sn, strlen(sn)); + } + else { + fprintf (stderr, "cannot see PATH_TRANSLATED variable\n"); + exit (EXIT_FAILURE); + } + + // init service + TIPC_P_Q (ipc_connection (env, srv, service_name), "application connection", EXIT_FAILURE); + + SECURE_DECLARATION (struct ipc_event, event); + SECURE_DECLARATION (struct ipc_connection_infos, services); + + ipc_add (&services, srv); + ipc_add_fd (&services, 0); // add STDIN + + while (1) { + TIPC_P_Q (ipc_wait_event (&services, NULL, &event), "wait event", EXIT_FAILURE); + + switch (event.type) { + case IPC_EVENT_TYPE_EXTRA_SOCKET: + { + // structure not read, should read the message here + SECURE_BUFFER_DECLARATION (char, buf, 4096); + ssize_t len; + + len = read (event.origin->fd, buf, 4096); + + // in case we want to quit the program + if ( len == 0 + || strncmp (buf, "quit", 4) == 0 + || strncmp (buf, "exit", 4) == 0) { + + TIPC_P_Q (ipc_close (srv), "application close", EXIT_FAILURE); + + ipc_connections_free (&services); + + exit (EXIT_SUCCESS); + } + + // send the message read on STDIN + ssize_t len_sent = write (srv->fd, buf, len); + if (len_sent != len) { + fprintf (stderr, "cannot send the message %lu-byte message, sent %lu bytes" + , len, len_sent); + exit (EXIT_FAILURE); + } + } + break; + case IPC_EVENT_TYPE_MESSAGE: + { + struct ipc_message *m = event.m; + SECURE_BUFFER_DECLARATION (char, buf, 4096); + uint32_t size; + size = ipc_message_raw_serialize (buf, m->type, m->user_type, m->payload, m->length); + + write (1, buf, size); +#ifdef WEBSOCKETD_BULLSHIT + printf ("\n"); +#endif + fflush (stdout); + }; + break; + ERROR_CASE (IPC_EVENT_TYPE_DISCONNECTION, "main loop", "disconnection: should not happen"); + ERROR_CASE (IPC_EVENT_TYPE_NOT_SET , "main loop", "not set: should not happen"); + ERROR_CASE (IPC_EVENT_TYPE_CONNECTION , "main loop", "connection: should not happen"); + // ERROR_CASE (IPC_EVENT_TYPE_ERROR , "main loop", "error"); + default : + fprintf (stderr, "event type error: should not happen, event type %d\n", event.type); + } + } +} + +int main (int argc, char *argv[], char *env[]) +{ + argc = argc; // warnings + argv = argv; // warnings + + srv = malloc (sizeof (struct ipc_connection_info)); + memset (srv, 0, sizeof (struct ipc_connection_info)); + + // index and version should be filled + srv->index = 0; + srv->version = 0; + + interactive (env); + + return EXIT_SUCCESS; +}