// ------------------------------- // // -------- Start of File -------- // // ------------------------------- // // ----------------------------------------------------------- // // C++ Source Code File Name: server.cpp // C++ Compiler Used: MSVC, BCC32, GCC, HPUX aCC, SOLARIS CC // Produced By: DataReel Software Development Team // File Creation Date: 09/20/1999 // Date Last Modified: 06/17/2016 // Copyright (c) 2001-2024 DataReel Software Development // ----------------------------------------------------------- // // ------------- Program Description and Details ------------- // // ----------------------------------------------------------- // /* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA This is a test program for the device cache classes. */ // ----------------------------------------------------------- // #include "gxdlcode.h" #if defined (__USE_ANSI_CPP__) // Use the ANSI Standard C++ library #include <iostream> using namespace std; // Use unqualified names for Standard C++ library #else // Use the old iostream library by default #include <iostream.h> #endif // __USE_ANSI_CPP__ #include "gxsfile.h" #ifdef __MSVC_DEBUG__ #include "leaktest.h" #endif void ClearInputStream(istream &s) { char c; s.clear(); while(s.get(c) && c != '\n') { ; } } void InputString(char *mesg, MemoryBuffer &s) { cout << mesg << ": "; char buf[255]; for(int i = 0; i < 255; i++) buf[i] = 0; cin >> buf; s.Load(buf, (strlen(buf) + 1)); s[s.length()] += '\0'; // Null terminate the string } void InputInt(char *mesg, int &i) { cout << mesg << ": "; cin >> i; ClearInputStream(cin); } void Menu() { cout << "\n" << flush; cout << "(?) Display this menu" << "\n" << flush; cout << "(D) Copy a Datagram Socket to a disk file" << "\n" << flush; cout << "(F) Copy a disk file to another disk file" << "\n" << flush; cout << "(P) Copy a Serial port to a disk file" << "\n" << flush; cout << "(Q) Quit this program" << "\n" << flush; cout << "(S) Copy a Stream Socket to a disk file" << "\n" << flush; cout << "\n" << flush; } int CopyStreamSocketToFile(gxsFile *dev) // Copies data from a stream socket to the memory cache // and flushes the cache buffers to a disk file. { MemoryBuffer s; InputString("Enter the name of the output file", s); if(!dev->OpenOutputFile((char *)s)) { cout << "Could not open the " << (char *)s << " file" << "\n" << flush; return 0; } int port; InputInt("Enter the server's port number", port); gxStream server; gxsSocket_t remote_socket; FAU_t byte_count = (FAU_t)0; cout << "Initializing the GX stream server..." << "\n" << flush; if(server.StreamServer(port) != 0) { cout << server.SocketExceptionMessage() << "\n" << flush; return 1; } // Get the host name assigned to this machine char hostname[gxsMAX_NAME_LEN]; if(server.HostName(hostname) != 0) { cout << server.SocketExceptionMessage() << "\n" << flush; return 1; } cout << "Opening stream server on host " << hostname << "\n" << flush; int server_up = 1; cout << "Listening on port " << port << "\n" << flush; remote_socket = server.Accept(); if(remote_socket < 0) { cout << server.SocketExceptionMessage() << "\n" << flush; return 1; } while(server_up) { // Read the block following a client connection gxBlockHeader gx; if(server.ReadClientHeader(gx) != 0) { cout << server.SocketExceptionMessage() << "\n" << flush; return 1; } // Get the client info char client_name[gxsMAX_NAME_LEN]; int r_port = -1; server.GetClientInfo(client_name, r_port); cout << client_name << " connecting on port " << r_port << "\n" << flush; // Read the status byte to determine what to do with this block __ULWORD__ block_status = gx.block_status; __SBYTE__ status = (__SBYTE__)((block_status & 0xFF00)>>8); switch(status) { // Process each block of data case gxSendBlock : cout << "Reading " << gx.block_length << " bytes from " << client_name << " remote port " << r_port << "\n" << flush; if(!dev->CopyStreamSocketToFile(&server, gx)) { cout << "Error copying from stream to the file." << "\n" << flush; return 0; } byte_count += (__ULWORD__)gx.block_length; break; case gxKillServer: cout << "Client shutdown the server" << "\n" << flush; server.Close(); server_up = 0; break; default: cout << "Only accepting raw data blocks" << "\n" << flush; cout << "The \"" << status << "\" command was rejected" << "\n" << flush; server.CloseRemoteSocket(); break; } } cout << "Number of cache buckets in use = " << dev->BucketsInUse() << "\n" << flush; dev->Flush(); // Flush all the cache buffers before exiting dev->CloseOutputFile(); cout << "Exiting..." << "\n" << flush; return 1; } int CopyDatagramSocketToFile(gxsFile *dev) // Copies data from a stream socket to the memory cache // and flushes the cache buffers to a disk file. { MemoryBuffer s; InputString("Enter the name of the output file", s); if(!dev->OpenOutputFile((char *)s)) { cout << "Could not open the " << (char *)s << " file" << "\n" << flush; return 0; } int port; InputInt("Enter the server's port number", port); gxDatagram server; FAU_t byte_count = (FAU_t)0; cout << "Initializing the GX datagram server..." << "\n" << flush; if(server.DatagramServer(port) != 0) { cout << server.SocketExceptionMessage() << "\n" << flush; return 1; } // Get the host name assigned to this machine char hostname[gxsMAX_NAME_LEN]; if(server.HostName(hostname) != 0) { cout << server.SocketExceptionMessage() << "\n" << flush; return 1; } cout << "Opening GX datagram server on host " << hostname << "\n" << flush; // Find out what port was really assigned int assigned_port; if(server.PortNumber(assigned_port) != 0) { cout << server.SocketExceptionMessage() << "\n" << flush; return 1; } cout << "Port assigned is " << assigned_port << "\n" << flush; int server_up = 1; while(server_up) { // Read the block following a client connection gxBlockHeader gx; if(server.ReadClientHeader(gx) != 0) { cout << server.SocketExceptionMessage() << "\n" << flush; return 1; } // Get the client info char client_name[gxsMAX_NAME_LEN]; int r_port = -1; server.GetClientInfo(client_name, r_port); cout << client_name << " connecting on port " << r_port << "\n" << flush; // Read the status byte to determine what to do with this block __ULWORD__ block_status = gx.block_status; __SBYTE__ status = (__SBYTE__)((block_status & 0xFF00)>>8); switch(status) { // Process each block of data case gxSendBlock : cout << "Reading " << gx.block_length << " bytes from " << client_name << " remote port " << r_port << "\n" << flush; if(!dev->CopyDatagramSocketToFile(&server, gx)) { cout << "Error copying from stream to the file." << "\n" << flush; return 0; } byte_count += (__ULWORD__)gx.block_length; break; case gxKillServer: cout << "Client shutdown the server" << "\n" << flush; server.Close(); server_up = 0; break; default: cout << "Only accepting raw data blocks" << "\n" << flush; cout << "The \"" << status << "\" command was rejected" << "\n" << flush; break; } } cout << "Number of cache buckets in use = " << dev->BucketsInUse() << "\n" << flush; dev->Flush(); // Flush all the cache buffers before exiting dev->CloseOutputFile(); cout << "Exiting..." << "\n" << flush; return 1; } void CopyFileToFile(gxsFile *dev) { MemoryBuffer in, out; InputString("Enter the name of the input file", in); if(!dev->OpenInputFile(in)) { cout << "Cannot open the specified file!" << "\n" << flush; return; } InputString("Enter the name of the output file", out); if(!dev->OpenOutputFile(out)) { cout << "Cannot open the specified file!" << "\n" << flush; return; } FAU_t byte_count = (FAU_t)0; if(!dev->CopyFileToFile(byte_count)) { cout << "Error copying file." << "\n" << flush; return; } cout << "Number of cache buckets in use = " << dev->BucketsInUse() << "\n" << flush; cout << "Flushing the device cache..." << "\n" << flush; dev->Flush(); dev->CloseInputFile(); dev->CloseOutputFile(); cout << "Finished processing file." << "\n" << flush; cout << "Byte count = " << (long)byte_count << "\n" << flush; } void CopySerialPortToFile(gxsFile *dev) { MemoryBuffer out, port; InputString("Enter the name of the serial device", port); InputString("Enter the name of the output file", out); if(!dev->OpenOutputFile(out)) { cout << "Cannot open the specified file!" << "\n" << flush; return; } FAU_t byte_count = (FAU_t)0; gxSerialCommServer server; cout << "Initializing the GX serial port server..." << "\n" << flush; int rv = server.InitCommServer(port); if(rv != gxSerialComm::scomm_NO_ERROR) { cout << server.SerialCommExceptionMessage() << "\n" << flush; return; } cout << "Opening GX serial port server on " << (char*)port << "\n" << flush; int server_up = 1; while(server_up) { // Wait for a block header. gxBlockHeader gx; if(server.ReadHeader(gx) != 0) { cout << server.SerialCommExceptionMessage() << "\n" << flush; return; } cout << "Client connecting on " << (char *)port << "\n" << flush; // Read the status byte to determine what to do with this block __ULWORD__ block_status = gx.block_status; __SBYTE__ status = (__SBYTE__)((block_status & 0xFF00)>>8); switch(status) { // Process each block of data case gxSendBlock : cout << "Reading database block " << gx.block_length << " bytes in length" << "\n" << flush; if(!dev->CopySerialPortToFile(&server, gx)) { cout << "Error copying from serial port to the file." << "\n" << flush; return; } byte_count += (__ULWORD__)gx.block_length; break; case gxKillServer: cout << "Client shutdown the server" << "\n" << flush; server.Close(); server_up = 0; break; default: cout << "Only accepting raw data blocks" << "\n" << flush; cout << "The \"" << status << "\" command was rejected" << "\n" << flush; break; } } cout << "Number of cache buckets in use = " << dev->BucketsInUse() << "\n" << flush; cout << "Flushing the device cache..." << "\n" << flush; dev->Flush(); dev->CloseOutputFile(); cout << "Finished processing file." << "\n" << flush; cout << "Byte count = " << (long)byte_count << "\n" << flush; } void SetupServer(int server_type) { int cache_size = 1024; gxsFile dev(cache_size); // Device cache used to process a file cout << "Creating a device cache using " << cache_size << " cache buckets." << "\n" << flush; cout << "Reserving " << (sizeof(gxDeviceBucket) * cache_size) << " bytes of memory." << "\n" << flush; cout << "Number of cache buckets in use = " << dev.BucketsInUse() << "\n" << flush; cout << "\n" << flush; switch(server_type) { case gxSOCKET_STREAM_SERVER: CopyStreamSocketToFile(&dev); Menu(); break; case gxSOCKET_DATAGRAM_SERVER: CopyDatagramSocketToFile(&dev); Menu(); break; case gxSOCKET_SERIAL_PORT_SERVER: CopySerialPortToFile(&dev); Menu(); break; case gxSOCKET_LOCAL_FILE_SYSTEM: CopyFileToFile(&dev); Menu(); break; default: break; } } int main() { #ifdef __MSVC_DEBUG__ InitLeakTest(); #endif Menu(); char key; int rv = 1; while(rv) { if (!cin) { ClearInputStream(cin); if (!cin) { cout << "Input stream error" << "\n" << flush; return 0; } } cout << "\n" << flush; cout << '>'; cin >> key; if (!cin) continue; switch(key) { case 'd' : case 'D' : ClearInputStream(cin); SetupServer(gxSOCKET_DATAGRAM_SERVER); break; case 'f' : case 'F' : ClearInputStream(cin); SetupServer(gxSOCKET_LOCAL_FILE_SYSTEM); break; case 'p' : case 'P' : ClearInputStream(cin); SetupServer(gxSOCKET_SERIAL_PORT_SERVER); break; case 's' : case 'S' : ClearInputStream(cin); SetupServer(gxSOCKET_STREAM_SERVER); break; case 'q' : case 'Q' : rv = 0; break; case '?' : Menu(); break; default: cout << "Unrecognized command" << "\n" << flush; cout << "\n" << flush; } } return 0; } // ----------------------------------------------------------- // // ------------------------------- // // --------- End of File --------- // // ------------------------------- //