OpenSS7
SS7 for the
Common Man

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified:

Home Overview Status News Documentation Resources About
   
 Overview
 Status
 News
 Documentation
 Resources
 About

   
Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/test/test-sctp_ns.c


File /code/strss7/test/test-sctp_ns.c



#ident "@(#) $RCSfile: test-sctp_ns.c,v $ $Name:  $($Revision: 0.8.2.3 $) $Date: 2002/10/18 04:00:52 $"

static char const ident[] =
    "$RCSfile: test-sctp_ns.c,v $ $Name:  $($Revision: 0.8.2.3 $) $Date: 2002/10/18 04:00:52 $";

#include <stropts.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include <signal.h>
#include <getopt.h>

#include <sys/npi.h>
#include <sys/npi_sctp.h>

#define BUFSIZE 4096

union {
	np_ulong prim;
	union N_primitives npi;
	char cbuf[BUFSIZE];
} cmd;

char dbuf[BUFSIZE];
struct strbuf ctrl = { BUFSIZE, 0, cmd.cbuf };
struct strbuf data = { BUFSIZE, 0, dbuf };

typedef struct addr {
	uint16_t port __attribute__ ((packed));
	struct in_addr addr[1] __attribute__ ((packed));
} addr_t;

N_qos_sel_data_sctp_t qos_data = {
	N_QOS_SEL_DATA_SCTP,		/* n_qos_type */
	10,				/* ppi */
	0,				/* sid */
	0,				/* ssn */
	0,				/* tsn */
	0				/* more */
};

N_qos_sel_conn_sctp_t qos_conn = {
	N_QOS_SEL_CONN_SCTP,		/* n_qos_type */
	1,				/* i_streams */
	1				/* o_streams */
};

N_qos_sel_info_sctp_t qos_info = {
	N_QOS_SEL_INFO_SCTP,		/* n_qos_type */
	1,				/* i_streams */
	1,				/* o_streams */
	10,				/* ppi */
	0,				/* sid */
	12,				/* max_inits */
	12,				/* max_retrans */
	-1UL,				/* ck_life */
	-1UL,				/* ck_inc */
	-1UL,				/* hmac */
	-1UL,				/* throttle */
	20,				/* max_sack */
	100,				/* rto_ini */
	20,				/* rto_min */
	200,				/* rto_max */
	5,				/* rtx_path */
	200,				/* hb_itvl */
	0x00				/* options */
};

void usage(void)
{
	fprintf(stderr, "Usage:  test-tcps [options]\n");
	fprintf(stderr, "Options:\n");
	fprintf(stderr, "  -p, --port port           (default: 10000)\n");
	fprintf(stderr, "      port specifies both the local and remote port number\n");
	fprintf(stderr, "  -l, --loc_host loc_host   (default: 127.0.0.1)\n");
	fprintf(stderr, "      loc_host specifies the local (bind) host for the TCP\n");
	fprintf(stderr, "      socket with optional local port number\n");
	fprintf(stderr, "  -r, --rem_host rem_host   (default: 127.0.0.2)\n");
	fprintf(stderr, "      rem_host specifies the remote (connect) address for the TCP\n");
	fprintf(stderr, "      socket with optional remote port number\n");
	fprintf(stderr, "  -t, --rep_time time       (default: 1 second)\n");
	fprintf(stderr, "      time give the time in seconds between reports\n");
}

#define HOST_BUF_LEN 256

static volatile int timer_timeout = 0;

static void timer_handler(int signum)
{
	if (signum == SIGALRM)
		timer_timeout = 1;
	return;
}

static int timer_sethandler(void)
{
	sigset_t mask;
	struct sigaction act;
	act.sa_handler = timer_handler;
	act.sa_flags = SA_RESTART | SA_ONESHOT;
	act.sa_restorer = NULL;
	sigemptyset(&act.sa_mask);
	if (sigaction(SIGALRM, &act, NULL))
		return -1;
	sigemptyset(&mask);
	sigaddset(&mask, SIGALRM);
	sigprocmask(SIG_UNBLOCK, &mask, NULL);
	return 0;
}

