/* Jungle Monkey Search Server
* Copyright (C) 2000-2001 The Regents of the University of Michigan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/mman.h>
#ifdef JM_ENABLE_GNOME
#include <popt-gnome.h>
#else
#include <popt.h>
#endif
#include "jmintl.h"
#include "util/util.h"
#include "mtp_server.h"
#include "mtp_mirror.h"
#include "mtp_debug.h"
#define DUMP_SERVER_TIMEOUT 5 * 60 * 1000 /* 5 minutes */
static gboolean dump_server_cb (gpointer data);
static guint read_func(MtpLocalMirror* mirror,
guint offset, gchar* buffer, guint length,
gpointer user_data);
static gboolean timeout_func (gpointer p);
/* ******************** */
/* Globals */
static int verbose = 0;
static const gchar* filename = NULL;
static gboolean sha = FALSE;
static gint timeout = 30;
static MtpServer* server = NULL;
static GURL* url = NULL;
static gchar* buffer = NULL;
static gint length = 0;
static FILE* file = NULL;
static guint timer = 0;
static MtpLocalMirror* mirror = NULL;
static MtpLocalMirror* sha_mirror = NULL;
int main (int argc, char* argv[])
{
const gchar* url_str = NULL;
GMainLoop* main_loop;
GInetAddr* iface = NULL;
gchar* interface_name = NULL;
gint port = 0;
gboolean force_port = FALSE;
gboolean rendezvous = FALSE;
gboolean path = FALSE;
struct poptOption jm_options[] =
{
{"help", 'h', POPT_ARG_NONE, NULL, 1,
"Show this help message", NULL},
{"usage", '\0', POPT_ARG_NONE, NULL, 2,
"Display brief usage message", NULL},
{"version", 0, POPT_ARG_NONE, NULL, 3,
"Output verson information and exit", NULL},
{"verbose", 'v', POPT_ARG_NONE, &verbose, 0,
"Print lots of stuff", NULL},
{"interface", '\0', POPT_ARG_STRING, &interface_name, 0,
"Interface address for listening socket", "ADDR"},
{"port", '\0', POPT_ARG_INT, &port, 0,
"Port for listening socket", "PORT"},
{"force-port", '\0', POPT_ARG_NONE, &force_port, 0,
"Fail if can't set port", NULL},
{"rendezvous", '\0', POPT_ARG_NONE, &rendezvous, 0,
"Act as rendezvous server also", NULL},
{"sha", '\0', POPT_ARG_NONE, &sha, 0,
"Mirror using SHA as name too", NULL},
{"path", '\0', POPT_ARG_NONE, &path, 0,
"Use mtp_mirror_path function", NULL},
{"timeout", '\0', POPT_ARG_INT, &timeout, 0,
"Remove file from memory after TIMEOUT seconds", "TIMEOUT"},
{"debug-flags", 'd', POPT_ARG_INT, &mtp_debug_flags, 0,
"Set the MTP debug flags", "FLAGS"},
{NULL, '\0', 0, NULL, 0, NULL, NULL}
};
poptContext ctx;
int rc;
int exit_status = EXIT_SUCCESS;
/* ******************** */
/* Initialize NLS */
#ifdef ENABLE_NLS
{
/* gtk_set_locale(); */
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
}
#endif
/* ******************** */
/* Parse command line */
ctx = poptGetContext (NULL, argc, (const char**) argv, jm_options, 0);
poptSetOtherOptionHelp (ctx, _("[OPTION]... [FILENAME] [RENDEZVOUS URL]"));
while ((rc = poptGetNextOpt(ctx)) > 0)
{
switch (rc)
{
case 1: goto help; break;
case 2: goto usage; break;
case 3: goto version; break;
}
}
filename = poptGetArg (ctx);
url_str = poptGetArg (ctx);
poptFreeContext (ctx);
/* Must have filename */
if (!filename)
my_error (_("You must specify a file to mirror.\n"));
/* Must have URL */
if (!url_str)
my_error (_("You must specify a URL of a rendezvous server.\n"));
if (timeout < 10)
timeout = 10;
url = gnet_url_new (url_str);
if (!url || !url->resource)
my_error (_("Malformed rendezvous URL: %s\n"), url_str);
/* If an interface was specified, make sure it resoves to an address */
if (interface_name)
{
/* Convert interface_name to InetAddr. */
iface = gnet_inetaddr_new (interface_name, 0);
if (!iface)
my_error (_("Bad interface name: %s.\n"), interface_name);
}
/* Otherwise, auto-detect the interface */
else
{
iface = gnet_inetaddr_autodetect_internet_interface ();
if (!iface)
my_error (_("Could not auto-detect an internet interface. "
"Use the --interface option to set it manually.\n"));
}
/* ******************** */
/* Open the file */
length = file_size (filename);
if (length < 0)
my_error (_("Could not get length of file %s\n"), filename);
/* ******************** */
/* Create the server */
gnet_inetaddr_set_port (iface, port);
server = mtp_server_new (NULL, iface, force_port, MTP_SERVER_TYPE_MIRROR, TRUE);
if (!server)
my_error (_("Could not start mirror server.\n"));
if (rendezvous)
{
mtp_server_set_type (server, MTP_SERVER_TYPE_BOTH);
server->is_global = TRUE;
}
server->verbose = verbose;
if (verbose)
{
g_print (_("MTP mirror server started on port %d\n"), server->server->port);
g_timeout_add (DUMP_SERVER_TIMEOUT, dump_server_cb, NULL);
dump_server_cb (NULL);
}
if (!path)
mirror = mtp_mirror (server, url, read_func, NULL, length);
else
mirror = mtp_mirror_path (server, url, filename);
if (!mirror)
g_warning ("Could not create mirror\n");
/* ******************** */
/* Start the main loop */
main_loop = g_main_new (FALSE);
g_main_run (main_loop);
exit (EXIT_SUCCESS);
usage:
poptPrintUsage (ctx, stdout, 0);
exit (exit_status);
help:
g_print (_("`mtpmirror' - MTP Mirror Server (NOT USEFUL - FOR TESTING ONLY)\n"));
poptPrintHelp (ctx, stdout, 0);
g_print (_("\n"
"Report bugs to <jm-dev@umich.edu>\n"));
exit (exit_status);
version:
g_print (_("mtpmirror %s\n"
"Written by David A. Helder\n"
"\n"
"Copyright (C) 2000-2001 The Regents of the University of Michigan\n"
"This is free software; see the source for copying conditions. There is NO\n"
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
VERSION);
exit (exit_status);
}
/* **************************************** */
static gboolean
dump_server_cb (gpointer data)
{
time_t t;
char* time_str;
t = time(NULL);
t = mktime(gmtime(&t));
time_str = ctime(&t); /* don't free string */
time_str[strlen(time_str) - 1] = '\0';
g_print ("time: %s UTC\n", time_str);
mtp_server_print (server, stderr);
return TRUE;
}
static guint
read_func (MtpLocalMirror* mirror, guint offset, gchar* buf, guint blength,
gpointer user_data)
{
g_return_val_if_fail (mirror, 0);
g_return_val_if_fail (buf, 0);
MTPP (1, "read_func offset = %d, length = %d\n", offset, blength);
/* Load file if not loaded */
if (!file)
{
MTPP (1, "LOADING FILE\n");
/* Open file */
file = fopen (filename, "r");
if (!file)
goto error;
/* Verify length */
if (length != file_size (filename))
goto error;
buffer = mmap (NULL, length, PROT_READ, MAP_PRIVATE, fileno(file), 0);
if (buffer == NULL || ((int) buffer == -1))
goto error;
/* Get SHA if we don't have it */
if (!sha_mirror)
{
GSHA* sha;
gchar* str;
GURL* sha_url;
sha = gnet_sha_new (buffer, length);
str = gnet_sha_get_string (sha);
sha_url = gnet_url_clone (url);
gnet_url_set_resource (sha_url, str);
sha_mirror = mtp_mirror (server, sha_url, read_func, NULL, length);
if (!sha_mirror)
g_warning (_("Unable to mirror file by SHA.\n"));
gnet_sha_delete (sha);
g_free (str);
gnet_url_delete (sha_url);
}
}
if (!buffer)
goto error;
if (offset + blength > length)
goto error;
/* Reset timer */
if (timer)
g_source_remove (timer);
timer = g_timeout_add (timeout * 1000, timeout_func, NULL);
memcpy (buf, &buffer[offset], blength);
return blength;
error:
MTPP (1, "error\n");
if (file)
fclose (file);
file = NULL;
return 0;
}
static gboolean
timeout_func (gpointer p)
{
g_return_val_if_fail (buffer, FALSE);
g_return_val_if_fail (file, FALSE);
munmap (buffer, length);
buffer = NULL;
fclose (file);
file = NULL;
return FALSE;
}
syntax highlighted by Code2HTML, v. 0.9.1