/******************************************************** * * stopandwait.c * * Adapted by Jeff Ondich from Chris McDonald's * stopandwait.c. * ********************************************************/ #include #include #include "stopandwait.h" /* Sender globals. */ static char *gMessage; static int gMessageLength; static CnetTimer gTimer; static int gAckExpected = 0; static int gNextFrameToSend = 0; /* Receiver globals. */ static int gFrameExpected = 0; void reboot_node( CnetEvent ev, CnetTimer timer, CnetData data ) { /* Bail out if there are too many nodes in the network. */ if( nodeinfo.nodenumber > 1 ) { fprintf( stderr, "This is not a 2-node network.\n" ); exit( 1 ); } /* Allocate memory for the message buffer. */ gMessage = (char *)malloc( MAX_MESSAGE_SIZE * sizeof(char) ); if( gMessage == NULL ) { fprintf( stderr, "Memory allocation error in %s.\n", nodeinfo.nodename ); exit( 1 ); } /* Register the relevant event handlers. */ CHECK( CNET_set_handler( EV_APPLICATIONREADY, on_application_ready, 0 ) ); CHECK( CNET_set_handler( EV_PHYSICALREADY, on_physical_ready, 0 ) ); CHECK( CNET_set_handler( EV_TIMER1, on_timer_expired, 0 ) ); /* Turn on message generation in the sender node. */ if( nodeinfo.nodenumber == 1 ) CHECK( CNET_enable_application( ALLNODES ) ); } static void transmit_frame( char *message, int messageLength, FrameKind kind, int sequenceNumber ) { int frameLength; Frame f; f.kind = kind; f.sequenceNumber = sequenceNumber; f.checksum = 0; f.messageLength = messageLength; if( kind == DATA ) { memcpy( f.message, message, messageLength ); } frameLength = FRAME_SIZE( f ); f.checksum = checksum_crc32( (unsigned char *)(&f), frameLength ); CHECK( CNET_write_physical( 1, (char *)(&f), &frameLength ) ); } static void on_application_ready( CnetEvent ev, CnetTimer timer, CnetData data ) { CnetAddr destaddr; /* Get the message from the application layer. */ gMessageLength = MAX_MESSAGE_SIZE * sizeof(char); CHECK( CNET_read_application( &destaddr, gMessage, &gMessageLength ) ); CNET_disable_application( ALLNODES ); /* Send the message to the physical layer. */ transmit_frame( gMessage, gMessageLength, DATA, gNextFrameToSend ); gNextFrameToSend = 1 - gNextFrameToSend; gTimer = CNET_start_timer( EV_TIMER1, 3*linkinfo[1].propagationdelay, 0 ); } static void on_physical_ready(CnetEvent ev, CnetTimer timer, CnetData data) { Frame f; int link, length, checksum; /* Get the incoming frame from the physical layer. */ length = sizeof( Frame ); CHECK( CNET_read_physical( &link, (char *)(&f), &length ) ); /* If the checksum is bad, ignore the frame. */ checksum = f.checksum; f.checksum = 0; if( checksum_crc32( (unsigned char *)(&f), length ) != checksum ) { return; } /* The frame looks okay. Process it. */ switch( f.kind ) { /* The frame is an acknowledgement, so this node must be a sender. If this was the acknowledgement we were expecting, clean up (stop the timer) and move on to sending the next frame (enable the application layer). Otherwise, ignore the frame. */ case ACK: if( f.sequenceNumber == gAckExpected ) { CNET_stop_timer( gTimer ); gAckExpected = 1 - gAckExpected; CNET_enable_application( ALLNODES ); } break; /* The frame is a data frame, so this node must be a receiver. If it's the frame we expected, pass it along to the application layer, otherwise ignore it. In either case, we need to acknowledge the frame. */ case DATA: if( f.sequenceNumber == gFrameExpected ) { length = f.messageLength; CHECK( CNET_write_application( f.message, &length ) ); gFrameExpected = 1 - gFrameExpected; } transmit_frame( 0, 0, ACK, f.sequenceNumber ); break; } } static void on_timer_expired( CnetEvent ev, CnetTimer timer, CnetData data ) { if( timer == gTimer ) { transmit_frame( gMessage, gMessageLength, DATA, gAckExpected ); gTimer = CNET_start_timer( EV_TIMER1, 3*linkinfo[1].propagationdelay, 0 ); } }