static int start_timer(void)
{
	struct itimerval setting = { {0, 0}, {1, 0} };
	if (timer_sethandler())
		return -1;
	if (setitimer(ITIMER_REAL, &setting, NULL))
		return -1;
	timer_timeout = 0;
	return 0;
}

int sctp_get(int fd, int wait)
{
	int ret;
	int flags = 0;
	while ((ret = getmsg(fd, &ctrl, &data, &flags)) < 0) {
		switch (errno) {
		default:
		case EPROTO:
		case EINVAL:
			perror("sctp_get: gestmsg");
			return -1;
		case EINTR:
		case ERESTART:
			continue;
		case EAGAIN:
			break;
		}
		break;
	}
	if (!ret)
		return cmd.prim;
	if (!wait) {
		/* 
		   fprintf(stderr,"sctp_get: no data and no wait specified\n"); */
		return -1;
	}
	do {
		struct pollfd pfd[] = { {fd, POLLIN | POLLPRI, 0} };
		if (!(ret = poll(pfd, 1, wait))) {
			perror("sctp_get: poll");
			return -1;
		}
		if ((ret == 1) | (ret == 2)) {
			if (pfd[0].revents & (POLLIN | POLLPRI)) {
				flags = 0;
				if (getmsg(fd, &ctrl, &data, &flags) < 0) {
					perror("sctp_get: getmsg");
					return -1;
				}
				return cmd.prim;
			}
		}
		if (ret == -1) {
			perror("sctp_get: poll");
			return -1;
		}
	}
	while (1);
}

int sctp_options(int fd, ulong flags, N_qos_sel_info_sctp_t * qos)
{
	int ret;
	ctrl.len = sizeof(cmd.npi.optmgmt_req) + sizeof(*qos);
	cmd.prim = N_OPTMGMT_REQ;
	cmd.npi.optmgmt_req.OPTMGMT_flags = flags;
	cmd.npi.optmgmt_req.QOS_length = sizeof(*qos);
	cmd.npi.optmgmt_req.QOS_offset = sizeof(cmd.npi.optmgmt_req);
	bcopy(qos, (cmd.cbuf + sizeof(cmd.npi.optmgmt_req)), sizeof(*qos));
	if (putmsg(fd, &ctrl, NULL, MSG_HIPRI) < 0) {
		perror("sctp_options: putmsg");
		return -1;
	}
	if ((ret = sctp_get(fd, 0)) < 0) {
		fprintf(stderr, "sctp_options: couldn't get message\n");
		return -1;
	}
	if (ret != N_OK_ACK) {
		fprintf(stderr, "sctp_options: didn't get N_OK_ACK\n");
		return -1;
	}
	fprintf(stderr, "Options set\n");
	return 0;
}

int sctp_bind(int fd, addr_t * addr, int coninds)
{
	int ret;
	ctrl.len = sizeof(cmd.npi.bind_req) + sizeof(*addr);
	cmd.prim = N_BIND_REQ;
	cmd.npi.bind_req.ADDR_length = sizeof(*addr);
	cmd.npi.bind_req.ADDR_offset = sizeof(cmd.npi.bind_req);
	cmd.npi.bind_req.CONIND_number = coninds;
	cmd.npi.bind_req.BIND_flags = TOKEN_REQUEST;
	cmd.npi.bind_req.PROTOID_length = 0;
	cmd.npi.bind_req.PROTOID_offset = 0;
	bcopy(addr, (&cmd.npi.bind_req) + 1, sizeof(*addr));
	if (putmsg(fd, &ctrl, NULL, MSG_HIPRI) < 0) {
		perror("sctp_bind: putmsg");
		return -1;
	}
	if ((ret = sctp_get(fd, 0)) < 0) {
		fprintf(stderr, "sctp_bind: couldn't get message\n");
		return -1;
	}
	if (ret != N_BIND_ACK) {
		fprintf(stderr, "sctp_bind: didn't get N_BIND_ACK\n");
		return -1;
	}
	fprintf(stderr, "STREAM bound\n");
	return 0;
}

