#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "rtr.h"

/*
Copyright Digital Equipment Corporation 1994-1995. All rights reserved.

Restricted Rights: Use, duplication, or disclosure by the U.S. Government
is subject to restrictions as set forth in subparagraph (c) (1) (ii) of
DFARS 252.227-7013, or in FAR 52.227-19, or in FAR 52.227-14 Alt. III, as
applicable.

This software is proprietary to and embodies the confidential technology
of Digital Equipment Corporation. Possession, use, or copying of this
software and media is authorized only pursuant to a valid written license
from Digital or an authorized sublicensor.
*/

/*
    File: rtrsrv.c

On OSF/1
	
    compile and link using:

	cc -o rtrsrv rtrsrv.c -lrtr

On WINNT

    build using:

       nmake -f rtrsrv.mak

    	
Simple test on one node:

	- start rtr
	    > rtr start rtr
    	- create a facility
	    > rtr create facility /all_roles=<your node name>
	    > rtr create facility /all_roles=<your node name>
	- run this server
	    > rtrsrv
	- run the client
	    > rtrreq
*/

#define APITSTBUFSIZ 10000	


/******************************************************************************/
static void exit_if_error (
    char		*msgtxt,
    rtr_status_t	sts
    )
{
    if ( sts > 0 )
    {
    	return ;
    }
    printf ( "%s unexpected error(%d)\n", msgtxt, sts);
    printf ( "%s\n", rtr_error_text (sts));
    exit (1);
}
/******************************************************************************/
static void continue_if_error (
    char		*msgtxt,
    rtr_status_t	sts
    )
{
    if ( sts > 0 )
    {
	printf ( "%s didn't get expected error(%d)\n", msgtxt, sts);
	printf ( "%s\n", rtr_error_text (sts));
	exit (1);
    }
    else
    {
	printf ( "%s got expected error(%d)\n", msgtxt, sts);
	printf ( "%s\n", rtr_error_text (sts));
	return ;
    }
}

/******************************************************************************/
static void print_rtr_status_data (
    char		*rcvbuf
    )
{
    rtr_status_data_t	status_data ;

    memcpy (
    	(char *)&status_data,
    	rcvbuf,
    	sizeof ( rtr_status_data_t )
    	) ;
    printf ( "  status: %d (%s)\n",
		status_data.status,
		rtr_error_text ( status_data.status )
	    ) ;
    printf ( "  reason: %d\n",
		status_data.reason
	    ) ;
}

/******************************************************************************/
static void print_msgsb (
    rtr_msgsb_t		*msgsb,
    char		*rcvbuf
    )
{
    switch ( msgsb->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" ) ;
	    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 ;
	default:
	    printf ( "Unexpected msgtype %d\n", msgsb->msgtype ) ;
    }

    printf ("usrhdl=%lu msglen=%d tid=%x,%x,%x,%x,%x,%x,%x evtnum=%d\n",
	    (unsigned long)msgsb->usrhdl,
	    msgsb->msglen,
	    msgsb->tid.tid32[0],
	    msgsb->tid.tid32[1],
	    msgsb->tid.tid32[2],
	    msgsb->tid.tid32[3],
	    msgsb->tid.tid32[4],
	    msgsb->tid.tid32[5],
	    msgsb->tid.tid32[6],
	    msgsb->evtnum
	    ) ;
}

/******************************************************************************/
static void process_msgsb ( rtr_msgsb_t *msgsb, rtr_channel_t srvchn )
{
    rtr_status_t    sts;

    switch ( msgsb->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 ( srvchn, 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 ;
    }

}

/******************************************************************************/
static rtr_status_t get_message_from_rtr (
    rtr_channel_t	*pchannel,
    char		*rcvbuf,
    rtr_msgsb_t		*msgsb,
    rtr_channel_t	srvchn
    )
{
    rtr_status_t sts ;

printf ( "------------------------------ rtr_receive_message \n" ) ;
    sts = rtr_receive_message (
	    /* pchannel	*/ pchannel,
	    /* flags	*/ RTR_NO_FLAGS,
	    /* prcvchan	*/ RTR_ANYCHAN,
	    /* pmsg	*/ rcvbuf,
	    /* maxlen	*/ APITSTBUFSIZ,
	    /* timoutms	*/ RTR_NO_TIMOUTMS,
	    /* pmsgsb	*/ msgsb
	    ) ;
    if (sts > 0)
    {
	printf ( "Got message on channel %d\n", *pchannel ) ;
	print_msgsb ( msgsb, rcvbuf ) ;
	process_msgsb ( msgsb , srvchn) ;
    }
    return sts;
}

typedef rtr_uns_8_t tst_key_t ;

/******************************************************************************/
main ( int argc, char *argv[] )
{
    tst_key_t 		High ;
    tst_key_t 		Low ;
    char		rcvbuf [ APITSTBUFSIZ ] ;
    rtr_channel_t	srvchn ;
    rtr_channel_t	inch ;
    rtr_msgsb_t		msgsb ;
    rtr_status_t	sts ;

    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.1A (50) Test Server\n" ) ;

    Low = 0;
    High = ~((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	*/ &srvchn,
	    /* 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 ) ;

    while (
	    (sts = get_message_from_rtr (
		    /* rcvchn	*/ &inch,
		    /* rcvbuf	*/ rcvbuf,
		    /* msgsb	*/ &msgsb,
		    /* srvchn	*/ srvchn
		    )
	    )
	    > 0
	  );

    exit_if_error ( "rtr_receive_message", sts ) ;

printf ( "------------------------------ server rtr_close_channel \n" ) ;
    sts = rtr_close_channel ( srvchn, RTR_NO_FLAGS );
    exit_if_error ( "rtr_close_channel", sts ) ;
    return ( 0 );
}
