#include #include #include "stopandwait.h" /* These are used for storing the latest message between events. Note that I usually name my global variables starting with a "g" so I'm reminded of their nature when I see them in the code. */ static char *gBuffer; static int gBufferLength; /* Variables with which to track the expected frames and acknowledgements. */ static int gNext_frame_to_send; static int gFrame_expected; static CnetTimer gTimer; void reboot_node( CnetEvent ev, CnetTimer ts, CnetData data ) { /* This protocol is only good for 2-node networks. A multi-node version of a stop-and-wait protocol is more complicated. */ if( nodeinfo.nodenumber > 1 ) { fprintf( stderr, "This is not a 2-node network.\n" ); exit( 1 ); } /* This protocol is simplex, so we make node 0 the sender and node 1 the receiver. */ if( nodeinfo.nodenumber == 0 ) CHECK( CNET_enable_application( ALLNODES ) ); /* Register the event handlers. */ CHECK( CNET_set_handler( EV_APPLICATIONREADY, OnApplicationReady, 0 ) ); CHECK( CNET_set_handler( EV_PHYSICALREADY, OnPhysicalReady, 0 ) ); CHECK( CNET_set_handler( EV_PHYSICALREADY, OnTimer, 0 ) ); /* Allocate memory for the buffer. */ gBuffer = (char *)malloc( MAX_MESSAGE_SIZE * sizeof(char) ); if( gBuffer == 0 ) { fprintf( stderr, "Memory allocation error in node '%s.'\n", nodeinfo.nodename ); exit( 1 ); } gBufferLength = 0; /* Initialize other globals. */ gNext_frame_to_send = 0; gFrame_expected = 0; } void OnApplicationReady( CnetEvent ev, CnetTimer ts, CnetData data ) { CnetAddr destAddr; Frame frame; int frameLength; /* Get the packet from the Application/Network layer, and disable the application layer until we receive an acknowledgement for this frame. */ gBufferLength = MAX_MESSAGE_SIZE; CHECK( CNET_read_application( &destAddr, gBuffer, &gBufferLength ) ); CHECK( CNET_disable_application( ALLNODES ) ); /* Build the frame and send it to the Physical layer. */ frame.seq = gNext_frame_to_send; memcpy( frame.info, gBuffer, gBufferLength ); frame.checksum = 0; frame.checksum = checksum_crc32( (unsigned char *)(&frame), frameLength ); frameLength = FRAME_HEADER_SIZE + gBufferLength; CHECK( CNET_write_physical( 1, (char *)(&frame), &frameLength ) ); gTimer = CNET_start_timer( EV_TIMER1, TIMER_DELAY, 0 ); } void OnPhysicalReady( CnetEvent ev, CnetTimer ts, CnetData data ) { Frame frame; int frameLength; int link; frameLength = sizeof( gBuffer ); CHECK( CNET_read_physical( &link, (unsigned char *)(&frame), &frameLength ) ); if( nodeinfo.nodenumber == 0 ) /* sender */ { } else /* receiver */ { } } void OnTimer( CnetEvent ev, CnetTimer ts, CnetData data ) { }