#include <stdio.h>
#include <stdlib.h>
#include <snorkel.h>
#define DEFAULT_NUM_THREADS 2
void
syntax (char *pszProg)
{
fprintf (stderr, "syntax error:\n");
fprintf (stderr,
"%s -i <index_file_directory> [-p <http_port>] [-P <https_port>][-l <log>] "
"[[-b <bandwidth_in_megabits> -d|r <delay_in_ms>]|[-w tcp_window_size]][-t number_of_threads]\n"
"[-L linger_time_in_seconds][-T timeout_in_seconds][-k keep_alive_connections][-K keep_alive_timeout]\n",
pszProg);
exit (1);
}
void
main (int argc, char *argv[])
{
int i = 1;
int http_port = 0;
int https_port = 0;
char *pszIndex = 0;
char *pszLog = 0;
char szExit[10];
snorkel_obj_t logobj = 0;
snorkel_obj_t http = 0;
char *pszBandwidthInMegabits = 0;
double bandwidth = 0.0;
double roundtrip = 0.0;
char *pszRoundTripMilliseconds = 0;
int sndbuffsize = 66560;
int chthreads = DEFAULT_NUM_THREADS;
int slinger = 10;
int timeout = 0;
int keep_alive = 0; /* no keep alive by default */
int keep_alive_timeout = 15;
for (; i < argc; i++)
{
if (argv[i][0] == '-' || argv[i][0] == '/')
{
char carg = argv[i][1];
switch (carg)
{
case 'K':
keep_alive_timeout = atoi (argv[i + 1]);
break;
case 'k':
keep_alive = atoi (argv[i + 1]);
i++;
break;
case 'P':
https_port = atoi (argv[i + 1]);
i++;
break;
case 'p':
http_port = atoi (argv[i + 1]);
i++;
break;
case 'L':
slinger = atoi (argv[i + 1]);
i++;
break;
case 'i':
pszIndex = argv[i + 1];
i++;
break;
case 'l':
pszLog = argv[i + 1];
i++;
break;
case 'b':
bandwidth = (atof (argv[i + 1]) * 1000000.0);
i++;
break;
case 'r':
case 'd':
roundtrip = atof (argv[i + 1]) / 1000;
i++;
break;
case 'w':
sndbuffsize = atoi (argv[i + 1]);
i++;
break;
case 't':
chthreads = atoi (argv[i + 1]);
i++;
break;
case 'T':
timeout = atoi (argv[i + 1]);
i++;
break;
case 'h':
syntax (argv[0]);
break;
default:
syntax (argv[0]);
break;
}
}
}
if (!http_port && !https_port)
http_port = 80;
if (roundtrip > 0.0 && bandwidth > 0.0)
{
sndbuffsize = (int) ((bandwidth * roundtrip) / 8.0F);
}
/* align to a page if greater */
if (sndbuffsize > 0)
{
if (sndbuffsize > 1024)
{
sndbuffsize /= 1024;
sndbuffsize = sndbuffsize * 1024;
}
printf ("send buffer size set to %d bytes\n",
sndbuffsize);
}
if (pszLog)
{
logobj = snorkel_obj_create (snorkel_obj_log, pszLog);
if (!logobj)
{
perror ("could not create log file\n");
exit (1);
}
#if defined(_DEBUG) || defined(DEBUG)
snorkel_debug (1);
#endif
}
/*
*
* always call first to initialize
* snorkel API
*
*/
if (snorkel_init () != SNORKEL_SUCCESS)
{
perror ("could not initialize snorkel\n");
exit (1);
}
/*
*
* disable thread governor
*
*/
if (chthreads > DEFAULT_NUM_THREADS)
{
snorkel_obj_t sys = snorkel_get_sys ();
snorkel_obj_set (sys, snorkel_attrib_thread_governor, chthreads);
}
/*
*
* create a server object
*
*/
http = snorkel_obj_create (snorkel_obj_server,
chthreads, pszIndex);
if (!http)
{
perror ("could not create server object!\n");
exit (1);
}
/*
*
* identify plug-in directory
*
*
*/
/* note: path to bubble directory or NULL (current directory)/bubbles */
if (snorkel_obj_set (http, snorkel_attrib_bubbles, NULL)
!= SNORKEL_SUCCESS)
{
fprintf (stderr,
"error encountered setting bubbles!\n");
exit (1);
}
snorkel_obj_set (http, snorkel_attrib_show_dir, 1); /* turn on directory display */
/*
*
* add listeners
*
*/
if (http_port) /* http port */
{
if (snorkel_obj_set (http,
snorkel_attrib_listener,
http_port, 0) != SNORKEL_SUCCESS)
{
fprintf (stderr,
"error could not add listener for port %d\n",
http_port);
exit (1);
}
}
if (https_port) /* https port */
{
/*
*
* tell server where SSL certificate is
*
*/
if (snorkel_obj_set (http,
snorkel_attrib_ssl,
"snorkel.pem") !=
SNORKEL_SUCCESS)
{
fprintf (stderr,
"error could not add listener for port %d\n",
https_port);
exit (1);
}
/*
*
* set up SSL listener
*
*/
if (snorkel_obj_set (http,
snorkel_attrib_listener,
https_port,
1) != SNORKEL_SUCCESS)
{
fprintf (stderr,
"error could not add listener for port %d\n",
https_port);
exit (1);
}
}
/*
*
* connection linger
*
*/
if (snorkel_obj_set
(http, snorkel_attrib_linger, slinger)
== SNORKEL_ERROR)
{
fprintf (stderr,
"error could not set linger value\n");
exit (1);
}
if (timeout
&& snorkel_obj_set (http, snorkel_attrib_timeout,
timeout) == SNORKEL_ERROR)
{
fprintf (stderr, "error could not set timeout\n");
exit (1);
}
if (snorkel_obj_set
(http, snorkel_attrib_ipvers, IPVERS_IPV4,
SOCK_SET) == SNORKEL_ERROR)
{
fprintf (stderr, "error could not set ip version\n");
exit (1);
}
/*
*
* set http keepalive attribute
*
*/
if (keep_alive >= 0)
{
if (snorkel_obj_set (http, snorkel_attrib_keepalive, keep_alive)
!= SNORKEL_SUCCESS)
{
fprintf (stderr,
"error encountered setting keep alive!\n");
exit (1);
}
}
if (snorkel_obj_set (http, snorkel_attrib_keepalive_timeout, keep_alive_timeout)
!= SNORKEL_SUCCESS)
{
fprintf (stderr,
"error encountered setting keep alive timeout!\n");
exit (1);
}
/*
*
* set send/receive buffer size.
* must be called after listeners added,
* only applies to existing listeners.
* can't be called after server started.
*
*/
if (sndbuffsize)
{
if (snorkel_obj_set
(http, snorkel_attrib_tcpbuffsize,
sndbuffsize) != SNORKEL_SUCCESS)
perror ("could not set send buffer size!\n");
}
fprintf (stderr,
"\n\n[HTTPS] starting embedded server...\n");
/*
*
* start server, no more editing or creation
* of objects allowed after this point
*
*/
if (snorkel_obj_start (http) != SNORKEL_SUCCESS)
{
perror ("could not start server\n");
snorkel_obj_destroy (http);
if (logobj)
snorkel_obj_destroy (logobj);
exit (1);
}
/*
*
* server is on a separate thread
* we need to do something to prevent from exiting
*
*/
#ifdef FOREGROUND
fprintf (stderr,
"\n[HTTP] started.\n\n--hit enter to terminate--\n");
fgets (szExit, sizeof (szExit), stdin);
fprintf (stderr, "[HTTP] bye\n");
/*
*
* graceful termination of server
*
*/
if (http)
snorkel_obj_destroy (http);
if (logobj)
snorkel_obj_destroy (logobj);
exit (0);
#else
while (1)
{
sleep (120);
}
#endif
}