You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

444 lines
10 KiB

// $Id: testnet.cc,v 1.11 2003/07/21 08:16:12 angusgb Exp $
#ifdef HAVE_CONFIG_H
#include <htconfig.h>
#endif /* HAVE_CONFIG_H */
#include "Transport.h"
#include "HtHTTP.h"
#include "HtHTTPBasic.h"
#include "HtDateTime.h"
#include <URL.h>
#ifdef HAVE_STD
#include <iostream>
#include <iomanip>
#ifdef HAVE_NAMESPACES
using namespace std;
#endif
#else
#include <iostream.h>
#include <iomanip.h>
#endif /* HAVE_STD */
#include <errno.h>
#include <string.h>
// If we have this, we probably want it.
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <unistd.h>
#define DEFAULT_MAX_DOCUMENT_SIZE 40000
int debug = 0;
int timesvar = 1;
int persistent = 1;
int timeout = 10;
int head_before_get = 1;
int max_doc = DEFAULT_MAX_DOCUMENT_SIZE;
int retries = 1;
int waittime = 5;
URL *url;
Transport *transportConnect = NULL;
HtHTTP *HTTPConnect = NULL;
static void usage();
void reportError(char *msg);
Transport::DocStatus Retrieve();
int Parser(char *ct);
int main(int ac, char **av)
{
///////
// Local variables
///////
// Url to be retrieved
String URL_To_Retrieve="";
// Character for get_opt function
int c;
// Transport return Status
Transport::DocStatus _return_status;
// Variable storing the number of timed out requests
int _timed_out = 0;
// Flag variable for errors
int _errors = 0;
///////
// Retrieving options from command line with getopt
///////
while((c = getopt(ac, av, "vU:T:t:ngm:r:w:")) != -1)
{
switch (c)
{
case 'v':
debug++;
break;
case 'U':
URL_To_Retrieve=optarg;
break;
case 'T':
timesvar=atoi(optarg);
break;
case 't':
timeout=atoi(optarg);
break;
case 'r':
retries=atoi(optarg);
break;
case 'w':
waittime=atoi(optarg);
break;
case 'm':
max_doc=atoi(optarg);
break;
case 'n':
persistent = 0;
break;
case 'g':
head_before_get = 0;
HtHTTP::DisableHeadBeforeGet();
break;
case '?':
usage();
}
}
if (URL_To_Retrieve.length() == 0) usage();
if (!persistent)
head_before_get=0; // No HEAD before GET if no persistent connections
// Create the new URL
url = new URL ((char*)URL_To_Retrieve);
if (!url) reportError(strerror(errno));
if (debug>0)
{
cout << "Testing the net for " << url->get() << endl;
cout << "Host: " << url->host() << " - Port: " << url->port()
<< " - Service: " << url->service() << endl;
cout << endl;
}
Transport::SetDebugLevel(debug);
HtHTTP::SetParsingController(Parser);
int i;
HtDateTime StartTime;
for (i=0; i < timesvar; i++)
{
if (debug>0)
cout << setw(5) << i+1 << "/" << timesvar;
_return_status = Retrieve();
if (debug>0)
{
cout << " | Start time: " << transportConnect->GetStartTime()->GetISO8601();
cout << " | End time: " << transportConnect->GetEndTime()->GetISO8601()
<< " | ";
}
switch(_return_status)
{
case Transport::Document_ok:
if(debug>0) cout << "OK ("
<< transportConnect->GetResponse()->GetStatusCode() << ")";
break;
case Transport::Document_not_changed:
if(debug>0) cout << "Not changed ("
<< transportConnect->GetResponse()->GetStatusCode() << ")";
break;
case Transport::Document_not_found:
if(debug>0) cout << "Not found ("
<< transportConnect->GetResponse()->GetStatusCode() << ")";
break;
case Transport::Document_not_parsable:
if(debug>0) cout << "Not parsable ("
<< transportConnect->GetResponse()->GetContentType() << ")";
break;
case Transport::Document_redirect:
if(debug>0) cout << "Redirected ("
<< transportConnect->GetResponse()->GetStatusCode() << ")";
break;
case Transport::Document_not_authorized:
if(debug>0) cout << "Not authorized";
break;
case Transport::Document_no_connection:
if(debug>0) cout << "No Connection";
break;
case Transport::Document_connection_down:
if(debug>0) cout << "Connection down";
_timed_out++;
break;
case Transport::Document_no_header:
if(debug>0) cout << "No header";
break;
case Transport::Document_no_host:
if(debug>0) cout << "No host";
break;
case Transport::Document_no_port:
if(debug>0) cout << "No port";
break;
case Transport::Document_not_local:
if(debug>0) cout << "Not local";
break;
case Transport::Document_not_recognized_service:
if(debug>0) cout << "Service not recognized";
break;
case Transport::Document_other_error:
if(debug>0) cout << "Other error";
_errors++;
break;
}
if (debug>0)
cout << endl;
}
HtDateTime EndTime;
// Memory freeing
if (HTTPConnect)
delete HTTPConnect;
if (url) delete url;
// Show statistics
if(debug>0)
{
cout << endl;
cout << "HTTP Info" << endl;
cout << "=========" << endl;
if (persistent)
{
cout << " Persistent connections : On" << endl;
if (head_before_get)
cout << " HTTP/1.1 HEAD before GET : On" << endl;
else
cout << " HTTP/1.1 HEAD before GET : Off" << endl;
}
else
cout << " Persistent connections : Off" << endl;
cout << " Timeout value : " << timeout << endl;
cout << " Retries for timeout : " << retries << endl;
cout << " Sleep after timeout : " << waittime << endl;
cout << " Document requests : " << timesvar << endl;
HtHTTP::ShowStatistics(cout);
cout << " Timed out : " << _timed_out << endl;
cout << " Unknown errors : " << _errors << endl;
cout << " Elapsed time : approximately "
<< HtDateTime::GetDiff(EndTime, StartTime) << " secs" << endl;
}
// Return values
if (_errors) return -1;
if (_timed_out) return 1;
return 0;
}
void usage()
{
cout << "usage: testnet [-v] [-n] [-g] [-U URL] [-t times]" << endl;
cout << "Ht://Dig " << VERSION << endl << endl;
cout << "Options:" << endl;
cout << "\t-v\tVerbose mode" << endl << endl;
cout << "\t-U URL" << endl;
cout << "\t\tURL to be retrieved" << endl << endl;
cout << "\t-T times" << endl;
cout << "\t\tTimes to retrieve it" << endl << endl;
cout << "\t-t timeout" << endl;
cout << "\t\tTimeout value" << endl << endl;
cout << "\t-r retries" << endl;
cout << "\t\tNumber of retries after a timeout" << endl << endl;
cout << "\t-w wait time" << endl;
cout << "\t\tWait time value after a timeout" << endl << endl;
cout << "\t-m maxdocsize" << endl;
cout << "\t\tMax Document size to be retrieved" << endl << endl;
cout << "\t-n\tNormal connection (disable persistent)" << endl << endl;
cout << "\t-g\tOnly GET requests instead of HEAD+GET" << endl << endl;
exit(1);
}
//
// Report an error and die
//
void reportError(char *msg)
{
cout << "testnet: " << msg << "\n\n";
exit(1);
}
Transport::DocStatus Retrieve()
{
// Right now we just handle http:// service
// Soon this will include file://
// as well as an ExternalTransport system
// eventually maybe ftp:// and a few others
Transport::DocStatus status;
Transport_Response *response = 0;
HtDateTime *ptrdatetime = 0;
HtDateTime modtime;
String contents;
String contentType;
int contentLength;
transportConnect = 0;
if (mystrncasecmp(url->service(), "http", 4) == 0)
{
if (!HTTPConnect)
{
if (debug>1)
cout << "Creating an HtHTTP object" << endl;
HTTPConnect = new HtHTTPBasic();
if (!HTTPConnect)
reportError(strerror(errno));
}
if (HTTPConnect)
{
// Here we must set only thing for a HTTP request
HTTPConnect->SetRequestURL(*url);
// Let's disable the cookies for this test
HTTPConnect->DisableCookies();
// We may issue a config paramater to enable/disable them
if (!persistent) HTTPConnect->DisablePersistentConnection();
// HTTPConnect->SetRequestMethod(HtHTTP::Method_GET);
if (debug > 2)
{
cout << "Making HTTP request on " << url->get();
cout << endl;
}
}
transportConnect = HTTPConnect;
transportConnect->SetRequestMaxDocumentSize(max_doc);
transportConnect->SetTimeOut(timeout);
transportConnect->SetRetry(retries);
transportConnect->SetWaitTime(waittime);
}
else
{
if (debug)
{
cout << '"' << url->service() <<
"\" not a recognized transport service. Ignoring\n";
}
}
// Is a transport object pointer available?
if (transportConnect)
{
transportConnect->SetConnection(url);
// Make the request
// Here is the main operation ... Let's make the request !!!
status = transportConnect->Request();
// Let's get out the info we need
response = transportConnect->GetResponse();
if (response)
{
// We got the response
contents = response->GetContents();
contentType = response->GetContentType();
contentLength = response->GetContentLength();
ptrdatetime = response->GetModificationTime();
if (ptrdatetime)
{
// We got the modification date/time
modtime = *ptrdatetime;
}
// How to manage it when there's no modification date/time?
if (debug > 5)
{
cout << "Contents:\n" << contents << endl;
cout << "Content Type: " << contentType << endl;
cout << "Content Lenght: " << contentLength << endl;
cout << "Modification Time: " << modtime.GetISO8601() << endl;
}
}
return status;
}
else
return Transport::Document_not_found;
}
int Parser(char *)
{
return false;
}