// brainy.cpp - BRAINDEAD FILE SERVER // // MODULE INDEX // NAME CONTENTS // RELAY::RELAY Relay process constructor // RELAY::~RELAY Relay process destructor // RELAY::RelayInit Relay process initiation // RELAY::RequestReady Process request ready // RELAY::PutDone Process put done // FindRelayInst Find relay process instance // RequestReady Request ready function for braindead // PutDone Put done function for braindead // main Main line // // MAINTENANCE HISTORY // DATE PROGRAMMER AND DETAILS // 16-05-02 JS Original // //----------------------------------------------------------------------------- #include // Standard input/output #include // String manipulation functions #include // Standard library declarations #include // System error codes #include "braindead.h" // Braindead declarations //----------------------------------------------------------------------------- // DEFINITIONS #define FILEBUFLEN 1024 // File buffer length #define FILENAMELEN 256 // File name length //----------------------------------------------------------------------------- // RELAY PROCESS STATES enum RELAYSTATE { RELAYIDLE, // Idle RELAYCONNECTING, // Waiting for a connection RELAYPUTTING // Waiting for a PutData to complete }; //----------------------------------------------------------------------------- // RELAY PROCESS CLASS class RELAY { RELAYSTATE relayState; // Current state int relayChanId; // Channel identifier char relayFileName[FILENAMELEN+1]; // File name FILE *relayFp; // File pointer char relayBuf[FILEBUFLEN]; // File data buffer int relayLen; // File data length public: RELAY (); // Constructor ~RELAY (); // Destructor void RelayInit (); // Initiation void RequestReady (const char *fileName); // Request ready void PutDone (); // Transmission completed int RelayActive () { return relayState != RELAYIDLE; } // Test if channel is active int RelayChanId () { return relayChanId; } // Return channel identifier }; //----------------------------------------------------------------------------- // GLOBAL DATA RELAY relayArr[MAXCHAN]; // Relay process array //----------------------------------------------------------------------------- // RELAY PROCESS CONSTRUCTOR RELAY::RELAY () { relayState = RELAYIDLE; } //----------------------------------------------------------------------------- // RELAY PROCESS DESTRUCTOR RELAY::~RELAY () { if (relayState == RELAYPUTTING) fclose (relayFp); relayState = RELAYIDLE; } //----------------------------------------------------------------------------- // RELAY PROCESS INITIATION void RELAY::RelayInit () { if (relayState != RELAYIDLE) { fprintf (stderr, "RelayInit: bad state\n"); abort (); } // Request a connection from Braindead relayState = RELAYCONNECTING; relayChanId = GetRequest (); } //----------------------------------------------------------------------------- // PROCESS REQUEST READY void RELAY::RequestReady ( const char *fileName) { // Validate state and arguments if (relayState != RELAYCONNECTING) { fprintf (stderr, "RequestReady: bad state\n"); abort (); } if (strlen(fileName) > FILENAMELEN) { fprintf (stderr, "RequestReady: file name too long\n"); abort (); } // Log transmission of the requested data strcpy (relayFileName, fileName); printf ("brainy: sending %s\n", relayFileName); // Open the requested file name and load the look-ahead character if ((relayFp = fopen (fileName, "r")) == NULL) { fprintf (stderr, "brainy: open %s: %s\n", fileName, strerror (errno)); abort (); } // Send the first buffer relayState = RELAYPUTTING; PutDone (); } //----------------------------------------------------------------------------- // PROCESS PUT DONE void RELAY::PutDone () { // Validate state if (relayState != RELAYPUTTING) { fprintf (stderr, "PutDone: bad state\n"); abort (); } // Load the next buffer relayLen = fread (relayBuf, 1, FILEBUFLEN, relayFp); if (relayLen < 0) { fprintf (stderr, "brainy: read %s: %s\n", relayFileName, strerror (errno)); abort (); } // If data was read, return the data to Braindead if (relayLen != 0) { relayState = RELAYPUTTING; PutData (relayChanId, relayBuf, relayLen); } // If there is no more data to be read, flag the request // as completed and get another request else { fclose (relayFp); RequestDone (relayChanId); printf ("brainy: finished %s\n", relayFileName); relayState = RELAYCONNECTING; relayChanId = GetRequest (); } } //----------------------------------------------------------------------------- // FIND RELAY PROCESS INSTANCE RELAY * FindRelayInst ( int chanId) // Channel identifier { int i; // General purpose index for ( i = 0; i < MAXCHAN && ( ! relayArr[i].RelayActive() || relayArr[i].RelayChanId() != chanId ); i ++ ); if (i >= MAXCHAN) { fprintf (stderr, "brainy: unrecognised channel id %d\n", chanId); abort (); } return relayArr + i; } //----------------------------------------------------------------------------- // REQUEST READY FUNCTION FOR BRAINDEAD void RequestReady ( int chanId, // Channel identifier const char *fileName) // File name { FindRelayInst(chanId) -> RequestReady (fileName); } //----------------------------------------------------------------------------- // PUT DONE FUNCTION FOR BRAINDEAD void PutDone ( int chanId) // Channel identifier { FindRelayInst(chanId) -> PutDone (); } //----------------------------------------------------------------------------- // MAIN LINE int main () { int i; // General purpose index // Initiate the relay processes for (i = 0; i < MAXCHAN; i++) relayArr[i].RelayInit (); // Yield until we get tired of it for (i = 0; i < 20000; i++) Yield (); // Exit gracefully return 0; }