From: Gonzalo A. <ga...@us...> - 2006-09-08 14:55:39
|
Update of /cvsroot/mod-c/ehtml/src/dss_tool In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv26225/src/dss_tool Added Files: ChangeLog Makefile.am dss_tool.cpp Log Message: session handling & testing shifted from mod_c to EHTML. --- NEW FILE: dss_tool.cpp --- #include <sys/socket.h> #include <sys/un.h> #include <stdio.h> #include <errno.h> #include <pthread.h> #include <fcntl.h> #include <unistd.h> #include <DefaultSessionProtocol.h> #include <iostream> #include <string> #include <fstream> #include <sstream> #include <ehtml/ehtml.h> using namespace std; /*** * * * * * Testing * * * */ /** * This structure is used internally by the session driver to pass * configuration data to itself. * <p>Configuration data is created by <code>InitConnection</code> which must * be the first call.</p> * */ struct DefSesDr_ConfigStruct { /** * The opened connection to the default session server. */ int Socket; }; int DefSesDr_GetSessionData( PerSessionData *Parms, request_context* req_con, void * conf ) { DefSesDr_ConfigStruct * tmp = ( DefSesDr_ConfigStruct * ) conf; // We are connected. Send the request and wait for the answer DSSGetData get_data; get_data.MsgType = DSS_CMD_GET_DATA; get_data.IdSize = Parms->IdSize; memcpy( get_data.Id, Parms->Id, get_data.IdSize ); // Send the request if ( send( tmp->Socket, &get_data, sizeof( DSSGetData ), 0 ) < 0 ) return EHTML_ERR; // Receive the answer from the server - it should be data... DSSFetcherStruct buf; if ( recv( tmp->Socket, &buf, sizeof( DSSFetcherStruct ), 0 ) < 0 || buf.MsgType != DSS_CMD_GET_DATA ) { if ( buf.MsgType == DSS_CMD_STATUS && ((DSSStatusRespond*)&buf)->Type == DSS_STATUS_SESSION_OVER ) return EHTML_TIMEOUT; else return EHTML_ERR; } // Ok, we've got the data. Read the size and put it into the 'Parms' structure DSSGetData_Response * resp = ( DSSGetData_Response * ) &buf; Parms->DataSize = resp->DataSize; Parms->Duration = resp->Duration; Parms->LastAccess = resp->LastAccess; Parms->SessionStarted = resp->SessionStarted; Parms->Modified = resp->Modified; // Ensure enough space... if ( Parms->Capacity < Parms->DataSize ) { Parms->Capacity = Parms->DataSize + 256; Parms->Data = new char[ Parms->DataSize ]; } // Two scenarios: a) one packet, or b) two packets if ( Parms->DataSize <= MAX_GET_DATA_SIZE ) memcpy( Parms->Data, resp->Data, Parms->DataSize ); else { memcpy( Parms->Data, resp->Data, MAX_GET_DATA_SIZE ); if ( recv( tmp->Socket, ((char*)Parms->Data) + MAX_GET_DATA_SIZE, Parms->DataSize - MAX_GET_DATA_SIZE, 0 ) < 0 || buf.MsgType != DSS_CMD_GET_DATA ) return EHTML_ERR; } return EHTML_OK; } int DefSesDr_SetSessionData( PerSessionData * Parms, request_context* req_con, void * conf ) { DefSesDr_ConfigStruct * tmp = ( DefSesDr_ConfigStruct * ) conf; // We are connected. Send the request and wait for the answer DSSFetcherStruct max_size; DSSSetData * set_data = (DSSSetData*)&max_size; set_data->MsgType = DSS_CMD_SET_DATA; set_data->IdSize = Parms->IdSize; set_data->DataSize = Parms->DataSize; set_data->Duration = Parms->Duration; memcpy( set_data->Id, Parms->Id, set_data->IdSize ); // We have 2 scenarios: a) either all data fits into the first packet, or b) the alternative ;) if ( set_data->DataSize <= MAX_SET_DATA_SIZE ) { memcpy( set_data->Data, Parms->Data, set_data->DataSize ); if ( send( tmp->Socket, set_data, sizeof( DSSSetData ) + set_data->DataSize, 0) < 0 ) goto error; } else { memcpy( set_data->Data, Parms->Data, MAX_SET_DATA_SIZE ); if ( send( tmp->Socket, set_data, sizeof( DSSSetData ) + MAX_SET_DATA_SIZE, 0) < 0 || send( tmp->Socket, ((char*)Parms->Data) + MAX_SET_DATA_SIZE, set_data->DataSize - MAX_SET_DATA_SIZE, 0 ) < 0 ) goto error; } // Receive the status answer... DSSStatusRespond response; if ( recv( tmp->Socket, &response, sizeof( DSSStatusRespond ), 0 ) < 0 ) goto error; else if ( response.MsgType == DSS_CMD_STATUS ) { int retVal = EHTML_OK; switch (response.Type ) { case DSS_STATUS_SESSION_OVER: retVal = EHTML_TIMEOUT; break; case DSS_STATUS_ERROR: retVal = EHTML_ERR; break; } return retVal; } error: return EHTML_ERR; } int DefSesDr_SetDuration( PerSessionData* Parms, request_context* req_con, void * conf ) { DefSesDr_ConfigStruct * tmp = ( DefSesDr_ConfigStruct * ) conf; // Send the request and wait for the answer DSSSetDuration set_dur; set_dur.MsgType = DSS_CMD_SET_DURATION; set_dur.IdSize = Parms->IdSize; set_dur.Duration = Parms->Duration; memcpy( set_dur.Id, Parms->Id, set_dur.IdSize ); // Here goes our request if( send( tmp->Socket, &set_dur, sizeof( DSSSetDuration ), 0) < 0 ) goto error; // Get the answer DSSStatusRespond response; if ( recv( tmp->Socket, &response, sizeof( DSSStatusRespond ), 0 ) > 0 && response.MsgType == DSS_CMD_STATUS ) { int retVal = EHTML_OK; switch ( response.Type ) { case DSS_STATUS_ERROR: retVal = EHTML_ERR; break; case DSS_STATUS_SESSION_OVER: retVal = EHTML_TIMEOUT; break; } return retVal; } error: return EHTML_ERR; } int DefSesDr_UnregisterID( PerSessionData* Parms, request_context* req_con, void * conf ) { DefSesDr_ConfigStruct * tmp = ( DefSesDr_ConfigStruct * ) conf; // Send the request and wait for the answer DSSUnregisterID unreg; unreg.MsgType = DSS_CMD_UNREGISTER_ID; unreg.IdSize = Parms->IdSize; memcpy( unreg.Id, Parms->Id, unreg.IdSize ); // Here goes our request if( send( tmp->Socket, &unreg, sizeof( DSSUnregisterID ), 0 ) < 0 ) goto error; // Get the answer DSSStatusRespond response; if ( recv( tmp->Socket, &response, sizeof( DSSStatusRespond ), 0 ) > 0 && response.MsgType == DSS_CMD_STATUS && response.Type == DSS_STATUS_OK ) return EHTML_OK; error: return EHTML_ERR; } int DefSesDr_RegisterID( PerSessionData* Buf, request_context* req_con, void * conf ) { DefSesDr_ConfigStruct * tmp = ( DefSesDr_ConfigStruct * ) conf; // Send the request and wait for the answer DSSRegisterID reg_id; reg_id.Duration = Buf->Duration; reg_id.IdSize = Buf->IdSize; reg_id.MsgType = DSS_CMD_REGISTER_ID; // Here goes our request if( send( tmp->Socket, ®_id, sizeof( DSSRegisterID ), 0) < 0 ) goto error; // Get the answer DSSRegisterID_Respond response; if ( recv( tmp->Socket, &response, sizeof( DSSRegisterID_Respond ), 0 ) > 0 && response.MsgType == DSS_CMD_REGISTER_ID ) { // We've got our session - copy data Buf->Id = new char[ Buf->IdSize = response.IdSize ]; memcpy( Buf->Id, response.Id, Buf->IdSize ); Buf->Duration = response.Duration; Buf->LastAccess = response.LastAccess; Buf->SessionStarted = response.SessionStarted; Buf->Modified = response.Modified; return EHTML_OK; } error: return EHTML_ERR; } int DefSesDr_InitConnection( PerSessionData* Buf, request_context* req_con, void ** Config ) { // Open a new connection to the server int sock = socket( PF_UNIX, SOCK_STREAM, 0 ); sockaddr_un addr; addr.sun_family = AF_UNIX; strncpy( addr.sun_path, UNIX_SOCKET_ADDRESS, 108 ); // Try to connect int retVal = connect( sock, ( sockaddr* ) &addr, sizeof( sockaddr_un ) ); if ( retVal >= 0 ) { // We are connected // Create a new configuration structure and store it into the Config // parameter DefSesDr_ConfigStruct * tmp = ( DefSesDr_ConfigStruct * ) new char[ sizeof( DefSesDr_ConfigStruct ) ]; tmp->Socket = sock; *Config = tmp; // Everything went OK. return EHTML_OK; } else // We couldn't establish a connection. Return an error code return EHTML_ERR; } int DefSesDr_EndConnection( PerSessionData* Buf, request_context* Req, void * Config ) { // Close the connection with the server DefSesDr_ConfigStruct * tmp = (DefSesDr_ConfigStruct *) Config; // The return value int retVal = EHTML_OK; // Post a quit message and close the connection DSSStandard rec; rec.MsgType = DSS_CMD_CLOSE; if( send( tmp->Socket, &rec, sizeof( DSSStandard ), 0) < 0 ) retVal = EHTML_ERR; // Close the connection in any event shutdown( tmp->Socket, SHUT_RDWR ); close( tmp->Socket ); return retVal; } /** * * * * * End testing * * * */ static inline unsigned short GetHexFromByte( unsigned char num ) { register char a = ( 0xf0 & num ) >> 4; register char b = 0x0f & num; if ( a < 10 ) a = ( '0' + a ); else a = ( 'a' - 10 + a ); if ( b < 10 ) b = ( '0' + b ); else b = ( 'a' - 10 + b ); return a | ( b << 8 ); } static inline unsigned char GetByteFromHex( char a, char b ) { register unsigned char retVal = 0; if ( a >= '0' && a <= '9' ) retVal |= (a - '0') << 4; else if ( a >= 'a' && a <= 'f' ) retVal |= (a - 'a' + 10) << 4; else if ( a >= 'A' && a <= 'F' ) retVal |= (a - 'A' + 10) << 4; if ( b >= '0' && b <= '9' ) retVal |= b - '0'; else if ( b >= 'a' && b <= 'f' ) retVal |= b - 'a' + 10; else if ( b >= 'A' && b <= 'F' ) retVal |= b - 'A' + 10; return retVal; } int GetStringFromByte( char * buf, int buf_len, const unsigned char * binary_array, int arr_len ) { // Sanity check if ( buf && binary_array && arr_len > 0 && buf_len >= (arr_len << 1) ) { register int i = 0; unsigned short * tmpBuf = (unsigned short*) buf; for ( ; i < arr_len; i++) tmpBuf[i] = GetHexFromByte( binary_array[i] ); if ( ( i << 1 ) < buf_len ) { buf[ i << 1 ] = 0; return i << 1 + 1; } else return buf_len; } else return -1; } int GetByteFromString( unsigned char * buf, int buf_len, const char * hex_string ) { if ( buf && hex_string ) { register int i = 0; register int j = 0; while( hex_string[i] && hex_string[i+1] && j < buf_len ) { buf[j] = GetByteFromHex( hex_string[i], hex_string[i+1] ); i+=2; j++; } return j; } else return -1; } /** * This structure is used internally by the session driver to pass * configuration data to itself. * <p>Configuration data is created by <code>InitConnection</code> which must * be the first call.</p> * */ struct ConfigStruct : public DefSesDr_ConfigStruct { }; void DisplayMenu(); void PrintStatus( ConfigStruct * Config ); void CleanSessions( ConfigStruct * Config ); int InitConnection( ConfigStruct ** Config ); int EndConnection( ConfigStruct * Config ); int main(int argc, char **argv) { cout << "This is a utility tool for the mod_c default session server." << endl << endl; cout << "You can use this tool to gather info about the session server or perform" << endl; cout << "any kind of supported operation on the session server." << endl; bool run = true; string buf; ConfigStruct * config; if ( InitConnection( &config ) ) { cout << "Could not open a connection with the default session server." << endl; cout << "Shutting down..." << endl; } else { PerSessionData psd; memset( &psd, 0, sizeof( PerSessionData ) ); psd.IdSize = 32; psd.Duration = 1; bool SessionOpened = false; while( run ) { cout << endl; DisplayMenu(); getline( cin, buf ); switch ( buf[0] ) { case 'p': PrintStatus( config ); break; case 'c': CleanSessions( config ); break; case 'q': run = false; break; // Session related stuff... case 'n': // Create a new session if ( SessionOpened ) cout << "You must close the session first." << endl; else { int retVal = DefSesDr_RegisterID( &psd, NULL, config ); if ( retVal != EHTML_OK ) cout << "An error occured while trying to create a new session: " << retVal << endl; else { SessionOpened = true; cout << "A new session was created." << endl; } } { cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } break; case 'd': // Set the duration if ( SessionOpened ) { int old_dur = psd.Duration; cout << "Enter the duration: "; cin >> psd.Duration; int retVal = DefSesDr_SetDuration( &psd, NULL, config ); switch( retVal ) { case EHTML_OK: cout << "The duration was set." << endl; break; case EHTML_TIMEOUT: cout << "The session timed out." << endl; SessionOpened = false; if ( psd.Data ) delete ((char*)psd.Data); psd.Data = 0; break; default: cout << "An error occured: " << retVal << endl; cout << "The duration was not set." << endl; psd.Duration = old_dur; break; } } else cout << "You must open a new session first." << endl; { cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } break; case 's': // Put some data if ( SessionOpened ) { // Get the string string str; cout << "Enter a string: "; getline( cin, str ); if ( !psd.Data ) { psd.Data = new char[ str.length() ]; psd.Capacity = str.length(); } else if ( psd.Capacity < (int)str.length() ) { delete ((char*)psd.Data); psd.Data = new char[ str.length() ]; psd.Capacity = str.length(); } // Copy the string memcpy( psd.Data, str.c_str(), str.length() ); psd.DataSize = str.length(); // Store it int retVal = DefSesDr_SetSessionData( &psd, NULL, config ); switch( retVal ) { case EHTML_OK: cout << "The data was stored." << endl; break; case EHTML_TIMEOUT: cout << "The session timed out." << endl; SessionOpened = false; if ( psd.Data ) delete ((char*)psd.Data); psd.Data = 0; break; default: cout << "An error occured: " << retVal << endl; cout << "The data was not stored." << endl; break; } } else cout << "You must open a new session first." << endl; { cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } break; case 'f': // Fetch data if ( SessionOpened ) { // Store it int retVal = DefSesDr_GetSessionData( &psd, NULL, config ); switch( retVal ) { case EHTML_OK: cout << "Here is the data: " << endl; cout.write( ( const char * )psd.Data, psd.DataSize ); cout << endl; break; case EHTML_TIMEOUT: cout << "The session timed out." << endl; SessionOpened = false; if ( psd.Data ) delete ((char*)psd.Data); psd.Data = 0; break; default: cout << "An error occured: " << retVal << endl; cout << "The data was not fetched." << endl; break; } } else cout << "You must open a new session first." << endl; { cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } break; case 'o': // Output data if ( SessionOpened ) { // Store it if ( psd.DataSize > 0 && psd.Data ) { cout << "Here is the data: " << endl << endl; cout.write( (char*) psd.Data, psd.DataSize ); } cout << endl; } else cout << "You must open a new session first." << endl; { cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } break; case 'e': // End the session if ( SessionOpened ) { // Store it DefSesDr_UnregisterID( &psd, NULL, config ); cout << "The session was closed." << endl; SessionOpened = false; if ( psd.Data ) delete ((char*)psd.Data); psd.Data = 0; } else cout << "You must open a new session first." << endl; { cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } break; case 'i': // Print the ID out if ( SessionOpened ) { char buf[1024]; GetStringFromByte( buf, 1024, (unsigned char*)psd.Id, psd.IdSize ); cout << "The ID: " << buf << endl; } else cout << "You must open a new session first." << endl; { cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } break; case 'w': if ( SessionOpened ) { string astr; cout << "Enter the name of the file: "; getline( cin, astr ); fstream istr; istr.open( astr.c_str(), ios_base::in ); if ( istr.good() ) { stringbuf sb; char c; while ( !istr.eof() ) { istr.get( c ); sb.sputc( c ); } string str = sb.str(); if ( !psd.Data ) { psd.Data = new char[ str.length() ]; psd.Capacity = str.length(); } else if ( psd.Capacity < (int)str.length() ) { delete ((char*)psd.Data); psd.Data = new char[ str.length() ]; psd.Capacity = str.length(); } // Copy the string memcpy( psd.Data, str.c_str(), str.length() ); psd.DataSize = str.length(); // Store it int retVal = DefSesDr_SetSessionData( &psd, NULL, config ); switch( retVal ) { case EHTML_OK: cout << "The data was stored." << endl; break; case EHTML_TIMEOUT: cout << "The session timed out." << endl; SessionOpened = false; if ( psd.Data ) delete ((char*)psd.Data); psd.Data = 0; break; default: cout << "An error occured: " << retVal << endl; cout << "The data was not stored." << endl; break; } } else cout << "Could not open the file..." << endl; } else cout << "You must open a new session first." << endl; { cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } break; case 'r': // Restore a session if ( SessionOpened ) cout << "You must close the session first." << endl; else { string str; cout << "Enter the ID (in hexadecimal): "; getline( cin, str ); if ( psd.Id ) delete ((char*)psd.Id); psd.Id = new char[ str.length() ]; int retVal = GetByteFromString( (unsigned char*)psd.Id, MAX_ID_SIZE, str.c_str() ); if ( retVal < 0 ) cout << "The ID is not correctly formatted."; else { // Store it retVal = DefSesDr_GetSessionData( &psd, NULL, config ); switch( retVal ) { case EHTML_OK: cout << "The session was restored." << endl; SessionOpened = true; break; case EHTML_TIMEOUT: cout << "The session timed out." << endl; if ( psd.Data ) delete ((char*)psd.Data); psd.Data = 0; break; default: cout << "An error occured: " << retVal << endl; cout << "The session was not restored." << endl; break; } } } { cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } break; default: break; } } if ( psd.Id ) delete [] ((char*) psd.Id); if (psd.Data) delete [] ((char*)psd.Data); EndConnection( config ); } return 0; } void DisplayMenu() { cout << "+-----------------------------------------------------------------+" << endl; cout << "| Select a desired operation: |" << endl; cout << "| |" << endl; cout << "| 'p': Print the status of the server |" << endl; cout << "| 'c': Clean outdated sessions. |" << endl; cout << "| |" << endl; cout << "| 'n': Create a new session. |" << endl; cout << "| 'r': Restore a session with a given ID. |" << endl; cout << "| |" << endl; cout << "| 'd': Set the duration of the session. |" << endl; cout << "| 's': Put some data into the session server. |" << endl; cout << "| 'f': Fetch data from the session server. |" << endl; cout << "| 'o': Output fetched data. |" << endl; cout << "| 'e': End the session. |" << endl; cout << "| |" << endl; cout << "| 'w': Put the contents of a file into the session server. |" << endl; cout << "| |" << endl; cout << "| 'i': Print out the session ID. |" << endl; cout << "| |" << endl; cout << "| 'q': Quit |" << endl; cout << "| |" << endl; cout << "+-----------------------------------------------------------------+" << endl; cout << "Your choice: "; } void PrintStatus( ConfigStruct * Config ) { // Send the request... DSSServerStatus buf; buf.MsgType = DSS_SERVER_STATUS; if ( send( Config->Socket, &buf, sizeof( DSSStandard ), 0 ) < 0 ) { cout << "Could not send data to the server. Error code: '" << errno << "'" << endl; goto error; } // Receive the answer if ( recv( Config->Socket, &buf, sizeof( DSSServerStatus ), 0 ) < 0 ) { cout << "Could not receive data from the server. Error code: '" << errno << "'" << endl; goto error; } // Do we have the correct answer? if ( buf.MsgType == DSS_SERVER_STATUS ) { cout << endl << "The server status:" << endl; cout << "Total sessions: " << buf.TotalSessions << endl; cout << "Outdated sessions: " << buf.OutdatedSessions << endl; cout << "Total stored bytes: " << buf.TotalBytes << endl; } else { cout << "The server responded with an error code." << endl; goto error; } error: cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } void CleanSessions( ConfigStruct * Config ) { // Send the request... DSSStandard buf; buf.MsgType = DSS_CLEANUP; if ( send( Config->Socket, &buf, sizeof( DSSStandard ), 0 ) < 0 ) { cout << "Could not send data to the server. Error code: '" << errno << "'" << endl; goto error; } error: cout << endl << "Press 'return' to continue... "; char tmp; cin.get( tmp ); } int InitConnection( ConfigStruct ** Config ) { // Open a new connection to the server int sock = socket( PF_UNIX, SOCK_STREAM, 0 ); sockaddr_un addr; addr.sun_family = AF_UNIX; strncpy( addr.sun_path, UNIX_SOCKET_ADDRESS, 108 ); // Try to connect int retVal = connect( sock, ( sockaddr* ) &addr, sizeof( sockaddr_un ) ); if ( retVal >= 0 ) { // We are connected // Create a new configuration structure and store it into the Config // parameter ConfigStruct * tmp = new ConfigStruct; tmp->Socket = sock; *Config = tmp; // Everything went OK. return 0; } else // We couldn't establish a connection. Return an error code return 1; } int EndConnection( ConfigStruct * Config ) { // Close the connection with the server // The return value int retVal = 0; // Post a quit message and close the connection DSSStandard rec; rec.MsgType = DSS_CMD_CLOSE; if( send( Config->Socket, &rec, sizeof( DSSStandard ), 0) < 0 ) retVal = 1; // Close the connection in any event shutdown( Config->Socket, SHUT_RDWR ); close( Config->Socket ); delete Config; return retVal; } --- NEW FILE: Makefile.am --- APR_0_INCLUDE = @APR_LOCATION@ HTTPD_INCLUDE_DIR = @APACHE_LOCATION@ EHTML_INCLUDE_DIR = @EHTML_LOCATION@ INCLUDE_DIRS = -I$(APR_0_INCLUDE) -I$(HTTPD_INCLUDE_DIR) -I$(EHTML_INCLUDE_DIR) INCLUDES = -I$(top_srcdir)/src $(INCLUDE_DIRS) METASOURCES = AUTO noinst_PROGRAMS = dss_tool dss_tool_SOURCES = dss_tool.cpp --- NEW FILE: ChangeLog --- 2006-08-23 Matej Urbas <mat...@gm...> * ChangeLog: Added ChangeLog. |