#include <winsock2.h>
#include <ws2tcpip.h>
#define OPT_TYPE char
-#define SETBLOCK(fd) do { u_long _m = 0; ioctlsocket (fd, FIONBIO, &_m); } while (0)
-#define SETNOBLK(fd) do { u_long _m = 1; ioctlsocket (fd, FIONBIO, &_m); } while (0)
#else /* Linux */
#include <netdb.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/socket.h>
#define OPT_TYPE int
-#define SETBLOCK(fd) fcntl (fd, F_SETFL, 0)
-#define SETNOBLK(fd) fcntl (fd, F_SETFL, O_NONBLOCK)
#endif
#include <stdint.h>
#include <stdio.h>
SAP address structure
*/
typedef struct {
- enum { SAP_error, SAP_tcp, SAP_udp } type;
+ enum { SAP_error, SAP_udp } type;
struct sockaddr_in sockaddr;
} SAP_addr_t;
strncpy (url_to_parse, ascii_url, sizeof (url_to_parse) - 1);
if (strncmp (url_to_parse, "udp://", 6) == 0) {
addr->type = SAP_udp;
- } else if (strncmp (url_to_parse, "tcp://", 6) == 0) {
- addr->type = SAP_tcp;
} else {
return -1;
}
return 0;
}
-static inline int sap_create_and_listen (char *local_address, int doListen,
- int port_offset)
+static inline int sap_create_and_listen (char *local_address)
{
VERBOSE (sap, TRACE, PRINTF ("sap_create_and_listen\n"));
return -1;
}
- addr.sockaddr.sin_port =
- htons (ntohs (addr.sockaddr.sin_port) + port_offset);
VERBOSE (sap, DEBUG, PRINTF ("local port: %d\n", ntohs (addr.sockaddr.sin_port)));
switch (addr.type) {
- case SAP_tcp:
- sap = socket (PF_INET, SOCK_STREAM, 0);
- if (sap >= 0) {
- int val = 1;
- setsockopt (sap, SOL_SOCKET, SO_REUSEADDR, (OPT_TYPE *)&val, sizeof (val));
- if (bind (sap, (struct sockaddr *)&addr.sockaddr, sizeof (addr.sockaddr)) < 0) {
- VERBOSE (sap, ERROR, PRINTF ("cant bind on SAP %d\n", sap));
- return -1;
- }
- if (doListen) {
- if (listen (sap, 5) < 0) {
- VERBOSE (sap, ERROR, PRINTF ("cant listen on SAP %d\n", sap));
- return -1;
- }
- }
- }
- break;
case SAP_udp:
sap = socket (PF_INET, SOCK_DGRAM, 0);
if (sap >= 0) {
break;
}
- SETNOBLK (sap);
-
return sap;
}
VERBOSE (sap, TRACE, PRINTF ("SAP_Create\n"));
- return sap_create_and_listen (local_address, 1, 0);
+ return sap_create_and_listen (local_address);
}
int SAP_Connect (char *local_address, char * remote_address)
VERBOSE (sap, TRACE, PRINTF ("SAP_Connect\n"));
- return SAP_Connect_Offset (local_address, remote_address, 0);
-}
-
-int SAP_Connect_Offset (char *local_address, char *remote_address, int port_offset)
-{
-
- VERBOSE (sap, TRACE, PRINTF ("SAP_Connect_Offset\n"));
-
SAP_addr_t addr;
int sap;
return -1;
}
- addr.sockaddr.sin_port =
- htons (ntohs (addr.sockaddr.sin_port) + port_offset);
VERBOSE (sap, DEBUG, PRINTF ("remote port: %d\n", ntohs (addr.sockaddr.sin_port)));
if (local_address) {
- sap = sap_create_and_listen (local_address, 0, port_offset);
+ VERBOSE (sap, DEBUG, PRINTF ("SAP local addr %s\n", local_address));
+ sap = sap_create_and_listen (local_address);
} else {
+ VERBOSE (sap, DEBUG, PRINTF ("SAP local addr '*'\n"));
switch (addr.type) {
- case SAP_tcp:
- sap = socket (PF_INET, SOCK_STREAM, 0);
- break;
case SAP_udp:
sap = socket (PF_INET, SOCK_DGRAM, 0);
break;
return -1;
}
- SETNOBLK (sap);
if (connect (sap, (struct sockaddr *)&addr.sockaddr, sizeof (addr.sockaddr)) < 0) {
VERBOSE (sap, ERROR, PRINTF ("can't connect on soket %d\n", sap));
return -1;
}
- if (addr.type == SAP_tcp) {
- int val = 1;
- if (setsockopt (sap, IPPROTO_TCP, TCP_NODELAY, (OPT_TYPE *)&val, sizeof (val)) < 0) {
- VERBOSE (sap, ERROR, PRINTF ("error on setsockopt/TCP_NODELAY\n"));
- return -1;
- }
- }
-
assert (SAP_list[sap] == NULL);
SAP_list[sap] = (SAP_descriptor_t *) calloc (1, sizeof (SAP_descriptor_t));
assert (SAP_list[sap]);
return -1;
}
-int SAP_Accept (int sap)
-{
-
- VERBOSE (sap, TRACE, PRINTF ("SAP_Accept\n"));
-
- int newsap = accept (sap, NULL, 0);
- if (newsap < 0) {
- VERBOSE (sap, ERROR, PRINTF ("can't accept SAP %d\n", sap));
- return newsap;
- }
- if (newsap >= MAX_SAP_NUMBER) {
- VERBOSE (sap, ERROR, PRINTF ("no more SAP avaliable\n"));
- errno = ENOMEM;
- return -1;
- }
-
- assert (SAP_list[newsap] == NULL);
- SAP_list[newsap] = (SAP_descriptor_t *)calloc (1, sizeof (SAP_descriptor_t));
- assert (SAP_list[newsap]);
-
- if (__sync_bool_compare_and_swap (&__init, 1, 0)) {
- atexit (free_saps);
- }
-
- SETNOBLK (newsap);
-
- int val = 1;
- if (setsockopt (newsap, IPPROTO_TCP, TCP_NODELAY, (OPT_TYPE *)&val, sizeof (val)) < 0) {
- VERBOSE (sap, ERROR, PRINTF ("error on setsockopt/TCP_NODELAY\n"));
- return -1;
- }
-
- return newsap;
-}
-
void SAP_Reject (int sap)
{
SAP_list[sap] = NULL;
}
-void SAP_Set_Blocking (int sap)
-{
-
- VERBOSE (sap, TRACE, PRINTF ("SAP_Set_Blocking\n"));
-
- SETBLOCK (sap);
- if (SAP_list[sap]) {
- SAP_list[sap]->is_blocking = 0;
- }
-}
-
int SAP_Send (int sap, unsigned char *data, int len)
{
#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;
#define UNUSED __attribute__ ((unused))
-void *tcp_server (UNUSED void *dummy)
-{
-
- VERBOSE (sap, TRACE, PRINTF ("tcp_server\n"));
-
- int sap = SAP_Create ("tcp://localhost:12500");
- if (sap < 0) {
- VERBOSE (sap, ERROR, PRINTF ("SAP_Create"));
- exit (1);
- }
-
- VERBOSE (sap, DEBUG, 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, DEBUG, PRINTF ("tcp_server connected, waiting for data\n"));
-
- while (1) {
- unsigned char data[8192];
-
- int rx_len = SAP_Receive (newsap, data, sizeof (data));
- if (rx_len == 0) {
- SAP_Receive_TCP_NONBLOCK_OK = 1;
- sleep (1);
- continue;
- }
- if (rx_len < 0) {
- VERBOSE (sap, WARNING, PRINTF ("tcp_server connection closed by peer\n"));
- SAP_Close (newsap);
- break;
- }
-
- VERBOSE (sap, INFO, PRINTF ("tcp_server receive data len=%d, sending echo\n", rx_len));
-
- int tx_len = SAP_Send (newsap, data, rx_len);
- if (tx_len == rx_len) {
- SAP_Send_TCP_OK = 1;
- }
- if (tx_len < 0) {
- VERBOSE (sap, WARNING, PRINTF ("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)
+void *udp_client (UNUSED void *dummy)
{
VERBOSE (sap, TRACE, PRINTF ("test_client\n"));
unsigned char tx_data[10][1500];
int tx_len[10];
- VERBOSE (sap, DEBUG, PRINTF ("%s started\n", remote_address));
-
- int sap = SAP_Connect (local_address, remote_address);
+ int sap = SAP_Connect ("udp://localhost:13501", "udp://localhost:12501");
if (sap < 0) {
- VERBOSE (sap, WARNING, PRINTF ("%s SAP_Connect error\n", remote_address));
- return -1;
+ VERBOSE (sap, WARNING, PRINTF ("client SAP_Connect error\n"));
+ SAP_Echo_UDP_OK = 0;
+ return NULL;
}
- VERBOSE (sap, 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);
- }
+ 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 (i = 0; i < tx_len[count]; i++)
+ for (int i = 0; i < tx_len[count]; i++)
tx_data[count][i] = rand () % 256;
- rc = SAP_Send (sap, tx_data[count], tx_len[count]);
+ int rc = SAP_Send (sap, tx_data[count], tx_len[count]);
if (rc < 0) {
- VERBOSE (sap, WARNING, PRINTF ("%s SAP_Send tx error (%d/%d-%d)\n", remote_address, rc, tx_len[count], errno));
- return -1;
+ 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 ("%s SAP_Send tx len error tx=%d rc=%d\n", remote_address, tx_len[count], rc));
- return -1;
+ 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 ("%s SAP_Send ok (%d)\n", remote_address, tx_len[count]));
+ VERBOSE (sap, DEBUG, PRINTF ("client SAP_Send ok (%d)\n", tx_len[count]));
}
for (count = 0; count < 10; count++) {
do {
rx_len = SAP_Receive (sap, rx_data, sizeof (rx_data));
if (rx_len == 0) {
+ VERBOSE (sap, DEBUG, PRINTF ("client's sleeping...\n"));
sleep (1);
}
} while (rx_len == 0);
- VERBOSE (sap, INFO, PRINTF ("%s echo received count=%d len=%d, sap=%d\n", remote_address, count, rx_len, sap));
+ 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 ("%s SAP_Receive rx len error : tx=%d / rx=%d\n", remote_address, tx_len[count], rx_len));
- return -1;
+ 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 ("%s SAP_Receive rx corrupted data\n",remote_address));
- return -1;
+ 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 ("%s end of test, %d echo processed\n", remote_address, count));
- return 0;
+ 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)
int rx_len = SAP_Receive (sap, data, sizeof (data));
if (rx_len == 0) {
- SAP_Receive_UDP_NONBLOCK_OK = 1;
+ VERBOSE (sap, DEBUG, PRINTF ("server's sleeping...\n"));
sleep (1);
continue;
}
if (rx_len < 0) {
+ VERBOSE (sap, ERROR, PRINTF ("error receiving from SAP %d\n", sap));
SAP_Close (sap);
break;
}
return NULL;
}
-void *tcp_client (UNUSED void *dummy)
-{
-
- VERBOSE (sap, TRACE, PRINTF ("tdp_client\n"));
-
- for (int i = 0; i < 5; i++) {
- int rc = test_client (NULL, "tcp://localhost:12500");
- if (rc) {
- pthread_exit (&SAP_Echo_TCP_OK);
- }
- }
- for (int 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)
-{
-
- VERBOSE (sap, TRACE, PRINTF ("udp_client\n"));
-
- for (int 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
*/
printf ("*** STARTING SERVERS ***\n");
- pthread_t tcp_thread, udp_thread;
+ pthread_t 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 */
printf ("*** STARTING TEST SEQUENCE ***\n");
- pthread_t tcp_client_thread, udp_client_thread;
+ pthread_t 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);