int sctp_connect(int fd, addr_t * addr, N_qos_sel_conn_sctp_t * qos)
{
	int ret;
	ctrl.len = sizeof(cmd.npi.conn_req) + sizeof(*addr) + sizeof(*qos);
	cmd.prim = N_CONN_REQ;
	cmd.npi.conn_req.DEST_length = sizeof(*addr);
	cmd.npi.conn_req.DEST_offset = sizeof(cmd.npi.conn_req);
	cmd.npi.conn_req.CONN_flags = REC_CONF_OPT | EX_DATA_OPT;
	cmd.npi.conn_req.QOS_length = sizeof(*qos);
	cmd.npi.conn_req.QOS_offset = sizeof(cmd.npi.conn_req) + sizeof(*addr);
	bcopy(addr, (cmd.cbuf + sizeof(cmd.npi.conn_req)), sizeof(*addr));
	bcopy(qos, (cmd.cbuf + sizeof(cmd.npi.conn_req) + sizeof(*addr)), sizeof(*qos));
	if (putmsg(fd, &ctrl, NULL, 0) < 0) {
		perror("sctp_connect: putmsg");
		return -1;
	}
	if ((ret = sctp_get(fd, 10000)) < 0) {
		fprintf(stderr, "sctp_connect: couldn't get message\n");
		return -1;
	}
	if (ret != N_CONN_CON) {
		fprintf(stderr, "sctp_connect: didn't get N_CONN_CON\n");
		return -1;
	}
	fprintf(stderr, "STREAM connected\n");
	return 0;
}

int sctp_accept(int fd, int fd2, int tok)
{
	int ret, seq;
	if ((ret = sctp_get(fd, -1)) < 0) {
		fprintf(stderr, "sctp_accept: couldn't get message on listener\n");
		return -1;
	}
	if (ret != N_CONN_IND) {
		fprintf(stderr, "sctp_accept: didn't get N_CONN_IND\n");
		return -1;
	}
	seq = cmd.npi.conn_ind.SEQ_number;
	ctrl.len = sizeof(cmd.npi.conn_res);
	cmd.prim = N_CONN_RES;
	cmd.npi.conn_res.TOKEN_value = tok;
	cmd.npi.conn_res.RES_offset = 0;
	cmd.npi.conn_res.RES_length = 0;
	cmd.npi.conn_res.SEQ_number = seq;
	cmd.npi.conn_res.CONN_flags = REC_CONF_OPT | EX_DATA_OPT;
	cmd.npi.conn_res.QOS_offset = 0;
	cmd.npi.conn_res.QOS_length = 0;
	if (putmsg(fd, &ctrl, NULL, 0) < 0) {
		perror("sctp_accept: putmsg");
		return -1;
	}
	if ((ret = sctp_get(fd, 0)) < 0) {
		fprintf(stderr, "sctp_accept: couldn't get message\n");
		return -1;
	}
	if (ret != N_OK_ACK) {
		fprintf(stderr, "sctp_accept: didn't get N_OK_ACK\n");
		return -1;
	}
	fprintf(stderr, "Connection Indication accepted\n");
	return 0;
}

int sctp_write(int fd, void *msg, size_t len, int flags, N_qos_sel_data_sctp_t * qos)
{
	data.buf = msg;
	data.len = len;
	data.maxlen = len;
	ctrl.len = sizeof(cmd.npi.data_req) + sizeof(*qos);
	cmd.prim = N_DATA_REQ;
	cmd.npi.data_req.DATA_xfer_flags = flags;
	bcopy(qos, cmd.cbuf + sizeof(cmd.npi.data_req), sizeof(*qos));
	if (putmsg(fd, &ctrl, &data, 0) < 0) {
		if (errno != EAGAIN)
			perror("sctp_write: putmsg");
		return -1;
	}
	return (0);
}

