From 9177b3df34440478356db4de0b24dfafaae73dc3 Mon Sep 17 00:00:00 2001 From: Mazet Laurent Date: Thu, 22 May 2025 16:36:43 +0200 Subject: [PATCH] rename library --- mapec.c | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++ mapec.h | 114 +++++++++++++++++++++ mapec_test.c | 202 +++++++++++++++++++++++++++++++++++++ sap.c | 275 --------------------------------------------------- sap.h | 110 --------------------- sap_test.c | 197 ------------------------------------ 6 files changed, 591 insertions(+), 582 deletions(-) create mode 100644 mapec.c create mode 100644 mapec.h create mode 100644 mapec_test.c delete mode 100644 sap.c delete mode 100644 sap.h delete mode 100644 sap_test.c diff --git a/mapec.c b/mapec.c new file mode 100644 index 0000000..8f1a420 --- /dev/null +++ b/mapec.c @@ -0,0 +1,275 @@ +/* + File name : mapec.h + Projet : MERLIN + Date of creation : 2025/05/22 + Version : 1.0 + Copyright : Thales SIX + Author : Laurent Mazet + + Description : Minimal API for Packet Exchange Commmunication + + History : + - initial version +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "verbose.h" + +#include "mapec.h" + +DECLARE_VERBOSE_LEVEL (mapec, INFO); + +/** + MAPEC type +*/ +typedef enum { + MAPEC_error_e = 0, + MAPEC_udp_e +} MAPEC_type_t; + +/** + MAPEC address structure +*/ +typedef struct { + MAPEC_type_t type; + struct sockaddr_in addrin; + struct sockaddr_in addrout; +} MAPEC_addr_t; + +#define MAX_MAPEC_NUMBER 4096 + +/** + List of private descriptor associated to each connected MAPEC. +*/ +MAPEC_addr_t *MAPEC_list[MAX_MAPEC_NUMBER] = { 0 }; + +MAPEC_addr_t *mapecdup (MAPEC_addr_t *mapec) +{ + + VERBOSE (mapec, TRACE, PRINTF ("mapecdup\n")); + + MAPEC_addr_t *newmapec = (MAPEC_addr_t *) calloc (1, sizeof (MAPEC_addr_t)); + memcpy (newmapec, mapec, sizeof (MAPEC_addr_t)); + + return newmapec; +} + +void free_all_mapecs (void) +{ + + VERBOSE (mapec, TRACE, PRINTF ("free_mapecs\n")); + + for (int i = 0; i < MAX_MAPEC_NUMBER; i++) { + free (MAPEC_list[i]); + MAPEC_list[i] = NULL; + } +} + +void __attribute__ ((constructor)) _init_morep_ (void) +{ + atexit (free_all_mapecs); +} + +int parse_protocol (MAPEC_addr_t *addr, char *url) +{ + + VERBOSE (mapec, TRACE, PRINTF ("parse_protocol\n")); + + int rc = -1; + MAPEC_type_t type = MAPEC_error_e; + if (strncmp (url, "udp://", 6) == 0) { + type = MAPEC_udp_e; + rc = 6; + } + if (addr->type == MAPEC_error_e) { + addr->type = type; + } else if (addr->type != type) { + rc = -1; + } + + return rc; +} + + +int parse_address (struct sockaddr_in *addr, char *url) +{ + + VERBOSE (mapec, TRACE, PRINTF ("parse_addr\n")); + + char *pt = strchr (url, ':'); + if (pt == NULL) { + VERBOSE (mapec, WARNING, PRINTF ("can't parse address '%s'\n", url)); + return -1; + } + + char *hostname = (char *) calloc (pt - url + 1, 1); + memcpy (hostname, url, pt - url); + char *port = pt + 1; + if ((*hostname == '\0') || (*port == '\0')) { + errno = EINVAL; + free (hostname); + return -1; + } + + addr->sin_family = AF_INET; + addr->sin_port = htons (atoi (port)); + + VERBOSE (mapec, INFO, PRINTF ("parse URL -> %s %s\n", hostname, port)); + + if (hostname[0] != '*') { + struct hostent *he = gethostbyname (hostname); + if (he == NULL) { + errno = EHOSTUNREACH; + return -1; + } + + struct in_addr **addr_list = (struct in_addr **) he->h_addr_list; + addr->sin_addr.s_addr = addr_list[0]->s_addr; + } else { + addr->sin_addr.s_addr = INADDR_ANY; + } + free (hostname); + + return 0; +} + +int MAPEC_Connect (char *local_address, char * remote_address) +{ + + VERBOSE (mapec, TRACE, PRINTF ("MAPEC_Connect\n")); + + MAPEC_addr_t mapec = { 0 }; + int rc; + + /* parse local url */ + VERBOSE (mapec, DEBUG, PRINTF ("MAPEC local addr %s\n", local_address)); + rc = parse_protocol (&mapec, local_address); + if ((rc <= 0) || (parse_address (&mapec.addrin, local_address + rc) < 0)) { + VERBOSE (mapec, ERROR, PRINTF ("can't parse local url\n")); + errno = EINVAL; + return -1; + } + VERBOSE (mapec, DEBUG, PRINTF ("local port -> %d\n", ntohs (mapec.addrin.sin_port))); + + /* parse remote url */ + VERBOSE (mapec, DEBUG, PRINTF ("MAPEC remote addr %s\n", remote_address)); + rc = parse_protocol (&mapec, remote_address); + if ((rc <= 0) || (parse_address (&mapec.addrout, remote_address + rc) < 0)) { + VERBOSE (mapec, ERROR, PRINTF ("can't parse remote url\n")); + errno = EINVAL; + return -1; + } + VERBOSE (mapec, DEBUG, PRINTF ("remote port -> %d\n", ntohs (mapec.addrout.sin_port))); + + /* create socket */ + int fid = socket (PF_INET, SOCK_DGRAM, 0); + if ((fid < 0) || (fid >= MAX_MAPEC_NUMBER) || (MAPEC_list[fid] != NULL)) { + VERBOSE (mapec, ERROR, PRINTF ("can't accept socket %d\n", fid)); + errno = ENOMEM; + return -1; + } + + /* bind on local */ + int val = 1; + setsockopt (fid, SOL_SOCKET, SO_REUSEADDR, (int *)&val, sizeof (val)); + if (bind (fid, (struct sockaddr *)&mapec.addrin, sizeof (mapec.addrin)) < 0) { + VERBOSE (mapec, ERROR, PRINTF ("can't bind socket %d\n", fid)); + return -1; + } + + /* connect on remote */ + if (connect (fid, (struct sockaddr *)&mapec.addrout, sizeof (mapec.addrout)) < 0) { + VERBOSE (mapec, ERROR, PRINTF ("can't connect socket %d\n", fid)); + return -1; + } + + MAPEC_list[fid] = mapecdup (&mapec); + + return fid; +} + +void MAPEC_Close (int fid) +{ + + VERBOSE (mapec, TRACE, PRINTF ("MAPEC_Close\n")); + + if ((fid < 0) || (fid >= MAX_MAPEC_NUMBER)) { + return; + } + + close (fid); + + free (MAPEC_list[fid]); + MAPEC_list[fid] = NULL; +} + +int MAPEC_Send (int fid, unsigned char *data, int len) +{ + + VERBOSE (mapec, TRACE, PRINTF ("MAPEC_Send\n")); + + assert (((data != NULL) && (len > 0)) || ((data == NULL) && (len == 0))); + + if ((fid < 0) || (fid >= MAX_MAPEC_NUMBER) || (MAPEC_list[fid] == NULL)) { + errno = EBADF; + return -1; + } + + VERBOSE (mapec, DEBUG, PRINTF ("MAPEC_Send writting...\n")); + + return write (fid, data, len); +} + +int MAPEC_Receive_timeout (int fid, unsigned char *buffer, int maxlen, int ms) +{ + + VERBOSE (mapec, TRACE, PRINTF ("MAPEC_Receive_timeout\n")); + + fd_set rfds; + struct timeval tv = { 0, ms }; + FD_ZERO (&rfds); + FD_SET (fid, &rfds); + + int retval = select (fid + 1, &rfds, NULL, NULL, &tv); + if (retval != 1) { + return retval; + } + + return MAPEC_Receive (fid, buffer, maxlen); +} + +int MAPEC_Receive (int fid, unsigned char *buffer, int maxlen) +{ + + VERBOSE (mapec, TRACE, PRINTF ("MAPEC_Receive\n")); + + if ((fid < 0) || (fid >= MAX_MAPEC_NUMBER) || (MAPEC_list[fid] == NULL)) { + errno = EBADF; + return -1; + } + + VERBOSE (mapec, DEBUG, PRINTF ("MAPEC_Receive reading...\n")); + + int rc = read (fid, buffer, maxlen); + + if ((rc < 0) && (errno == EAGAIN)) { + rc = 0; + } + + return rc; +} + +/* vim: set ts=4 sw=4 si et: */ diff --git a/mapec.h b/mapec.h new file mode 100644 index 0000000..b2fc202 --- /dev/null +++ b/mapec.h @@ -0,0 +1,114 @@ +/* + File name : mapec.h + Projet : MERLIN + Date of creation : 2025/05/22 + Version : 1.0 + Copyright : Thales SIX + Author : Laurent Mazet + + Description : Minimal API for Packet Exchange Commmunication + + History : + - initial version +*/ + +#ifndef __MAPEC_H__ +#define __MAPEC_H__ + +#include + +__BEGIN_DECLS + +/** + @defgroup MAPEC Public API of MAPEC + + This library offers connections over UDP socket or TUN interface. In + both case, communication is based on packet exchanges. + + Values returned by MAPEC_Connect are standard Linux file descriptors + that can be used in select()/poll() system calls. +*/ + +/** + @ingroup MAPEC + + Establish a connection between a local URL and a remote URL. Block + until connection is established or refused. + + @param local_address local address of the MAPEC with the following + syntax: 'udp://hostname:port' or 'tun://device'. + @param remote_address same format as for local_address. For TUN, + remote address is not usesfull. + + @return a new file descriptor associated with this connection + + @see MAPEC_Close() + @see MAPEC_Send() + @see MAPEC_Receive() +*/ +int MAPEC_Connect (char *local_address, char *remote_address); + +/** + @ingroup MAPEC + + Destroy a MAPEC. + + @param fid the file descriptor retuned by MAPEC_Connect() + + @see MAPEC_Connect() +*/ +void MAPEC_Close (int fid); + +/** + @ingroup MAPEC + + Send a message over an existing MAPEC connection. Will block until + resolution in case of congestion. + + @param fid the file descriptor retuned by MAPEC_Connect() + @param data a pointer to the buffer containing the message to be + transmitted + @param len length of the message + + @return 0 on success, -1 on error + + @see MAPEC_Connect() +*/ +int MAPEC_Send (int fid, unsigned char *data, int len); + +/** + @ingroup MAPEC + + Received a message over an existing MAPEC connection. + + @param fid the file descriptor retuned by MAPEC_Connect() + @param buffer a pointer to the reception buffer + @param maxlen maximum length of the reception buffer + + @return length of the message or -1 on error + + @see MAPEC_Connect() +*/ +int MAPEC_Receive (int sap, unsigned char *buffer, int maxlen); + +/** + @ingroup MAPEC + + Received a message over an existing MAPEC connection with a timeout + + @param sap the file descriptor retuned by MAPEC_Connect() + @param buffer a pointer to the reception buffer + @param maxlen max length of the reception buffer + @param ms exit after x microseconds if no data is received + + @return length of the message or -1 on error + + @see MAPEC_Connect() +*/ +int MAPEC_Receive_timeout (int sap, unsigned char *buffer, int maxlen, int ms); + +__END_DECLS + +#endif /* __MAPEC_H__ */ + +/* vim: set ts=4 sw=4 si et: */ diff --git a/mapec_test.c b/mapec_test.c new file mode 100644 index 0000000..b197573 --- /dev/null +++ b/mapec_test.c @@ -0,0 +1,202 @@ +/* + File name : mapec_test.c + Projet : MERLIN + Date of creation : 2025/05/22 + Version : 1.0 + Copyright : Thales SIX + Author : Laurent Mazet + + Description : Test program for MAPEC socket + + History : + - initial version +*/ + +/* depend: */ +/* cflags: */ +/* linker: mapec.o */ + +#include +#include +#include +#include +#include +#include +#include + +#include "verbose.h" + +#include "mapec.h" + +int MAPEC_Send_UDP_OK = 0; +int MAPEC_Echo_UDP_OK = 0; + +#define UNUSED __attribute__ ((unused)) + +void *udp_client (UNUSED void *dummy) +{ + + VERBOSE (mapec, TRACE, PRINTF ("test_client\n")); + + int count; + unsigned char tx_data[10][1500]; + int tx_len[10]; + + int fid = MAPEC_Connect ("udp://localhost:13501", "udp://localhost:12501"); + if (fid < 0) { + VERBOSE (mapec, WARNING, PRINTF ("client MAPEC_Connect error\n")); + MAPEC_Echo_UDP_OK = 0; + return NULL; + } + + int nb_messages = 10; + VERBOSE (mapec, INFO, PRINTF ("client connected to server, trying to exchange %d messages\n", nb_messages)); + + for (count = 0; count < nb_messages; count++) { + + tx_len[count] = rand () % sizeof (tx_data[count]); + for (int i = 0; i < tx_len[count]; i++) + tx_data[count][i] = rand () % 256; + + int rc = MAPEC_Send (fid, tx_data[count], tx_len[count]); + if (rc < 0) { + VERBOSE (mapec, WARNING, PRINTF ("client MAPEC_Send tx error (%d/%d-%d)\n", rc, tx_len[count], errno)); + MAPEC_Echo_UDP_OK = 0; + return NULL; + } + + if (tx_len[count] != rc) { + VERBOSE (mapec, WARNING, PRINTF ("client MAPEC_Send tx len error tx=%d rc=%d\n", tx_len[count], rc)); + MAPEC_Echo_UDP_OK = 0; + return NULL; + } + VERBOSE (mapec, DEBUG, PRINTF ("client MAPEC_Send ok (%d)\n", tx_len[count])); + + usleep (1e4); + + int rx_len; + unsigned char rx_data[32768]; + + do { + rx_len = MAPEC_Receive (fid, rx_data, sizeof (rx_data)); + if (rx_len == 0) { + VERBOSE (mapec, DEBUG, PRINTF ("client's sleeping...\n")); + usleep (1e3); + } + } while (rx_len == 0); + + VERBOSE (mapec, INFO, PRINTF ("client received echo count=%d len=%d, fid=%d\n", count, rx_len, fid)); + + if (tx_len[count] != rx_len) { + VERBOSE (mapec, WARNING, PRINTF ("client MAPEC_Receive rx len error : tx=%d / rx=%d\n", tx_len[count], rx_len)); + MAPEC_Echo_UDP_OK = 0; + return NULL; + } + + if (memcmp (rx_data, tx_data[count], tx_len[count]) != 0 ) { + VERBOSE (mapec, WARNING, PRINTF ("client MAPEC_Receive rx corrupted data\n")); + MAPEC_Echo_UDP_OK = 0; + return NULL; + } + } + + MAPEC_Close (fid); + VERBOSE (mapec, INFO, PRINTF ("client end of test, %d echo processed\n", count)); + MAPEC_Echo_UDP_OK = 1; + + return NULL; +} + +void *udp_server (UNUSED void *dummy) +{ + + VERBOSE (mapec, TRACE, PRINTF ("udp_server\n")); + + int fid = MAPEC_Connect ("udp://localhost:12501", "udp://localhost:13501"); + if (fid < 0) { + VERBOSE (mapec, ERROR, PRINTF ("MAPEC_Connect (%d)", fid)); + exit (1); + } + + VERBOSE (mapec, INFO, PRINTF ("udp_server waiting for data\n")); + + while (1) { + unsigned char data[8192]; + + int rx_len = MAPEC_Receive (fid, data, sizeof (data)); + if (rx_len == 0) { + VERBOSE (mapec, DEBUG, PRINTF ("server's sleeping...\n")); + usleep (1e3); + continue; + } + if (rx_len < 0) { + VERBOSE (mapec, ERROR, PRINTF ("error receiving from MAPEC %d\n", fid)); + MAPEC_Close (fid); + break; + } + + VERBOSE (mapec, INFO, PRINTF ("udp_server receive data len=%d, sending echo\n", rx_len)); + usleep (1e4); + + int tx_len = MAPEC_Send (fid, data, rx_len); + if (tx_len == rx_len) { + MAPEC_Send_UDP_OK = 1; + } + } + + return NULL; +} + +/** + Dump status macro +*/ +#define DUMP_STATUS(x) do { \ + printf (#x " %s\n", (x) ? "OK" : "BAD"); \ + if (!(x)) { \ + failed = 1; \ + } \ + } while (0) \ + +int main (int argc, char **argv) +{ + + /* process arguments */ + if (argc > 1) { + CHANGE_VERBOSE_LEVEL (mapec, atoi (argv[1])); + argc--; + } + if (argc > 1) { + printf ("usage: %s [verbose level]\n", argv[0]); + exit (1); + } + + printf ("*** STARTING SERVERS ***\n"); + + pthread_t udp_thread; + + pthread_create (&udp_thread, NULL, udp_server, NULL); + + /* Give some delay to server to setup there MAPEC */ + usleep (1e6); + + printf ("*** STARTING TEST SEQUENCE ***\n"); + + pthread_t udp_client_thread; + + pthread_create (&udp_client_thread, NULL, udp_client, NULL); + + pthread_join (udp_client_thread, NULL); + + printf ("*** END OF TEST SEQUENCE ***\n"); + + int failed = 0; + DUMP_STATUS (MAPEC_Send_UDP_OK); + DUMP_STATUS (MAPEC_Echo_UDP_OK); + + return failed ? EXIT_FAILURE : EXIT_SUCCESS; +} + +/* test: mapec_test.exe */ +/* test: mapec_test.exe 4 */ + +/* vim: set ts=4 sw=4 si et: */ diff --git a/sap.c b/sap.c deleted file mode 100644 index 7006764..0000000 --- a/sap.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - Service Access Point communication library - - Copyrigth Eichos 20100319 -*/ - -#include -#include -#include -#if WIN32 -#include -#include -#define OPT_TYPE char -#else /* Linux */ -#include -#include -#include -#include -#include -#define OPT_TYPE int -#endif -#include -#include -#include -#include -#include - -//#include "tools.h" -#include "verbose.h" - -#include "sap.h" - -DECLARE_VERBOSE_LEVEL (sap, INFO); - -/** - SAP type -*/ -typedef enum { - SAP_error_e = 0, - SAP_udp_e -} SAP_type_t; - -/** - SAP address structure -*/ -typedef struct { - SAP_type_t type; - struct sockaddr_in addrin; - struct sockaddr_in addrout; -} SAP_addr_t; - -#define MAX_SAP_NUMBER 4096 - -/** - List of private descriptor associated to each connected SAP. -*/ -SAP_addr_t *SAP_list[MAX_SAP_NUMBER] = { 0 }; - -SAP_addr_t *sapdup (SAP_addr_t *sap) -{ - - VERBOSE (sap, TRACE, PRINTF ("sapdup\n")); - - SAP_addr_t *newsap = (SAP_addr_t *) calloc (1, sizeof (SAP_addr_t)); - memcpy (newsap, sap, sizeof (SAP_addr_t)); - - return newsap; -} - -void free_all_saps (void) -{ - - VERBOSE (sap, TRACE, PRINTF ("free_saps\n")); - - for (int i = 0; i < MAX_SAP_NUMBER; i++) { - free (SAP_list[i]); - SAP_list[i] = NULL; - } -} - -void __attribute__ ((constructor)) _init_morep_ (void) -{ - atexit (free_all_saps); -} - -int parse_protocol (SAP_addr_t *addr, char *url) -{ - - VERBOSE (sap, TRACE, PRINTF ("parse_protocol\n")); - - int rc = -1; - SAP_type_t type = SAP_error_e; - if (strncmp (url, "udp://", 6) == 0) { - type = SAP_udp_e; - rc = 6; - } - if (addr->type == SAP_error_e) { - addr->type = type; - } else if (addr->type != type) { - rc = -1; - } - - return rc; -} - - -int parse_address (struct sockaddr_in *addr, char *url) -{ - - VERBOSE (sap, TRACE, PRINTF ("parse_addr\n")); - - char *pt = strchr (url, ':'); - if (pt == NULL) { - VERBOSE (sap, WARNING, PRINTF ("can't parse address '%s'\n", url)); - return -1; - } - - char *hostname = (char *) calloc (pt - url + 1, 1); - memcpy (hostname, url, pt - url); - char *port = pt + 1; - if ((*hostname == '\0') || (*port == '\0')) { - errno = EINVAL; - free (hostname); - return -1; - } - - addr->sin_family = AF_INET; - addr->sin_port = htons (atoi (port)); - - VERBOSE (sap, INFO, PRINTF ("parse URL -> %s %s\n", hostname, port)); - - if (hostname[0] != '*') { - struct hostent *he = gethostbyname (hostname); - if (he == NULL) { - errno = EHOSTUNREACH; - return -1; - } - - struct in_addr **addr_list = (struct in_addr **) he->h_addr_list; - addr->sin_addr.s_addr = addr_list[0]->s_addr; - } else { - addr->sin_addr.s_addr = INADDR_ANY; - } - free (hostname); - - return 0; -} - -int SAP_Connect (char *local_address, char * remote_address) -{ - - VERBOSE (sap, TRACE, PRINTF ("SAP_Connect\n")); - - SAP_addr_t sap = { 0 }; - int rc; - - /* parse local url */ - VERBOSE (sap, DEBUG, PRINTF ("SAP local addr %s\n", local_address)); - rc = parse_protocol (&sap, local_address); - if ((rc <= 0) || (parse_address (&sap.addrin, local_address + rc) < 0)) { - VERBOSE (sap, ERROR, PRINTF ("can't parse local url\n")); - errno = EINVAL; - return -1; - } - VERBOSE (sap, DEBUG, PRINTF ("local port -> %d\n", ntohs (sap.addrin.sin_port))); - - /* parse remote url */ - VERBOSE (sap, DEBUG, PRINTF ("SAP remote addr %s\n", remote_address)); - rc = parse_protocol (&sap, remote_address); - if ((rc <= 0) || (parse_address (&sap.addrout, remote_address + rc) < 0)) { - VERBOSE (sap, ERROR, PRINTF ("can't parse remote url\n")); - errno = EINVAL; - return -1; - } - VERBOSE (sap, DEBUG, PRINTF ("remote port -> %d\n", ntohs (sap.addrout.sin_port))); - - /* create socket */ - int sock = socket (PF_INET, SOCK_DGRAM, 0); - if ((sock < 0) || (sock >= MAX_SAP_NUMBER) || (SAP_list[sock] != NULL)) { - VERBOSE (sap, ERROR, PRINTF ("can't accept socket %d\n", sock)); - errno = ENOMEM; - return -1; - } - - /* bind on local */ - int val = 1; - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (OPT_TYPE *)&val, sizeof (val)); - if (bind (sock, (struct sockaddr *)&sap.addrin, sizeof (sap.addrin)) < 0) { - VERBOSE (sap, ERROR, PRINTF ("can't bind socket %d\n", sock)); - return -1; - } - - /* connect on remote */ - if (connect (sock, (struct sockaddr *)&sap.addrout, sizeof (sap.addrout)) < 0) { - VERBOSE (sap, ERROR, PRINTF ("can't connect socket %d\n", sock)); - return -1; - } - - SAP_list[sock] = sapdup (&sap); - - return sock; -} - -void SAP_Close (int sap) -{ - - VERBOSE (sap, TRACE, PRINTF ("SAP_Close\n")); - - if ((sap < 0) || (sap >= MAX_SAP_NUMBER)) { - return; - } - - close (sap); - - free (SAP_list[sap]); - SAP_list[sap] = NULL; -} - -int SAP_Send (int sap, unsigned char *data, int len) -{ - - VERBOSE (sap, TRACE, PRINTF ("SAP_Send\n")); - - assert (((data != NULL) && (len > 0)) || ((data == NULL) && (len == 0))); - - if ((sap < 0) || (sap >= MAX_SAP_NUMBER) || (SAP_list[sap] == NULL)) { - errno = EBADF; - return -1; - } - - VERBOSE (sap, TRACE, PRINTF ("SAP_Send writting...\n")); - - return write (sap, data, len); -} - -int SAP_Receive_timeout (int sap, unsigned char *buffer, int maxlen, int ms) -{ - - VERBOSE (sap, TRACE, PRINTF ("SAP_Receive_timeout\n")); - - fd_set rfds; - struct timeval tv = { 0, ms }; - FD_ZERO (&rfds); - FD_SET (sap, &rfds); - - int retval = select (sap + 1, &rfds, NULL, NULL, &tv); - if (retval != 1) { - return retval; - } - - return SAP_Receive (sap, buffer, maxlen); -} - -int SAP_Receive (int sap, unsigned char *buffer, int maxlen) -{ - - VERBOSE (sap, TRACE, PRINTF ("SAP_Receive\n")); - - if ((sap < 0) || (sap >= MAX_SAP_NUMBER) || (SAP_list[sap] == NULL)) { - errno = EBADF; - return -1; - } - - VERBOSE (sap, TRACE, PRINTF ("SAP_Receive reading...\n")); - - int rc = read (sap, buffer, maxlen); - - if ((rc < 0) && (errno == EAGAIN)) { - rc = 0; - } - - return rc; -} - -/* vim: set ts=4 sw=4 si et: */ diff --git a/sap.h b/sap.h deleted file mode 100644 index a4b810f..0000000 --- a/sap.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - Service Access Point communication library - - Copyrigth Eichos 20100319 -*/ - -#ifndef __SAP_H__ -#define __SAP_H__ - -#include - -__BEGIN_DECLS - -/** - @defgroup SAP Public API of SAP - - The common message passing library offers both reliable and - unreliable connection oriented data blocks exchange service between - software modules running on separate CPU. The current - implementation is based on TCP (reliable) and UDP (unreliable), - however, the abstraction level provided by this library will permit - future implementations on other communication networks (shared - memory for example). - - sap values returned by SAP_Connect is a standard Linux file - descriptors that can be used in select()/poll() system calls. -*/ - -/** - @ingroup SAP - - Establish a connection between a local SAP and a remote SAP. Block - until connection is established or refused. - - @param local_address local address of the SAP with the following - syntax: 'udp://hostname:port'. - @param remote_address same format as for local_address - - @return a new file descriptor associated with this connection - - @see SAP_Close() - @see SAP_Send() - @see SAP_Receive() -*/ -int SAP_Connect (char *local_address, char *remote_address); - -/** - @ingroup SAP - - Destroy a SAP. - - @param sap the file descriptor retuned by SAP_Connect() - - @see SAP_Connect() -*/ -void SAP_Close (int sap); - -/** - @ingroup SAP - - Send a message over an existing SAP connection. Will block until - resolution in case of congestion. - - @param sap the file descriptor retuned by SAP_Connect() or - SAP_Accept() - @param data a pointer to the buffer containing the message to be - transmitted - @param len length of the message - - @see SAP_Connect() -*/ -int SAP_Send (int sap, unsigned char *data, int len); - -/** - @ingroup SAP - - Received a message over an existing SAP connection. Returns - immediately if SAP not set to blocking mode - - @param sap the file descriptor retuned by SAP_Connect() - @param buffer a pointer to the reception buffer - @param maxlen max length of the reception buffer - - @return length of the message or 0 if no message was pending - - @see SAP_Connect() -*/ -int SAP_Receive (int sap, unsigned char *buffer, int maxlen); - -/** - @ingroup SAP - - Received a message over an existing SAP connection with a timeout - - @param sap the file descriptor retuned by SAP_Connect() - @param buffer a pointer to the reception buffer - @param maxlen max length of the reception buffer - @param ms Exit after microseconds if now data is received - - @return length of the message or 0 if no message was pending - - @see SAP_Connect() -*/ -int SAP_Receive_timeout (int sap, unsigned char *buffer, int maxlen, int ms); - -__END_DECLS - -#endif /* __SAP_H__ */ - -/* vim: set ts=4 sw=4 si et: */ diff --git a/sap_test.c b/sap_test.c deleted file mode 100644 index 45a59a8..0000000 --- a/sap_test.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - File: sap_valid.c - Author: Laurent Mazet - - Validation test suite for SAP library - - Copyrigth Eichos 20100322 -*/ - -/* depend: */ -/* cflags: */ -/* linker: sap.o */ - -#include -#include -#include -#include -#include -#include -#include - -#include "verbose.h" - -#include "sap.h" - -int SAP_Send_UDP_OK = 0; -int SAP_Echo_UDP_OK = 0; - -#define UNUSED __attribute__ ((unused)) - -void *udp_client (UNUSED void *dummy) -{ - - VERBOSE (sap, TRACE, PRINTF ("test_client\n")); - - int count; - unsigned char tx_data[10][1500]; - int tx_len[10]; - - int sap = SAP_Connect ("udp://localhost:13501", "udp://localhost:12501"); - if (sap < 0) { - VERBOSE (sap, WARNING, PRINTF ("client SAP_Connect error\n")); - SAP_Echo_UDP_OK = 0; - return NULL; - } - - int nb_messages = 10; - VERBOSE (sap, INFO, PRINTF ("client connected to server, trying to exchange %d messages\n", nb_messages)); - - for (count = 0; count < nb_messages; count++) { - - tx_len[count] = rand () % sizeof (tx_data[count]); - for (int i = 0; i < tx_len[count]; i++) - tx_data[count][i] = rand () % 256; - - int rc = SAP_Send (sap, tx_data[count], tx_len[count]); - if (rc < 0) { - VERBOSE (sap, WARNING, PRINTF ("client SAP_Send tx error (%d/%d-%d)\n", rc, tx_len[count], errno)); - SAP_Echo_UDP_OK = 0; - return NULL; - } - - if (tx_len[count] != rc) { - VERBOSE (sap, WARNING, PRINTF ("client SAP_Send tx len error tx=%d rc=%d\n", tx_len[count], rc)); - SAP_Echo_UDP_OK = 0; - return NULL; - } - VERBOSE (sap, DEBUG, PRINTF ("client SAP_Send ok (%d)\n", tx_len[count])); - - usleep (1e4); - - int rx_len; - unsigned char rx_data[32768]; - - do { - rx_len = SAP_Receive (sap, rx_data, sizeof (rx_data)); - if (rx_len == 0) { - VERBOSE (sap, DEBUG, PRINTF ("client's sleeping...\n")); - usleep (1e3); - } - } while (rx_len == 0); - - VERBOSE (sap, INFO, PRINTF ("client received echo count=%d len=%d, sap=%d\n", count, rx_len, sap)); - - if (tx_len[count] != rx_len) { - VERBOSE (sap, WARNING, PRINTF ("client SAP_Receive rx len error : tx=%d / rx=%d\n", tx_len[count], rx_len)); - SAP_Echo_UDP_OK = 0; - return NULL; - } - - if (memcmp (rx_data, tx_data[count], tx_len[count]) != 0 ) { - VERBOSE (sap, WARNING, PRINTF ("client SAP_Receive rx corrupted data\n")); - SAP_Echo_UDP_OK = 0; - return NULL; - } - } - - SAP_Close (sap); - VERBOSE (sap, INFO, PRINTF ("client end of test, %d echo processed\n", count)); - SAP_Echo_UDP_OK = 1; - - return NULL; -} - -void *udp_server (UNUSED void *dummy) -{ - - VERBOSE (sap, TRACE, PRINTF ("udp_server\n")); - - int sap = SAP_Connect ("udp://localhost:12501", "udp://localhost:13501"); - if (sap < 0) { - VERBOSE (sap, ERROR, PRINTF ("SAP_Connect (%d)", sap)); - exit (1); - } - - VERBOSE (sap, INFO, PRINTF ("udp_server waiting for data\n")); - - while (1) { - unsigned char data[8192]; - - int rx_len = SAP_Receive (sap, data, sizeof (data)); - if (rx_len == 0) { - VERBOSE (sap, DEBUG, PRINTF ("server's sleeping...\n")); - usleep (1e3); - continue; - } - if (rx_len < 0) { - VERBOSE (sap, ERROR, PRINTF ("error receiving from SAP %d\n", sap)); - SAP_Close (sap); - break; - } - - VERBOSE (sap, INFO, PRINTF ("udp_server receive data len=%d, sending echo\n", rx_len)); - usleep (1e4); - - int tx_len = SAP_Send (sap, data, rx_len); - if (tx_len == rx_len) { - SAP_Send_UDP_OK = 1; - } - } - - return NULL; -} - -/** - Dump status macro -*/ -#define DUMP_STATUS(x) do { \ - printf (#x " %s\n", (x) ? "OK" : "BAD"); \ - if (!(x)) { \ - failed = 1; \ - } \ - } while (0) \ - -int main (int argc, char **argv) -{ - - /* process arguments */ - if (argc > 1) { - CHANGE_VERBOSE_LEVEL(sap, atoi (argv[1])); - argc--; - } - if (argc > 1) { - printf ("usage: %s [verbose level]\n", argv[0]); - exit (1); - } - - printf ("*** STARTING SERVERS ***\n"); - - pthread_t udp_thread; - - pthread_create (&udp_thread, NULL, udp_server, NULL); - - /* Give some delay to server to setup there SAP */ - usleep (1e6); - - printf ("*** STARTING TEST SEQUENCE ***\n"); - - pthread_t udp_client_thread; - - pthread_create (&udp_client_thread, NULL, udp_client, NULL); - - pthread_join (udp_client_thread, NULL); - - printf ("*** END OF TEST SEQUENCE ***\n"); - - int failed = 0; - DUMP_STATUS (SAP_Send_UDP_OK); - DUMP_STATUS (SAP_Echo_UDP_OK); - - return failed ? EXIT_FAILURE : EXIT_SUCCESS; -} - -/* test: sap_test.exe */ -/* test: sap_test.exe 1 */ - -/* vim: set ts=4 sw=4 si et: */ -- 2.30.2