--- /dev/null
+// :vim ts=4 sw=4 noet:
+
+/*
+ Mnemonic: sender.c
+ Abstract: Very simple test sender. Sends messages with a given delay between each.
+ The sender also uses epoll_wait() to ensure that any received messages
+ don't clog the queue.
+
+ Parms: The following positional parameters are recognised on the command line:
+ [listen_port [delay [stats-freq] [msg-type]]]]
+
+ Defaults:
+ listen_port 43086
+ delay (mu-sec) 1000000 (1 sec)
+ stats-freq 10
+ msg-type 0
+
+ Date: 1 April 2019
+*/
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/epoll.h>
+#include <time.h>
+
+#include <rmr/rmr.h>
+
+int main( int argc, char** argv ) {
+ void* mrc; //msg router context
+ struct epoll_event events[1]; // list of events to give to epoll
+ struct epoll_event epe; // event definition for event to listen to
+ int ep_fd = -1; // epoll's file des (given to epoll_wait)
+ int rcv_fd; // file des that NNG tickles -- give this to epoll to listen on
+ int nready; // number of events ready for receive
+ rmr_mbuf_t* sbuf; // send buffer
+ rmr_mbuf_t* rbuf; // received buffer
+ int count = 0;
+ int rcvd_count = 0;
+ char* listen_port = "43086";
+ int delay = 1000000; // mu-sec delay between messages
+ int mtype = 0;
+ int stats_freq = 100;
+
+ if( argc > 1 ) {
+ listen_port = argv[1];
+ }
+ if( argc > 2 ) {
+ delay = atoi( argv[2] );
+ }
+ if( argc > 3 ) {
+ mtype = atoi( argv[3] );
+ }
+
+ fprintf( stderr, "<DEMO> listen port: %s; mtype: %d; delay: %d\n", listen_port, mtype, delay );
+
+ if( (mrc = rmr_init( listen_port, 1400, RMRFL_NONE )) == NULL ) {
+ fprintf( stderr, "<DEMO> unable to initialise RMr\n" );
+ exit( 1 );
+ }
+
+ rcv_fd = rmr_get_rcvfd( mrc ); // set up epoll things, start by getting the FD from MRr
+ if( rcv_fd < 0 ) {
+ fprintf( stderr, "<DEMO> unable to set up polling fd\n" );
+ exit( 1 );
+ }
+ if( (ep_fd = epoll_create1( 0 )) < 0 ) {
+ fprintf( stderr, "[FAIL] unable to create epoll fd: %d\n", errno );
+ exit( 1 );
+ }
+ epe.events = EPOLLIN;
+ epe.data.fd = rcv_fd;
+
+ if( epoll_ctl( ep_fd, EPOLL_CTL_ADD, rcv_fd, &epe ) != 0 ) {
+ fprintf( stderr, "[FAIL] epoll_ctl status not 0 : %s\n", strerror( errno ) );
+ exit( 1 );
+ }
+
+ sbuf = rmr_alloc_msg( mrc, 256 ); // alloc first send buffer; subsequent buffers allcoated on send
+ rbuf = NULL; // don't need to alloc receive buffer
+
+ while( ! rmr_ready( mrc ) ) { // must have a route table before we can send; wait til RMr say it has one
+ sleep( 1 );
+ }
+ fprintf( stderr, "<DEMO> rmr is ready\n" );
+
+
+ while( 1 ) { // send messages until the cows come home
+ snprintf( sbuf->payload, 200, "count=%d received= %d ts=%lld %d stand up and cheer!", // create the payload
+ count, rcvd_count, (long long) time( NULL ), rand() );
+
+ sbuf->mtype = mtype; // fill in the message bits
+ sbuf->len = strlen( sbuf->payload ) + 1; // our receiver likely wants a nice acsii-z string
+ sbuf->state = 0;
+ sbuf = rmr_send_msg( mrc, sbuf ); // send it (send returns an empty payload on success, or the original payload on fail/retry)
+ while( sbuf->state == RMR_ERR_RETRY ) { // soft failure (device busy?) retry
+ sbuf = rmr_send_msg( mrc, sbuf ); // retry send until it's good (simple test; real programmes should do better)
+ }
+ count++;
+
+ while( (nready = epoll_wait( ep_fd, events, 1, 0 )) > 0 ) { // if something ready to receive (non-blocking check)
+ if( events[0].data.fd == rcv_fd ) { // we only are waiting on 1 thing, so [0] is ok
+ errno = 0;
+ rbuf = rmr_rcv_msg( mrc, rbuf );
+ if( rbuf ) {
+ rcvd_count++;
+ }
+ }
+ }
+
+ if( (count % stats_freq) == 0 ) {
+ fprintf( stderr, "<DEMO> sent %d received %d\n", count, rcvd_count );
+ }
+
+ usleep( delay );
+ }
+}
+