int sctp_read(int fd, void *msg, size_t len)
{
	int ret;
	data.buf = msg;
	data.len = 0;
	data.maxlen = len;
	if ((ret = sctp_get(fd, 0)) < 0) {
		/* 
		   fprintf(stderr,"sctp_read: couldn't get message\n"); */
		return -1;
	}
	if (ret != N_DATA_IND) {
		fprintf(stderr, "sctp_read: didn't get N_DATA_IND\n");
		return -1;
	}
	return 0;
}

static addr_t loc_addr = { 0, {{INADDR_ANY}} };
static addr_t rem_addr = { 0, {{INADDR_ANY}} };

int len = 32;

int test_sctps(void)
{
	int lfd, fd;
	long inp_count = 0, out_count = 0;
	struct pollfd pfd[1] = { {0, POLLIN | POLLOUT | POLLERR | POLLHUP, 0} };
	unsigned char my_msg[] = "This is a good short test message that has some 64 bytes in it.";
	unsigned char ur_msg[4096];

	fprintf(stderr, "Opening stream\n");

	if ((lfd = open("/dev/sctp_n", O_NONBLOCK | O_RDWR)) < 0) {
		perror("open");
		close(lfd);
		exit(2);
	}
	if (ioctl(lfd, I_SRDOPT, RMSGD) < 0) {
		perror("ioctl");
		close(lfd);
		exit(2);
	}
	fprintf(stderr, "--> STREAM listener opened\n");
	if ((fd = open("/dev/sctp_n", O_NONBLOCK | O_RDWR)) < 0) {
		perror("open");
		goto dead;
	}
	if (ioctl(fd, I_SRDOPT, RMSGD) < 0) {
		perror("ioctl");
		goto dead;
	}
	fprintf(stderr, "--> STREAM acceptor opened\n");
	if (sctp_bind(lfd, &loc_addr, 1) < 0)
		goto dead;
	fprintf(stderr, "--> STREAM listener bound\n");
	if (sctp_bind(fd, &loc_addr, 0) < 0)
		goto dead;
	fprintf(stderr, "--> STREAM acceptor bound\n");
	if (sctp_accept(lfd, fd, cmd.npi.bind_ack.TOKEN_value) < 0)
		goto dead;
	fprintf(stderr, "--> STREAM connection accepted\n");

	if (start_timer()) {
		perror("timer");
		goto dead;
	}
	fprintf(stderr, "--> Timer started\n");

	/* 
	   for (;;) { pfd[0].fd = fd; pfd[0].revents = 0; pfd[0].events = POLLIN; if (
	   timer_timeout ) { printf("Msgs sent: %5ld, recv: %5ld, tot: %5ld, dif: %5ld\n",
	   inp_count, out_count, inp_count+out_count, out_count-inp_count); inp_count = 0;
	   out_count = 0; if ( start_timer() ) { perror("timer"); goto dead; } } if ( poll(&pfd[0], 
	   1, -1) < 0 ) { if ( errno == EINTR ) continue; perror("poll"); goto dead; } if (
	   pfd[0].revents & POLLIN ) { while ( sctp_read(fd, ur_msg, sizeof(ur_msg)) == 0 &&
	   ++inp_count ) { sctp_write(fd, ur_msg, data.len, 0, &qos_data); ++out_count; } if (
	   errno != EAGAIN ) { fprintf(stderr,"sctp_read: couldn't read message\n"); goto dead; }
	   } } */
	for (;;) {
		pfd[0].fd = fd;
		pfd[0].events = POLLIN | POLLOUT;
		pfd[0].revents = 0;
		if (timer_timeout) {
			printf("Msgs sent: %5ld, recv: %5ld, tot: %5ld, dif: %5ld, tput: %10ld\n",
			       inp_count, out_count, inp_count + out_count, out_count - inp_count,
			       8 * (42 + len) * (inp_count + out_count));
			inp_count = 0;
			out_count = 0;
			if (start_timer()) {
				perror("timer");
				goto dead;
			}
		}
		if (poll(&pfd[0], 1, -1) < 0) {
			switch (errno) {
			case EINTR:
			case ERESTART:
				continue;
			}
			perror("poll");
			goto dead;
		}
		if (pfd[0].revents & POLLIN) {
			if (sctp_read(fd, ur_msg, sizeof(ur_msg)) < 0) {
				if (errno != EAGAIN) {
					fprintf(stderr, "sctp_read: couldn't read message\n");
					goto dead;
				}
				pfd[0].revents &= ~POLLIN;
			} else
				++inp_count;
			continue;
		}
		if (pfd[0].revents & POLLOUT) {
			if (sctp_write(fd, my_msg, len, 0, &qos_data) < 0) {
				if (errno != EAGAIN) {
					fprintf(stderr, "sctp_write: couldn't write message\n");
					goto dead;
				}
				pfd[0].revents &= ~POLLOUT;
			} else
				++out_count;
			continue;
		}
	}
      dead:
	close(lfd);
	close(fd);
	return (0);
}

