--- /dev/null
+/*
+ File name : verbose.h
+ Projet : MERLIN
+ Date of creation : 2025/03/19
+ Version : 1.0
+ Copyright : Thales SIX
+ Author : Laurent Mazet <laurent.mazet@thalesgroup.com>
+
+ Description : This file contains verbose macros
+
+ History :
+ - initial version
+*/
MDIR = $(shell pwd)
-PACKAGE = more
+PACKAGE = morep
IFLAGS += -I. -I../src/debug -I../src/gpio
OFLAGS = -O4 -minline-all-stringops -fsingle-precision-constant
/* MAC address format: XX:XX:XX:XX:XX:XX */
if (strlen (hexa_str) != 17) {
+ VERBOSE (morep, WARNING, PRINTF ("incorrect mac address format (%s)\n", hexa));
return -1;
}
char one_byte[3] = "xx";
char ptr = NULL;
memcpy (one_byte, hexa + 3 * i, 2);
- mac[i] = strtoul(one_byte, NULL, 16, &ptr);
- if (ptr != NULL) {
+
+ mac[i] = strtoul (one_byte, NULL, 16, &ptr);
+ if ((ptr != NULL) || ((i < 5) && (hexa[3 * i + 2] != ':'))) {
+ VERBOSE (morep, WARNING, PRINTF ("can't parse mac address (%s)\n", hexa));
return -1;
}
- if (i < 5) {
- if (hexa[3 * i + 2] != ':') {
- return -1;
- }
- }
}
+
+ return 0;
+}
+
+int _get_interface_index (char *ifname)
+{
+ VERBOSE (morep, TRACE, FPRINTF (stdout, "_get_interface_index\n"));
+
+ struct ifreq ifr = {0};
+ strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+
+ if (ioctl (sock, SIOCGIFINDEX, &ifr) != 0) {
+ VERBOSE (morep, WARNING, PRINTF ("can't get interface index (%s)\n", strerror (errno)));
+ return -1;
+ }
+ return ifr.ifr_ifindex;
+}
+
+int _get_mac_address (char *ifname, uint8_t *mac)
+{
+ VERBOSE (morep, TRACE, FPRINTF (stdout, "_get_mac_address\n"));
+
+ struct ifreq ifr = {0};
+ strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+
+ if (ioctl (sock, SIOCGIFHWADDR, &ifr) != 0) {
+ VERBOSE (morep, WARNING, PRINTF ("can't get interface mac address (%s)\n", strerror (errno)));
+ return -1;
+ }
+
+ unsigned char *p = (unsigned char *)ifr.ifr_hwaddr.sa_data;
+ for (int i = 0; i < 6; i++) {
+ mac[i] = *p++;
+ }
+
return 0;
}
--- /dev/null
+/*
+ File name : morep.h
+ Projet : MERLIN
+ Date of creation : 2025/03/19
+ Version : 1.0
+ Copyright : Thales SIX
+ Author : Laurent Mazet <laurent.mazet@thalesgroup.com>
+
+ Description : Messaging Over Raw Ethernet Packets communication
+
+ History :
+ - initial version
+*/
+
+#ifndef __MOREP_H__
+#define __MOREP_H__
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ @defgroup MOREP Public API of MOREP
+
+ The common message passing library offers unreliable connection oriented
+ data blocks exchange messaging between software modules over raw Ethernet
+ packets.
+
+ morep values returned by MOREP_Create(), MOREP_Connect and
+ MOREP_Accept() are standard Linux file descriptors that can be used in
+ select()/poll() system calls.
+*/
+
+/**
+ @ingroup MOREP
+
+ Create a new MOREP (Messaging Over Raw Ethernet Packets) that will be used
+ later for outgoing or incoming connection
+
+ @param local_address local address of the MOREP with the following
+ syntax: 'rep://macaddress/ethertype
+ - macaddress format is xx:xx:xx:xx:xx:xx
+ - ethertype is a number from 1536 to 65355
+
+ @return a new file descriptor associated with this MOREP
+
+ @see MOREP_Connect()
+ @see MOREP_Accept()
+ @see MOREP_Reject()
+ @see MOREP_Close()
+*/
+int MOREP_Create (char *local_address);
+
+/**
+ @ingroup MOREP
+
+ Establish a connection between a local MOREP and a remote MOREP. Block
+ until connection is established or refused.
+
+ @param local_address local address of the MOREP with the following
+ syntax: 'rep://macaddress/ethertype
+ - macaddress format is xx:xx:xx:xx:xx:xx
+ - ethertype is a number from 1536 to 65355
+ Can be NULL if local address dot not need to be specified
+ @param remote_address same format as for local_address
+
+ @return a new file descriptor associated with this connection
+
+ @see MOREP_Create()
+ @see MOREP_Accept()
+ @see MOREP_Reject()
+ @see MOREP_Close()
+ @see MOREP_Send()
+ @see MOREP_Receive()
+*/
+int MOREP_Connect (char *local_address, char *remote_address);
+
+/**
+ @ingroup MOREP
+
+ Check if connection is established, typ. called after MOREP_Connect()
+
+ @param morep file descriptor retuned by MOREP_Connect
+
+ @return -1=error, 0=not yet connected, 1=connected
+
+ @see MOREP_Connect()
+*/
+int MOREP_Is_Connected (int morep);
+
+/**
+ @ingroup MOREP
+
+ Accept an incoming connection. Returns immediately, even there is
+ no pending incoming connection.
+
+ @param morep file descriptor retuned by MOREP_Create()
+
+ @return a new file descriptor associated with this connection or -1,
+ errno=EWOULDBLOCK if there is no pending connection.
+
+ @see MOREP_Create()
+ @see MOREP_Reject()
+ @see MOREP_Close()
+ @see MOREP_Send()
+ @see MOREP_Receive()
+*/
+int MOREP_Accept (int morep);
+
+/**
+ @ingroup MOREP
+
+ Reject an incoming connection. Returns immediately.
+
+ @param morep file descriptor retuned by MOREP_Create()
+
+ @see MOREP_Create()
+ @see MOREP_Accept()
+ @see MOREP_Close()
+ @see MOREP_Send()
+ @see MOREP_Receive()
+*/
+void MOREP_Reject (int morep);
+
+/**
+ @ingroup MOREP
+
+ Destroy a MOREP.
+
+ @param morep file descriptor retuned by MOREP_Create() or MOREP_Connect()
+ or MOREP_Accept()
+
+ @see MOREP_Create()
+ @see MOREP_Accept()
+ @see MOREP_Connect()
+*/
+void MOREP_Close (int morep);
+
+/**
+ @ingroup MOREP
+
+ Turn a MOREP in I/O blocking mode.
+
+ @param morep file descriptor retuned by MOREP_Create() or MOREP_Connect()
+ or MOREP_Accept()
+
+ @see MOREP_Create()
+ @see MOREP_Accept()
+ @see MOREP_Connect()
+*/
+void MOREP_Set_Blocking (int morep);
+
+/**
+ @ingroup MOREP
+
+ Send a message over an existing MOREP connection. Will block until
+ resolution in case of congestion.
+
+ @param morep file descriptor retuned by MOREP_Connect() or MOREP_Accept()
+ @param msgtype a user defined message type identifier, transported
+ transparently
+ @param data a pointer to the buffer containing the message to be
+ transmitted
+ @param len length of the message
+
+ @see MOREP_Accept()
+ @see MOREP_Connect()
+*/
+int MOREP_Send (int morep, unsigned long msgtype, unsigned char *data, int len);
+
+/**
+ @ingroup MOREP
+
+ Received a message over an existing MOREP connection. Returns
+ immediately if MOREP not set to blocking mode
+
+ @param morep file descriptor retuned by MOREP_Connect() or
+ MOREP_Accept()
+ @param msgtype a pointer to an unsigned long to receive the user
+ defined message type identifier, transported transparently
+ @param buffer a pointer to the reception buffer
+ @param buflen length of the reception buffer
+
+ @return length of the message or 0 if no message was pending
+
+ @see MOREP_Accept()
+ @see MOREP_Connect()
+*/
+int MOREP_Receive (int morep, unsigned long *msgtype, unsigned char *buffer, int buflen);
+
+/**
+ @ingroup MOREP
+
+ Received a message over an existing MOREP connection with a timeout
+
+ @param morep file descriptor retuned by MOREP_Connect() or
+ MOREP_Accept()
+ @param msgtype a pointer to an unsigned long to receive the user
+ defined message type identifier, transported transparently
+ @param buffer a pointer to the reception buffer
+ @param buflen 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 MOREP_Accept()
+ @see MOREP_Connect()
+*/
+int MOREP_Receive_timeout (int morep, unsigned long *msgtype, unsigned char *buffer, int buflen, int ms);
+
+__END_DECLS
+
+#endif /* __MOREP_H__ */
+
+/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode */
--- /dev/null
+/*
+ File name : morep_valid.c
+ Projet : MERLIN
+ Date of creation : 2025/03/18
+ Version : 1.0
+ Copyright : Thales SIX
+ Author : Laurent Mazet <laurent.mazet@thalesgroup.com>
+
+ Description : Validation test suite for MOREP library
+
+ History :
+ - initial version
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "debug.h"
+
+#include "morep.h"
+
+int MOREP_Accept_NONBLOCK_OK = 0;
+int MOREP_Receive_NONBLOCK_OK = 0;
+int MOREP_Send_OK = 0;
+int MOREP_Echo_OK = 0;
+
+int test_client (char *local_address, char *remote_address)
+{
+ VERBOSE (morep, TRACE, PRINTF ("test_client\n"));
+
+ int count;
+ unsigned char tx_data[10][8192];
+ unsigned long tx_msgtype[10];
+ int tx_len[10];
+
+ VERBOSE (morep, INFO, PRINTF ("%s started\n", remote_address));
+
+ int morep = MOREP_Connect (local_address, remote_address);
+ if (morep < 0) {
+ VERBOSE (morep, ERROR, PRINTF ("%s MOREP_Connect error\n", remote_address));
+ return -1;
+ }
+
+ VERBOSE (morep, INFO, PRINTF ("%s connected to server, trying to exchange 10 messages\n", remote_address));
+
+ for (count = 0; count < 10; count++) {
+ int i, rc;
+
+ /* to valid non block */
+ if (count == 5)
+ sleep (1);
+
+ tx_len[count] = rand () % sizeof (tx_data[count]);
+ tx_msgtype[count] = rand ();
+ for (i = 0; i < tx_len[count]; i++)
+ tx_data[count][i] = rand () % 256;
+
+ rc = MOREP_Send (morep, tx_msgtype[count], tx_data[count], tx_len[count]);
+ if (rc < 0) {
+ VERBOSE (morep, ERROR, PRINTF ("%s MOREP_Send tx error\n", remote_address));
+ return -1;
+
+ }
+ if (tx_len[count] != rc) {
+ VERBOSE (morep, ERROR, PRINTF ("%s MOREP_Send tx len error tx=%d rc=%d\n", remote_address, tx_len[count], rc));
+ return -1;
+ }
+ }
+
+ for (count = 0; count < 10; count++) {
+ int rx_len;
+ unsigned char rx_data[32768];
+ unsigned long rx_msgtype;
+
+
+ do {
+ rx_len = MOREP_Receive (morep, &rx_msgtype, rx_data, sizeof (rx_data));
+ if (rx_len == 0)
+ sleep (1);
+ } while (rx_len == 0);
+
+ VERBOSE (morep, INFO, PRINTF ("%s echo received count=%d len=%d, morep=%d\n", remote_address, count, rx_len, morep));
+
+ if (tx_len[count] != rx_len) {
+ VERBOSE (morep, WARNING, PRINTF ("%s MOREP_Receive rx len error : tx=%d / rx=%d\n", remote_address, tx_len[count], rx_len));
+ return -1;
+ }
+
+ if (tx_msgtype[count] != rx_msgtype) {
+ VERBOSE (morep, WARNING, PRINTF ("%s MOREP_Receive rx msgtype error : tx=%08lX / rx=%08lX\n", remote_address, tx_msgtype[count], rx_msgtype));
+ return -1;
+ }
+
+ if (memcmp (rx_data, tx_data[count], tx_len[count]) != 0 ) {
+ VERBOSE (morep, WARNING, PRINTF ("%s MOREP_Receive rx corrupted data\n",remote_address));
+ return -1;
+ }
+ }
+
+ MOREP_Close (morep);
+ VERBOSE (morep, INFO, PRINTF ("%s end of test, %d echo processed\n", remote_address, count));
+ return 0;
+}
+
+void *rep_server (UNUSED void *dummy)
+{
+ VERBOSE (morep, TRACE, PRINTF ("rep_server\n"));
+
+ VERBOSE (morep, INFO, PRINTF ("rep_server started\n"));
+
+ int morep = MOREP_Connect ("rep://01:02:03:04:05:06/2064", "rep://07:08:08:0a:0b:0C/2065"); /* 0x0810 / 0x0811 */
+ if (morep < 0) {
+ VERBOSE (morep, ERROR, PRINTF ("MOREP_Connect (%d)", errno);
+ exit (1);
+ }
+
+ VERBOSE (morep, INFO, PRINTF ("rep_server waiting for data\n"));
+
+ while (1) {
+ unsigned char data[1024];
+ unsigned long msgtype;
+
+ int rx_len = MOREP_Receive (morep, &msgtype, data, sizeof (data));
+ if (rx_len == 0) {
+ MOREP_Receive_NONBLOCK_OK = 1;
+ sleep (1);
+ continue;
+ }
+ if (rx_len < 0) {
+ MOREP_Close (morep);
+ break;
+ }
+
+ VERBOSE (morep, INFO, PRINTF ("rep_server receive data len=%d, sending echo\n", rx_len));
+
+ int tx_len = MOREP_Send (morep, msgtype, data, rx_len);
+ if (tx_len == rx_len)
+ MOREP_Send_OK = 1;
+ }
+
+ return NULL;
+}
+
+void *rep_client (UNUSED void *dummy)
+{
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ int rc = test_client ("rep://07:08:08:0a:0b:0C/2065" "rep://01:02:03:04:05:06/2064");
+ if (rc)
+ pthread_exit (&MOREP_Echo_OK);
+ }
+
+ MOREP_Echo_OK = 1;
+ pthread_exit (&MOREP_Echo_OK);
+ return NULL;
+}
+
+/**
+ Dump status macro
+*/
+#define DUMP_STATUS(x) do { \
+ printf (#x " %s\n", (x) ? "OK" : "BAD"); \
+ if (!(x)) \
+ failed = 1; \
+ } while (0) \
+
+/**
+ Verbose level
+*/
+DECLARE_VERBOSE_LEVEL (morep, INFO);
+
+int main (int argc, char **argv)
+{
+
+ /* process arguments */
+ if (argc > 1) {
+ CHANGE_VERBOSE_LEVEL (morep, atoi (argv[1]));
+ argc--;
+ }
+ if (argc > 1) {
+ printf ("usage: %s [verbose level]\n", argv[0]);
+ exit (1);
+ }
+
+ printf ("*** STARTING TEST SEQUENCE ***\n");
+
+ pthread_t rep_thread;
+
+ pthread_create (&rep_thread, NULL, rep_server, NULL);
+
+ /* Give some delay to server to setup there MOREP */
+ sleep (1);
+
+ pthread_t rep_client_thread;
+
+ pthread_create (&rep_client_thread, NULL, rep_client, NULL);
+
+ pthread_join (rep_client_thread, NULL);
+
+ printf ("*** END OF TEST SEQUENCE ***\n");
+
+ int failed = 0;
+ DUMP_STATUS (MOREP_Accept_NONBLOCK_OK);
+ DUMP_STATUS (MOREP_Receive_NONBLOCK_OK);
+ DUMP_STATUS (MOREP_Send_OK);
+ DUMP_STATUS (MOREP_Echo_OK);
+
+ return failed ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+/* test-depend: morep_valid */
+
+/* test: morep_valid */
+/* test: morep_valid 1 */
+
+/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode*/
+++ /dev/null
-/*
- Service Access Point communication library
-
- Copyrigth Eichos 20100319
-*/
-
-#ifndef __SAP_H__
-#define __SAP_H__
-
-#include <sys/cdefs.h>
-
-__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_Create(), SAP_Connect and
- SAP_Accept() are standard Linux file descriptors that can be used
- in select()/poll() system calls.
-*/
-
-/**
- @ingroup SAP
-
- Create a new SAP (Service Access Point) that will be used later for
- outgoing or incoming connection
-
- @param local_address local address of the SAP with the following
- syntax: 'udp://hostname:port' or 'tcp://hostname:port', hostname
- can be '*' to listen on any address handled by the host
-
- @return a new file descriptor associated with this SAP
-
- @see SAP_Connect()
- @see SAP_Accept()
- @see SAP_Reject()
- @see SAP_Close()
-*/
-int SAP_Create (char *local_address);
-
-/**
- @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' or 'tcp://hostname:port'. Can be
- NULL if local address dot not need to be specified
- @param remote_address same format as for local_address
-
- @return a new file descriptor associated with this connection
-
- @see SAP_Create()
- @see SAP_Accept()
- @see SAP_Reject()
- @see SAP_Close()
- @see SAP_Send()
- @see SAP_Receive()
-*/
-int SAP_Connect (char *local_address, char *remote_address);
-
-/**
- @ingroup SAP
-
- Establish a connection between a local SAP and a remote SAP. Block
- until connection is established or refused. Apply the specified
- offset to local and remote port number
-
- @param local_address local address of the SAP with the following
- syntax: 'udp://hostname:port' or 'tcp://hostname:port'. Can be
- NULL if local address dot not need to be specified
- @param remote_address same format as for local_address
- @param port_offset offset to apply to port numbers
-
- @return a new file descriptor associated with this connection
-
- @see SAP_Create()
- @see SAP_Accept()
- @see SAP_Reject()
- @see SAP_Close()
- @see SAP_Send()
- @see SAP_Receive()
-*/
-int SAP_Connect_Offset (char *local_address, char *remote_address,
- int port_offset);
-
-/**
- @ingroup SAP
-
- Check if connection is established, typ. called after
- SAP_Connect()
-
- @param sap sap retuned by SAP_Connect
-
- @return -1=error, 0=not yet connected, 1=connected
-
- @see SAP_Connect()
-*/
-int SAP_Is_Connected (int sap);
-
-/**
- @ingroup SAP
-
- Accept an incoming connection. Returns immediately, even there is
- no pending incoming connection.
-
- @param sap the file descriptor retuned by SAP_Create()
-
- @return a new file descriptor associated with this connection or -1,
- errno=EWOULDBLOCK if there is no pending connection.
-
- @see SAP_Create()
- @see SAP_Reject()
- @see SAP_Close()
- @see SAP_Send()
- @see SAP_Receive()
-*/
-int SAP_Accept (int sap);
-
-/**
- @ingroup SAP
-
- Reject an incoming connection. Returns immediately.
-
- @param sap the file descriptor retuned by SAP_Create()
-
- @see SAP_Create()
- @see SAP_Accept()
- @see SAP_Close()
- @see SAP_Send()
- @see SAP_Receive()
-*/
-void SAP_Reject (int sap);
-
-/**
- @ingroup SAP
-
- Destroy a SAP.
-
- @param sap the file descriptor retuned by SAP_Create() or
- SAP_Connect() or SAP_Accept()
-
- @see SAP_Create()
- @see SAP_Accept()
- @see SAP_Connect()
-*/
-void SAP_Close (int sap);
-
-/**
- @ingroup SAP
-
- Turn a SAP in I/O blocking mode.
-
- @param sap the file descriptor retuned by SAP_Create() or
- SAP_Connect() or SAP_Accept()
-
- @see SAP_Create()
- @see SAP_Accept()
- @see SAP_Connect()
-*/
-void SAP_Set_Blocking (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 msgtype a user defined message type identifier, transported
- transparently
- @param data a pointer to the buffer containing the message to be
- transmitted
- @param len length of the message
-
- @see SAP_Accept()
- @see SAP_Connect()
-*/
-int SAP_Send (int sap, unsigned long msgtype, 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() or
- SAP_Accept()
- @param msgtype a pointer to an unsigned long to receive the user
- defined message type identifier, transported transparently
- @param buffer a pointer to the reception buffer
- @param buflen length of the reception buffer
-
- @return length of the message or 0 if no message was pending
-
- @see SAP_Accept()
- @see SAP_Connect()
-*/
-int SAP_Receive (int sap, unsigned long *msgtype, unsigned char *buffer,
- int buflen);
-
-/**
- @ingroup SAP
-
- Received a message over an existing SAP connection with a timeout
-
- @param sap the file descriptor retuned by SAP_Connect() or
- SAP_Accept()
- @param msgtype a pointer to an unsigned long to receive the user
- defined message type identifier, transported transparently
- @param buffer a pointer to the reception buffer
- @param buflen 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_Accept()
- @see SAP_Connect()
-*/
-int SAP_Receive_timeout (int sap, unsigned long *msgtype,
- unsigned char *buffer, int buflen, int ms);
-
-__END_DECLS
-
-#endif /* __SAP_H__ */
-
-/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode */
+++ /dev/null
-/*
- File: sap_valid.c
- Author: Laurent Mazet <mazet@eichos.com>
-
- Validation test suite for SAP library
-
- Copyrigth Eichos 20100322
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <assert.h>
-#include <pthread.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "tools.h"
-
-#include "sap.h"
-
-int SAP_Accept_NONBLOCK_OK = 0;
-int SAP_Receive_TCP_NONBLOCK_OK = 0;
-int SAP_Receive_UDP_NONBLOCK_OK = 0;
-int SAP_Send_TCP_OK = 0;
-int SAP_Echo_TCP_OK = 0;
-int SAP_Send_UDP_OK = 0;
-int SAP_Echo_UDP_OK = 0;
-
-void *tcp_server (UNUSED void *dummy)
-{
-
- VERBOSE (sap, 1, PRINTF ("tcp_server started\n"));
-
- int sap = SAP_Create ("tcp://localhost:12500");
- if (sap < 0) {
- perror ("SAP_Create");
- exit (0);
- }
-
- VERBOSE (sap, 1, PRINTF ("tcp_server waiting for connection\n"));
-
- while (1) {
- int newsap = SAP_Accept (sap);
- if (newsap < 0 && errno == EAGAIN)
- SAP_Accept_NONBLOCK_OK = 1;
- if (newsap < 0) {
- sleep (1);
- continue;
- }
-
- VERBOSE (sap, 1, PRINTF ("tcp_server connected, waiting for data\n"));
-
- while (1) {
- unsigned char data[8192];
- unsigned long msgtype;
-
- int rx_len = SAP_Receive (newsap, &msgtype, data, sizeof (data));
- if (rx_len == 0) {
- SAP_Receive_TCP_NONBLOCK_OK = 1;
- sleep (1);
- continue;
- }
- if (rx_len < 0) {
- VERBOSE (sap, 1, FPRINTF (stderr, "tcp_server connection closed by peer\n"));
- SAP_Close (newsap);
- break;
- }
-
- VERBOSE (sap, 1, PRINTF ("tcp_server receive data len=%d, sending echo\n", rx_len));
-
- int tx_len = SAP_Send (newsap, msgtype, data, rx_len);
- if (tx_len == rx_len)
- SAP_Send_TCP_OK = 1;
- if (tx_len < 0) {
- VERBOSE (sap, 1, FPRINTF (stderr, "tcp_server connection closed by peer\n"));
- SAP_Close (newsap);
- break;
- }
- /* sleep so that we go through remaining data case in
- receive buffer */
- usleep (1e5);
- }
- }
-}
-
-int test_client (char *local_address, char *remote_address)
-{
- int count;
- unsigned char tx_data[10][8192];
- unsigned long tx_msgtype[10];
- int tx_len[10];
-
- VERBOSE (sap, 0, PRINTF ("%s started\n", remote_address));
-
- int sap = SAP_Connect (local_address, remote_address);
- if (sap < 0) {
- VERBOSE (sap, 0, FPRINTF (stderr, "%s SAP_Connect error\n", remote_address));
- return -1;
- }
-
- VERBOSE (sap, 0, PRINTF ("%s connected to server, trying to exchange 10 messages\n", remote_address));
-
- for (count = 0; count < 10; count++) {
- int i, rc;
-
- /* to valid non block */
- if (count == 5)
- sleep (1);
-
- tx_len[count] = rand () % sizeof (tx_data[count]);
- tx_msgtype[count] = rand ();
- for (i = 0; i < tx_len[count]; i++)
- tx_data[count][i] = rand () % 256;
-
- rc = SAP_Send (sap, tx_msgtype[count], tx_data[count], tx_len[count]);
- if (rc < 0) {
- VERBOSE (sap, 0, FPRINTF (stderr, "%s SAP_Send tx error\n", remote_address));
- return -1;
-
- }
- if (tx_len[count] != rc) {
- VERBOSE (sap, 0, FPRINTF (stderr, "%s SAP_Send tx len error tx=%d rc=%d\n", remote_address, tx_len[count], rc));
- return -1;
- }
- }
-
- for (count = 0; count < 10; count++) {
- int rx_len;
- unsigned char rx_data[32768];
- unsigned long rx_msgtype;
-
-
- do {
- rx_len = SAP_Receive (sap, &rx_msgtype, rx_data, sizeof (rx_data));
- if (rx_len == 0)
- sleep (1);
- } while (rx_len == 0);
-
- VERBOSE (sap, 1, PRINTF ("%s echo received count=%d len=%d, sap=%d\n", remote_address, count, rx_len, sap));
-
- if (tx_len[count] != rx_len) {
- VERBOSE (sap, 0, FPRINTF (stderr, "%s SAP_Receive rx len error : tx=%d / rx=%d\n", remote_address, tx_len[count], rx_len));
- return -1;
- }
-
- if (tx_msgtype[count] != rx_msgtype) {
- VERBOSE (sap, 0, FPRINTF (stderr, "%s SAP_Receive rx msgtype error : tx=%08lX / rx=%08lX\n", remote_address, tx_msgtype[count], rx_msgtype));
- return -1;
- }
-
- if (memcmp (rx_data, tx_data[count], tx_len[count]) != 0 ) {
- VERBOSE (sap, 0, FPRINTF (stderr, "%s SAP_Receive rx corrupted data\n",remote_address));
- return -1;
- }
- }
-
- SAP_Close (sap);
- VERBOSE (sap, 0, PRINTF ("%s end of test, %d echo processed\n", remote_address, count));
- return 0;
-}
-
-void *udp_server (UNUSED void *dummy)
-{
- VERBOSE (sap, 0, PRINTF ("udp_server started\n"));
-
- int sap = SAP_Connect ("udp://localhost:12501", "udp://localhost:13501");
- if (sap < 0) {
- perror ("SAP_Connect (%d)");
- exit (1);
- }
-
- VERBOSE (sap, 0, PRINTF ("udp_server waiting for data\n"));
-
- while (1) {
- unsigned char data[8192];
- unsigned long msgtype;
-
- int rx_len = SAP_Receive (sap, &msgtype, data, sizeof (data));
- if (rx_len == 0) {
- SAP_Receive_UDP_NONBLOCK_OK = 1;
- sleep (1);
- continue;
- }
- if (rx_len < 0) {
- SAP_Close (sap);
- break;
- }
-
- VERBOSE (sap, 1, PRINTF ("udp_server receive data len=%d, sending echo\n", rx_len));
-
- int tx_len = SAP_Send (sap, msgtype, data, rx_len);
- if (tx_len == rx_len)
- SAP_Send_UDP_OK = 1;
- }
-
- return NULL;
-}
-
-void *tcp_client (UNUSED void *dummy)
-{
- int i;
-
- for (i = 0; i < 5; i++) {
- int rc = test_client (NULL, "tcp://localhost:12500");
- if (rc)
- pthread_exit (&SAP_Echo_TCP_OK);
- }
- for (i = 0; i < 5; i++) {
- int rc = test_client ("tcp://*:0", "tcp://localhost:12500");
- if (rc)
- pthread_exit (&SAP_Echo_TCP_OK);
- }
-
-
- SAP_Echo_TCP_OK = 1;
- pthread_exit (&SAP_Echo_TCP_OK);
- return NULL;
-}
-
-void *udp_client (UNUSED void *dummy)
-{
- int i;
-
- for (i = 0; i < 5; i++) {
- int rc = test_client ("udp://localhost:13501", "udp://localhost:12501");
- if (rc)
- pthread_exit (&SAP_Echo_UDP_OK);
- }
-
- SAP_Echo_UDP_OK = 1;
- pthread_exit (&SAP_Echo_UDP_OK);
- return NULL;
-}
-
-/**
- Dump status macro
-*/
-#define DUMP_STATUS(x) do { \
- printf (#x " %s\n", (x) ? "OK" : "BAD"); \
- if (!(x)) \
- failed = 1; \
- } while (0) \
-
-/**
- Verbose level
-*/
-DECLARE_VERBOSE_LEVEL(sap, 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 TEST SEQUENCE ***\n");
-
- pthread_t tcp_thread, udp_thread;
-
- pthread_create (&tcp_thread, NULL, tcp_server, NULL);
- pthread_create (&udp_thread, NULL, udp_server, NULL);
-
- /* Give some delay to server to setup there SAP */
- sleep (1);
-
- pthread_t tcp_client_thread, udp_client_thread;
-
- pthread_create (&tcp_client_thread, NULL, tcp_client, NULL);
- pthread_create (&udp_client_thread, NULL, udp_client, NULL);
-
- pthread_join (tcp_client_thread, NULL);
- pthread_join (udp_client_thread, NULL);
-
- printf ("*** END OF TEST SEQUENCE ***\n");
-
- int failed = 0;
- DUMP_STATUS (SAP_Accept_NONBLOCK_OK);
- DUMP_STATUS (SAP_Receive_TCP_NONBLOCK_OK);
- DUMP_STATUS (SAP_Receive_UDP_NONBLOCK_OK);
- DUMP_STATUS (SAP_Send_TCP_OK);
- DUMP_STATUS (SAP_Echo_TCP_OK);
- DUMP_STATUS (SAP_Send_UDP_OK);
- DUMP_STATUS (SAP_Echo_UDP_OK);
-
- return failed ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-/* test-depend: sap_valid */
-
-/* test: ./sap_valid */
-/* test: ./sap_valid 1 */
-
-/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode*/