#include /* UCHAR_MAX */ #include #include #include #include "rtr.h" /* Copyright 1994 Compaq Computer Corporation. Confidential computer software. Valid license from Compaq required for possession, use or copying. Consistent with FAR 12.211 and 12.212, Commercial Computer Software, Computer Software, Computer Software Documentation, and Technical Data for Commercial Items are licensed to the U.S. Government under vendor's standard commercial license. Compaq, the Compaq logo, and the Digital logo are registered in the U.S. Patent and Trademark Office. */ /* File: rtrsrv.c Purpose: sample RTR application, used in Installation Verification Procedure On Tru64 Unix: compile with ANSI C compiler and link using: % cc -std -o rtrsrv rtrsrv.c -lrtr or % cc -std -pthread -o rtrsrv rtrsrv.c -lrtr_r On Windows: build multithreaded console application using: > nmake rtrsrv.exe CFLAGS="/MT rtrdll.lib" On OpenVMS: build using: $ CC/DECC rtrsrv $ LINK rtrsrv,sys$input/opt sys$share:librtr.exe/share or sys$share:librtr_r.exe/share Simple test on one node: - start rtr > rtr start rtr - create a facility > rtr create facility /all_roles=yournode - run this server > rtrsrv - run the client > rtrreq */ /* This RTR application program is written in ANSI C with the assumption * that printf "%d" int format tokens can also be used for 32 bit datatypes. */ /******************************************************************************/ static void print_rtr_status_data ( const void *rcvbuf ) { rtr_status_data_t status_data ; /* Because we chose to use an unaligned char array for rcvbuf, * instead of a union like in rtrreq.c, * the status data must be copied to a properly aligned variable * before it can be inspected. A cast will not do. */ memcpy (&status_data, rcvbuf, sizeof(rtr_status_data_t) ) ; printf ( " status: %s (%d)\n", rtr_error_text(status_data.status), status_data.status ) ; printf ( " reason: %d\n", status_data.reason ) ; } /******************************************************************************/ static void exit_if_error ( const char *msgtxt, rtr_status_t sts ) { if ( sts > 0 ) /* success */ { return ; } /* The error strategy in this sample program is to terminate the process. * An alternative for errors like rtr stopped or not yet started * is to wait a while and then start over with rtr_open_channel(). */ printf ( "%s unexpected error\n", msgtxt); printf ( " status: %s (%d)\n", rtr_error_text(sts), sts ) ; if (sts == RTR_STS_NOACP) printf ( "------------------------------ usual server exit on stop rtr\n" ) ; exit (EXIT_FAILURE); } /******************************************************************************/ static void print_rtr_event_text ( rtr_evtnum_t evtnum ) { switch ( evtnum ) { case RTR_EVTNUM_FACREADY: printf ( "FACREADY - facility ready\n" ) ; break ; case RTR_EVTNUM_FACDEAD: printf ( "FACDEAD - facility not ready\n" ) ; break ; case RTR_EVTNUM_FERTRGAIN: printf ( "FERTRGAIN - FE link to router\n" ) ; break ; case RTR_EVTNUM_FERTRLOSS: printf ( "FERTRLOSS - FE lost link to router\n" ) ; break ; case RTR_EVTNUM_RTRBEGAIN: printf ( "RTRBEGAIN - router link to BE\n" ) ; break ; case RTR_EVTNUM_RTRBELOSS: printf ( "RTRBELOSS - router lost link to BE\n" ) ; break ; case RTR_EVTNUM_KEYRANGEGAIN: printf ( "KEYRANGEGAIN - new key range available\n" ) ; break ; case RTR_EVTNUM_KEYRANGELOSS: printf ( "KEYRANGELOSS - a key range not available\n" ) ; break ; case RTR_EVTNUM_BERTRGAIN: printf ( "BERTRGAIN - BE link to a router\n" ) ; break ; case RTR_EVTNUM_BERTRLOSS: printf ( "BERTRLOSS - BE lost link to a router\n" ) ; break ; case RTR_EVTNUM_RTRFEGAIN: printf ( "RTRFEGAIN - Router link to an FE\n" ) ; break ; case RTR_EVTNUM_RTRFELOSS: printf ( "RTRFELOSS - Router lost link to an FE\n" ) ; break ; case RTR_EVTNUM_SRPRIMARY: printf ( "SRPRIMARY - Server is primary mode\n" ) ; break ; case RTR_EVTNUM_SRSTANDBY: printf ( "SRSTANDBY - Server is standby mode\n" ) ; break ; case RTR_EVTNUM_SRSECONDARY: printf ( "SRSECONDARY - Server is secondary mode\n" ) ; break ; case RTR_EVTNUM_SRSHADOWLOST: printf ( "SRSHADOWLOST - Server lost shadow\n" ) ; break ; case RTR_EVTNUM_SRSHADOWGAIN: printf ( "SRSHADOWGAIN - Server gained shadow\n" ) ; break ; case RTR_EVTNUM_SRRECOVERCMPL: printf ("SRRECOVERCMPL - Server recovered\n" ) ; break ; default: printf ( "Unexpected RTR event %u\n", evtnum ) ; } } /******************************************************************************/ static void print_msgsb ( const rtr_msgsb_t *pmsgsb, const char *rcvbuf ) { switch ( pmsgsb->msgtype ) { case rtr_mt_msg1: printf ( "rtr_mt_msg1 - first message of a transaction\n" ) ; break ; case rtr_mt_msgn: printf ( "rtr_mt_msgn - nth message (i.e. not the first) of a tx\n" ) ; break ; case rtr_mt_msg1_uncertain: printf ( "rtr_mt_msg1_uncertain - first message - might have been received\n" ) ; break ; case rtr_mt_reply: printf ( "rtr_mt_reply - message sent by a server to a client\n" ) ; break ; case rtr_mt_prepare: printf ( "rtr_mt_prepare - expects server to accept or reject\n" ) ; break ; case rtr_mt_rtr_event: printf ( "rtr_mt_rtr_event - received message is an RTR event\n" ) ; print_rtr_event_text ( pmsgsb->evtnum ) ; break ; case rtr_mt_user_event: printf ( "rtr_mt_user_event - received message is a user event\n" ) ; break ; case rtr_mt_accepted: printf ( "rtr_mt_accepted - tx has been accepted by all participants\n" ) ; print_rtr_status_data ( rcvbuf ) ; break ; case rtr_mt_rejected: printf ( "rtr_mt_rejected - specified tx was rejected by a participant\n" ) ; print_rtr_status_data ( rcvbuf ) ; break ; case rtr_mt_opened: printf ( "rtr_mt_opened - channel opened\n" ) ; print_rtr_status_data ( rcvbuf ) ; break ; case rtr_mt_closed: printf ( "rtr_mt_closed - channel closed\n" ) ; print_rtr_status_data ( rcvbuf ) ; break ; case rtr_mt_request_info: printf ( "rtr_mt_request_info - message from rtr_request_info\n" ) ; break ; case rtr_mt_set_info: printf ( "rtr_mt_set_info - message from rtr_set_info\n" ) ; break ; case rtr_mt_rettosend: printf ( "rtr_mt_rettosend - message has been returned to sender\n" ) ; break ; case rtr_mt_prepared: /* new in RTR 3.2 */ printf ( "rtr_mt_prepared - tx has been prepared by all participants\n" ) ; break ; default: printf ( "Unexpected msgtype %d\n", pmsgsb->msgtype ) ; } printf (" usrhdl: %lu msglen: %u evtnum: %u\n", (unsigned long)pmsgsb->usrhdl, pmsgsb->msglen, pmsgsb->evtnum ) ; printf (" tid: %x,%x,%x,%x,%x,%x,%x\n", /* varies between runs */ pmsgsb->tid.tid32[0], pmsgsb->tid.tid32[1], pmsgsb->tid.tid32[2], pmsgsb->tid.tid32[3], pmsgsb->tid.tid32[4], pmsgsb->tid.tid32[5], pmsgsb->tid.tid32[6] ) ; } /******************************************************************************/ static void process_msgsb ( const rtr_msgsb_t *pmsgsb, rtr_channel_t opened_server_channel ) { rtr_status_t sts; switch ( pmsgsb->msgtype ) { case rtr_mt_msg1: break ; case rtr_mt_msgn: break ; case rtr_mt_msg1_uncertain: break ; case rtr_mt_reply: break ; case rtr_mt_prepare: printf ( "------------------------------ rtr_accept_tx\n" ) ; sts = rtr_accept_tx ( opened_server_channel, RTR_NO_FLAGS, RTR_NO_REASON ) ; exit_if_error ( "rtr_accept_tx", sts ) ; break ; case rtr_mt_rtr_event: break ; case rtr_mt_user_event: break ; case rtr_mt_accepted: break ; case rtr_mt_rejected: break ; case rtr_mt_opened: break ; case rtr_mt_closed: break ; case rtr_mt_request_info: break ; case rtr_mt_set_info: break ; case rtr_mt_rettosend: break ; case rtr_mt_prepared: /* new in RTR 3.2, not used in this program */ break ; } } /******************************************************************************/ /* Application-specific definitions */ #define APITSTBUFSIZ 10000 typedef rtr_uns_8_t tst_key_t ; /* Server application */ int main ( int argc, char *argv[] ) { tst_key_t High ; tst_key_t Low ; char rcvbuf [ APITSTBUFSIZ ] ; /* or use union like in rtrreq.c */ rtr_channel_t opened_server_channel ; rtr_channel_t received_message_channel ; rtr_msgsb_t msgsb ; rtr_status_t sts ; const rtr_evtnum_t pevtnum[] = { RTR_EVTNUM_USERDEF, RTR_EVTNUM_USERBASE, RTR_EVTNUM_UP_TO, RTR_EVTNUM_USERMAX, RTR_EVTNUM_RTRDEF, RTR_EVTNUM_RTRBASE, RTR_EVTNUM_UP_TO, RTR_EVTNUM_RTRMAX, RTR_EVTNUM_ENDLIST }; rtr_keyseg_t keyseg[1]; printf ( "RTR V3.2 rtrsrv Test Server\n" ) ; Low = 0; High = UCHAR_MAX; /* is this the same as ~((tst_key_t)0) ? */ keyseg[0].ks_type = rtr_keyseg_unsigned; keyseg[0].ks_length = sizeof(tst_key_t); keyseg[0].ks_offset = 0; keyseg[0].ks_lo_bound = &Low; keyseg[0].ks_hi_bound = &High; printf ( "------------------------------ server rtr_open_channel\n" ) ; sts = rtr_open_channel ( /* pchannel */ &opened_server_channel, /* flags */ (RTR_F_OPE_SERVER | RTR_F_OPE_EXPLICIT_PREPARE | RTR_F_OPE_EXPLICIT_ACCEPT), /* facnam */ "RTR$DEFAULT_FACILITY", /* chanam */ "RECEIVER", /* pevtnum */ pevtnum, /* access */ "ACCSTR", /* numseg */ 1, /* pkeyseg */ keyseg ) ; exit_if_error ( "rtr_open_channel", sts ) ; for (;;) { printf ( "------------------------------ rtr_receive_message\n" ) ; sts = rtr_receive_message ( /* pchannel */ &received_message_channel, /* flags */ RTR_NO_FLAGS, /* prcvchan */ RTR_ANYCHAN, /* pmsg */ rcvbuf, /* maxlen */ APITSTBUFSIZ, /* timoutms */ RTR_NO_TIMOUTMS, /* pmsgsb */ &msgsb ) ; exit_if_error ( "rtr_receive_message", sts ) ; printf ( "Got message on channel %u\n", received_message_channel ) ; print_msgsb ( &msgsb, rcvbuf ) ; process_msgsb ( &msgsb , opened_server_channel) ; } /*NOTREACHED*/ printf ( "------------------------------ server rtr_close_channel\n" ) ; sts = rtr_close_channel ( /* channel */ opened_server_channel, /* flags */ RTR_NO_FLAGS ) ; exit_if_error ( "rtr_close_channel", sts ) ; return ( EXIT_SUCCESS ); }