int main(int argc, char **argv)
{
	int c;
	char *hostl = "127.0.0.1";
	char *hostr = "127.0.0.1";
	char hostbufl[HOST_BUF_LEN];
	char hostbufr[HOST_BUF_LEN];
	char **hostlp = &hostl;
	char **hostrp = &hostr;
	short portl = 10001;
	short portr = 10000;
	int time;
	struct hostent *haddr;
	while (1) {
		int option_index = 0;
		static struct option long_options[] = {
			{"loc_host", 1, 0, 'l'},
			{"rem_host", 1, 0, 'r'},
			{"rep_time", 1, 0, 't'},
			{"help", 0, 0, 'h'},
			{"port", 1, 0, 'p'},
			{"length", 1, 0, 'w'}
		};
		c = getopt_long(argc, argv, "l:r:t:hp:w:", long_options, &option_index);
		if (c == -1)
			break;
		switch (c) {
		case 0:
			switch (option_index) {
			case 0:	/* loc_host */
				strncpy(hostbufl, optarg, HOST_BUF_LEN);
				hostl = hostbufl;
				hostlp = &hostl;
				break;
			case 1:	/* rem_host */
				strncpy(hostbufr, optarg, HOST_BUF_LEN);
				hostr = hostbufr;
				hostrp = &hostr;
				break;
			case 2:	/* rep_time */
				time = atoi(optarg);
				break;
			case 3:	/* help */
				usage();
				exit(0);
			case 4:	/* port */
				portl = atoi(optarg);
				portr = portl;
				break;
			case 5:	/* length */
				len = atoi(optarg);
				if (len > 1024) {
					len = 1024;
				}
				break;
			default:
				usage();
				exit(1);
			}
			break;
		case 'l':
			strncpy(hostbufl, optarg, HOST_BUF_LEN);
			hostl = hostbufl;
			hostlp = &hostl;
			break;
		case 'r':
			strncpy(hostbufr, optarg, HOST_BUF_LEN);
			hostr = hostbufr;
			hostrp = &hostr;
			break;
		case 't':
			time = atoi(optarg);
			break;
		case 'h':
			usage();
			exit(0);
		case 'p':
			portl = atoi(optarg);
			portr = portl;
			break;
		case 'w':
			len = atoi(optarg);
			if (len > 1024)
				len = 1024;
			break;
		default:
			fprintf(stderr, "ERROR: Unrecognized option `%c'.\n", c);
			usage();
			exit(1);
		}
	}
	if (optind < argc) {
		fprintf(stderr, "ERROR: Option syntax: ");
		while (optind < argc)
			fprintf(stderr, "%s ", argv[optind++]);
		fprintf(stderr, "\n");
		usage();
		exit(1);
	}

	haddr = gethostbyname(*hostlp);
	loc_addr.port = htons(portl);
	loc_addr.addr[0].s_addr = *(uint32_t *) (haddr->h_addr);

	haddr = gethostbyname(*hostrp);
	rem_addr.port = htons(portr);
	rem_addr.addr[0].s_addr = *(uint32_t *) (haddr->h_addr);

	return test_sctps();
}


Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/test/test-sctp_ns.c

OpenSS7
SS7 for the
Common Man
Home Overview Status News Documentation Resources About

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified: