[netperf-dev] netperf4 commit notice r82 -
branches/glib_migration/src
raj at netperf.org
raj at netperf.org
Thu Mar 16 15:53:05 PST 2006
Author: raj
Date: 2006-03-16 15:53:04 -0800 (Thu, 16 Mar 2006)
New Revision: 82
Modified:
branches/glib_migration/src/netperf.h
branches/glib_migration/src/netserver.c
Log:
Start migrating the netserver to use the glib process spawning and
eventloop constructs.
Modified: branches/glib_migration/src/netperf.h
===================================================================
--- branches/glib_migration/src/netperf.h 2006-03-16 21:16:57 UTC (rev 81)
+++ branches/glib_migration/src/netperf.h 2006-03-16 23:53:04 UTC (rev 82)
@@ -118,6 +118,7 @@
#define NETPERF_DEBUG_LOG_SUFFIX ".log"
#define netperf_socklen_t socklen_t
#define close(x) closesocket(x)
+#define CLOSE_SOCKET(x) closesocket(x)
#define strcasecmp(a,b) _stricmp(a,b)
#define getpid() ((int)GetCurrentProcessId())
#else
@@ -127,6 +128,7 @@
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define SOCKET int
+#define CLOSE_SOCKET(x) close(x)
#endif
#include "netconfidence.h"
@@ -135,7 +137,7 @@
#define NETPERF_DTD_FILE (const xmlChar *)"http://www.netperf.org/netperf_docs.dtd/1.0"
#define NETPERF_VERSION (const xmlChar *)"4"
#define NETPERF_UPDATE (const xmlChar *)"0"
-#define NETPERF_FIX (const xmlChar *)"999"
+#define NETPERF_FIX (const xmlChar *)"997"
#define NETPERF_DEBUG_ENTRY(d,w) \
if (d) { \
Modified: branches/glib_migration/src/netserver.c
===================================================================
--- branches/glib_migration/src/netserver.c 2006-03-16 21:16:57 UTC (rev 81)
+++ branches/glib_migration/src/netserver.c 2006-03-16 23:53:04 UTC (rev 82)
@@ -1,5 +1,5 @@
char netserver_id[]="\
-@(#)netserver.c (c) Copyright 2005, Hewlett-Packard Company, $Id$";
+@(#)netserver.c (c) Copyright 2006, Hewlett-Packard Company, $Id$";
/*
This file is part of netperf4.
@@ -29,10 +29,6 @@
but you are not obligated to do so. If you do not wish to do so,
delete this exception statement from your version.
-#include <termios.h>
-#include <grp.h>
-#include <pwd.h>
-
*/
#ifdef HAVE_CONFIG_H
@@ -40,13 +36,9 @@
#endif
#ifdef WITH_GLIB
-# ifdef HAVE_GLIB_H
-# include <glib.h>
-# endif
+# include <glib.h>
#else
-# ifdef HAVE_PTHREAD_H
-# include <pthread.h>
-# endif
+# error sorry, this netserver requires glib
#endif
#ifdef HAVE_STDIO_H
@@ -140,38 +132,328 @@
int want_quiet; /* --quiet, --silent */
int want_brief; /* --brief */
int want_verbose; /* --verbose */
+gboolean spawn_on_accept = TRUE;
+gboolean want_daemonize = TRUE;
+gboolean exit_on_control_eof = TRUE;
+gboolean stdin_is_socket = FALSE;
+int control_socket = -1;
+
+GIOChannel *control_channel;
+
int forground = 0;
char *listen_port = NETPERF_DEFAULT_SERVICE_NAME; /* --port */
-uint16_t listen_port_num = 0; /* --port */
+guint16 listen_port_num = 0; /* --port */
char *local_host_name = NULL;
int local_address_family = AF_UNSPEC;
-int need_setup = 0;
+gboolean need_setup = FALSE;
+int orig_argc;
+gchar **orig_argv;
+
char local_host_name_buf[BUFSIZ];
char local_addr_fam_buf[BUFSIZ];
-/* getopt_long return codes */
-enum {DUMMY_CODE=129
- ,BRIEF_CODE
-};
+
-static struct option const long_options[] =
-{
- {"output", required_argument, 0, 'o'},
- {"input", required_argument, 0, 'i'},
- {"config", required_argument, 0, 'c'},
- {"debug", no_argument, 0, 'd'},
- {"forground", no_argument, 0, 'f'},
- {"quiet", no_argument, 0, 'q'},
- {"local", required_argument, 0, 'L'},
- {"silent", no_argument, 0, 'q'},
- {"brief", no_argument, 0, BRIEF_CODE},
- {"verbose", no_argument, 0, 'v'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {NULL, 0, NULL, 0}
-};
+gboolean set_port_number(gchar *option_name, gchar *option_value, gpointer data, GError **error) {
+ listen_port = g_strdup(option_value);
+ listen_port_num = atoi(listen_port);
+
+ return(TRUE);
+
+}
+gboolean set_local_address(gchar *option_name, gchar *option_value, gpointer data, GError **error) {
+
+ break_args_explicit(option_value,local_host_name_buf,local_addr_fam_buf);
+ if (local_host_name_buf[0]) {
+ local_host_name = &local_host_name_buf[0];
+ }
+ if (local_addr_fam_buf[0]) {
+ local_address_family = parse_address_family(local_addr_fam_buf);
+ /* if only the address family was set, we may need to set the
+ local_host_name accordingly. since our defaults are IPv4 this
+ should only be necessary if we have IPv6 support raj
+ 2005-02-07 */
+#if defined (AF_INET6)
+ if (!local_host_name_buf[0]) {
+ strncpy(local_host_name_buf,"::0",sizeof(local_host_name_buf));
+ local_host_name = &local_host_name_buf[0];
+ }
+#endif
+ }
+
+ return(TRUE);
+}
+
+gboolean set_output_destination(gchar *option_name, gchar *option_value, gpointer data, GError **error) {
+ oname = g_strdup(option_value);
+ ofile = fopen(oname, "w");
+ if (!ofile) {
+ g_fprintf(stderr,
+ "%s: cannot open %s for writing\n",
+ program_name,
+ option_value);
+ exit(1);
+ }
+ return(TRUE);
+}
+
+gboolean do_closesocket(gchar *option_name, gchar *option_value, gpointer data, GError **error) {
+ SOCKET toclose;
+
+ toclose = atoi(option_value);
+ g_fprintf(where,"was asked to close socket %d\n",toclose);
+#ifdef G_OS_WIN32
+ closesocket(toclose);
+#else
+ close(toclose);
+#endif
+ return(TRUE);
+}
+
+
+gboolean set_debug(gchar *option_name, gchar *option_value, gpointer data, GError **error) {
+ if (option_value) {
+ /* set to value */
+ debug = atoi(option_value);
+ }
+ else {
+ /* simple increment */
+ debug++;
+ }
+ return(TRUE);
+}
+
+
+
+gboolean set_verbose(gchar *option_name, gchar *option_value, gpointer data, GError **error) {
+ if (option_value) {
+ /* set to value */
+ want_verbose = atoi(option_value);
+ }
+ else {
+ /* simple increment */
+ want_verbose++;
+ }
+ return(TRUE);
+}
+
+
+gboolean show_version(gchar *option_name, gchar *option_value, gpointer data, GError **error) {
+ g_printf("netserver: %s.%s.%s\n",
+ NETPERF_VERSION,
+ NETPERF_UPDATE,
+ NETPERF_FIX);
+ exit(0);
+}
+
+gboolean
+spawn_new_netserver(int argc, char *argv[], SOCKET control, SOCKET toclose) {
+
+ int new_argc;
+ int i,j;
+ gboolean ret;
+ gboolean need_nodaemonize = TRUE;
+ gboolean need_nospawn = TRUE;
+ gchar **new_argv;
+ gchar control_string[10]; /* that should be more than enough
+ characters I hope */
+ GPid new_pid;
+ GError *error=NULL;
+
+ /* while we will _probably_ be stripping things from the argument
+ vector, we want to make sure we have enough to add the control FD
+ specification and the --nospawn. */
+
+ new_argv = g_new(gchar *,argc+6);
+
+ for (i = 0, j = 0, new_argc = 0; i < argc; i++) {
+ /* this actually isn't correct for the future, but for now it will
+ suffice to test passing the control FD to the new process */
+ if (strcmp(argv[i],"--daemonize") == 0) {
+ if (need_nodaemonize) {
+ /* replace it with "--nodaemonize" in the new argument vector */
+ new_argv[j++] = g_strdup("--nodaemonize");
+ new_argc++;
+ need_nodaemonize = FALSE;
+ }
+ continue;
+ }
+ if (strcmp(argv[i],"--nodaemonize") == 0) {
+ if (need_nodaemonize) {
+ need_nodaemonize = FALSE;
+ }
+ else {
+ /* we already have one, so skip it */
+ continue;
+ }
+ }
+ if (strcmp(argv[i],"--nospawn") == 0) {
+ if (need_nospawn) {
+ need_nospawn = FALSE;
+ }
+ else {
+ /* skip it */
+ continue;
+ }
+ }
+ if (strcmp(argv[i],"--spawn") == 0) {
+ if (need_nospawn) {
+ /* replace it with --nospawn */
+ new_argv[j++] = g_strdup("--nospawn");
+ new_argc++;
+ need_nospawn = FALSE;
+ }
+ continue;
+ }
+ /* it is exceedingly unlikely that some of these options will be
+ in the original argument vector, but just in case */
+ if ((strcmp(argv[i],"--control") == 0) ||
+ (strcmp(argv[i],"--port") == 0) ||
+ (strcmp(argv[i],"-p") == 0) ||
+ (strcmp(argv[i],"-L") == 0) ||
+ (strcmp(argv[i],"--local") == 0)) {
+ /* we want to skip the option AND its argument */
+ i++;
+ continue;
+ }
+ /* otherwise, we just copy old to new */
+ new_argc++;
+ new_argv[j++] = g_strdup(argv[i]);
+
+ }
+ if (need_nospawn) {
+ new_argv[j++] = g_strdup("--nospawn"); /* don't recurse :) */
+ new_argc++;
+ }
+ if (need_nodaemonize) {
+ new_argv[j++] = g_strdup("--nodaemonize"); /* don't recurse */
+ new_argc++;
+ }
+ new_argv[j++] = g_strdup("--control");
+ g_snprintf(control_string,sizeof(control_string),"%d",control);
+ new_argv[j++] = g_strdup(control_string);
+ new_argc += 2;
+ new_argv[j++] = g_strdup("--closesocket");
+ g_snprintf(control_string,sizeof(control_string),"%d",toclose);
+ new_argv[j++] = g_strdup(control_string);
+ new_argc += 2;
+ new_argv[j] = NULL;
+
+ if (debug) {
+ g_fprintf(where,"spawning with new_argc of %d and:\n",new_argc);
+ for (i = 0; i < new_argc; i++) {
+ g_fprintf(where,"\targv[%d] %s\n",i,new_argv[i]);
+ }
+ }
+
+ ret = g_spawn_async_with_pipes(NULL, /* working dir */
+ new_argv, /* argument vector */
+ NULL, /* env ptr */
+ G_SPAWN_LEAVE_DESCRIPTORS_OPEN, /* flags */
+ NULL, /* setup func */
+ NULL, /* its arg */
+ &new_pid, /* new process' id */
+ NULL, /* dont watch stdin */
+ NULL, /* ditto stdout */
+ NULL, /* ditto stderr */
+ &error);
+ if (error) {
+ g_warning("%s g_io_spawn_async_with_pipes %s %d %s\n",
+ __func__,
+ g_quark_to_string(error->domain),
+ error->code,
+ error->message);
+ g_clear_error(&error);
+ }
+ return(TRUE);
+}
+
+/* make a call to g_spawn_async_with_pipes to let us disconnect, at
+ least after a fashion, from the controlling terminal. we will
+ though remove the daemonze option from the argument vector used to
+ start the new process */
+
+gboolean
+daemonize(int argc, char *argv[]) {
+
+ int new_argc;
+ int i,j;
+ gboolean ret;
+ gboolean need_nodaemonize = TRUE;
+ char **new_argv;
+ GPid new_pid;
+ GError *error=NULL;
+
+ /* make sure we have room for the --nodeamonize option we will be adding */
+ new_argv = g_new(gchar *,argc+1);
+
+ /* it is slightly kludgy, but simply taking a --nodeamonize to the
+ end of the argument vector should suffice. as things get more
+ sophisticated, we may want to strip certain options from the
+ vector. raj 2006-03-14 */
+
+ for (i = 0, j = 0, new_argc = 0; i < argc; i++) {
+ if (strcmp(argv[i], "--daemonize") == 0) {
+ if (need_nodaemonize) {
+ /* replace with --nodaemonize" */
+ new_argv[j++] = g_strdup("--nodaemonize");
+ new_argc++;
+ need_nodaemonize = FALSE;
+ }
+ continue;
+ }
+ /* I seriously doubt we'd ever hit this but still */
+ if (strcmp(argv[i],"--nodaemonize") == 0) {
+ if (need_nodaemonize) {
+ need_nodaemonize = FALSE;
+ }
+ else {
+ /* skip it */
+ continue;
+ }
+ }
+
+ /* otherwise, we just copy old to new */
+ new_argc++;
+ new_argv[j++] = g_strdup(argv[i]);
+ }
+ if (need_nodaemonize) {
+ new_argv[j++] = g_strdup("--nodaemonize");
+ new_argc++;
+ }
+ new_argv[j] = NULL;
+
+ if (debug) {
+ g_fprintf(where,"daemonizing with new_argc of %d and:\n",new_argc);
+ for (i = 0; i < new_argc; i++) {
+ g_fprintf(where,"\targv[%d] %s\n",i,new_argv[i]);
+ }
+ }
+
+ ret = g_spawn_async_with_pipes(NULL, /* working dir */
+ new_argv, /* argument vector */
+ NULL, /* env ptr */
+ G_SPAWN_LEAVE_DESCRIPTORS_OPEN, /* flags */
+ NULL, /* setup func */
+ NULL, /* its arg */
+ &new_pid, /* new process' id */
+ NULL, /* dont watch stdin */
+ NULL, /* ditto stdout */
+ NULL, /* ditto stderr */
+ &error);
+ if (error) {
+ g_warning("%s g_io_spawn_async_with_pipes %s %d %s\n",
+ __func__,
+ g_quark_to_string(error->domain),
+ error->code,
+ error->message);
+ g_clear_error(&error);
+ }
+ exit(0);
+}
+
static void
usage (int status)
{
@@ -192,100 +474,8 @@
exit (status);
}
-/* Set all the option flags according to the switches specified.
- Return the index of the first non-option argument. */
-static int
-decode_command_line (int argc, char **argv)
-{
- int c;
- while ((c = getopt_long (argc, argv,
- "d" /* debug */
- "f" /* forground */
- "L:" /* local control sock address info */
- "o:" /* output */
- "p:" /* port */
- "q" /* quiet or silent */
- "v" /* verbose */
- "h" /* help */
- "V", /* version */
- long_options, (int *) 0)) != EOF)
- {
- switch (c)
- {
- case 'd': /* --debug */
- debug++;
- break;
- case 'f': /* --forground */
- forground++; /* 1 means no deamon, 2 means no fork after accept */
- need_setup = 1;
- break;
- case 'L':
- break_args_explicit(optarg,local_host_name_buf,local_addr_fam_buf);
- if (local_host_name_buf[0]) {
- local_host_name = &local_host_name_buf[0];
- }
- if (local_addr_fam_buf[0]) {
- local_address_family = parse_address_family(local_addr_fam_buf);
- /* if only the address family was set, we may need to set the
- local_host_name accordingly. since our defaults are IPv4
- this should only be necessary if we have IPv6 support raj
- 2005-02-07 */
-#if defined (AF_INET6)
- if (!local_host_name_buf[0]) {
- strncpy(local_host_name_buf,"::0",sizeof(local_host_name_buf));
- local_host_name = &local_host_name_buf[0];
- }
-#endif
- }
- need_setup = 1;
- break;
- case 'o': /* --output */
- oname = strdup(optarg);
- ofile = fopen(oname, "w");
- if (!ofile) {
- fprintf(stderr,
- "%s: cannot open %s for writing\n",
- program_name,
- optarg);
- exit(1);
- }
- break;
- case 'p':
- /* we want to open a listen socket at a */
- /* specified port number */
- listen_port = strdup(optarg);
- listen_port_num = atoi(listen_port);
- need_setup = 1;
- break;
- case 'q': /* --quiet, --silent */
- want_quiet = 1;
- break;
- case BRIEF_CODE: /* --brief */
- want_brief = 1;
- break;
- case 'v': /* --verbose */
- want_verbose = 1;
- break;
- case 'V':
- printf ("netserver %s.%s.%s\n",
- NETPERF_VERSION,
- NETPERF_UPDATE,
- NETPERF_FIX);
- exit (0);
- case 'h':
- usage (0);
- default:
- usage (EXIT_FAILURE);
- }
- }
-
- return optind;
-}
-
-
-
int
add_netperf_to_hash(server_t *new_netperf) {
@@ -385,19 +575,19 @@
rc = recv_control_message(sock,&message);
if (rc > 0) { /* received a message */
if (debug) {
- fprintf(where, "Received a control message to doc %p\n", message);
+ g_fprintf(where, "Received a control message to doc %p\n", message);
fflush(where);
}
msg = xmlDocGetRootElement(message);
if (msg == NULL) {
- fprintf(stderr,"empty document\n");
+ g_fprintf(stderr,"empty document\n");
xmlFreeDoc(message);
rc = NPE_EMPTY_MSG;
} else {
cur = msg->xmlChildrenNode;
if (xmlStrcmp(cur->name,(const xmlChar *)"version")!=0) {
if (debug) {
- fprintf(where,
+ g_fprintf(where,
"%s: Received an unexpected message\n", __func__);
fflush(where);
}
@@ -408,7 +598,7 @@
from_nid = xmlStrdup(xmlGetProp(msg,(const xmlChar *)"fromnid"));
if ((netperf = (server_t *)malloc(sizeof(server_t))) == NULL) {
- fprintf(where,"%s: malloc failed\n", __func__);
+ g_fprintf(where,"%s: malloc failed\n", __func__);
fflush(where);
exit(1);
}
@@ -431,7 +621,7 @@
}
else {
if (debug) {
- fprintf(where,"%s: close connection remote close\n", __func__);
+ g_fprintf(where,"%s: close connection remote close\n", __func__);
fflush(where);
}
close(sock);
@@ -447,65 +637,7 @@
return(rc);
}
-/* daemonize will fork a daemon into the background, freeing-up the
- shell prompt for other uses. I suspect that for non-Unix OSes,
- something other than fork() may be required? raj 2/98 */
-void
-daemonize()
-{
- char filename[PATH_MAX];
- /* fork off - only the client will return, the parent will exit */
-
- switch (fork()) {
- case -1:
- /* something went wrong */
- perror("netserver fork error");
- exit(-1);
- case 0:
- /* we are the child process. set ourselves up as the session
- leader so we detatch from the parent, and then return to the
- caller so he can do whatever it is he wants to do */
-
- fclose(stdin);
-
- snprintf(filename,
- PATH_MAX,
- "%s%s%d%s",
- NETPERF_DEBUG_LOG_DIR,
- NETPERF_DEBUG_LOG_PREFIX,
- getpid(),
- NETPERF_DEBUG_LOG_SUFFIX);
- where = freopen(filename,"w",where);
- if (NULL == where) {
- fprintf(stderr,
- "ERROR netserver could not freopen where to %s errno %d\n",
- filename,
- errno);
- fflush(stderr);
- exit(-1);
- }
-
- /* at this point should I close stderr?!? */
- setsid();
-
- /* not all OSes have SIGCLD as SIGCHLD */
-#ifndef SIGCLD
-#define SIGCLD SIGCHLD
-#endif /* SIGCLD */
-
- signal(SIGCLD, SIG_IGN);
-
- break;
- default:
- /* we are the parent process - the one invoked from the
- shell. since the first child will detach itself, we can just go
- ahead and slowly fade away */
- exit(0);
- }
-}
-
-
static void
report_stuck_test_status(server_t *netperf)
{
@@ -566,7 +698,7 @@
if (orig != new) {
/* report change in test state */
if (debug) {
- fprintf(where,"%s:tid = %s state %d new_state %d\n",
+ g_fprintf(where,"%s:tid = %s state %d new_state %d\n",
__func__, test->id, orig, new);
fflush(where);
}
@@ -613,7 +745,7 @@
rc = send_control_message(netperf->sock, msg, netperf->id, my_nid);
if (rc != NPE_SUCCESS) {
if (debug) {
- fprintf(where,
+ g_fprintf(where,
"%s: send_control_message failed\n", __func__);
fflush(where);
}
@@ -693,7 +825,7 @@
rc = send_control_message(netperf->sock, msg, netperf->id, my_nid);
if (rc != NPE_SUCCESS) {
if (debug) {
- fprintf(where,
+ g_fprintf(where,
"%s: send_control_message failed\n", __func__);
fflush(where);
}
@@ -702,8 +834,8 @@
delete_netperf(netperf->id);
} else {
/* we should never really get here sgb 2005-12-06 */
- fprintf(where, "%s entered through some unknown path!!!!\n", __func__);
- fprintf(where, "netperf->state_req = %d \t netperf->err_rc = %d\n",
+ g_fprintf(where, "%s entered through some unknown path!!!!\n", __func__);
+ g_fprintf(where, "netperf->state_req = %d \t netperf->err_rc = %d\n",
netperf->state_req, netperf->err_rc);
fflush(where);
exit(-2);
@@ -724,7 +856,7 @@
rc = instantiate_netperf(sock);
if (rc != NPE_SUCCESS) {
- fprintf(where,
+ g_fprintf(where,
"%s %s: instantiate_netperf error %d\n",
program_name,
__func__,
@@ -754,7 +886,7 @@
if (rc > 0) {
rc = process_message(netperf, message);
if (rc) {
- fprintf(where,"process_message returned %d %s\n",
+ g_fprintf(where,"process_message returned %d %s\n",
rc, netperf_error_name(rc));
fflush(where);
}
@@ -764,7 +896,7 @@
if (rc == 0) {
netperf->err_rc = NPE_REMOTE_CLOSE;
} else {
- fprintf(where,"recv_control_message returned %d %s\n",
+ g_fprintf(where,"recv_control_message returned %d %s\n",
rc, netperf_error_name(rc));
fflush(where);
netperf->err_rc = rc;
@@ -772,7 +904,7 @@
}
} else {
if (debug) {
- fprintf(where,"ho hum, nothing to do\n");
+ g_fprintf(where,"ho hum, nothing to do\n");
fflush(where);
report_servers_test_status(netperf);
}
@@ -800,16 +932,68 @@
}
+/* called when it is time to accept a new control connection off the
+ listen endpoint */
+gboolean accept_connection(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data) {
+ SOCKET control_socket;
+ SOCKET listen_socket;
+ gboolean ret;
-static void
+ g_fprintf(where,"accepting a new connection\n");
+
+#ifdef G_OS_WIN32
+ listen_socket = g_io_channel_win32_get_fd(source);
+#else
+ listen_socket = g_io_channel_unix_get_fd(source);
+#endif
+
+ control_socket = accept(listen_socket,NULL,0);
+ if (control_socket == SOCKET_ERROR) {
+ g_fprintf(where,
+ "%s: accept failed errno %d %s\n",
+ __func__,
+ errno,
+ strerror(errno));
+ fflush(where);
+ exit(-1);
+ }
+ if (debug) {
+ g_fprintf(where,
+ "%s: accepted connection on sock %d\n",
+ __func__,
+ control_socket);
+ fflush(where);
+ }
+
+ if (spawn_on_accept) {
+ ret = spawn_new_netserver(orig_argc,orig_argv,
+ control_socket,listen_socket);
+ CLOSE_SOCKET(control_socket); /* don't want to leak descriptors */
+ }
+ else {
+ /* for now, we will simply start processing requests the
+ "original" way. later we will establish a recv callback for a
+ proper glib event loop */
+ g_fprintf(where,"accepted a connection but told not to spawn\n");
+ handle_netperf_requests(control_socket);
+ CLOSE_SOCKET(control_socket);
+ }
+
+ return(TRUE);
+}
+
+
+static SOCKET
setup_listen_endpoint(char service[]) {
struct sockaddr name;
struct sockaddr *peeraddr = &name;
int namelen = sizeof(name);
netperf_socklen_t peerlen = namelen;
- int sock;
- int listenfd = 0;
+ SOCKET sock;
+ SOCKET listenfd = 0;
int loop = 1;
char filename[PATH_MAX];
@@ -830,17 +1014,21 @@
&peerlen);
if (listenfd == -1) {
- fprintf(where,"%s: failed to open listen socket\n", __func__);
+ g_fprintf(where,"%s: failed to open listen socket\n", __func__);
fflush(where);
exit(1);
}
-
+ return(listenfd);
+ }
+ return(-1);
+}
+#ifdef notdef
if (peerlen > namelen) {
peeraddr = (struct sockaddr *)malloc (peerlen);
}
if (!forground) {
- daemonize();
+ daemonize(orig_argc, orig_argv);
}
/* loopdeloop */
@@ -848,7 +1036,7 @@
while (loop) {
printf("about to accept on socket %d\n",listenfd);
if ((sock = accept(listenfd,peeraddr,&peerlen)) == -1) {
- fprintf(where,
+ g_fprintf(where,
"%s: accept failed errno %d %s\n",
__func__,
errno,
@@ -857,7 +1045,7 @@
exit(1);
}
if (debug) {
- fprintf(where,
+ g_fprintf(where,
"%s: accepted connection on sock %d\n",
__func__,
sock);
@@ -903,7 +1091,7 @@
where = freopen(filename,"w",where);
if (NULL == where) {
- fprintf(stderr,
+ g_fprintf(stderr,
"ERROR netserver could not freopen where to %s errno %d\n",
filename,
errno);
@@ -925,8 +1113,8 @@
}
}
}
+#endif
-
/* Netserver initialization */
static void
netserver_init()
@@ -943,14 +1131,14 @@
netperf_hash[i].hash_lock = g_mutex_new();
if (NULL == netperf_hash[i].hash_lock) {
/* not sure we will even get here */
- fprintf(where, "%s: g_mutex_new error \n",__func__);
+ g_fprintf(where, "%s: g_mutex_new error \n",__func__);
fflush(where);
exit(-2);
}
netperf_hash[i].condition = g_cond_new();
if (NULL == netperf_hash[i].condition) {
/* not sure we will even get here */
- fprintf(where, "%s: g_cond_new error \n",__func__);
+ g_fprintf(where, "%s: g_cond_new error \n",__func__);
fflush(where);
exit(-2);
}
@@ -959,14 +1147,14 @@
(pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
if (NULL == netperf_hash[i].hash_lock) {
- fprintf(where, "%s: unable to malloc a mutex \n",__func__);
+ g_fprintf(where, "%s: unable to malloc a mutex \n",__func__);
fflush(where);
exit(-2);
}
rc = pthread_mutex_init(netperf_hash[i].hash_lock, NULL);
if (rc) {
- fprintf(where, "%s: server pthread_mutex_init error %d\n", __func__, rc);
+ g_fprintf(where, "%s: server pthread_mutex_init error %d\n", __func__, rc);
fflush(where);
exit(rc);
}
@@ -975,14 +1163,14 @@
(pthread_cond_t *)malloc(sizeof(pthread_cond_t));
if (NULL == netperf_hash[i].condition) {
- fprintf(where, "%s: unable to malloc a pthread_cond_t \n",__func__);
+ g_fprintf(where, "%s: unable to malloc a pthread_cond_t \n",__func__);
fflush(where);
exit(-2);
}
rc = pthread_cond_init(netperf_hash[i].condition, NULL);
if (rc) {
- fprintf(where, "%s: server pthread_cond_init error %d\n", __func__, rc);
+ g_fprintf(where, "%s: server pthread_cond_init error %d\n", __func__, rc);
fflush(where);
exit(rc);
}
@@ -995,14 +1183,14 @@
test_hash[i].hash_lock = g_mutex_new();
if (NULL == test_hash[i].hash_lock) {
/* not sure we will even get here */
- fprintf(where, "%s: g_cond_new error \n",__func__);
+ g_fprintf(where, "%s: g_cond_new error \n",__func__);
fflush(where);
exit(-2);
}
test_hash[i].condition = g_cond_new();
if (NULL == test_hash[i].condition) {
/* not sure we will even get here */
- fprintf(where, "%s: g_cond_new error \n",__func__);
+ g_fprintf(where, "%s: g_cond_new error \n",__func__);
fflush(where);
exit(-2);
}
@@ -1011,14 +1199,14 @@
(pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
if (NULL == test_hash[i].hash_lock) {
- fprintf(where, "%s: unable to malloc a mutex \n",__func__);
+ g_fprintf(where, "%s: unable to malloc a mutex \n",__func__);
fflush(where);
exit(-2);
}
rc = pthread_mutex_init(test_hash[i].hash_lock, NULL);
if (rc) {
- fprintf(where, "%s: test pthread_mutex_init error %d\n", __func__, rc);
+ g_fprintf(where, "%s: test pthread_mutex_init error %d\n", __func__, rc);
fflush(where);
exit(rc);
}
@@ -1026,14 +1214,14 @@
(pthread_cond_t *)malloc(sizeof(pthread_cond_t));
if (NULL == test_hash[i].condition) {
- fprintf(where, "%s: unable to malloc a pthread_cond_t \n",__func__);
+ g_fprintf(where, "%s: unable to malloc a pthread_cond_t \n",__func__);
fflush(where);
exit(-2);
}
rc = pthread_cond_init(test_hash[i].condition, NULL);
if (rc) {
- fprintf(where, "%s: test pthread_cond_init error %d\n", __func__, rc);
+ g_fprintf(where, "%s: test pthread_cond_init error %d\n", __func__, rc);
fflush(where);
exit(rc);
}
@@ -1045,38 +1233,113 @@
}
+static GOptionEntry netserver_entries[] =
+ {
+ {"daemonize", 0, 0, G_OPTION_ARG_NONE, &want_daemonize, "When launched from a shell, disconnect from that shell (default)", NULL},
+ {"nodaemonize", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &want_daemonize, "When launched from a shell, do not disconnect from that shell", NULL},
+ {"spawn", 0, 0, G_OPTION_ARG_NONE, &spawn_on_accept, "Spawn a new process for each control connection (default)", NULL},
+ {"nospawn", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &spawn_on_accept, "Do not spawn a new process for each control connection", NULL},
+ {"control", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &control_socket, "The FD that should be used for the control channel (internal)", NULL},
+ {"closesocket", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, do_closesocket,"Close the specified socket", NULL},
+ {"local", 'L', 0, G_OPTION_ARG_CALLBACK, set_local_address, "Specify the local addressing for the control endpoint", NULL},
+ {"output", 'o', 0, G_OPTION_ARG_CALLBACK, set_output_destination, "Specify where misc. output should go", NULL},
+ {"port", 'p', 0, G_OPTION_ARG_CALLBACK, set_port_number, "Specify the port number for the control connection", NULL},
+ {"debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, set_debug, "Set the level of debugging",NULL},
+ {"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version, "Display the netserver version and exit", NULL},
+ {"verbose", 'v', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, set_verbose, "Set verbosity level for output", NULL},
+ {"brief", 'b', 0, G_OPTION_ARG_NONE, &want_brief, "Request brief output", NULL},
+ {"quiet", 'q', 0, G_OPTION_ARG_NONE, &want_quiet, "Display no test banners", NULL},
+ { NULL }
+ };
+
int
-main (int argc, char **argv)
+main(int argc, char **argv)
{
- int sock;
+ int i;
struct sockaddr name;
netperf_socklen_t namelen = sizeof(name);
+ SOCKET sock, listen_sock;
+ guint watch_id;
+ GOptionContext *option_context;
+ gboolean ret;
+ GError *error = NULL;
+ GIOStatus status;
+ GMainLoop *loop;
+
+#ifdef G_OS_WIN32
+ WSADATA wsa_data ;
+
+#endif
+ /* make sure that where points somewhere to begin with */
+ where = stderr;
+
+#ifdef G_OS_WIN32
+ /* Initialize the winsock lib ( version 2.2 ) */
+ if ( WSAStartup(MAKEWORD(2,2), &wsa_data) == SOCKET_ERROR ){
+ g_fprintf(where,"WSAStartup() failed : %d\n", GetLastError()) ;
+ return 1 ;
+ }
+#endif
+
program_name = argv[0];
#ifdef WITH_GLIB
g_thread_init(NULL);
#endif
- /* if netserver is invoked with any of the -L, -p or -f options it
- will necessary to setup the listen endpoint. similarly, if
- standard in is not a socket, it will be necessary to setup the
- listen endpoint. otherwise, we assume we sprang-forth from inetd
- or the like and should start processing requests. */
+ /* save-off the initial command-line stuff in case we need it for
+ daemonizing or spawning after an accept */
+ orig_argc = argc;
+ orig_argv = g_new(gchar *,argc);
+ for (i = 0; i < argc; i++){
+ orig_argv[i] = g_strdup(argv[i]);
+ }
- if (getsockname(0, &name, &namelen) == -1) {
- /* we may not be a child of inetd */
- if (CHECK_FOR_NOT_SOCKET) {
- need_setup = 1;
- }
+ option_context = g_option_context_new(" - netperf4 netserver options");
+ g_option_context_add_main_entries(option_context,netserver_entries, NULL);
+ ret = g_option_context_parse(option_context, &argc, &argv, &error);
+ if (error) {
+ /* it sure would be nice to know how to trigger the help output */
+ g_error("%s g_option_context_parse %s %d %s\n",
+ __func__,
+ g_quark_to_string(error->domain),
+ error->code,
+ error->message);
+ g_clear_error(&error);
}
- decode_command_line(argc, argv);
+ /* if we daemonize, we will not be returning, and we will be
+ starting a whole new instance of this binary, because that is what
+ g_spawn_asyync_with_pipes() does. */
+ if (want_daemonize) {
+ daemonize(orig_argc,orig_argv);
+ }
+ /* if neither stdin, nor control_socket are sockets, we need to
+ setup a listen endpoint and go from there, otherwise, we assume
+ we are a child of inetd or launched from a parent netserver raj
+ 2006-03-16 */
+
+ if (getsockname(0, &name, &namelen) == 0) {
+ /* we are a child of inetd or the like */
+ need_setup = FALSE;
+ sock = 0;
+ }
+ else if (getsockname(control_socket, &name, &namelen) == 0) {
+ /* we were spawned by a parent netserver */
+ need_setup = FALSE;
+ sock = control_socket;
+ }
+ else {
+ need_setup = TRUE;
+ }
+
if (ofile) {
- /* send our stuff to wherever the user told us to */
+ /* send our stuff to wherever the user told us to. likely we need
+ to revisit this in the face of spawning processes... */
where = ofile;
}
else {
@@ -1126,24 +1389,51 @@
whether we are a child of inetd or not. raj 2005-10-11 */
netserver_init();
- /* if netserver is invoked with any of the -L, -p or -f options it
- will necessary to setup the listen endpoint. similarly, if
- standard in is not a socket, it will be necessary to setup the
- listen endpoint. otherwise, we assume we sprang-forth from inetd
- or the like and should start processing requests. */
+ loop = g_main_loop_new(NULL, FALSE);
- if (getsockname(0, &name, &namelen) == -1) {
- /* we may not be a child of inetd */
- if (CHECK_FOR_NOT_SOCKET) {
- need_setup = 1;
- }
- }
+ if (need_setup) {
+ listen_sock = setup_listen_endpoint(listen_port);
+#ifdef G_OS_WIN32
+ control_channel = g_io_channel_win32_new_socket(listen_sock);
+#else
+ control_channel = g_io_channel_unix_new(listen_sock);
+#endif
+ status = g_io_channel_set_flags(control_channel,G_IO_FLAG_NONBLOCK,&error);
+ if (error) {
+ g_warning("g_io_channel_set_flags %s %d %s\n",
+ g_quark_to_string(error->domain),
+ error->code,
+ error->message);
+ g_clear_error(&error);
+ }
+ g_print("status after set flags %d control_channel %p\n",status,control_channel);
+
+ status = g_io_channel_set_encoding(control_channel,NULL,&error);
+ if (error) {
+ g_warning("g_io_channel_set_encoding %s %d %s\n",
+ g_quark_to_string(error->domain),
+ error->code,
+ error->message);
+ g_clear_error(&error);
+ }
+
+ g_print("status after set_encoding %d\n");
+
+ g_io_channel_set_buffered(control_channel,FALSE);
+
+ /* loop is passed just to have something passed */
+ watch_id = g_io_add_watch(control_channel,
+ G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
+ accept_connection,
+ loop);
+ g_print("added watch id %d\n",watch_id);
- if (need_setup) {
- setup_listen_endpoint(listen_port);
+ g_print("Starting loop to accept stuff...\n");
+ g_main_loop_run(loop);
+ g_print("Came out of the main loop\n");
+
}
else {
- sock = 0;
handle_netperf_requests(sock);
}
}
More information about the netperf-dev
mailing list