[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r3037 - in GNUnet/src: include util util/network util/os ut
From: |
grothoff |
Subject: |
[GNUnet-SVN] r3037 - in GNUnet/src: include util util/network util/os util/threads |
Date: |
Sat, 24 Jun 2006 13:38:05 -0700 (PDT) |
Author: grothoff
Date: 2006-06-24 13:37:52 -0700 (Sat, 24 Jun 2006)
New Revision: 3037
Added:
GNUnet/src/util/os/cpustatus.c
GNUnet/src/util/threads/time.c
Removed:
GNUnet/src/util/network/port.c
GNUnet/src/util/network/tcp_return.c
Modified:
GNUnet/src/include/gnunet_util.h
GNUnet/src/include/gnunet_util_config.h
GNUnet/src/include/gnunet_util_cron.h
GNUnet/src/include/gnunet_util_network.h
GNUnet/src/include/gnunet_util_os.h
GNUnet/src/include/gnunet_util_threads.h
GNUnet/src/util/README
GNUnet/src/util/initialize.c
GNUnet/src/util/network/Makefile.am
GNUnet/src/util/network/endian.c
GNUnet/src/util/network/io.c
GNUnet/src/util/network/ipcheck.c
GNUnet/src/util/network/tcpio.c
GNUnet/src/util/os/Makefile.am
GNUnet/src/util/os/daemon.c
GNUnet/src/util/os/dso.c
GNUnet/src/util/os/osconfig.c
GNUnet/src/util/os/semaphore.c
GNUnet/src/util/os/statuscalls.c
GNUnet/src/util/threads/Makefile.am
Log:
denver
Modified: GNUnet/src/include/gnunet_util.h
===================================================================
--- GNUnet/src/include/gnunet_util.h 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/include/gnunet_util.h 2006-06-24 20:37:52 UTC (rev 3037)
@@ -146,13 +146,6 @@
/**
- * The configuration was re-loaded. All
- * util modules should check if it has
- * changed for them.
- */
-void resetUtil(void);
-
-/**
* Shutdown the util services in proper order.
*/
void doneUtil(void);
Modified: GNUnet/src/include/gnunet_util_config.h
===================================================================
--- GNUnet/src/include/gnunet_util_config.h 2006-06-24 16:34:56 UTC (rev
3036)
+++ GNUnet/src/include/gnunet_util_config.h 2006-06-24 20:37:52 UTC (rev
3037)
@@ -19,14 +19,14 @@
*/
/**
- * @file include/gnunet_config.h
+ * @file include/gnunet_util_config.h
* @brief configuration API
*
* @author Christian Grothoff
*/
-#ifndef GNUNET_CONFIG_H
-#define GNUNET_CONFIG_H
+#ifndef GNUNET_UTIL_CONFIG_H
+#define GNUNET_UTIL_CONFIG_H
#include "gnunet_util_error.h"
@@ -52,8 +52,8 @@
* used (since failing to change an option may have to be reported
* in a fundamentally different way to the user).
*
- * @parm ectx maybe NULL, in that case errors will no longer
- * be reported
+ * @param ectx may be NULL, in that case errors will no longer
+ * be reported
*/
void GC_set_error_context(struct GC_Configuration * cfg,
struct GE_Context * ectx);
Modified: GNUnet/src/include/gnunet_util_cron.h
===================================================================
--- GNUnet/src/include/gnunet_util_cron.h 2006-06-24 16:34:56 UTC (rev
3036)
+++ GNUnet/src/include/gnunet_util_cron.h 2006-06-24 20:37:52 UTC (rev
3037)
@@ -38,28 +38,11 @@
#endif
/**
- * @brief constants to specify time
- */
-#define cronMILLIS ((cron_t)1)
-#define cronSECONDS ((cron_t)(1000 * cronMILLIS))
-#define cronMINUTES ((cron_t) (60 * cronSECONDS))
-#define cronHOURS ((cron_t)(60 * cronMINUTES))
-#define cronDAYS ((cron_t)(24 * cronHOURS))
-#define cronWEEKS ((cron_t)(7 * cronDAYS))
-#define cronMONTHS ((cron_t)(30 * cronDAYS))
-#define cronYEARS ((cron_t)(365 * cronDAYS))
-
-/**
* Type of a cron-job method.
*/
typedef void (*CronJob)(void *);
/**
- * Time for absolute times used by cron (64 bit)
- */
-typedef unsigned long long cron_t;
-
-/**
* Start the cron jobs.
*/
void cron_start_jobs(void);
@@ -95,13 +78,6 @@
int cron_test_running(void);
/**
- * Get the current time (in cron-units).
- *
- * @return the current time
- */
-cron_t cron_get_time(void);
-
-/**
* Add a cron-job to the delta list.
* @param method which method should we run
* @param delta how many milliseconds until we run the method
Modified: GNUnet/src/include/gnunet_util_network.h
===================================================================
--- GNUnet/src/include/gnunet_util_network.h 2006-06-24 16:34:56 UTC (rev
3036)
+++ GNUnet/src/include/gnunet_util_network.h 2006-06-24 20:37:52 UTC (rev
3037)
@@ -27,30 +27,15 @@
* @author Gerd Knorr <address@hidden>
* @author Ioana Patrascu
* @author Tzvetan Horozov
- *
- *
- * TODO:
- * - add configuration argument to
- * methods that need it
- * - abstract sockets that are
- * represented as "int"
- * (typedef int GNUNET_SOCKET or so)
- * -
*/
#ifndef GNUNET_UTIL_NETWORK_H
#define GNUNET_UTIL_NETWORK_H
-/* we need size_t, and since it can be both unsigned int
- or unsigned long long, this IS platform dependent;
- but "stdlib.h" should be portable 'enough' to be
- unconditionally available... */
-#include <stdlib.h>
-
-/* add error and config prototypes */
#include "gnunet_util_config.h"
#include "gnunet_util_string.h"
#include "gnunet_util_os.h"
+#include "gnunet_util_threads.h"
#ifdef __cplusplus
extern "C" {
@@ -68,19 +53,23 @@
* @brief Specify low-level network IO behavior
*/
typedef enum {
+
/**
* Do not block.
*/
NC_Nonblocking = 0x000,
+
/**
* Call may block.
*/
NC_Blocking = 0x001,
+
/**
* Ignore interrupts (re-try if operation
* was aborted due to interrupt)
*/
NC_IgnoreInt = 0x010,
+
/**
* Always try to read/write the maximum
* amount of data (using possibly multiple
@@ -88,6 +77,7 @@
* error or if completely done.
*/
NC_Complete = 0x111,
+
} NC_KIND;
/**
@@ -126,7 +116,10 @@
* @brief an IPv4 address
*/
typedef struct {
- unsigned int addr; /* struct in_addr */
+ /**
+ * struct in_addr
+ */
+ unsigned int addr;
} IPaddr;
/**
@@ -138,7 +131,10 @@
* @brief an IPV6 address.
*/
typedef struct {
- unsigned int addr[4]; /* struct in6_addr addr; */
+ /**
+ * struct in6_addr addr;
+ */
+ unsigned int addr[4];
} IP6addr;
/**
@@ -247,7 +243,7 @@
struct ClientServerConnection *
client_connection_create(struct GE_Context * ectx,
struct GC_Configuration * cfg,
- SocketHandle sock);
+ struct SocketHandle * sock);
/**
* Close a GNUnet TCP socket for now (use to temporarily close
@@ -303,16 +299,13 @@
*
* @param sock the socket to write to
* @param buffer the buffer to write
- * @param isBlocking is this call allowed to block
* @return OK if the write was sucessful,
* NO if it would block and isBlocking was NO,
* SYSERR if the write failed (error will be logged)
*/
int connection_write(struct ClientServerConnection * sock,
- const CS_MESSAGE_HEADER * buffer,
- int isBlocking);
+ const MESSAGE_HEADER * buffer);
-
/**
* Obtain a simple return value from the connection.
* Note that the protocol will automatically communicate
@@ -340,6 +333,22 @@
int ret);
/**
+ * Send a return value that indicates
+ * a serious error to the other side.
+ *
+ * @param sock the TCP socket
+ * @param mask GE_MASK
+ * @param date date string
+ * @param msg message string
+ * @return SYSERR on error, OK if the error code was send
+ * successfully
+ */
+int connection_write_error(struct ClientServerConnection * sock,
+ GE_KIND mask,
+ const char * date,
+ const char * msg);
+
+/**
* Stop gnunetd
*
* Note that returning an error does NOT mean that
@@ -367,7 +376,8 @@
*
* @return OK if gnunetd is running, SYSERR if not
*/
-int connection_test_running(struct GE_Context * ectx);
+int connection_test_running(struct GE_Context * ectx,
+ struct GC_Configuration * cfg);
/**
* Wait until the gnunet daemon is
@@ -377,24 +387,9 @@
* @return OK if gnunetd is now running
*/
int connection_wait_for_running(struct GE_Context * ectx,
- unsigned long long_t timeout);
+ struct GC_Configuration * cfg,
+ cron_t timeout);
-/**
- * Send a return value that indicates
- * a serious error to the other side.
- *
- * @param sock the TCP socket
- * @param mask GE_MASK
- * @param date date string
- * @param msg message string
- * @return SYSERR on error, OK if the error code was send
- * successfully
- */
-int connection_write_error(struct ClientServerConnection * sock,
- GE_KIND mask,
- const char * date,
- const char * msg);
-
/* ********************* low-level socket operations **************** */
/**
Modified: GNUnet/src/include/gnunet_util_os.h
===================================================================
--- GNUnet/src/include/gnunet_util_os.h 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/include/gnunet_util_os.h 2006-06-24 20:37:52 UTC (rev 3037)
@@ -72,12 +72,15 @@
const char * basename,
unsigned int initialValue);
-void IPC_SEMAPHORE_DESTROY(struct IPC_Semaphore * sem);
+void IPC_SEMAPHORE_DESTROY(struct IPC_SEMAPHORE * sem);
void IPC_SEMAPHORE_UP(struct IPC_SEMAPHORE * sem);
-void IPC_SEMAPHORE_DOWN(struct IPC_SEMAPHORE * sem,
- int mayBlock);
+/**
+ * @return OK on success, SYSERR if would block
+ */
+int IPC_SEMAPHORE_DOWN(struct IPC_SEMAPHORE * sem,
+ int mayBlock);
/**
* Load plugin
@@ -105,7 +108,7 @@
struct LoadMonitor *
os_network_monitor_create(struct GE_Context * ectx,
- struct GC_Configuration * cfg);
+ struct GC_Configuration * cfg);
void os_network_monitor_destroy(struct LoadMonitor * mon);
@@ -116,12 +119,13 @@
* (100 is equivalent to full load)
*/
int os_network_monitor_get_load(struct LoadMonitor * monitor,
- NetworkDirection dir);
+ NetworkDirection dir);
/**
* Tell monitor to increment the number of bytes sent/received
*/
-void os_network_monitor_notify_transmission(NetworkDirection dir,
+void os_network_monitor_notify_transmission(struct LoadMonitor * monitor,
+ NetworkDirection dir,
unsigned long long delta);
/**
@@ -156,7 +160,7 @@
int os_modify_autostart(struct GE_Context * ectx,
int testCapability,
int doAutoStart,
- const char * application
+ const char * application,
const char * username,
const char * groupname);
@@ -179,6 +183,7 @@
* @return OK on success, SYSERR on error
*/
int os_modify_user(struct GE_Context * ectx,
+ int testCapability,
int doAdd,
const char * name,
const char * group);
@@ -201,6 +206,7 @@
* daemonized sucessfully, -1 on error
*/
int os_daemon_start(struct GE_Context * ectx,
+ struct GC_Configuration * cfg,
const char * cfgFile,
int daemonize);
Modified: GNUnet/src/include/gnunet_util_threads.h
===================================================================
--- GNUnet/src/include/gnunet_util_threads.h 2006-06-24 16:34:56 UTC (rev
3036)
+++ GNUnet/src/include/gnunet_util_threads.h 2006-06-24 20:37:52 UTC (rev
3037)
@@ -27,11 +27,6 @@
* @author Gerd Knorr <address@hidden>
* @author Ioana Patrascu
* @author Tzvetan Horozov
- *
- * TODO:
- * - consider moving SHUTDOWN into
- * seperate shared library (not part of
- * libgnunetutil binary at all!)
*/
#ifndef GNUNET_UTIL_THREADS_H
@@ -45,6 +40,24 @@
#endif
/**
+ * Time for absolute times used by cron (64 bit)
+ */
+typedef unsigned long long cron_t;
+
+
+/**
+ * @brief constants to specify time
+ */
+#define cronMILLIS ((cron_t)1)
+#define cronSECONDS ((cron_t)(1000 * cronMILLIS))
+#define cronMINUTES ((cron_t) (60 * cronSECONDS))
+#define cronHOURS ((cron_t)(60 * cronMINUTES))
+#define cronDAYS ((cron_t)(24 * cronHOURS))
+#define cronWEEKS ((cron_t)(7 * cronDAYS))
+#define cronMONTHS ((cron_t)(30 * cronDAYS))
+#define cronYEARS ((cron_t)(365 * cronDAYS))
+
+/**
* Main method of a thread.
*/
typedef void * (*PThreadMain)(void*);
@@ -111,9 +124,16 @@
*
* @param time how long to sleep (in milli seconds)
*/
-void PTHREAD_SLEEP(unsigned long long time);
+void PTHREAD_SLEEP(cron_t time);
/**
+ * Get the current time (in cron-units).
+ *
+ * @return the current time
+ */
+cron_t get_time(void);
+
+/**
* Stop the sleep of anothe thread.
*/
void PTHREAD_STOP_SLEEP(struct PTHREAD * handle);
Modified: GNUnet/src/util/README
===================================================================
--- GNUnet/src/util/README 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/README 2006-06-24 20:37:52 UTC (rev 3037)
@@ -7,9 +7,9 @@
util/config: configuration handling (depends on error)
util/getopt: command line parsing (depends on config)
util/threads: pthread abstractions (depends on error)
+ util/os: process and system abstractions (depends on threads, config)
-------- TODO ----------
- util/os: process and system abstractions (depends on threads, config)
util/network: network IO abstractions (depends on threads, config, os)
util: main utility library (depends on all of the above)
Modified: GNUnet/src/util/initialize.c
===================================================================
--- GNUnet/src/util/initialize.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/initialize.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -195,4 +195,41 @@
gnunet_util_doneIO();
}
+
+
+
+char * winErrorStr(const char *prefix,
+ int dwErr) {
+#ifdef WINDOWS
+ char *err, *ret;
+ int mem;
+
+ if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ (DWORD) dwErr,
+ MAKELANGID(LANG_NEUTRAL,
+ SUBLANG_DEFAULT),
+ (LPTSTR) &err,
+ 0,
+ NULL )) {
+ err = "";
+ }
+
+ mem = strlen(err) + strlen(prefix) + 20;
+ ret = (char *) malloc(mem);
+
+ snprintf(ret, mem, "%s: %s (#%u)",
+ prefix,
+ err,
+ dwErr);
+ LocalFree(err);
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+
+
+
/* end of initialize.c */
Modified: GNUnet/src/util/network/Makefile.am
===================================================================
--- GNUnet/src/util/network/Makefile.am 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/network/Makefile.am 2006-06-24 20:37:52 UTC (rev 3037)
@@ -6,11 +6,10 @@
libnetwork.la
libnetwork_la_SOURCES = \
+ daemon.c \
endian.c \
io.c \
ipcheck.c \
- port.c \
- tcp_return.c \
tcpio.c
check_PROGRAMS = \
Modified: GNUnet/src/util/network/endian.c
===================================================================
--- GNUnet/src/util/network/endian.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/network/endian.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -19,13 +19,13 @@
*/
/**
- * @file util/endian.c
+ * @file util/network/endian.c
* @brief endian conversion helpers
* @author Christian Grothoff
*/
#include "platform.h"
-#include "gnunet_util.h"
+#include "gnunet_util_network.h"
unsigned long long ntohll(unsigned long long n) {
#if __BYTE_ORDER == __BIG_ENDIAN
Modified: GNUnet/src/util/network/io.c
===================================================================
--- GNUnet/src/util/network/io.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/network/io.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2003 Christian Grothoff (and other contributing authors)
+ (C) 2003, 2006 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -19,297 +19,244 @@
*/
/**
- * @file util/io.c
+ * @file util/network/io.c
* @brief (network) input/output operations
* @author Christian Grothoff
*/
-#include "gnunet_util.h"
+#include "gnunet_util_network.h"
#include "platform.h"
-/* some systems send us signals, so we'd better
- catch them (& ignore) */
-#ifndef LINUX
-static void catcher(int sig) {
- LOG(LOG_INFO,
- _("Caught signal %d.\n"),
- sig);
- /* re-install signal handler! */
- signal(sig, catcher);
-}
+typedef struct SocketHandle {
+ struct LoadMonitor * mon;
+
+ struct GE_Context * ectx;
-#endif
+ int handle;
+
+} SocketHandle;
-void gnunet_util_initIO() {
-#if ! (defined(LINUX) || defined(MINGW))
- if ( SIG_ERR == signal(SIGPIPE, SIG_IGN))
- if ( SIG_ERR == signal(SIGPIPE, catcher))
- LOG_STRERROR(LOG_WARNING, "signal");
-#endif
+struct SocketHandle *
+socket_create(struct GE_Context * ectx,
+ struct LoadMonitor * mon,
+ int osSocket) {
+ SocketHandle * ret;
+
+ ret = MALLOC(sizeof(SocketHandle));
+ ret->ectx = ectx;
+ ret->mon = mon;
+ ret->handle = osSocket;
+ return ret;
}
-void gnunet_util_doneIO() {
+void socket_destroy(struct SocketHandle * s) {
+ if (0 != CLOSE(s->handle))
+ GE_LOG_STRERROR(s->ectx,
+ GE_WARNING | GE_USER | GE_DEVELOPER | GE_BULK,
+ "close");
+ FREE(s);
}
-/**
- * Depending on doBlock, enable or disable the nonblocking mode
- * of socket s.
- *
- * @param doBlock use YES to change the socket to blocking, NO to non-blocking
- * @return Upon successful completion, it returns zero, otherwise -1
- */
-int setBlocking(int s, int doBlock) {
+/* TODO: log errors! */
+int socket_set_blocking(struct SocketHandle * s,
+ int doBlock) {
#if MINGW
u_long l = !doBlock;
- if (ioctlsocket(s, FIONBIO, &l) == SOCKET_ERROR) {
+ if (ioctlsocket(s->handle,
+ FIONBIO, &l) == SOCKET_ERROR) {
SetErrnoFromWinsockError(WSAGetLastError());
-
+
return -1;
} else {
/* store the blocking mode */
- __win_SetHandleBlockingMode(s, doBlock);
+ __win_SetHandleBlockingMode(s->handle, doBlock);
return 0;
}
#else
- int flags = fcntl(s, F_GETFL);
+ int flags = fcntl(s->handle, F_GETFL);
if (doBlock)
flags &= ~O_NONBLOCK;
else
flags |= O_NONBLOCK;
-
- return fcntl(s,
+ return fcntl(s->handle,
F_SETFL,
flags);
#endif
}
-/**
- * Check whether the socket is blocking
- * @param s the socket
- * @return YES if blocking, NO non-blocking
- */
-int isSocketBlocking(int s)
+int socket_test_blocking(struct SocketHandle * s)
{
#ifndef MINGW
- return (fcntl(s, F_GETFL) & O_NONBLOCK) ? NO : YES;
+ return (fcntl(s->handle,
+ F_GETFL) & O_NONBLOCK) ? NO : YES;
#else
- return __win_IsHandleMarkedAsBlocking(s);
+ return __win_IsHandleMarkedAsBlocking(s->handle);
#endif
}
-/* recv wrappers */
-
-/**
- * Do a NONBLOCKING read on the given socket. Note that in order to
- * avoid blocking, the caller MUST have done a select call before
- * calling this function. Though the caller must be prepared to the
- * fact that this function may fail with EWOULDBLOCK in any case (Win32).
- *
- * @brief Reads at most max bytes to buf. Interrupts are IGNORED.
- * @param s socket
- * @param buf buffer
- * @param max maximum number of bytes to read
- * @param read number of bytes actually read.
- * 0 is returned if no more bytes can be read
- * @return SYSERR on error, YES on success or NO if the operation
- * would have blocked
- */
-int RECV_NONBLOCKING(int s,
- void * buf,
- size_t max,
- size_t *read) {
+int socket_recv(struct SocketHandle * s,
+ NC_KIND nc,
+ void * buf,
+ size_t max,
+ size_t * read) {
int flags;
+ size_t pos;
+ size_t ret;
- setBlocking(s, NO);
-
+ socket_set_blocking(s,
+ 0 == (nc & NC_Blocking));
+ flags = 0;
#ifdef CYGWIN
- flags = MSG_NOSIGNAL;
+ if (0 == (nc & NC_IgnoreInt))
+ flags |= MSG_NOSIGNAL;
#elif OSX
- flags = 0;
+ /* anything? */
#elif SOMEBSD || SOLARIS
- flags = MSG_DONTWAIT;
+ if (0 == (nc & NC_Blocking))
+ flags |= MSG_DONTWAIT;
#elif LINUX
- flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+ if (0 == (nc & NC_Blocking))
+ flags |= MSG_DONTWAIT;
+ if (0 == (nc & NC_IgnoreInt))
+ flags |= MSG_NOSIGNAL;
#else
- /* good luck */
- flags = 0;
+ /* good luck */
#endif
-
- do {
- *read = (size_t) RECV(s,
- buf,
- max,
- flags);
- } while ( ( *read == -1) && ( errno == EINTR) );
-
- setBlocking(s, YES);
-
- if (*read == SYSERR && (errno == EWOULDBLOCK || errno == EAGAIN))
- return NO;
- else if ( (*read < 0) || (*read > max) )
- return SYSERR;
-
- return YES;
-}
-
-/**
- * Do a BLOCKING read on the given socket. Read len bytes (if needed
- * try multiple reads). Interrupts are ignored.
- *
- * @return SYSERR if len bytes could not be read,
- * otherwise the number of bytes read (must be len)
- */
-int RECV_BLOCKING_ALL(int s,
- void * buf,
- size_t len) {
- size_t pos;
- int i, flags;
-
pos = 0;
- setBlocking(s, YES);
-
- while (pos < len) {
-#if LINUX || CYGWIN
- flags = MSG_NOSIGNAL;
-#else
- flags = 0;
-#endif
-
- i = RECV(s,
- &((char*)buf)[pos],
- len - pos,
- flags);
-
- if ( (i == -1) && (errno == EINTR) )
+ do {
+ ret = (size_t) RECV(s->handle,
+ &((char*)buf)[pos],
+ max - pos,
+ flags);
+ if ( (ret == (size_t) -1) &&
+ (errno == EINTR) &&
+ (0 != (nc & NC_IgnoreInt)) )
continue;
- if (i <= 0)
- {
- setBlocking(s, NO);
+ if (ret == (size_t) -1) {
+ if (errno == EINTR) {
+ *read = pos;
+ return YES;
+ }
+ if ( (errno == EAGAIN) ||
+ (errno == EWOULDBLOCK) ) {
+ if (0 != (nc & NC_Blocking))
+ continue;
+ *read = pos;
+ return (pos == 0) ? NO : YES;
+ }
+ GE_LOG_STRERROR(s->ectx,
+ GE_DEBUG | GE_USER | GE_REQUEST,
+ "recv");
+ *read = pos;
return SYSERR;
}
- pos += i;
- }
- GNUNET_ASSERT(pos == len);
-
- setBlocking(s, NO);
-
- return pos;
+ pos += ret;
+ } while ( (pos < max) &&
+ (0 != (nc & NC_Blocking)) );
+ *read = pos;
+ return YES;
}
-/**
- * Do a NONBLOCKING write on the given socket.
- * Write at most max bytes from buf.
- * Interrupts are ignored (cause a re-try).
- *
- * The caller must be prepared to the fact that this function
- * may fail with EWOULDBLOCK in any case (Win32).
- *
- * @param s socket
- * @param buf buffer to send
- * @param max maximum number of bytes to send
- * @param sent number of bytes actually sent
- * @return SYSERR on error, YES on success or
- * NO if the operation would have blocked.
- */
-int SEND_NONBLOCKING(int s,
- const void * buf,
- size_t max,
- size_t * sent) {
+int socket_send(struct SocketHandle * s,
+ NC_KIND nc,
+ const void * buf,
+ size_t max,
+ size_t * sent) {
int flags;
+ size_t pos;
+ size_t ret;
- setBlocking(s, NO);
-
-#ifdef SOMEBSD
- flags = MSG_DONTWAIT;
-#elif SOLARIS
- flags = MSG_DONTWAIT;
+ socket_set_blocking(s,
+ 0 == (nc & NC_Blocking));
+ flags = 0;
+#if SOMEBSD || SOLARIS
+ if (0 == (nc & NC_Blocking))
+ flags |= MSG_DONTWAIT;
#elif OSX
- /* As braindead as Win32? */
- flags = 0;
+ /* As braindead as Win32? */
#elif CYGWIN
- flags = MSG_NOSIGNAL;
+ if (0 == (nc & NC_IgnoreInt))
+ flags |= MSG_NOSIGNAL;
#elif LINUX
- flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+ if (0 == (nc & NC_Blocking))
+ flags |= MSG_DONTWAIT;
+ if (0 == (nc & NC_IgnoreInt))
+ flags |= MSG_NOSIGNAL;
#else
- /* pray */
- flags = 0;
+ /* pray */
#endif
- do {
- *sent = (size_t) SEND(s,
- buf,
- max,
- flags);
-
- } while ( (*sent == -1) &&
- (errno == EINTR) );
-
- setBlocking(s, YES);
-
- if (*sent == SYSERR && (errno == EWOULDBLOCK || errno == EAGAIN))
- return NO;
- else if ( (*sent < 0) || (*sent > max) )
- return SYSERR;
-
- return YES;
-}
-
-/**
- * Do a BLOCKING write on the given socket. Write len bytes (if
- * needed do multiple write). Interrupts are ignored (cause a
- * re-try).
- *
- * @return SYSERR if len bytes could not be send,
- * otherwise the number of bytes transmitted (must be len)
- */
-int SEND_BLOCKING_ALL(int s,
- const void * buf,
- size_t len) {
- size_t pos;
- int i, flags;
-
pos = 0;
- setBlocking(s, YES);
- while (pos < len) {
-#if CYGWIN || LINUX
- flags = MSG_NOSIGNAL;
-#else
- flags = 0;
-#endif
- i = SEND(s,
- &((char*)buf)[pos],
- len - pos,
- flags);
-
- if ( (i == -1) &&
- (errno == EINTR) )
- continue; /* ingnore interrupts */
- if (i <= 0) {
- if (i == -1)
- LOG_STRERROR(LOG_WARNING, "send");
+ do {
+ ret = (size_t) SEND(s->handle,
+ &((char*)buf)[pos],
+ max - pos,
+ flags);
+ if ( (ret == (size_t) -1) &&
+ (errno == EINTR) &&
+ (0 != (nc & NC_IgnoreInt)) )
+ continue;
+ if (ret == (size_t) -1) {
+ if (errno == EINTR) {
+ *sent = pos;
+ return YES;
+ }
+ if ( (errno == EAGAIN) ||
+ (errno == EWOULDBLOCK) ) {
+ if (0 != (nc & NC_Blocking))
+ continue;
+ *sent = pos;
+ return (pos == 0) ? NO : YES;
+ }
+ GE_LOG_STRERROR(s->ectx,
+ GE_DEBUG | GE_USER | GE_REQUEST,
+ "send");
+ *sent = pos;
return SYSERR;
}
- pos += i;
- }
- setBlocking(s, NO);
- GNUNET_ASSERT(pos == len);
- return pos;
+ pos += ret;
+ } while ( (pos < max) &&
+ (0 != (nc & NC_Blocking)) );
+ *sent = pos;
+ return YES;
}
/**
* Check if socket is valid
* @return 1 if valid, 0 otherwise
*/
-int isSocketValid(int s)
-{
+int socket_test_valid(struct SocketHandle * s) {
#ifndef MINGW
struct stat buf;
- return -1 != fstat(s, &buf);
+ return -1 != fstat(s->handle,
+ &buf);
#else
long l;
- return ioctlsocket(s, FIONREAD, &l) != SOCKET_ERROR;
+ return ioctlsocket(s->handle,
+ FIONREAD,
+ &l) != SOCKET_ERROR;
#endif
}
+
+/* some systems send us signals, so we'd better
+ catch them (& ignore) */
+#ifndef LINUX
+static void catcher(int sig) {
+ /* re-install signal handler! */
+ signal(sig, &catcher);
+}
+#endif
+
+/* TODO: add destructor to restore signal handler */
+void __attribute__ ((constructor)) gnunet_io_ltdl_init() {
+#if ! (defined(LINUX) || defined(MINGW))
+ if ( SIG_ERR == signal(SIGPIPE, SIG_IGN))
+ if ( SIG_ERR == signal(SIGPIPE, &catcher))
+ LOG_STRERROR(LOG_WARNING, "signal");
+#endif
+}
+
+
/* end of io.c */
Modified: GNUnet/src/util/network/ipcheck.c
===================================================================
--- GNUnet/src/util/network/ipcheck.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/network/ipcheck.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2001, 2002, 2003, 2004 Christian Grothoff (and other contributing
authors)
+ (C) 2001, 2002, 2003, 2004, 2006 Christian Grothoff (and other
contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -19,12 +19,14 @@
*/
/**
- * @file util/ipcheck.c
+ * @file util/network/ipcheck.c
* @brief test if an IP matches a given subnet
* @author Christian Grothoff
*/
-#include "gnunet_util.h"
+#include "gnunet_util_network.h"
+#include "gnunet_util_string.h"
+#include "gnunet_util_error.h"
#include "platform.h"
/**
@@ -55,7 +57,8 @@
* @param routeList a string specifying the forbidden networks
* @return the converted list, NULL if the synatx is flawed
*/
-CIDRNetwork * parseRoutes(const char * routeList) {
+CIDRNetwork * parse_ipv4_network_specification(struct GE_Context * ectx,
+ const char * routeList) {
unsigned int count;
unsigned int i;
unsigned int j;
@@ -96,9 +99,10 @@
if (cnt == 8) {
for (j=0;j<8;j++)
if (temps[j] > 0xFF) {
- LOG(LOG_ERROR,
- _("Invalid format for IP: `%s'\n"),
- &routeList[pos]);
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_IMMEDIATE,
+ _("Invalid format for IP: `%s'\n"),
+ &routeList[pos]);
FREE(result);
return NULL;
}
@@ -123,9 +127,10 @@
if (cnt == 5) {
for (j=0;j<4;j++)
if (temps[j] > 0xFF) {
- LOG(LOG_ERROR,
- "wrong format for IP: %s\n",
- &routeList[pos]);
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_IMMEDIATE,
+ _("Invalid format for IP: `%s'\n"),
+ &routeList[pos]);
FREE(result);
return NULL;
}
@@ -146,23 +151,26 @@
i++;
continue;
} else {
- LOG(LOG_ERROR,
- _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
- slash);
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_IMMEDIATE,
+ _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
+ slash);
FREE(result);
return NULL; /* error */
}
}
- LOG(LOG_ERROR,
- "invalid network notation: >>%s<<",
- &routeList[pos]);
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_IMMEDIATE,
+ _("Invalid format for IP: `%s'\n"),
+ &routeList[pos]);
FREE(result);
return NULL; /* error */
}
if (pos < strlen(routeList)) {
- LOG(LOG_ERROR,
- _("Invalid network notation (additional characters: `%s')."),
- &routeList[pos]);
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_IMMEDIATE,
+ _("Invalid format for IP: `%s'\n"),
+ &routeList[pos]);
FREE(result);
return NULL; /* oops */
}
@@ -170,35 +178,7 @@
}
-
/**
- * Check if the given IP address is in the list of IP addresses.
- *
- * @param list a list of networks
- * @param ip the IP to check (in network byte order)
- * @return NO if the IP is not in the list, YES if it it is
- */
-int checkIPListed(const CIDRNetwork * list,
- IPaddr ip) {
- int i;
- IPaddr add;
-
- add = ip;
- i=0;
- if (list == NULL)
- return NO;
-
- while ( (list[i].network.addr != 0) ||
- (list[i].netmask.addr != 0) ) {
- if ( (add.addr & list[i].netmask.addr) ==
- (list[i].network.addr & list[i].netmask.addr) )
- return YES;
- i++;
- }
- return NO;
-}
-
-/**
* Parse a network specification. The argument specifies
* a list of networks. The format is
* <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
@@ -209,7 +189,8 @@
* @param routeList a string specifying the forbidden networks
* @return the converted list, NULL if the synatx is flawed
*/
-CIDR6Network * parseRoutes6(const char * routeListX) {
+CIDR6Network * parse_ipv6_network_specification(struct GE_Context * ectx,
+ const char * routeListX) {
unsigned int count;
unsigned int i;
unsigned int len;
@@ -231,9 +212,10 @@
if (routeList[i] == ';')
count++;
if (routeList[len-1] != ';') {
- LOG(LOG_ERROR,
- _("Invalid network notation (does not end with ';': `%s')\n"),
- routeList);
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_IMMEDIATE,
+ _("Invalid network notation (does not end with ';': `%s')\n"),
+ routeList);
FREE(routeList);
return NULL;
}
@@ -263,10 +245,11 @@
&routeList[slash+1],
&result[i].netmask);
if (ret <= 0) {
- LOG(LOG_ERROR,
- _("Wrong format `%s' for netmask: %s\n"),
- &routeList[slash+1],
- STRERROR(errno));
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_IMMEDIATE,
+ _("Wrong format `%s' for netmask: %s\n"),
+ &routeList[slash+1],
+ STRERROR(errno));
FREE(result);
FREE(routeList);
return NULL;
@@ -277,10 +260,11 @@
&routeList[start],
&result[i].network);
if (ret <= 0) {
- LOG(LOG_ERROR,
- _("Wrong format `%s' for network: %s\n"),
- &routeList[slash+1],
- STRERROR(errno));
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_IMMEDIATE,
+ _("Wrong format `%s' for network: %s\n"),
+ &routeList[slash+1],
+ STRERROR(errno));
FREE(result);
FREE(routeList);
return NULL;
@@ -291,6 +275,7 @@
return result;
}
+
/**
* Check if the given IP address is in the list of IP addresses.
*
@@ -298,8 +283,35 @@
* @param ip the IP to check (in network byte order)
* @return NO if the IP is not in the list, YES if it it is
*/
-int checkIP6Listed(const CIDR6Network * list,
- const IP6addr * ip) {
+int check_ipv4_listed(const CIDRNetwork * list,
+ IPaddr ip) {
+ int i;
+ IPaddr add;
+
+ add = ip;
+ i=0;
+ if (list == NULL)
+ return NO;
+
+ while ( (list[i].network.addr != 0) ||
+ (list[i].netmask.addr != 0) ) {
+ if ( (add.addr & list[i].netmask.addr) ==
+ (list[i].network.addr & list[i].netmask.addr) )
+ return YES;
+ i++;
+ }
+ return NO;
+}
+
+/**
+ * Check if the given IP address is in the list of IP addresses.
+ *
+ * @param list a list of networks
+ * @param ip the IP to check (in network byte order)
+ * @return NO if the IP is not in the list, YES if it it is
+ */
+int check_ipv6_listed(const CIDR6Network * list,
+ IP6addr ip) {
unsigned int i;
unsigned int j;
struct in6_addr zero;
@@ -312,7 +324,7 @@
while ( (memcmp(&zero, &list[i].network, sizeof(struct in6_addr)) != 0) ||
(memcmp(&zero, &list[i].netmask, sizeof(struct in6_addr)) != 0) ) {
for (j=0;j<sizeof(struct in6_addr)/sizeof(int);j++)
- if ( ((((int*)ip)[j] & ((int*)&list[i].netmask)[j])) !=
+ if ( ((((int*)&ip)[j] & ((int*)&list[i].netmask)[j])) !=
(((int*)&list[i].network)[j] & ((int*)&list[i].netmask)[j]) ) {
i++;
continue;
Deleted: GNUnet/src/util/network/port.c
===================================================================
--- GNUnet/src/util/network/port.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/network/port.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -1,102 +0,0 @@
-/*
- This file is part of GNUnet
-
- GNUnet 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, or (at your
- option) any later version.
-
- GNUnet 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 GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-/**
- * @file util/port.c
- * @brief functions for GNUnet clients to establish connection with gnunetd
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-/**
- * Return the port-number (in host byte order)
- */
-unsigned short getGNUnetPort() {
- static unsigned short port;
- const char *setting;
-
- if (port != 0)
- return port;
- if (testConfigurationString("GNUNETD",
- "_MAGIC_",
- "YES"))
- setting = "PORT";
- else
- setting = "CLIENT-PORT";
-
- port = (unsigned short) getConfigurationInt("NETWORK",
- setting);
- if (port == 0) {
- errexit(_("Cannot determine port of gnunetd server. "
- "Define in configuration file in section `%s' under `%s'.\n"),
- "NETWORK",
- setting);
- }
- return port;
-}
-
-/**
- * Configuration: get the GNUnetd host where the client
- * should connect to (via TCP)
- * @return the name of the host
- */
-static const char * getGNUnetdHost() {
- static char * res;
-
- if (res != NULL)
- return res;
- res = getConfigurationString("NETWORK",
- "HOST");
- if (res == NULL)
- res = "localhost";
- return res;
-}
-
-/**
- * Get a GNUnet TCP socket that is connected to gnunetd.
- */
-GNUNET_TCP_SOCKET * getClientSocket() {
- GNUNET_TCP_SOCKET * sock;
- const char * host;
-
- sock = MALLOC(sizeof(GNUNET_TCP_SOCKET));
- host = getGNUnetdHost();
- if (SYSERR == initGNUnetClientSocket(getGNUnetPort(),
- host,
- sock)) {
- LOG(LOG_ERROR,
- _("Could not connect to gnunetd.\n"));
- FREE(sock);
- return NULL;
- }
- return sock;
-}
-
-/**
- * Free a Client socket.
- */
-void releaseClientSocket(GNUNET_TCP_SOCKET * sock) {
- if (sock != NULL) {
- destroySocket(sock);
- FREE(sock);
- }
-}
-
-/* end of port.c */
Deleted: GNUnet/src/util/network/tcp_return.c
===================================================================
--- GNUnet/src/util/network/tcp_return.c 2006-06-24 16:34:56 UTC (rev
3036)
+++ GNUnet/src/util/network/tcp_return.c 2006-06-24 20:37:52 UTC (rev
3037)
@@ -1,94 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002, 2004 Christian Grothoff (and other contributing authors)
-
- GNUnet 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, or (at your
- option) any later version.
-
- GNUnet 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 GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file util/tcp_return.c
- * @brief code to communicate simple (int) return values via reliable
- * TCP stream
- * @author Christian Grothoff
- *
- * Helper methods to send and receive return values over a TCP stream
- * that has tcpio (see util/tcpio.c) semantics.
- */
-
-#include "gnunet_util.h"
-#include "gnunet_protocols.h"
-#include "platform.h"
-
-/**
- * Obtain a return value from a remote call from TCP.
- *
- * @param sock the TCP socket
- * @param ret the return value from TCP
- * @return SYSERR on error, OK if the return value was read
- * successfully
- */
-int readTCPResult(GNUNET_TCP_SOCKET * sock,
- int * ret) {
- CS_returnvalue_MESSAGE * rv;
-
- rv = NULL;
- if (SYSERR == readFromSocket(sock,
- (CS_MESSAGE_HEADER **) &rv)) {
- LOG(LOG_WARNING,
- _("`%s' failed, other side closed connection.\n"),
- __FUNCTION__);
- return SYSERR;
- }
- if ( (ntohs(rv->header.size) != sizeof(CS_returnvalue_MESSAGE)) ||
- (ntohs(rv->header.type) != CS_PROTO_RETURN_VALUE) ) {
- LOG(LOG_WARNING,
- _("`%s' failed, reply invalid!\n"),
- __FUNCTION__);
- FREE(rv);
- return SYSERR;
- }
- *ret = ntohl(rv->return_value);
- FREE(rv);
- return OK;
-}
-
-/**
- * Send a return value to the caller of a remote call via
- * TCP.
- * @param sock the TCP socket
- * @param ret the return value to send via TCP
- * @return SYSERR on error, OK if the return value was
- * send successfully
- */
-int sendTCPResult(GNUNET_TCP_SOCKET * sock,
- int ret) {
- CS_returnvalue_MESSAGE rv;
-
- rv.header.size
- = htons(sizeof(CS_returnvalue_MESSAGE));
- rv.header.type
- = htons(CS_PROTO_RETURN_VALUE);
- rv.return_value
- = htonl(ret);
- return writeToSocket(sock,
- &rv.header);
-}
-
-
-
-
-
-/* end of tcp_return.c */
Modified: GNUnet/src/util/network/tcpio.c
===================================================================
--- GNUnet/src/util/network/tcpio.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/network/tcpio.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -19,7 +19,7 @@
*/
/**
- * @file util/tcpio.c
+ * @file util/network/tcpio.c
* @brief code for synchronized access to TCP streams
* @author Christian Grothoff
*
@@ -53,7 +53,7 @@
/**
* the socket handle, -1 if invalid / not life
*/
- int socket;
+ struct SocketHandle * socket;
/**
* the following is the IP for the remote host for client-sockets,
@@ -81,108 +81,156 @@
struct Mutex * writelock;
+ struct CE_Context * ectx;
+
} GNUNET_TCP_SOCKET;
/**
- * CS communication: simple return value
+ * Return the port-number (in host byte order)
*/
-typedef struct {
+static unsigned short getGNUnetPort() {
+ // TODO!
+ static unsigned short port;
+ const char *setting;
- /**
- * The CS header (values: sizeof(CS_returnvalue_MESSAGE) + error-size,
CS_PROTO_RETURN_VALUE)
- */
- MESSAGE_HEADER header;
+ if (port != 0)
+ return port;
+ if (testConfigurationString("GNUNETD",
+ "_MAGIC_",
+ "YES"))
+ setting = "PORT";
+ else
+ setting = "CLIENT-PORT";
- /**
- * The return value (network byte order)
- */
- int return_value;
-} RETURN_VALUE_MESSAGE;
+ port = (unsigned short) getConfigurationInt("NETWORK",
+ setting);
+ if (port == 0) {
+ errexit(_("Cannot determine port of gnunetd server. "
+ "Define in configuration file in section `%s' under `%s'.\n"),
+ "NETWORK",
+ setting);
+ }
+ return port;
+}
+/**
+ * Configuration: get the GNUnetd host where the client
+ * should connect to (via TCP)
+ * @return the name of the host
+ */
+static const char * getGNUnetdHost() {
+ // TODO!
+ static char * res;
+ if (res != NULL)
+ return res;
+ res = getConfigurationString("NETWORK",
+ "HOST");
+ if (res == NULL)
+ res = "localhost";
+ return res;
+}
/**
- * Initialize a GNUnet client socket.
- * @param port the portnumber in host byte order
- * @param ip IP of the host to connect to, in network byte order
+ * Initialize a GNUnet server socket.
+ * @param sock the open socket
* @param result the SOCKET (filled in)
- * @return OK if successful, SYSERR on failure
+ * @return OK (always successful)
*/
-int initGNUnetClientSocketIP(unsigned short port,
- IPaddr ip,
- GNUNET_TCP_SOCKET * result) {
- result->ip = ip;
- result->port = port;
- result->socket = -1; /* closed */
+struct ClientServerConnection *
+client_connection_create(struct GE_Context * ectx,
+ struct GC_Configuration * cfg,
+ struct SocketHandle * sock) {
+ // TODO!
+ result->ip.addr = 0;
+ result->port = 0;
+ result->socket = sock;
result->outBufLen = 0;
result->outBufPending = NULL;
MUTEX_CREATE(&result->readlock);
MUTEX_CREATE(&result->writelock);
- return OK;
+ return result;
}
+
/**
- * Initialize a GNUnet client socket.
- * @param port the portnumber in host byte order
- * @param hostname the name of the host to connect to
- * @param result the SOCKET (filled in)
- * @return OK if successful, SYSERR on failure
+ * Get a GNUnet TCP socket that is connected to gnunetd.
*/
-int initGNUnetClientSocket(unsigned short port,
- const char * hostname,
- GNUNET_TCP_SOCKET * result) {
- GNUNET_ASSERT(hostname != NULL);
-#if DEBUG_TCPIO
- LOG(LOG_DEBUG,
- "Connecting to host '%s:%d'.\n",
- hostname,
- port);
-#endif
- if (OK != GN_getHostByName(hostname,
- &result->ip))
- return SYSERR;
+struct ClientServerConnection *
+daemon_connection_create(struct GE_Context * ectx,
+ struct GC_Configuration * cfg) {
+ // TODO!
+ struct ClientServerConnection * sock;
+ const char * host;
+
+ result->ip = ip;
result->port = port;
result->socket = -1; /* closed */
result->outBufLen = 0;
result->outBufPending = NULL;
MUTEX_CREATE(&result->readlock);
MUTEX_CREATE(&result->writelock);
- return OK;
+
+ if (OK != GN_getHostByName(hostname,
+ &result->ip))
+ return SYSERR;
+
+ sock = MALLOC(sizeof(struct ClientServerConnection));
+ host = getGNUnetdHost();
+ if (SYSERR == initGNUnetClientSocket(getGNUnetPort(),
+ host,
+ sock)) {
+ LOG(LOG_ERROR,
+ _("Could not connect to gnunetd.\n"));
+ FREE(sock);
+ return NULL;
+ }
+ return sock;
}
-/**
- * Initialize a GNUnet server socket.
- * @param sock the open socket
- * @param result the SOCKET (filled in)
- * @return OK (always successful)
- */
-int initGNUnetServerSocket(int sock,
- GNUNET_TCP_SOCKET * result) {
- result->ip.addr = 0;
- result->port = 0;
- result->socket = sock;
- result->outBufLen = 0;
- result->outBufPending = NULL;
- MUTEX_CREATE(&result->readlock);
- MUTEX_CREATE(&result->writelock);
- return OK;
+void connection_close_temporarily(struct ClientServerConnection * sock) {
+ // TODO!
+ int i;
+ GE_ASSERT(NULL, sock != NULL);
+ if (sock->socket != -1) {
+ i = sock->socket;
+#if DEBUG_TCPIO
+ LOG(LOG_DEBUG,
+ "TCP: closing socket %d.\n",
+ sock->socket);
+#endif
+ sock->socket = -1;
+ if (0 != SHUTDOWN(i, SHUT_RDWR))
+ LOG_STRERROR(LOG_DEBUG, "shutdown");
+ CLOSE(i);
+ }
+ sock->outBufLen = 0;
+ FREENONNULL(sock->outBufPending);
+ sock->outBufPending = NULL;
}
-/**
- * Check if a socket is open. Will ALWAYS return 'true'
- * for a valid client socket (even if the connection is
- * closed), but will return false for a closed server socket.
- * @return 1 if open, 0 if closed
- */
-int isOpenConnection(GNUNET_TCP_SOCKET * sock) {
+void connection_destroy(struct ClientServerConnection * sock) {
+ connection_close_temporarily(sock);
+ sock->ip.addr = 0;
+ sock->port = 0;
+ sock->outBufLen = 0;
+ FREENONNULL(sock->outBufPending);
+ sock->outBufPending = NULL;
+ MUTEX_DESTROY(sock->readlock);
+ MUTEX_DESTROY(sock->writelock);
+ FREE(sock);
+}
+
+int connection_test_open(struct ClientServerConnection * sock) {
return (sock->socket != -1);
}
/**
* Check a socket, open and connect if it is closed and it is a client-socket.
*/
-int checkSocket(GNUNET_TCP_SOCKET * sock) {
+int connection_ensure_connected(struct ClientServerConnection * sock) {
+ // TODO!
int res;
struct sockaddr_in soaddr;
fd_set rset;
@@ -265,8 +313,9 @@
* @param buffer the buffer to write
* @return OK if the write was sucessful, otherwise SYSERR.
*/
-int writeToSocket(GNUNET_TCP_SOCKET * sock,
- const CS_MESSAGE_HEADER * buffer) {
+int connection_write(struct ClientServerConnection * sock,
+ const MESSAGE_HEADER * buffer) {
+ // TODO!
int res;
int size;
@@ -315,152 +364,45 @@
return OK;
}
-
-/**
- * Write to a GNUnet TCP socket non-blocking. Note that it is
- * possible that only a part of the message is send and that tcpio
- * buffers the rest until the next writeToSocket operation. If that
- * buffer is full or if send did not transmit any byte of the message,
- * NO is returned to indicate that the write failed (would have
- * blocked).
- *
- * @param sock the socket to write to
- * @param buffer the buffer to write
- * @return OK if the write was sucessful, NO if it would have blocked and was
not performed,
- * otherwise SYSERR.
- */
-int writeToSocketNonBlocking(GNUNET_TCP_SOCKET * sock,
- const CS_MESSAGE_HEADER * buffer) {
- size_t res;
- size_t size;
-
- if (SYSERR == checkSocket(sock))
- return SYSERR;
- MUTEX_LOCK(&sock->writelock);
- if (sock->outBufLen > 0) {
- SEND_NONBLOCKING(sock->socket,
- sock->outBufPending,
- sock->outBufLen,
- &res);
- if (res == (size_t)-1) {
- if ( (errno == EWOULDBLOCK) ||
- (errno == EAGAIN) ) {
- MUTEX_UNLOCK(&sock->writelock);
- return NO;
- }
- LOG_STRERROR(LOG_INFO, "write");
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR;
- }
- if (res < sock->outBufLen) {
- memcpy(sock->outBufPending,
- &((char*)sock->outBufPending)[res],
- sock->outBufLen - res);
- sock->outBufLen -= res;
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR;
- }
- /* completely send out deferred buffer, so
- we can in fact continue! */
- FREENONNULL(sock->outBufPending);
- sock->outBufPending = NULL;
- sock->outBufLen = 0;
- }
-
- size = ntohs(buffer->size);
-
- SEND_NONBLOCKING(sock->socket,
- (const char*)buffer,
- size,
- &res);
- if (res == (size_t) -1) {
- if ( (errno == EWOULDBLOCK) ||
- (errno == EAGAIN) ) {
- MUTEX_UNLOCK(&sock->writelock);
- return NO; /* would block, can not send right now;
- but do NOT close socket in this case;
- do not use SYSERR as return value
- since this is not an error! */
- }
- LOG_STRERROR(LOG_INFO, "send");
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR;
- }
- GNUNET_ASSERT(res <= size);
- if (res != size) {
- sock->outBufPending = MALLOC(size - res);
- memcpy(sock->outBufPending,
- &((const char*)buffer)[res],
- size - res);
- sock->outBufLen = size - res;
- MUTEX_UNLOCK(&sock->writelock);
- return OK; /* return OK here means that the message will be transmitted,
- though it may be a bit later (on the next call, in fact). */
- }
- MUTEX_UNLOCK(&sock->writelock);
- return OK;
-}
-
-/**
- * Read from a GNUnet TCP socket.
- * @param sock the socket
- * @param buffer the buffer to write data to
- * @return OK if the read was successful, SYSERR if the socket
- * was closed by the other side (if the socket is a
- * client socket and is used again, tcpio will attempt
- * to re-establish the connection [temporary error]).
- */
-int readFromSocket(GNUNET_TCP_SOCKET * sock,
- CS_MESSAGE_HEADER ** buffer) {
+int connection_read(struct ClientServerConnection * sock,
+ MESSAGE_HEADER ** buffer) {
int res;
unsigned int pos;
char * buf;
unsigned short size;
- if (SYSERR == checkSocket(sock))
+ if (OK != connection_ensure_connected(sock))
return SYSERR;
-
- MUTEX_LOCK(&sock->readlock);
+
+ MUTEX_LOCK(sock->readlock);
pos = 0;
res = 0;
-
- pos = RECV_BLOCKING_ALL(sock->socket,
+ if ( (OK != socket_recv(sock->handle,
+ NC_Complete,
&size,
- sizeof(unsigned short));
- if (pos != sizeof(unsigned short)) {
-#if DEBUG_TCPIO
- LOG_STRERROR(LOG_INFO, "recv");
-#endif
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->readlock);
- return SYSERR; /* other side closed socket or invalid header */
+ sizeof(unsigned short),
+ &pos)) ||
+ (pos != sizeof(unsigned short)) ) {
+ connection_close_temporarily(sock);
+ MUTEX_UNLOCK(sock->readlock);
+ return SYSERR;
}
size = ntohs(size);
- if (size < sizeof(CS_MESSAGE_HEADER)) {
-#if DEBUG_TCPIO
- LOG_STRERROR(LOG_INFO, "recv");
-#endif
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->readlock);
+ if (size < sizeof(MESSAGE_HEADER)) {
+ connection_close_temporarily(sock);
+ MUTEX_UNLOCK(sock->readlock);
return SYSERR; /* invalid header */
}
- buf = (char*) *buffer;
- if (buf == NULL)
- buf = MALLOC(size);
-
- res = RECV_BLOCKING_ALL(sock->socket,
+ buf = MALLOC(size);
+ if ( (OK != socket_recv(sock->handle,
+ NC_Complete,
&buf[pos],
- size - pos);
-
- if (res != (int)(size - pos)) { /* error, abort */
- if (sock->socket != -1)
- LOG_STRERROR(LOG_INFO, "recv");
- closeSocketTemporarily(sock);
- if (*buffer == NULL)
- FREE(buf);
+ size - pos,
+ &pos)) ||
+ (pos != sizeof(unsigned short) + size) ) {
+ connection_close_temporarily(sock);
+ FREE(buf);
MUTEX_UNLOCK(&sock->readlock);
return SYSERR;
}
@@ -470,54 +412,102 @@
size);
#endif
MUTEX_UNLOCK(&sock->readlock);
- *buffer = (CS_MESSAGE_HEADER*) buf;
+ *buffer = (MESSAGE_HEADER*) buf;
(*buffer)->size = htons(size);
return OK; /* success */
}
+
+
/**
- * Close a GNUnet TCP socket for now (use to temporarily close
- * a TCP connection that will probably not be used for a long
- * time; the socket will still be auto-reopened by the
- * readFromSocket/writeToSocket methods if it is a client-socket).
+ * CS communication: simple return value
*/
-void closeSocketTemporarily(GNUNET_TCP_SOCKET * sock) {
- if (sock == NULL)
- return;
- if (sock->socket != -1) {
- int i;
+typedef struct {
- i = sock->socket;
-#if DEBUG_TCPIO
- LOG(LOG_DEBUG,
- "TCP: closing socket %d.\n",
- sock->socket);
-#endif
- sock->socket = -1;
- if (0 != SHUTDOWN(i, SHUT_RDWR))
- LOG_STRERROR(LOG_DEBUG, "shutdown");
- closefile(i);
+ /**
+ * The CS header (values: sizeof(CS_returnvalue_MESSAGE) + error-size,
CS_PROTO_RETURN_VALUE)
+ */
+ MESSAGE_HEADER header;
+
+ /**
+ * The return value (network byte order)
+ */
+ int return_value;
+
+} RETURN_VALUE_MESSAGE;
+
+/**
+ * Obtain a return value from a remote call from TCP.
+ *
+ * @param sock the TCP socket
+ * @param ret the return value from TCP
+ * @return SYSERR on error, OK if the return value was read
+ * successfully
+ */
+int connection_read_result(struct ClientServerConnection * sock,
+ int * ret) {
+ RETURN_VALUE_MESSAGE * rv;
+
+ rv = NULL;
+ if (SYSERR == connection_read(sock,
+ (MESSAGE_HEADER **) &rv))
+ return SYSERR;
+ if ( (ntohs(rv->header.size) != sizeof(RETURN_VALUE_MESSAGE)) ||
+ (ntohs(rv->header.type) != CS_PROTO_RETURN_VALUE) ) {
+ GE_LOG(sock->ectx,
+ GE_WARNING | GE_DEVELOPER | GE_BULK,
+ _("`%s' failed, reply invalid!\n"),
+ __FUNCTION__);
+ FREE(rv);
+ return SYSERR;
}
- sock->outBufLen = 0;
- FREENONNULL(sock->outBufPending);
- sock->outBufPending = NULL;
+ *ret = ntohl(rv->return_value);
+ FREE(rv);
+ return OK;
}
/**
- * Destroy a socket for good. If you use this socket afterwards,
- * you must first invoke initializeSocket, otherwise the operation
- * will fail.
+ * Send a return value to the caller of a remote call via
+ * TCP.
+ * @param sock the TCP socket
+ * @param ret the return value to send via TCP
+ * @return SYSERR on error, OK if the return value was
+ * send successfully
*/
-void destroySocket(GNUNET_TCP_SOCKET * sock) {
- closeSocketTemporarily(sock);
- sock->ip.addr = 0;
- sock->port = 0;
- sock->outBufLen = 0;
- FREENONNULL(sock->outBufPending);
- sock->outBufPending = NULL;
- MUTEX_DESTROY(&sock->readlock);
- MUTEX_DESTROY(&sock->writelock);
+int connection_write_result(struct ClientServerConnection * sock,
+ int ret) {
+ RETURN_VALUE_MESSAGE rv;
+
+ rv.header.size
+ = htons(sizeof(CS_returnvalue_MESSAGE));
+ rv.header.type
+ = htons(CS_PROTO_RETURN_VALUE);
+ rv.return_value
+ = htonl(ret);
+ return connection_write(sock,
+ &rv.header,
+ YES);
}
+/**
+ * Send a return value that indicates
+ * a serious error to the other side.
+ *
+ * @param sock the TCP socket
+ * @param mask GE_MASK
+ * @param date date string
+ * @param msg message string
+ * @return SYSERR on error, OK if the error code was send
+ * successfully
+ */
+int connection_write_error(struct ClientServerConnection * sock,
+ GE_KIND mask,
+ const char * date,
+ const char * msg) {
+ return SYSERR; /* not implemented! */
+}
+
+
+
/* end of tcpio.c */
Modified: GNUnet/src/util/os/Makefile.am
===================================================================
--- GNUnet/src/util/os/Makefile.am 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/os/Makefile.am 2006-06-24 20:37:52 UTC (rev 3037)
@@ -6,6 +6,7 @@
libos.la
libos_la_SOURCES = \
+ cpustatus.c \
daemon.c \
dso.c \
osconfig.c \
Added: GNUnet/src/util/os/cpustatus.c
===================================================================
--- GNUnet/src/util/os/cpustatus.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/os/cpustatus.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -0,0 +1,435 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 2005, 2006 Christian Grothoff (and other
contributing authors)
+
+ GNUnet 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, or (at your
+ option) any later version.
+
+ GNUnet 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 GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file util/os/cpustatus.c
+ * @brief calls to determine current network and CPU load
+ * @author Tzvetan Horozov
+ * @author Christian Grothoff
+ * @author Igor Wronsky
+ *
+ * Status calls implementation for load management.
+ */
+
+#include "platform.h"
+#include "gnunet_util_os.h"
+#include "gnunet_util_error.h"
+#include "gnunet_util_threads.h"
+
+#if SOLARIS
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+#if HAVE_SYS_SYSINFO_H
+#include <sys/sysinfo.h>
+#endif
+#if HAVE_KVM_H
+#include <kvm.h>
+#endif
+#endif
+#if SOMEBSD
+#if HAVE_KVM_H
+#include <kvm.h>
+#endif
+#endif
+
+#define DEBUG_STATUSCALLS NO
+
+#ifdef LINUX
+static FILE * proc_stat;
+#endif
+
+static struct MUTEX * statusMutex;
+
+/**
+ * The following routine returns a number between 0-100 (can be larger
+ * than 100 if the load is > 1) which indicates the percentage CPU
+ * usage.
+ *
+ * Before its first invocation the method initStatusCalls() must be called.
+ * If there is an error the method returns -1
+ */
+static int updateCpuUsage(){
+ int currentLoad;
+#ifdef LINUX
+ /* under linux, first try %idle/usage using /proc/stat;
+ if that does not work, disable /proc/stat for the future
+ by closing the file and use the next-best method. */
+ if (proc_stat != NULL) {
+ static unsigned long long last_cpu_results[4] = { 0, 0, 0, 0 };
+ static int have_last_cpu = NO;
+ char line[128];
+ unsigned long long user_read, system_read, nice_read, idle_read;
+ unsigned long long user, system, nice, idle;
+ unsigned long long usage_time=0, total_time=1;
+
+ /* Get the first line with the data */
+ rewind(proc_stat);
+ fflush(proc_stat);
+ if (NULL == fgets(line, 128, proc_stat)) {
+ GE_LOG_STRERROR_FILE(NULL,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_BULK,
+ "fgets",
+ "/proc/stat");
+ fclose(proc_stat);
+ proc_stat = NULL; /* don't try again */
+ } else {
+ if (sscanf(line, "%*s %llu %llu %llu %llu",
+ &user_read,
+ &system_read,
+ &nice_read,
+ &idle_read) != 4) {
+ GE_LOG_STRERROR_FILE(NULL,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_BULK,
+ "fgets-sscanf",
+ "/proc/stat");
+ fclose(proc_stat);
+ proc_stat = NULL; /* don't try again */
+ have_last_cpu = NO;
+ } else {
+ /* Store the current usage*/
+ user = user_read - last_cpu_results[0];
+ system = system_read - last_cpu_results[1];
+ nice = nice_read - last_cpu_results[2];
+ idle = idle_read - last_cpu_results[3];
+ /* Calculate the % usage */
+ if ( (user + system + nice + idle) > 0) {
+ usage_time = user + system + nice;
+ total_time = usage_time + idle;
+ }
+ if ( (total_time > 0) &&
+ (have_last_cpu == YES) )
+ currentLoad = (100 * usage_time) / total_time;
+ else
+ currentLoad = -1;
+ /* Store the values for the next calculation*/
+ last_cpu_results[0] = user_read;
+ last_cpu_results[1] = system_read;
+ last_cpu_results[2] = nice_read;
+ last_cpu_results[3] = idle_read;
+ have_last_cpu = YES;
+ return currentLoad;
+ }
+ }
+ }
+#endif
+
+ /* try kstat (Solaris only) */
+#if SOLARIS && HAVE_KSTAT_H && HAVE_SYS_SYSINFO_H
+ {
+ static long long last_idlecount;
+ static long long last_totalcount;
+ static int kstat_once; /* if open fails, don't keep
+ trying */
+ kstat_ctl_t * kc;
+ kstat_t * khelper;
+ long long idlecount;
+ long long totalcount;
+ long long deltaidle;
+ long long deltatotal;
+
+ if (kstat_once == 1)
+ goto ABORT_KSTAT;
+ kc = kstat_open();
+ if (kc == NULL) {
+ GE_LOG_STRERROR(NULL,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_BULK,
+ "kstat_open");
+ goto ABORT_KSTAT;
+ }
+
+ idlecount = 0;
+ totalcount = 0;
+ for (khelper = kc->kc_chain;
+ khelper != NULL;
+ khelper = khelper->ks_next) {
+ cpu_stat_t stats;
+
+ if (0 != strncmp(khelper->ks_name,
+ "cpu_stat",
+ strlen("cpu_stat")) )
+ continue;
+ if (khelper->ks_data_size > sizeof(cpu_stat_t))
+ continue; /* better save then sorry! */
+ if (-1 != kstat_read(kc, khelper, &stats)) {
+ idlecount
+ += stats.cpu_sysinfo.cpu[CPU_IDLE];
+ totalcount
+ += stats.cpu_sysinfo.cpu[CPU_IDLE] +
+ stats.cpu_sysinfo.cpu[CPU_USER] +
+ stats.cpu_sysinfo.cpu[CPU_KERNEL] +
+ stats.cpu_sysinfo.cpu[CPU_WAIT];
+ }
+ }
+ if (0 != kstat_close(kc))
+ GE_LOG_STRERROR(NULL,
+ GE_ERROR | GE_ADMIN | GE_USER | GE_BULK,
+ "kstat_close");
+ if ( (idlecount == 0) &&
+ (totalcount == 0) )
+ goto ABORT_KSTAT; /* no stats found => abort */
+ deltaidle = idlecount - last_idlecount;
+ deltatotal = totalcount - last_totalcount;
+ if ( (deltatotal > 0) &&
+ (last_totalcount > 0) )
+ currentLoad = (int) (100 * deltaidle / deltatotal);
+ else
+ currentLoad = -1;
+ last_idlecount = idlecount;
+ last_totalcount = totalcount;
+ return currentLoad;
+ ABORT_KSTAT:
+ kstat_once = 1; /* failed, don't try again */
+ }
+#endif
+
+ /* insert methods better than getloadavg for
+ other platforms HERE! */
+
+ /* ok, maybe we have getloadavg on this platform */
+#if HAVE_GETLOADAVG
+ {
+ static int warnOnce = 0;
+ double loadavg;
+ if (1 != getloadavg(&loadavg, 1)) {
+ /* only warn once, if there is a problem with
+ getloadavg, we're going to hit it frequently... */
+ if (warnOnce == 0) {
+ warnOnce = 1;
+ GE_LOG_STRERROR(NULL,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_BULK,
+ "getloadavg");
+ }
+ currentLoad = -1;
+ } else {
+ /* success with getloadavg */
+ currentLoad = (int) (100 * loadavg);
+ return currentLoad;
+ }
+ }
+#endif
+
+#if MINGW
+ /* Win NT? */
+ if (GNNtQuerySystemInformation) {
+ static double dLastKernel;
+ static double dLastIdle;
+ static double dLastUser;
+ double dKernel;
+ double dIdle;
+ double dUser;
+ double dDiffKernel;
+ double dDiffIdle;
+ double dDiffUser;
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION theInfo;
+
+ if (GNNtQuerySystemInformation(SystemProcessorPerformanceInformation,
+ &theInfo,
+ sizeof(theInfo),
+ NULL) == NO_ERROR) {
+ /* PORT-ME MINGW: Multi-processor? */
+ dKernel = Li2Double(theInfo.KernelTime);
+ dIdle = Li2Double(theInfo.IdleTime);
+ dUser = Li2Double(theInfo.UserTime);
+ dDiffKernel = dKernel - dLastKernel;
+ dDiffIdle = dIdle - dLastIdle;
+ dDiffUser = dUser - dLastUser;
+
+ if ( ( (dDiffKernel + dDiffUser) > 0) &&
+ (dLastIdle + dLastKernel + dLastUser > 0) )
+ currentLoad = 100.0 - (dDiffIdle / (dDiffKernel + dDiffUser)) * 100.0;
+ else
+ currentLoad = -1; /* don't know (yet) */
+
+ dLastKernel = dKernel;
+ dLastIdle = dIdle;
+ dLastUser = dUser;
+
+ return currentLoad;
+ } else {
+ /* only warn once, if there is a problem with
+ NtQuery..., we're going to hit it frequently... */
+ static int once;
+ if (once == 0) {
+ once = 1;
+ GE_LOG(NULL,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_BULK,
+ _("Cannot query the CPU usage (Windows NT).\n"));
+ }
+ }
+ } else { /* Win 9x */
+ HKEY hKey;
+ DWORD dwDataSize, dwType, dwDummy;
+
+ /* Start query */
+ if (RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StartSrv",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey) != ERROR_SUCCESS) {
+ /* only warn once */
+ static int once = 0;
+ if (once == 0) {
+ once = 1;
+ GE_LOG(NULL,
+ GE_USER | GE_ADMIN | GE_ERROR | GE_BULK,
+ _("Cannot query the CPU usage (Win 9x)\n"));
+ }
+ }
+
+ RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StartStat",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ dwDataSize = sizeof(dwDummy);
+ RegQueryValueEx(hKey,
+ "KERNEL\\CPUUsage",
+ NULL,
+ &dwType,
+ (LPBYTE) &dwDummy,
+ &dwDataSize);
+ RegCloseKey(hKey);
+
+ /* Get CPU usage */
+ RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StatData",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ dwDataSize = sizeof(currentLoad);
+ RegQueryValueEx(hKey,
+ "KERNEL\\CPUUsage",
+ NULL,
+ &dwType,
+ (LPBYTE) ¤tLoad,
+ &dwDataSize);
+ RegCloseKey(hKey);
+
+ /* Stop query */
+ RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StopStat",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StopSrv",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ dwDataSize = sizeof(dwDummy);
+ RegQueryValueEx(hKey,
+ "KERNEL\\CPUUsage",
+ NULL,
+ &dwType,
+ (LPBYTE)&dwDummy,
+ &dwDataSize);
+ RegCloseKey(hKey);
+
+ return currentLoad;
+ }
+#endif
+
+ /* loadaverage not defined and no platform
+ specific alternative defined
+ => default: error
+ */
+ return -1;
+}
+
+
+/**
+ * Get the load of the CPU relative to what is allowed.
+ * @return the CPU load as a percentage of allowed
+ * (100 is equivalent to full load)
+ */
+int os_cpu_get_load(struct GE_Context * ectx,
+ struct GC_Configuration * cfg) {
+ static int currentLoad;
+ static int lastRet = -1;
+ static cron_t lastCall;
+ unsigned long long maxCPULoad;
+ int ret;
+ cron_t now;
+
+ if (-1 == GC_get_configuration_value_number(cfg,
+ "LOAD",
+ "MAXCPULOAD",
+ 0,
+ 100,
+ 100,
+ &maxCPULoad))
+ return -1;
+ MUTEX_LOCK(statusMutex);
+ ret = (100 * currentLoad) / maxCPULoad;
+ now = get_time();
+ if ( (lastRet != -1) &&
+ (now - lastCall < 250 * cronMILLIS) ) {
+ /* use smoothing, but do NOT update lastRet at frequencies higher
+ than 250ms; this makes the smoothing (mostly) independent from
+ the frequency at which getCPULoad is called. */
+ ret = (ret + 7 * lastRet)/8;
+ MUTEX_UNLOCK(statusMutex);
+ return ret;
+ }
+ currentLoad = updateCpuUsage();
+ ret = (100 * currentLoad) / maxCPULoad;
+ /* for CPU, we don't do the 'fast increase' since CPU is much
+ more jitterish to begin with */
+ if (lastRet != -1)
+ ret = (ret + 7 * lastRet) / 8;
+ lastRet = ret;
+ lastCall = now;
+ MUTEX_UNLOCK(statusMutex);
+ return ret;
+}
+
+/**
+ * The following method is called in order to initialize the status calls
+ * routines. After that it is safe to call each of the status calls separately
+ * @return OK on success and SYSERR on error (or calls errexit).
+ */
+void __attribute__ ((constructor)) gnunet_cpustats_ltdl_init() {
+ statusMutex = MUTEX_CREATE(NO);
+#ifdef LINUX
+ proc_stat = fopen("/proc/stat", "r");
+ if (NULL == proc_stat)
+ GE_LOG_STRERROR_FILE(NULL,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_BULK,
+ "fopen",
+ "/proc/stat");
+#endif
+}
+
+/**
+ * Shutdown the status calls module.
+ */
+void __attribute__ ((destructor)) gnunet_cpustats_ltdl_fini() {
+#ifdef LINUX
+ if (proc_stat != NULL) {
+ fclose(proc_stat);
+ proc_stat = NULL;
+ }
+#endif
+ MUTEX_DESTROY(statusMutex);
+}
+
+
+/* end of cpustatus.c */
Modified: GNUnet/src/util/os/daemon.c
===================================================================
--- GNUnet/src/util/os/daemon.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/os/daemon.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -19,52 +19,15 @@
*/
/**
- * @file src/util/daemon.c
- * @brief code for client-gnunetd interaction (start, stop, waitpid, check
running)
+ * @file src/util/os/daemon.c
+ * @brief code for client-gnunetd interaction (start, stop, waitpid)
* @author Christian Grothoff
*/
#include "platform.h"
-#include "gnunet_util.h"
-#include "gnunet_protocols.h"
+#include "gnunet_util_os.h"
+#include "gnunet_util_string.h"
-
-/**
- * Checks if gnunetd is running
- *
- * Uses CS_PROTO_traffic_COUNT query to determine if gnunetd is
- * running.
- *
- * @return OK if gnunetd is running, SYSERR if not
- */
-int checkGNUnetDaemonRunning(struct GE_Context * ectx) {
- GNUNET_TCP_SOCKET * sock;
- CS_MESSAGE_HEADER csHdr;
- int ret;
-
- sock = getClientSocket(ectx);
- if (sock == NULL)
- return SYSERR;
-
- csHdr.size
- = htons(sizeof(CS_MESSAGE_HEADER));
- csHdr.type
- = htons(CS_PROTO_traffic_COUNT);
- if (SYSERR == writeToSocket(sock,
- &csHdr)) {
- releaseClientSocket(sock);
- return SYSERR;
- }
- if (SYSERR == readTCPResult(sock,
- &ret)) {
- releaseClientSocket(sock);
- return SYSERR;
- }
- releaseClientSocket(sock);
- return OK;
-}
-
-
#if LINUX || OSX || SOLARIS || SOMEBSD
/**
* Fork a gnunetd process
@@ -73,45 +36,44 @@
* @return pid_t of gnunetd if NOT daemonized, 0 if
* daemonized sucessfully, -1 on error
*/
-static pid_t launchWithExec(int daemonize) {
+static pid_t launchWithExec(struct GE_Context * ectx,
+ const char * binary_home,
+ const char * cfgFile,
+ int daemonize) {
pid_t pid;
pid = fork();
if (pid == 0) {
- char * args[5];
+ const char * args[5];
char * path;
char * cp;
+ int i;
path = NULL;
- cp = getConfigurationString("MAIN",
- "ARGV[0]");
- if (cp != NULL) {
- int i = strlen(cp);
- while ( (i >= 0) &&
- (cp[i] != DIR_SEPARATOR) )
+ cp = STRDUP(binary_home);
+ i = strlen(cp);
+ while ( (i >= 0) &&
+ (cp[i] != DIR_SEPARATOR) )
i--;
- if ( i != -1 ) {
- cp[i+1] = '\0';
- path = MALLOC(i+2+strlen("gnunetd"));
- strcpy(path, cp);
- strcat(path, "gnunetd");
- if (ACCESS(path, X_OK) == 0) {
- args[0] = path;
- } else {
- FREE(path);
- path = NULL;
- args[0] = "gnunetd";
- }
- FREE(cp);
+ if ( i != -1 ) {
+ cp[i+1] = '\0';
+ path = MALLOC(i+2+strlen("gnunetd"));
+ strcpy(path, cp);
+ strcat(path, "gnunetd");
+ if (ACCESS(path, X_OK) == 0) {
+ args[0] = path;
} else {
+ FREE(path);
+ path = NULL;
args[0] = "gnunetd";
}
+ FREE(cp);
+ } else {
+ args[0] = "gnunetd";
}
- cp = getConfigurationString("GNUNET",
- "GNUNETD-CONFIG");
- if (cp != NULL) {
+ if (cfgFile != NULL) {
args[1] = "-c";
- args[2] = cp;
+ args[2] = cfgFile;
if (NO == daemonize) {
args[3] = "-d";
args[4] = NULL;
@@ -127,20 +89,20 @@
errno = 0;
nice(10); /* return value is not well-defined */
if (errno != 0)
- LOG_STRERROR(LOG_WARNING, "nice");
+ GE_LOG_STRERROR(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "nice");
if (path != NULL)
execv(path,
- args);
+ (char**) args);
else
execvp("gnunetd",
- args);
- LOG_STRERROR(LOG_FAILURE, "exec");
- LOG(LOG_FAILURE,
- _("Attempted path to `%s' was `%s'.\n"),
- "gnunetd",
- (path == NULL) ? "gnunetd" : path);
- FREENONNULL(path); /* yeah, right, like we're likely to get
- here... */
+ (char**) args);
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_ERROR | GE_USER | GE_BULK,
+ "exec",
+ path == NULL ? "gnunetd" : path);
+ FREENONNULL(path);
_exit(-1);
} else if (daemonize) {
pid_t ret;
@@ -148,7 +110,9 @@
ret = waitpid(pid, &status, 0);
if (ret == -1) {
- LOG_STRERROR(LOG_ERROR, "waitpid");
+ GE_LOG_STRERROR(ectx,
+ GE_ERROR | GE_USER | GE_BULK,
+ "waitpid");
return SYSERR;
}
if ( (WIFEXITED(status) &&
@@ -177,9 +141,26 @@
* @return pid_t of gnunetd if NOT daemonized, 0 if
* daemonized sucessfully, -1 on error
*/
-int startGNUnetDaemon(int daemonize) {
+int os_daemon_start(struct GE_Context * ectx,
+ struct GC_Configuration * cfg,
+ const char * cfgFile,
+ int daemonize) {
#if LINUX || OSX || SOLARIS || SOMEBSD
- return launchWithExec(daemonize);
+ int ret;
+ char * binName;
+
+ if (0 != GC_get_configuration_value_string(cfg,
+ "ARGV",
+ "0",
+ NULL,
+ &binName))
+ return -1;
+ ret = launchWithExec(ectx,
+ cfgFile,
+ binName,
+ daemonize);
+ FREE(binName);
+ return ret;
#elif MINGW
char szCall[_MAX_PATH + 1], szWd[_MAX_PATH + 1], szCWd[_MAX_PATH + 1];
char *args[1], *cp = NULL;
@@ -193,20 +174,22 @@
chdir(szWd);
if (daemonize == NO) {
- args[0] = "-d";
- idx = 1;
-
+ args[0] = "-d";
+ idx = 1;
+
cp = getConfigurationString("GNUNET",
"GNUNETD-CONFIG");
- if (cp) {
- args[1] = "-c";
- args[2] = cp;
- idx=3;
- }
+ if (cp) {
+ args[1] = "-c";
+ args[2] = cp;
+ idx=3;
+ }
}
args[idx] = NULL;
- pid = spawnvp(_P_NOWAIT, szCall, (const char *const *) args);
+ pid = spawnvp(_P_NOWAIT,
+ szCall,
+ (const char *const *) args);
chdir(szCWd);
FREENONNULL(cp);
@@ -220,68 +203,33 @@
#endif
}
-
-/**
- * Stop gnunetd
- *
- * Note that returning an error does NOT mean that
- * gnunetd will continue to run (it may have been
- * shutdown by something else in the meantime or
- * crashed). Call checkDaemonRunning() frequently
- * to check the status of gnunetd.
- *
- * Furthermore, note that this WILL potentially kill
- * gnunetd processes on remote machines that cannot
- * be restarted with startGNUnetDaemon!
- *
- * This function does NOT need the PID and will also
- * kill daemonized gnunetd's.
- *
- * @return OK successfully stopped, SYSERR: error
- */
-int stopGNUnetDaemon() {
- GNUNET_TCP_SOCKET * sock;
- CS_MESSAGE_HEADER csHdr;
+static int termProcess(int pid) {
+#ifndef MINGW
+ return kill(pid, SIGTERM) == 0;
+#else
int ret;
-
- sock = getClientSocket();
- if (sock == NULL)
- return SYSERR;
- csHdr.size
- = htons(sizeof(CS_MESSAGE_HEADER));
- csHdr.type
- = htons(CS_PROTO_SHUTDOWN_REQUEST);
- if (SYSERR == writeToSocket(sock,
- &csHdr)) {
- releaseClientSocket(sock);
- return SYSERR;
+ DWORD dwExitCode = 0;
+
+ HANDLE hProc = OpenProcess(1, 0, pid);
+ GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid);
+
+ WaitForSingleObject(hProc, 3000);
+
+ GetExitCodeProcess(hProc, &dwExitCode);
+ if(dwExitCode == STILL_ACTIVE) {
+ ret = TerminateProcess(hProc, 0);
}
- if (SYSERR == readTCPResult(sock,
- &ret)) {
- releaseClientSocket(sock);
- return SYSERR;
- }
- releaseClientSocket(sock);
+ else
+ ret = 1;
+
+ CloseHandle(hProc);
+
return ret;
+#endif
}
-/**
- * Wait until the gnunet daemon is
- * running.
- *
- * @param timeout how long to wait at most
- * @return OK if gnunetd is now running
- */
-int waitForGNUnetDaemonRunning(cron_t timeout) {
- timeout += cronTime(NULL);
- while (OK != checkGNUnetDaemonRunning()) {
- gnunet_util_sleep(100 * cronMILLIS);
- if (timeout < cronTime(NULL))
- return checkGNUnetDaemonRunning();
- }
- return OK;
-}
+
/**
* Wait until the gnunet daemon (or any other CHILD process for that
* matter) with the given PID has terminated. Assumes that
@@ -293,13 +241,17 @@
* failed, NO if gnunetd shutdown with
* some error
*/
-int waitForGNUnetDaemonTermination(int pid) {
+int os_daemon_stop(struct GE_Context * ectx,
+ int pid) {
pid_t p;
int status;
+ termProcess(pid);
p = pid;
if (p != WAITPID(p, &status, 0)) {
- LOG_STRERROR(LOG_ERROR, "waitpid");
+ GE_LOG_STRERROR(ectx,
+ GE_ERROR | GE_USER | GE_BULK,
+ "waitpid");
return SYSERR;
}
if (WEXITSTATUS(status) == 0)
@@ -308,29 +260,4 @@
return NO;
}
-int termProcess(int pid) {
-#ifndef MINGW
- return kill(pid, SIGTERM) == 0;
-#else
- int ret;
- DWORD dwExitCode = 0;
-
- HANDLE hProc = OpenProcess(1, 0, pid);
- GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid);
-
- WaitForSingleObject(hProc, 3000);
-
- GetExitCodeProcess(hProc, &dwExitCode);
- if(dwExitCode == STILL_ACTIVE) {
- ret = TerminateProcess(hProc, 0);
- }
- else
- ret = 1;
-
- CloseHandle(hProc);
-
- return ret;
-#endif
-}
-
/* end of daemon.c */
Modified: GNUnet/src/util/os/dso.c
===================================================================
--- GNUnet/src/util/os/dso.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/os/dso.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -26,6 +26,7 @@
#include "platform.h"
#include "gnunet_util_os.h"
+#include "gnunet_util_string.h"
typedef struct PluginHandle {
struct GE_Context * ectx;
@@ -146,7 +147,7 @@
return plug;
}
-void os_plugin_unload(struct PluginHandle * libhandle) {
+void os_plugin_unload(struct PluginHandle * plugin) {
lt_dlclose(plugin->handle);
FREE(plugin->libprefix);
FREE(plugin->dsoname);
@@ -154,7 +155,7 @@
}
void *
-os_plugin_resolve_function(struct PluginHandle * plugin,
+os_plugin_resolve_function(struct PluginHandle * plug,
const char * methodprefix,
int logError) {
char * initName;
@@ -164,10 +165,10 @@
strlen(methodprefix) + 2);
strcpy(initName, "_");
strcat(initName, methodprefix);
- strcat(initName, dsoname);
- mptr = lt_dlsym(libhandle, &initName[1]);
+ strcat(initName, plug->dsoname);
+ mptr = lt_dlsym(plug->handle, &initName[1]);
if (mptr == NULL)
- mptr = lt_dlsym(libhandle, initName);
+ mptr = lt_dlsym(plug->handle, initName);
if ( (mptr == NULL) &&
(logError) )
GE_LOG(plug->ectx,
Modified: GNUnet/src/util/os/osconfig.c
===================================================================
--- GNUnet/src/util/os/osconfig.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/os/osconfig.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -20,21 +20,23 @@
*/
/**
- * @file util/osconfig.c
+ * @file util/os/osconfig.c
* @brief functions to read or change the OS configuration
* @author Nils Durner
*/
#include "platform.h"
-#include "gnunet_util.h"
+#include "gnunet_util_os.h"
+#include "gnunet_util_string.h"
/**
* @brief Enumerate all network interfaces
* @param callback the callback function
*/
-void enumNetworkIfs(void (*callback) (const char *, int, void *),
- void * cls) {
+void os_list_network_interfaces(struct GE_Context * ectx,
+ NetworkIfcProcessor proc,
+ void * cls) {
#ifdef MINGW
- ListNICs(callback, cls);
+ ListNICs(proc, cls);
#else
char entry[11], *dst;
FILE *f;
@@ -46,42 +48,46 @@
f = NULL;
else
f = popen("ifconfig 2> /dev/null", "r");
-
- if (!f)
+ if (!f) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_USER | GE_ADMIN | GE_BULK | GE_WARNING,
+ "popen",
+ "ifconfig");
return;
+ }
- while(1)
- {
- int i = 0;
- int c = fgetc(f);
-
- if (c == EOF)
- break;
-
- dst = entry;
-
- /* Read interface name until the first space (or colon under OS X) */
- while (c != EOF && c != '\n' &&
+ while(1) {
+ int i = 0;
+ int c = fgetc(f);
+
+ if (c == EOF)
+ break;
+
+ dst = entry;
+
+ /* Read interface name until the first space (or colon under OS X) */
+ while (c != EOF && c != '\n' &&
#ifdef OSX
- c != ':'
+ c != ':'
#else
- c != ' '
+ c != ' '
#endif
- && i < 10)
- {
- *dst++ = c;
- i++;
- c = fgetc(f);
- }
- *dst = 0;
-
- if (entry[0])
- callback(entry, strcmp(entry, "eth0") == 0, cls);
-
- while(c != '\n' && c != EOF)
- c = fgetc(f);
+ && i < 10) {
+ *dst++ = c;
+ i++;
+ c = fgetc(f);
}
-
+ *dst = 0;
+
+ if ( (entry[0] != '\0') &&
+ (OK != proc(entry,
+ strcmp(entry, "eth0") == 0,
+ cls)) )
+ break;
+
+ while ((c != '\n') && (c != EOF))
+ c = fgetc(f);
+ }
pclose(f);
#endif
}
@@ -90,159 +96,171 @@
* @brief Checks if we can start GNUnet automatically
* @return 1 if yes, 0 otherwise
*/
-int isOSAutostartCapable() {
+static int isOSAutostartCapable() {
#ifdef LINUX
- if (ACCESS("/usr/sbin/update-rc.d", X_OK) == 0) {
+ if (ACCESS("/usr/sbin/update-rc.d",
+ X_OK) == 0) {
/* Debian */
- if (ACCESS("/etc/init.d/", W_OK) == 0)
+ if (ACCESS("/etc/init.d/",
+ W_OK) == 0)
return 1;
}
return 0;
#else
- #ifdef WINDOWS
- return 1;
- #else
- return 0;
- #endif
+#ifdef WINDOWS
+ return IsWinNT();
+#else
+ return 0;
#endif
+#endif
}
-/**
- * @brief Make GNUnet start automatically
- * @param doAutoStart true to enable autostart, false to disable it
- * @param username name of the user account to use
- * @param groupname name of the group to use
- * @return 0 on success
- */
-int autostartService(int doAutoStart,
- const char * username,
- const char * groupname) {
+int os_modify_autostart(struct GE_Context * ectx,
+ int testCapability,
+ int doAutoStart,
+ const char * application,
+ const char * username,
+ const char * groupname) {
+ if (testCapability) {
+ /* TODO: check that user/group/application
+ exist! */
+ return isOSAutostartCapable();
+ }
#ifdef WINDOWS
- if (doAutoStart)
- {
- if (IsWinNT())
- {
- char *err = NULL;
- DWORD dwErr = 0;
+ if (doAutoStart) {
+ if (IsWinNT()) {
+ char *err = NULL;
+ DWORD dwErr = 0;
+
+ if (username && !strlen(username))
+ username = NULL;
+
+ /* Install service */
+ switch (InstallAsService(username)) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ if (GetLastError() != ERROR_SERVICE_EXISTS)
+ return 1;
+ case 3:
+ return 2;
+ default:
+ return -1;
+ }
+
+ /* Grant permissions to the GNUnet directory */
+ if ((!err || dwErr == ERROR_SERVICE_EXISTS) && username) {
+ char szHome[_MAX_PATH + 1];
- if (username && !strlen(username))
- username = NULL;
+ plibc_conv_to_win_path("/", szHome);
- /* Install service */
- switch(InstallAsService(username))
- {
- case 0:
- case 1:
- break;
- case 2:
- if (GetLastError() != ERROR_SERVICE_EXISTS)
- return 1;
- case 3:
- return 2;
- default:
- return -1;
- }
+ if (!AddPathAccessRights(szHome, username, GENERIC_ALL))
+ return 3;
+ }
+ } else {
+ char szPath[_MAX_PATH + 1];
+ HKEY hKey;
+
+ plibc_conv_to_win_path(application, szPath);
+
+ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0,
KEY_EXECUTE,
+ &hKey) == ERROR_SUCCESS) {
+ if (RegSetValueEx(hKey,
+ "GNUnet",
+ 0,
+ REG_SZ,
+ szPath,
+ strlen(szPath)) != ERROR_SUCCESS)
+ return 4;
- /* Grant permissions to the GNUnet directory */
- if ((!err || dwErr == ERROR_SERVICE_EXISTS) && username)
- {
- char szHome[_MAX_PATH + 1];
-
- plibc_conv_to_win_path("/", szHome);
-
- if (!AddPathAccessRights(szHome, username, GENERIC_ALL))
- return 3;
- }
- }
- else
- {
- char szPath[_MAX_PATH + 1];
- HKEY hKey;
-
- plibc_conv_to_win_path("/bin/gnunetd.exe", szPath);
-
- if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_EXECUTE,
- &hKey) == ERROR_SUCCESS)
- {
- if (RegSetValueEx(hKey, "GNUnet", 0, REG_SZ, szPath, strlen(szPath)) !=
- ERROR_SUCCESS)
- return 4;
-
- RegCloseKey(hKey);
+ RegCloseKey(hKey);
+ } else
+ return 4;
}
- else
- return 4;
- }
+ } else {
+ if (IsWinNT()) {
+ switch (UninstallService()) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ return 1;
+ case 3:
+ return 5;
+ case 4:
+ return 6;
+ default:
+ return -1;
+ }
+ } else {
+ HKEY hKey;
+
+ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
+ 0,
+ KEY_SET_VALUE,
+ &hKey) == ERROR_SUCCESS) {
+ RegDeleteValue(hKey, "GNUnet");
+ RegCloseKey(hKey);
+ }
}
- else
- {
- if (IsWinNT())
- {
- switch (UninstallService())
- {
- case 0:
- case 1:
- break;
- case 2:
- return 1;
- case 3:
- return 5;
- case 4:
- return 6;
- default:
- return -1;
- }
- }
- else
- {
- HKEY hKey;
-
- if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
0, KEY_SET_VALUE,
- &hKey) == ERROR_SUCCESS)
- {
- RegDeleteValue(hKey, "GNUnet");
-
- RegCloseKey(hKey);
- }
- }
- }
+ }
#else
+ struct stat buf;
+
/* Unix */
- if (ACCESS("/usr/sbin/update-rc.d", X_OK) == 0) {
- /* Debian */
- if (doAutoStart) {
- struct stat buf;
- if (STAT("/etc/init.d/gnunetd", &buf) == -1) {
- /* create init file */
- FILE *f = FOPEN("/etc/init.d/gnunetd", "w");
- if (! f)
- return 1;
-
- fputs("#! /bin/sh\n"
+ if ( (ACCESS("/usr/sbin/update-rc.d",
+ X_OK) != 0) ) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "access",
+ "/usr/sbin/update-rc.d");
+ return SYSERR;
+ }
+
+ /* Debian */
+ if (doAutoStart) {
+ if (ACCESS(application,
+ X_OK) != 0) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "access",
+ application);
+ }
+ if (STAT("/etc/init.d/gnunetd",
+ &buf) == -1) {
+ /* create init file */
+ FILE * f = FOPEN("/etc/init.d/gnunetd", "w");
+ if (! f) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "fopen",
+ "/etc/init.d/gnunetd");
+ return 1;
+ }
+
+ fprintf(f,
+ "#!/bin/sh\n"
"#\n"
- "# Automatically created by gnunet-setup\n"
+ "# Automatically created by %s\n"
"#\n"
"\n"
- "PATH=$PATH:" PREFIX_PATH "/bin"
"PIDFILE=/var/run/gnunetd/gnunetd.pid\n"
"\n"
"case \"$1\" in\n"
" start)\n"
" echo -n \"Starting GNUnet: \"\n"
- " gnunetd\n"
- " echo \"gnunetd\"\n"
+ " %s\n && echo ok || echo failed\n"
" ;;\n"
" stop)\n"
" echo -n \"Stopping GNUnet: \"\n"
- " kill `cat $PIDFILE`\n"
- " echo \"gnunetd\"\n"
+ " kill `cat $PIDFILE`\n && echo ok || echo failed\n"
" ;;\n"
" reload)\n"
" echo -n \"Reloading GNUnet: \"\n"
- " kill -HUP `cat $PIDFILE`\n"
- " echo \"gnunetd\"\n"
+ " kill -HUP `cat $PIDFILE`\n && echo ok || echo failed\n"
" ;;\n"
" restart|force-reload)\n"
" echo \"Restarting GNUnet: gnunetd...\"\n"
@@ -256,148 +274,132 @@
" ;;\n"
"\n"
"esac\n"
- "exit 0\n", f);
- fclose(f);
- CHMOD("/etc/init.d/gnunetd", S_IRWXU | S_IRGRP | S_IXGRP |
- S_IROTH | S_IXOTH);
+ "exit 0\n",
+ "gnunet-setup",
+ application);
+ fclose(f);
+ if (0 != CHMOD("/etc/init.d/gnunetd",
+ S_IRWXU | S_IRGRP | S_IXGRP |
+ S_IROTH | S_IXOTH)) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "chmod",
+ "/etc/init.d/gnunetd");
+ return SYSERR;
}
- errno = system("/usr/sbin/update-rc.d gnunetd defaults");
- if (errno != 0)
- return 1;
}
- else {
- if ( (UNLINK("/etc/init.d/gnunetd") != -1) ||
- (errno != ENOENT)) {
- if (ACCESS("/usr/sbin/update-rc.d", X_OK) == 0) {
- errno = system("/usr/sbin/update-rc.d gnunetd remove");
- if (errno != 0) {
- errno = EPERM;
- return 1;
- }
- }
- else {
- errno = EPERM;
- return 1;
- }
- }
- else
- return 0;
+ errno = 0;
+ if (-1 == system("/usr/sbin/update-rc.d gnunetd defaults")) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "system",
+ "/usr/sbin/update-rc.d");
+ return SYSERR;
}
+ return OK;
+ } else { /* REMOVE autostart */
+ if ( (UNLINK("/etc/init.d/gnunetd") == -1) &&
+ (errno != ENOENT)) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "unlink",
+ "/etc/init.d/gnunetd");
+ return SYSERR;
+ }
+ errno = 0;
+ if (-1 != system("/usr/sbin/update-rc.d gnunetd remove")) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "system",
+ "/usr/sbin/update-rc.d");
+ return SYSERR;
+ }
+ return OK;
}
- else
- return 1;
#endif
- return 0;
+ return SYSERR;
}
-/**
- * @brief Checks if we can add an user for the GNUnet service
- * @return 1 if yes, 0 otherwise
- * @todo support for useradd(8)
- */
-int isOSUserAddCapable(){
+int os_modify_user(struct GE_Context * ectx,
+ int testCapability,
+ int doAdd,
+ const char *group_name,
+ const char *user_name) {
+ int haveGroup;
+
+ if (testCapability) {
+ /* TODO: actually check that group/user
+ exists/does not yet exist */
#ifdef WINDOWS
- return IsWinNT();
+ return IsWinNT() ? OK : SYSERR;
#endif
#ifdef LINUX
- if (ACCESS("/usr/sbin/adduser", X_OK) == 0)
- return (geteuid() == 0);
- else
- /* TODO: useradd */
+ if (geteuid() != 0)
+ return SYSERR;
+ if (doAdd == YES) {
+ if ( ( (ACCESS("/usr/sbin/adduser", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/useradd", X_OK) == 0) ) &&
+ ( (ACCESS("/usr/sbin/addgroup", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/groupadd", X_OK) == 0) ) )
+ return OK;
+ return SYSERR;
+ } else if (doAdd == NO) {
+ if ( (ACCESS("/usr/sbin/deluser", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/userdel", X_OK) == 0) )
+ return OK;
+ return SYSERR;
+ } else if (doAdd == SYSERR) {
+ if ( ( (ACCESS("/usr/sbin/dleuser", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/userdel", X_OK) == 0) ) &&
+ ( (ACCESS("/usr/sbin/delgroup", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/groupdel", X_OK) == 0) ) )
+ return OK;
+ return SYSERR;
+ }
#endif
- return 0;
-}
-
-/**
- * @brief Checks if we can add a group for the GNUnet service
- * @return 1 if yes, 0 otherwise
- * @todo support for groupadd(8)
- */
-int isOSGroupAddCapable() {
-#ifdef LINUX
- if (ACCESS("/usr/sbin/addgroup", X_OK) == 0) {
- return (geteuid() == 0);
- }
- /* TODO: groupadd */
- else
-#endif
- return 0;
-}
-
-/**
- * @brief Add a service account for GNUnet
- * @param group the group of the new user
- * @param name the name of the new user
- * @return 0 on success
- */
-int createGroupUser(const char *group_name,
- const char *user_name) {
- int haveGroup;
-
- if ( (user_name == NULL) ||
- (0 == strlen(user_name)) )
- return 0;
-
+ return SYSERR;
+ }
+ if ( (user_name == NULL) ||
+ (0 == strlen(user_name)) )
+ return 0;
+
#ifdef WINDOWS
- if (IsWinNT())
- {
- return CreateServiceAccount(user_name, "GNUnet service
account");
- }
+ if (IsWinNT())
+ return CreateServiceAccount(user_name,
+ "GNUnet service account");
#else
+ if (ACCESS("/usr/sbin/adduser",
+ X_OK) == 0) {
+ /* Debian */
+ /* TODO: FreeBSD?
http://www.freebsd.org/cgi/man.cgi?query=adduser&sektion=8 */
+ char * cmd;
- if (ACCESS("/usr/sbin/adduser", X_OK) == 0) {
- /* Debian */
- /* TODO: FreeBSD?
http://www.freebsd.org/cgi/man.cgi?query=adduser&sektion=8 */
- char *cmd;
-
- haveGroup = group_name && strlen(group_name) > 0;
- cmd = MALLOC(haveGroup ? strlen(group_name) : 0 +
strlen(user_name) + 64);
-
- if (haveGroup) {
- sprintf(cmd, "/usr/sbin/addgroup --quiet --system %s",
group_name);
- system(cmd);
- }
-
- sprintf(cmd, "/usr/sbin/adduser --quiet --system %s %s "
- "--no-create-home %s", haveGroup ? "--ingroup" : "",
- haveGroup ? group_name : "", user_name);
- system(cmd);
-
- FREE(cmd);
- }
- /* TODO: useradd */
- else
- return 1;
+ haveGroup = group_name && strlen(group_name) > 0;
+ cmd = MALLOC(haveGroup ? strlen(group_name) : 0 + strlen(user_name) + 64);
+
+ if (haveGroup) {
+ sprintf(cmd,
+ "/usr/sbin/addgroup --quiet --system %s",
+ group_name);
+ system(cmd);
+ }
+
+ sprintf(cmd,
+ "/usr/sbin/adduser --quiet --system %s %s "
+ "--no-create-home %s",
+ haveGroup ? "--ingroup" : "",
+ haveGroup ? group_name : "",
+ user_name);
+ system(cmd);
+ FREE(cmd);
+ return OK;
+ }
+ /* TODO: useradd */
+ else
+ return SYSERR;
#endif
-
- return 0;
+ return SYSERR;
}
-char *winErrorStr(const char *prefix, int dwErr)
-{
-#ifdef WINDOWS
- char *err, *ret;
- int mem;
-
- if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, (DWORD) dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &err,
- 0, NULL ))
- {
- err = "";
- }
- mem = strlen(err) + strlen(prefix) + 20;
- ret = (char *) malloc(mem);
-
- snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr);
-
- LocalFree(err);
-
- return ret;
-#else
- return NULL;
-#endif
-}
-
-
/* end of osconfig.c */
Modified: GNUnet/src/util/os/semaphore.c
===================================================================
--- GNUnet/src/util/os/semaphore.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/os/semaphore.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -21,9 +21,13 @@
/**
* @file util/os/semaphore.c
* @brief functions related to IPC synchronization
+ *
+ * TODO: implement non-blocking semaphore down!
*/
#include "gnunet_util_os.h"
+#include "gnunet_util_string.h"
+#include "gnunet_util_error.h"
#include "platform.h"
#if SOLARIS || FREEBSD || OSX
@@ -148,8 +152,7 @@
#if SOLARIS || OSX || FREEBSD5
char * noslashBasename;
int i;
- IPC_Semaphore * rret;
- IPC_Semaphore_Internal * ret;
+ IPC_Semaphore * ret;
ret = MALLOC(sizeof(IPC_Semaphore));
ret->ectx = ectx;
@@ -180,19 +183,15 @@
noslashBasename);
FREE(noslashBasename);
return ret;
-
- /* *********************** fix from here *********** */
#elif WINDOWS
char * noslashBasename;
int i;
- IPC_Semaphore * rret;
- IPC_Semaphore_Internal * ret;
+ IPC_Semaphore * ret;
SECURITY_ATTRIBUTES sec;
DWORD dwErr;
- rret = MALLOC(sizeof(IPC_Semaphore));
- ret = MALLOC(sizeof(IPC_Semaphore_Internal));
- rret->platform = ret;
+ ret = MALLOC(sizeof(IPC_Semaphore));
+ ret->ectx = ectx;
noslashBasename = STRDUP(basename);
for (i=strlen(noslashBasename);i>0;i--)
if (noslashBasename[i] == '\\')
@@ -209,35 +208,35 @@
dwErr = GetLastError();
}
if (! ret->internal) {
- LOG(LOG_FAILURE, _("Can't create semaphore: %i"), dwErr);
- DIE_FILE_STRERROR("sem_open", noslashBasename);
+ GE_LOG(ectx,
+ GE_FAILURE | GE_USER | GE_DEVELOPER | GE_BULK,
+ _("Can't create semaphore: %i"),
+ dwErr);
+ DIE_STRERROR_FILE(ectx,
+ GE_FAILURE | GE_USER | GE_DEVELOPER | GE_BULK,
+ "OpenSemaphore", noslashBasename);
}
FREE(noslashBasename);
- return rret;
+ return ret;
#elif LINUX
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} semctl_arg;
- IPC_Semaphore * rret;
- IPC_Semaphore_Internal * ret;
+ IPC_Semaphore * ret;
key_t key;
FILE * fp;
int pcount;
- rret = MALLOC(sizeof(IPC_Semaphore));
- ret = MALLOC(sizeof(IPC_Semaphore_Internal));
- rret->platform = ret;
-
+ ret = MALLOC(sizeof(IPC_Semaphore));
+ ret->ectx = ectx;
fp = FOPEN(basename, "a+");
if (NULL == fp) {
- LOG_FILE_STRERROR_FL(LOG_FATAL,
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_ERROR | GE_USER | GE_BULK,
"fopen",
- basename,
- filename,
- linenumber);
- FREE(rret);
+ basename);
FREE(ret);
return NULL;
}
@@ -246,58 +245,81 @@
key = ftok(basename,'g');
again:
+ ret->internal = semget(key,
+ 3,
+ IPC_CREAT|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
- ret->internal = semget(key, 3, IPC_CREAT|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
-
if (ret->internal == -1)
- DIE_STRERROR_FL("semget", filename, linenumber);
+ GE_DIE_STRERROR(ectx,
+ GE_FATAL | GE_USER | GE_IMMEDIATE,
+ "semget");
if (semop(ret->internal, &op_lock[0], 2) < 0) {
if (errno == EINVAL)
goto again;
else
- DIE_STRERROR_FL("semop", filename, linenumber);
+ GE_DIE_STRERROR(ectx,
+ GE_FATAL | GE_USER | GE_IMMEDIATE,
+ "semop");
}
/* get process count */
- if ( (pcount = semctl(ret->internal, 1, GETVAL, 0)) < 0)
- DIE_STRERROR_FL("semctl", filename, linenumber);
+ if ( (pcount = semctl(ret->internal,
+ 1,
+ GETVAL,
+ 0)) < 0)
+ GE_DIE_STRERROR(ectx,
+ GE_FATAL | GE_USER | GE_IMMEDIATE,
+ "semctl");
if (pcount==0) {
semctl_arg.val = initialValue;
- if (semctl(ret->internal, 0, SETVAL, semctl_arg) < 0)
- DIE_STRERROR_FL("semtcl", filename, linenumber);
+ if (semctl(ret->internal,
+ 0,
+ SETVAL,
+ semctl_arg) < 0)
+ GE_DIE_STRERROR(ectx,
+ GE_FATAL | GE_USER | GE_IMMEDIATE,
+ "semtcl");
semctl_arg.val = PROCCOUNT;
- if (semctl(ret->internal, 1, SETVAL, semctl_arg) < 0)
- DIE_STRERROR_FL("semtcl", filename, linenumber);
+ if (semctl(ret->internal,
+ 1,
+ SETVAL,
+ semctl_arg) < 0)
+ GE_DIE_STRERROR(ectx,
+ GE_FATAL | GE_USER | GE_IMMEDIATE,
+ "semtcl");
}
- if (semop(ret->internal, &op_endcreate[0], 2) < 0)
- DIE_STRERROR_FL("semop", filename, linenumber);
-
+ if (semop(ret->internal,
+ &op_endcreate[0],
+ 2) < 0)
+ GE_DIE_STRERROR(ectx,
+ GE_FATAL | GE_USER | GE_IMMEDIATE,
+ "semop");
ret->filename = STRDUP(basename);
- return rret;
+ return ret;
#elif SOMEBSD
int fd;
int cnt;
- IPC_Semaphore * rret;
- IPC_Semaphore_Internal * ret;
+ IPC_Semaphore * ret;
- rret = MALLOC(sizeof(IPC_Semaphore));
- ret = MALLOC(sizeof(IPC_Semaphore_Internal));
- rret->platform = ret;
+ ret = MALLOC(sizeof(IPC_Semaphore));
+ ret->ectx = ectx;
MUTEX_CREATE(&ret->internalLock);
ret->filename = STRDUP(basename);
fd = -1;
while (fd == -1) {
- fd = fileopen(basename,
- O_CREAT|O_RDWR|O_EXCL,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP /* 660 */);
+ fd = disk_file_open(ectx,
+ basename,
+ O_CREAT|O_RDWR|O_EXCL,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP /* 660 */);
if ( (fd == -1) &&
(errno == EEXIST) ) {
/* try without creation */
- fd = fileopen(basename,
- O_RDWR,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP /* 660 */);
+ fd = disk_file_open(ectx,
+ basename,
+ O_RDWR,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP /* 660 */);
/* possibly the file was deleted in the meantime,
then try again with O_CREAT! */
if ( (fd == -1) &&
@@ -306,28 +328,48 @@
}
}
if (fd == -1) {
- LOG_FILE_STRERROR(LOG_ERROR, "open", ret->filename);
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_ERROR | GE_USER | GE_BULK,
+ "open",
+ ret->filename);
MUTEX_DESTROY(&ret->internalLock);
FREE(ret->filename);
FREE(ret);
- FREE(rret);
return NULL;
}
FLOCK(fd, LOCK_EX);
- if (sizeof(int) != READ(fd, &cnt, sizeof(int))) {
+ if (sizeof(int) != READ(fd,
+ &cnt,
+ sizeof(int))) {
cnt = htonl(initialValue);
- LSEEK(fd, 0, SEEK_SET);
- if (sizeof(int) != WRITE(fd, &cnt, sizeof(int)))
- LOG_FILE_STRERROR(LOG_WARNING, "write", basename);
+ LSEEK(fd,
+ 0,
+ SEEK_SET);
+ if (sizeof(int) != WRITE(fd,
+ &cnt,
+ sizeof(int)))
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_ERROR | GE_USER | GE_BULK,
+ "write",
+ basename);
}
- LSEEK(fd, sizeof(int), SEEK_SET);
- if (sizeof(int) != READ(fd, &cnt, sizeof(int)))
+ LSEEK(fd,
+ sizeof(int),
+ SEEK_SET);
+ if (sizeof(int) != READ(fd,
+ &cnt,
+ sizeof(int)))
cnt = htonl(1);
else
cnt = htonl(ntohl(cnt)+1);
LSEEK(fd, sizeof(int), SEEK_SET);
- if (sizeof(int) != WRITE(fd, &cnt, sizeof(int)))
- LOG_FILE_STRERROR(LOG_WARNING, "write", basename);
+ if (sizeof(int) != WRITE(fd,
+ &cnt,
+ sizeof(int)))
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "write",
+ basename);
FLOCK(fd, LOCK_UN);
ret->fd = fd;
ret->initialValue = initialValue;
@@ -342,244 +384,205 @@
#endif
}
-void ipc_semaphore_up_(IPC_Semaphore * rsem,
- const char * filename,
- const int linenumber) {
- IPC_Semaphore_Internal * sem;
- if (rsem == NULL) /* error on creation, optimistic execution; good luck */
+void IPC_SEMAPHORE_UP(IPC_Semaphore * sem) {
+ if (sem == NULL) /* error on creation, optimistic execution; good luck */
return;
- sem = rsem->platform;
#if SOLARIS || OSX || FREEBSD5
if (0 != sem_post(sem->internal))
- LOG(LOG_WARNING,
- "sem_post signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
+ GE_LOG_STRERROR(sem->ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "sem_post");
#elif WINDOWS
if (!ReleaseSemaphore(sem->internal, 1, NULL))
- LOG(LOG_WARNING,
- "ReleaseSemaphore signaled error: %i at %s:%d\n",
- GetLastError(),
- filename,
- linenumber);
+ GE_LOG(GE_WARNING | GE_USER | GE_BULK,
+ "ReleaseSemaphore signaled error: %i\n",
+ GetLastError());
#elif LINUX
{
struct sembuf sops = {0,1,SEM_UNDO};
if (0 != semop(sem->internal,&sops,1))
- LOG(LOG_WARNING,
- "semop signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
+ GE_LOG_STRERROR(sem->ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "semop");
}
#elif SOMEBSD
{
int cnt;
-
MUTEX_LOCK(&sem->internalLock);
- FLOCK(sem->fd, LOCK_EX);
- LSEEK(sem->fd, 0, SEEK_SET);
- if (sizeof(int) != READ(sem->fd, &cnt, sizeof(int))) {
- LOG(LOG_WARNING,
- "could not read IPC semaphore count (%s) at %s:%d!\n",
- STRERROR(errno),
- __FILE__,
- __LINE__);
+ FLOCK(sem->fd,
+ LOCK_EX);
+ LSEEK(sem->fd,
+ 0,
+ SEEK_SET);
+ if (sizeof(int) != READ(sem->fd,
+ &cnt,
+ sizeof(int))) {
+ GE_LOG_STRERROR_FILE(sem->ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "read",
+ sem->filename);
+ FLOCK(sem->fd,
+ LOCK_UN);
MUTEX_UNLOCK(&sem->internalLock);
return;
}
cnt = htonl(ntohl(cnt)+1);
- LSEEK(sem->fd, 0, SEEK_SET);
- if (sizeof(int) != WRITE(sem->fd, &cnt, sizeof(int)))
- LOG(LOG_WARNING,
- "could not write to IPC file %s (%s) at %s:%d\n",
- sem->filename,
- STRERROR(errno),
- __FILE__,
- __LINE__);
- FLOCK(sem->fd, LOCK_UN);
+ LSEEK(sem->fd,
+ 0,
+ SEEK_SET);
+ if (sizeof(int) != WRITE(sem->fd,
+ &cnt,
+ sizeof(int)))
+ GE_LOG_STRERROR_FILE(sem->ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "write",
+ sem->filename);
+ FLOCK(sem->fd,
+ LOCK_UN);
MUTEX_UNLOCK(&sem->internalLock);
}
#endif
}
-void ipc_semaphore_down_(IPC_Semaphore * rsem,
- const char * filename,
- const int linenumber) {
- IPC_Semaphore_Internal * sem;
-
- if (rsem == NULL) /* error on creation, optimistic execution; good luck */
- return;
- sem = rsem->platform;
+/* FIXME: add support for mayBlock! */
+int IPC_SEMAPHORE_DOWN(IPC_Semaphore * sem,
+ int mayBlock) {
+ if (sem == NULL) /* error on creation, optimistic execution; good luck */
+ return OK;
#if OSX || SOLARIS || FREEBSD5
while (0 != sem_wait(sem->internal)) {
- switch(errno) {
- case EINTR:
- break;
- case EINVAL:
- errexit(" ipc_semaphore_down called on invalid semaphore (in %s:%d)\n",
- filename,
- linenumber);
- case EDEADLK:
- errexit(" ipc_semaphore_down caused deadlock! (in %s:%d)\n",
- filename,
- linenumber);
- case EAGAIN:
- LOG(LOG_WARNING,
- "did not expect EAGAIN from sem_wait (in %s:%d).\n",
- filename,
- linenumber);
- break;
- default:
- LOG(LOG_ERROR,
- "did not expect %s from sem_wait at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
- break;
- }
+ if ( (errno == EINTR) ||
+ (errno == EAGAIN) )
+ continue;
+ GE_DIE_STRERROR(sem->ectx,
+ GE_FATAL | GE_USER | GE_IMMEDIATE,
+ "sem_wait");
}
+ return OK;
#elif WINDOWS
- if (WaitForSingleObject(sem->internal, INFINITE) == WAIT_FAILED)
- LOG(LOG_WARNING,
- "WaitForSingleObject signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
+ if (WaitForSingleObject(sem->internal,
+ INFINITE) == WAIT_FAILED)
+ GE_LOG_STRERROR(sem->ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "WaitForSingleObject");
+ return OK;
#elif LINUX
{
struct sembuf sops = {0,-1,SEM_UNDO};
- while (0 != semop(sem->internal,&sops,1)) {
- switch(errno) {
- case EINTR:
- break;
- case EINVAL:
- errexit(" ipc_semaphore_down called on invalid semaphore (in %s:%d)\n",
- filename,
- linenumber);
- case EAGAIN:
- LOG(LOG_WARNING,
- "did not expect EAGAIN from sem_wait (in %s:%d).\n",
- filename,
- linenumber);
- break;
- default:
- LOG(LOG_ERROR,
- "did not expect %s from sem_wait at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
- break;
- }
+ while (0 != semop(sem->internal,
+ &sops,
+ 1)) {
+ if ( (errno == EINTR) ||
+ (errno == EAGAIN) )
+ continue;
+ GE_DIE_STRERROR(sem->ectx,
+ GE_FATAL | GE_USER | GE_IMMEDIATE,
+ "semop");
}
+ return OK;
}
#elif SOMEBSD
{
int cnt;
MUTEX_LOCK(&sem->internalLock);
- FLOCK(sem->fd, LOCK_EX);
+ FLOCK(sem->fd,
+ LOCK_EX);
cnt = ntohl(0);
while (htonl(cnt) == 0) {
- LSEEK(sem->fd, 0, SEEK_SET);
- if (sizeof(int) != READ(sem->fd, &cnt, sizeof(int))) {
- LOG(LOG_WARNING,
- "could not read IPC semaphore count (%s) at %s:%d!\n",
- STRERROR(errno),
- __FILE__,
- __LINE__);
- FLOCK(sem->fd, LOCK_UN);
+ LSEEK(sem->fd,
+ 0,
+ SEEK_SET);
+ if (sizeof(int) != READ(sem->fd,
+ &cnt,
+ sizeof(int))) {
+ GE_LOG_STRERROR_FILE(sem->ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "read",
+ sem->filename);
+ FLOCK(sem->fd,
+ LOCK_UN);
MUTEX_UNLOCK(&sem->internalLock);
return;
}
if (htonl(cnt) == 0) {
/* busy wait! */
- FLOCK(sem->fd, LOCK_UN);
- gnunet_util_sleep(50 * cronMILLIS);
- FLOCK(sem->fd, LOCK_EX);
+ FLOCK(sem->fd,
+ LOCK_UN);
+ PTHREAD_SLEEP(50 * cronMILLIS);
+ FLOCK(sem->fd,
+ LOCK_EX);
}
}
cnt = htonl(ntohl(cnt)-1);
LSEEK(sem->fd, 0, SEEK_SET);
- if (sizeof(int) != WRITE(sem->fd, &cnt, sizeof(int)))
- LOG(LOG_WARNING,
- "could not write update to IPC file %s at %s:%d\n",
- sem->filename,
- __FILE__,
- __LINE__);
- FLOCK(sem->fd, LOCK_UN);
+ if (sizeof(int) != WRITE(sem->fd,
+ &cnt,
+ sizeof(int)))
+ GE_LOG_STRERROR_FILE(sem->ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "write",
+ sem->filename);
+ FLOCK(sem->fd,
+ LOCK_UN);
MUTEX_UNLOCK(&sem->internalLock);
}
+ return OK;
#else
+ return OK;
#endif
}
-void ipc_semaphore_free_(IPC_Semaphore * rsem,
- const char * filename,
- const int linenumber) {
- IPC_Semaphore_Internal * sem;
- if (rsem == NULL) /* error on creation, optimistic execution; good luck */
+void IPC_SEMAPHORE_DESTROY(IPC_Semaphore * sem) {
+ if (sem == NULL) /* error on creation, optimistic execution; good luck */
return;
- sem = rsem->platform;
- FREE(rsem);
#if SOLARIS || OSX || FREEBSD5
if (0 != sem_close(sem->internal))
- LOG(LOG_WARNING,
- "sem_close signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
+ GE_LOG_STRERROR(sem->ectx,
+ GE_USER | GE_WARNING | GE_BULK,
+ "sem_close");
#elif WINDOWS
if (!CloseHandle(sem->internal))
- LOG(LOG_WARNING,
- "CloseHandle signaled error: %i at %s:%d\n",
- GetLastError(),
- filename,
- linenumber);
+ GE_LOG(sem->ectx,
+ GE_USER | GE_WARNING | GE_BULK,
+ "CloseHandle signaled error: %i\n",
+ GetLastError());
#elif LINUX
{
int pcount;
if (semop(sem->internal, &op_close[0], 3) < 0)
- LOG(LOG_WARNING,
- "semop signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
-
- if ( (pcount = semctl(sem->internal, 1, GETVAL, 0)) < 0)
- LOG(LOG_WARNING,
- "semctl: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
- if (pcount > PROCCOUNT)
- LOG(LOG_WARNING,
- "pcount too large at %s:%d\n",
- filename,
- linenumber);
- else if (pcount == PROCCOUNT) {
- if (0 != semctl(sem->internal,0,IPC_RMID,0))
- LOG(LOG_WARNING,
- "semctl signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
+ GE_LOG_STRERROR(sem->ectx,
+ GE_USER | GE_WARNING | GE_BULK,
+ "semop");
+ if ( (pcount = semctl(sem->internal, 1, GETVAL, 0)) < 0)
+ GE_LOG_STRERROR(sem->ectx,
+ GE_USER | GE_WARNING | GE_BULK,
+ "semctl");
+ if (pcount > PROCCOUNT) {
+ GE_BREAK(sem->ectx, 0);
+ } else if (pcount == PROCCOUNT) {
+ if (0 != semctl(sem->internal,
+ 0,
+ IPC_RMID,
+ 0))
+ GE_LOG_STRERROR(sem->ectx,
+ GE_USER | GE_WARNING | GE_BULK,
+ "semctl");
UNLINK(sem->filename);
} else {
- if (semop(sem->internal, &op_unlock[0], 1) < 0)
- LOG(LOG_WARNING,
- "semop %s %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
+ if (semop(sem->internal,
+ &op_unlock[0],
+ 1) < 0)
+ GE_LOG_STRERROR(sem->ectx,
+ GE_USER | GE_WARNING | GE_BULK,
+ "semop");
}
- FREE(sem->filename);
+ FREE(sem->filename);
}
#elif SOMEBSD
{
@@ -592,23 +595,20 @@
cnt = htonl(ntohl(cnt)-1);
LSEEK(sem->fd, sizeof(int), SEEK_SET);
if (sizeof(int) != WRITE(sem->fd, &cnt, sizeof(int)))
- LOG(LOG_WARNING,
- "could not write to IPC file %s at %s:%d\n",
- sem->filename,
- __FILE__,
- __LINE__);
- if (ntohl(cnt) == 0) {
- UNLINK(sem->filename);
- }
+ GE_LOG_STRERROR(sem->ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "write");
+ if (ntohl(cnt) == 0)
+ UNLINK(sem->filename);
} else
- LOG(LOG_WARNING,
- "could not read process count of IPC %s at %s:%d\n",
- sem->filename,
- __FILE__,
- __LINE__);
+ GE_LOG_STRERROR(sem->ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "read");
+ FLOCK(sem->fd, LOCK_UN);
+ disk_file_close(sem->ectx,
+ sem->filename,
+ sem->fd);
FREE(sem->filename);
- FLOCK(sem->fd, LOCK_UN);
- closefile(sem->fd);
}
#else
#endif
Modified: GNUnet/src/util/os/statuscalls.c
===================================================================
--- GNUnet/src/util/os/statuscalls.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/os/statuscalls.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -19,8 +19,8 @@
*/
/**
- * @file util/statuscalls.c
- * @brief calls to determine current network and CPU load
+ * @file util/os/statuscalls.c
+ * @brief calls to determine current network load
* @author Tzvetan Horozov
* @author Christian Grothoff
* @author Igor Wronsky
@@ -29,7 +29,10 @@
*/
#include "platform.h"
-#include "gnunet_util.h"
+#include "gnunet_util_os.h"
+#include "gnunet_util_error.h"
+#include "gnunet_util_string.h"
+#include "gnunet_util_threads.h"
#if SOLARIS
#if HAVE_KSTAT_H
@@ -62,117 +65,87 @@
unsigned long long last_out;
} NetworkStats;
-/**
- * Traffic counter for only gnunetd traffic.
- */
-static NetworkStats globalTrafficBetweenProc;
+typedef struct LoadMonitor {
+
+ /**
+ * Traffic counter for only gnunetd traffic.
+ */
+ NetworkStats globalTrafficBetweenProc;
-/**
- * tracking
- */
-static NetworkStats * ifcs;
+ /**
+ * tracking
+ */
+ NetworkStats * ifcs;
-/**
- * how many interfaces do we have?
- */
-static unsigned int ifcsSize;
+ /**
+ * how many interfaces do we have?
+ */
+ unsigned int ifcsSize;
-/**
- * Current load of the machine, -1 for error
- */
-static int currentLoad;
+ /**
+ * Maximum bandwidth (down) as per config.
+ */
+ unsigned long long maxNetDownBPS;
-/**
- * Maximum bandwidth (down) as per config.
- */
-static int maxNetDownBPS;
+ /**
+ * Maximum bandwidth (up) as per config.
+ */
+ unsigned long long maxNetUpBPS;
-/**
- * Maximum bandwidth (up) as per config.
- */
-static int maxNetUpBPS;
+ /**
+ * How to measure traffic (YES == only gnunetd,
+ * NO == try to include all apps)
+ */
+ int useBasicMethod;
-/**
- * Maximum load as per config.
- */
-static int maxCPULoad;
-
-/**
- * How to measure traffic (YES == only gnunetd,
- * NO == try to include all apps)
- */
-static int useBasicMethod = YES;
-
-/**
- * Lock.
- */
-static Mutex statusMutex;
-
-static int initialized_ = NO;
-
#ifdef LINUX
-static FILE * proc_stat;
-static FILE * proc_net_dev;
+ FILE * proc_net_dev;
#endif
+
+ /**
+ * Lock.
+ */
+ struct MUTEX * statusMutex;
-/**
- * Increment the number of bytes sent. Transports should use this
- * so that statuscalls module can measure gnunet traffic usage between
- * calls to /proc.
- *
- * Note: the caller doesn't know what interface it is attached to,
- * so this type of bandwidth limitation is always global (for all
- * network interfaces).
- */
-void incrementBytesSent(unsigned long long delta) {
- if (initialized_ == NO)
- return;
- MUTEX_LOCK(&statusMutex);
- globalTrafficBetweenProc.last_out += delta;
- MUTEX_UNLOCK(&statusMutex);
-}
+ struct GE_Context * ectx;
-void incrementBytesReceived(unsigned long long delta) {
- if (initialized_ == NO)
- return;
- MUTEX_LOCK(&statusMutex);
- globalTrafficBetweenProc.last_in += delta;
- MUTEX_UNLOCK(&statusMutex);
-}
+ struct GC_Configuration * cfg;
-/**
- * Reset the traffic counters for GNUnet traffic between
- * systemwide readings.
- */
-static void resetBetweenProc() {
- globalTrafficBetweenProc.last_in = 0;
- globalTrafficBetweenProc.last_out = 0;
+} LoadMonitor;
+
+void os_network_monitor_notify_transmission(struct LoadMonitor * monitor,
+ NetworkDirection dir,
+ unsigned long long delta) {
+ MUTEX_LOCK(monitor->statusMutex);
+ monitor->globalTrafficBetweenProc.last_in += delta;
+ MUTEX_UNLOCK(monitor->statusMutex);
}
#define MAX_PROC_LINE 5000
-static void updateInterfaceTraffic() {
-#ifdef LINUX
+static void updateInterfaceTraffic(struct LoadMonitor * monitor) {
unsigned long long rxnew;
unsigned long long txnew;
+ int i;
char line[MAX_PROC_LINE];
+ NetworkStats * ifc;
+#ifdef LINUX
char * data;
- int i;
int found;
- MUTEX_LOCK(&statusMutex);
- if (proc_net_dev != NULL) {
+ if (monitor->proc_net_dev != NULL) {
found = 0;
- rewind(proc_net_dev);
- fflush(proc_net_dev);
+ rewind(monitor->proc_net_dev);
+ fflush(monitor->proc_net_dev);
/* Parse the line matching the interface ('eth0') */
- while (! feof(proc_net_dev) ) {
+ while (! feof(monitor->proc_net_dev) ) {
if (NULL == fgets(line,
MAX_PROC_LINE,
- proc_net_dev))
+ monitor->proc_net_dev))
break;
- for (i=0;i<ifcsSize;i++) {
- if (NULL != strstr(line, ifcs[i].name) ) {
+ for (i=0;i<monitor->ifcsSize;i++) {
+ ifc = &monitor->ifcs[i];
+ if (NULL != strstr(line, ifc->name) ) {
data = strchr(line, ':');
if (data == NULL)
continue;
@@ -181,58 +154,52 @@
"%llu %*s %*s %*s %*s %*s %*s %*s %llu",
&rxnew,
&txnew)) {
- LOG(LOG_ERROR,
- _("Failed to parse interface data from `%s' at %s:%d.\n"),
- PROC_NET_DEV,
- __FILE__,
- __LINE__);
+ GE_LOG(monitor->ectx,
+ GE_ERROR | GE_ADMIN | GE_BULK,
+ _("Failed to parse interface data from `%s'.\n"),
+ PROC_NET_DEV);
continue;
- }
- ifcs[i].last_in = rxnew;
- ifcs[i].last_out = txnew;
- resetBetweenProc();
+ }
+ ifc->last_in = rxnew;
+ ifc->last_out = txnew;
+ monitor->globalTrafficBetweenProc.last_in = 0;
+ monitor->globalTrafficBetweenProc.last_out = 0;
break;
}
}
}
}
- MUTEX_UNLOCK(&statusMutex);
#elif MINGW
- unsigned long long rxnew;
- unsigned long long txnew;
- int i;
PMIB_IFTABLE pTable;
DWORD dwIfIdx;
unsigned long long l;
BYTE bPhysAddr[MAXLEN_PHYSADDR];
int iLine = 0;
- char line[MAX_PROC_LINE];
FILE * command;
-
- MUTEX_LOCK(&statusMutex);
+
/* Win 98 and NT SP 4 */
if (GNGetIfEntry) {
EnumNICs(&pTable, NULL);
- for (i=0;i<ifcsSize;i++) {
+ for (i=0;i<monitor->ifcsSize;i++) {
+ ifc = &monitor->ifcs[i];
for (dwIfIdx=0; dwIfIdx < pTable->dwNumEntries; dwIfIdx++) {
- l = _atoi64(ifcs[i].name);
-
+ l = _atoi64(ifc->name);
memset(bPhysAddr,
0,
MAXLEN_PHYSADDR);
memcpy(bPhysAddr,
pTable->table[dwIfIdx].bPhysAddr,
pTable->table[dwIfIdx].dwPhysAddrLen);
-
if (0 == memcmp(bPhysAddr,
&l,
sizeof(unsigned long long))) {
- ifcs[i].last_in
+ ifc->last_in
= pTable->table[dwIfIdx].dwInOctets;
- ifcs[i].last_out
+ ifc->last_out
= pTable->table[dwIfIdx].dwOutOctets;
- resetBetweenProc();
+ monitor->globalTrafficBetweenProc.last_in = 0;
+ monitor->globalTrafficBetweenProc.last_out = 0;
break;
}
}
@@ -243,9 +210,9 @@
LOG_FILE_STRERROR(LOG_ERROR,
"popen",
"netstat -e");
- MUTEX_UNLOCK(&statusMutex);
return;
}
+ ifc = &monitor->ifcs[0];
while (!feof(command)) {
if (NULL == fgets(line,
MAX_PROC_LINE,
@@ -253,460 +220,120 @@
break;
/* PORT-ME: any way to do this per-ifc? */
if (iLine == 1) {
- sscanf("%*s%i%i",
- &rxnew,
- &txnew);
- ifcs[0].last_in
- = rxnew;
- ifcs[0].last_out
- = txnew;
- resetBetweenProc();
- break;
+ if (2 == sscanf("%*s%i%i",
+ &rxnew,
+ &txnew)) {
+ ifc->last_in
+ = rxnew;
+ ifc->last_out
+ = txnew;
+ monitor->globalTrafficBetweenProc.last_in = 0;
+ monitor->globalTrafficBetweenProc.last_out = 0;
+ break;
+ } else {
+ GE_LOG(monitor->ectx,
+ GE_ERROR | GE_ADMIN | GE_BULK,
+ _("Failed to parse interface data from `%s'.\n"),
+ PROC_NET_DEV);
+ }
}
iLine++;
}
pclose(command);
}
- MUTEX_UNLOCK(&statusMutex);
#else
/* PORT-ME! */
#endif
}
/**
- * The following routine returns a number between 0-100 (can be larger
- * than 100 if the load is > 1) which indicates the percentage CPU
- * usage.
- *
- * Before its first invocation the method initStatusCalls() must be called.
- * If there is an error the method returns -1
- */
-static void updateCpuUsage(){
- if (initialized_ == NO) {
- currentLoad = -1;
- return;
- }
- MUTEX_LOCK(&statusMutex);
-
-#ifdef LINUX
- /* under linux, first try %idle/usage using /proc/stat;
- if that does not work, disable /proc/stat for the future
- by closing the file and use the next-best method. */
- if (proc_stat != NULL) {
- static unsigned long long last_cpu_results[4] = { 0, 0, 0, 0 };
- static int have_last_cpu = NO;
- char line[128];
- unsigned long long user_read, system_read, nice_read, idle_read;
- unsigned long long user, system, nice, idle;
- unsigned long long usage_time=0, total_time=1;
-
- /* Get the first line with the data */
- rewind(proc_stat);
- fflush(proc_stat);
- if (NULL == fgets(line, 128, proc_stat)) {
- LOG_FILE_STRERROR(LOG_ERROR,
- "fgets",
- "/proc/stat");
- fclose(proc_stat);
- proc_stat = NULL; /* don't try again */
- } else {
- if (sscanf(line, "%*s %llu %llu %llu %llu",
- &user_read,
- &system_read,
- &nice_read,
- &idle_read) != 4) {
- LOG_FILE_STRERROR(LOG_ERROR,
- "fgets-sscanf",
- "/proc/stat");
- fclose(proc_stat);
- proc_stat = NULL; /* don't try again */
- have_last_cpu = NO;
- } else {
- /* Store the current usage*/
- user = user_read - last_cpu_results[0];
- system = system_read - last_cpu_results[1];
- nice = nice_read - last_cpu_results[2];
- idle = idle_read - last_cpu_results[3];
- /* Calculate the % usage */
- if ( (user + system + nice + idle) > 0) {
- usage_time = user + system + nice;
- total_time = usage_time + idle;
- }
- if ( (total_time > 0) &&
- (have_last_cpu == YES) )
- currentLoad = (100 * usage_time) / total_time;
- else
- currentLoad = -1;
- /* Store the values for the next calculation*/
- last_cpu_results[0] = user_read;
- last_cpu_results[1] = system_read;
- last_cpu_results[2] = nice_read;
- last_cpu_results[3] = idle_read;
- have_last_cpu = YES;
- MUTEX_UNLOCK(&statusMutex);
- return;
- }
- }
- }
-#endif
-
- /* try kstat (Solaris only) */
-#if SOLARIS && HAVE_KSTAT_H && HAVE_SYS_SYSINFO_H
- {
- static long long last_idlecount;
- static long long last_totalcount;
- static int kstat_once; /* if open fails, don't keep
- trying */
- kstat_ctl_t * kc;
- kstat_t * khelper;
- long long idlecount;
- long long totalcount;
- long long deltaidle;
- long long deltatotal;
-
- if (kstat_once == 1)
- goto ABORT_KSTAT;
- kc = kstat_open();
- if (kc == NULL) {
- LOG_STRERROR(LOG_ERROR, "kstat_open");
- goto ABORT_KSTAT;
- }
-
- idlecount = 0;
- totalcount = 0;
- for (khelper = kc->kc_chain;
- khelper != NULL;
- khelper = khelper->ks_next) {
- cpu_stat_t stats;
-
- if (0 != strncmp(khelper->ks_name,
- "cpu_stat",
- strlen("cpu_stat")) )
- continue;
- if (khelper->ks_data_size > sizeof(cpu_stat_t))
- continue; /* better save then sorry! */
- if (-1 != kstat_read(kc, khelper, &stats)) {
- idlecount
- += stats.cpu_sysinfo.cpu[CPU_IDLE];
- totalcount
- += stats.cpu_sysinfo.cpu[CPU_IDLE] +
- stats.cpu_sysinfo.cpu[CPU_USER] +
- stats.cpu_sysinfo.cpu[CPU_KERNEL] +
- stats.cpu_sysinfo.cpu[CPU_WAIT];
- }
- }
- if (0 != kstat_close(kc))
- LOG_STRERROR(LOG_ERROR, "kstat_close");
- if ( (idlecount == 0) &&
- (totalcount == 0) )
- goto ABORT_KSTAT; /* no stats found => abort */
- deltaidle = idlecount - last_idlecount;
- deltatotal = totalcount - last_totalcount;
- if ( (deltatotal > 0) &&
- (last_totalcount > 0) )
- currentLoad = (int) (100 * deltaidle / deltatotal);
- else
- currentLoad = -1;
- last_idlecount = idlecount;
- last_totalcount = totalcount;
- MUTEX_UNLOCK(&statusMutex);
- return;
- ABORT_KSTAT:
- kstat_once = 1; /* failed, don't try again */
- }
-#endif
-
- /* insert methods better than getloadavg for
- other platforms HERE! */
-
- /* ok, maybe we have getloadavg on this platform */
-#if HAVE_GETLOADAVG
- {
- static int warnOnce = 0;
- double loadavg;
- if (1 != getloadavg(&loadavg, 1)) {
- /* only warn once, if there is a problem with
- getloadavg, we're going to hit it frequently... */
- if (warnOnce == 0) {
- warnOnce = 1;
- LOG_STRERROR(LOG_ERROR, "getloadavg");
- }
- currentLoad = -1;
- } else {
- /* success with getloadavg */
- currentLoad = (int) (100 * loadavg);
- MUTEX_UNLOCK(&statusMutex);
- return;
- }
- }
-#endif
-
-#if MINGW
- /* Win NT? */
- if (GNNtQuerySystemInformation) {
- static double dLastKernel;
- static double dLastIdle;
- static double dLastUser;
- double dKernel;
- double dIdle;
- double dUser;
- double dDiffKernel;
- double dDiffIdle;
- double dDiffUser;
- SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION theInfo;
-
- if (GNNtQuerySystemInformation(SystemProcessorPerformanceInformation,
- &theInfo,
- sizeof(theInfo),
- NULL) == NO_ERROR) {
- /* PORT-ME MINGW: Multi-processor? */
- dKernel = Li2Double(theInfo.KernelTime);
- dIdle = Li2Double(theInfo.IdleTime);
- dUser = Li2Double(theInfo.UserTime);
- dDiffKernel = dKernel - dLastKernel;
- dDiffIdle = dIdle - dLastIdle;
- dDiffUser = dUser - dLastUser;
-
- if ( ( (dDiffKernel + dDiffUser) > 0) &&
- (dLastIdle + dLastKernel + dLastUser > 0) )
- currentLoad = 100.0 - (dDiffIdle / (dDiffKernel + dDiffUser)) * 100.0;
- else
- currentLoad = -1; /* don't know (yet) */
-
- dLastKernel = dKernel;
- dLastIdle = dIdle;
- dLastUser = dUser;
-
- MUTEX_UNLOCK(&statusMutex);
- return;
- } else {
- /* only warn once, if there is a problem with
- NtQuery..., we're going to hit it frequently... */
- static int once;
- if (once == 0) {
- once = 1;
- LOG(LOG_ERROR,
- _("Cannot query the CPU usage (Windows NT).\n"));
- }
- }
- } else { /* Win 9x */
- HKEY hKey;
- DWORD dwDataSize, dwType, dwDummy;
-
- /* Start query */
- if (RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StartSrv",
- 0,
- KEY_ALL_ACCESS,
- &hKey) != ERROR_SUCCESS) {
- /* only warn once */
- static int once = 0;
- if (once == 0) {
- once = 1;
- LOG(LOG_ERROR,
- _("Cannot query the CPU usage (Win 9x)\n"));
- }
- }
-
- RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StartStat",
- 0,
- KEY_ALL_ACCESS,
- &hKey);
- dwDataSize = sizeof(dwDummy);
- RegQueryValueEx(hKey,
- "KERNEL\\CPUUsage",
- NULL,
- &dwType,
- (LPBYTE) &dwDummy,
- &dwDataSize);
- RegCloseKey(hKey);
-
- /* Get CPU usage */
- RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StatData",
- 0,
- KEY_ALL_ACCESS,
- &hKey);
- dwDataSize = sizeof(currentLoad);
- RegQueryValueEx(hKey,
- "KERNEL\\CPUUsage",
- NULL,
- &dwType,
- (LPBYTE) ¤tLoad,
- &dwDataSize);
- RegCloseKey(hKey);
-
- /* Stop query */
- RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StopStat",
- 0,
- KEY_ALL_ACCESS,
- &hKey);
- RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StopSrv",
- 0,
- KEY_ALL_ACCESS,
- &hKey);
- dwDataSize = sizeof(dwDummy);
- RegQueryValueEx(hKey,
- "KERNEL\\CPUUsage",
- NULL,
- &dwType,
- (LPBYTE)&dwDummy,
- &dwDataSize);
- RegCloseKey(hKey);
-
- MUTEX_UNLOCK(&statusMutex);
- return;
- }
-#endif
-
- /* loadaverage not defined and no platform
- specific alternative defined
- => default: error
- */
- currentLoad = -1;
- MUTEX_UNLOCK(&statusMutex);
-}
-
-static void cronLoadUpdate(void * unused) {
- updateCpuUsage();
- if (! useBasicMethod)
- updateInterfaceTraffic();
-}
-
-/**
* Re-read the configuration for statuscalls.
*/
-static void resetStatusCalls() {
+static int resetStatusCalls(void * cls,
+ struct GC_Configuration * cfg,
+ struct GE_Context * ectx,
+ const char * sect,
+ const char * op) {
+ static const char * yesno[] = { "YES", "NO", NULL };
+ struct LoadMonitor * monitor = cls;
+ const char * y;
char * interfaces;
int i;
int numInterfaces;
+ int basic;
- MUTEX_LOCK(&statusMutex);
- for (i=0;i<ifcsSize;i++)
- FREE(ifcs[i].name);
- GROW(ifcs,
- ifcsSize,
- 0);
- interfaces
- = getConfigurationString("LOAD",
- "INTERFACES");
- /* fail if config-file is incomplete */
- if ( (interfaces == NULL) ||
- (strlen(interfaces) == 0) ) {
- LOG(LOG_ERROR,
- _("No network interfaces defined in configuration section `%s' under
`%s'!\n"),
- "LOAD",
- "INTERFACES");
- } else {
- /* The string containing the interfaces is formatted in the following way:
- * each comma is replaced by '\0' and the pointers to the beginning of
every
- * interface are stored
- */
- numInterfaces = 1;
- for (i=strlen(interfaces)-1;i>=0;i--)
- if (interfaces[i] == ',')
- numInterfaces++;
- GROW(ifcs,
- ifcsSize,
- numInterfaces);
- for (i=strlen(interfaces)-1;i>=0;i--) {
- if (interfaces[i] == ',') {
- ifcs[--numInterfaces].name = STRDUP(&interfaces[i+1]);
- numInterfaces++;
- interfaces[i] = '\0';
- }
- }
- ifcs[--numInterfaces].name = STRDUP(interfaces);
- GNUNET_ASSERT(numInterfaces == 0);
- for (i=0;i<ifcsSize;i++) {
- ifcs[i].last_in = 0;
- ifcs[i].last_out = 0;
- }
+ if (-1 == GC_get_configuration_value_choice(cfg,
+ "LOAD",
+ "BASICLIMITING",
+ yesno,
+ "NO",
+ &y))
+ return SYSERR;
+ basic = (y == "YES") ? YES : NO;
+ if (-1 == GC_get_configuration_value_string(cfg,
+ "LOAD",
+ "INTERFACES",
+ NULL,
+ &interfaces))
+ return SYSERR;
+ if (interfaces == NULL) {
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_BULK,
+ _("No network interfaces defined in configuration section `%s' under
`%s'!\n"),
+ "LOAD",
+ "INTERFACES");
+ return SYSERR;
}
- FREENONNULL(interfaces);
- useBasicMethod
- = testConfigurationString("LOAD",
- "BASICLIMITING",
- "YES");
- maxNetDownBPS
- = getConfigurationInt("LOAD",
- "MAXNETDOWNBPSTOTAL");
- if (maxNetDownBPS == 0)
- maxNetDownBPS = 50000;
- maxNetUpBPS
- = getConfigurationInt("LOAD",
- "MAXNETUPBPSTOTAL");
- if (maxNetUpBPS == 0)
- maxNetUpBPS = 50000;
- maxCPULoad
- = getConfigurationInt("LOAD",
- "MAXCPULOAD");
- if (maxCPULoad == 0)
- maxCPULoad = 100;
- MUTEX_UNLOCK(&statusMutex);
-}
-
-
-
-/**
- * Get the load of the network relative to what is allowed.
- * @return the network load as a percentage of allowed
- * (100 is equivalent to full load)
- */
-int getNetworkLoadUp() {
- static unsigned long long overload;
- static unsigned long long lastSum;
- static cron_t lastCall;
- static int lastValue;
- cron_t now;
- unsigned long long maxExpect;
- unsigned long long currentLoadSum;
- int i;
- int ret;
-
- MUTEX_LOCK(&statusMutex);
- currentLoadSum = globalTrafficBetweenProc.last_out;
- for (i=0;i<ifcsSize;i++)
- currentLoadSum += ifcs[i].last_out;
- cronTime(&now);
- if ( (lastSum > currentLoadSum) ||
- (lastSum == 0) ||
- (now < lastCall) ) {
- /* integer overflow or first datapoint; since we cannot tell where
- / by how much the overflow happened, all we can do is ignore
- this datapoint. So we return -1 -- AND reset lastSum / lastCall. */
- lastSum = currentLoadSum;
- lastCall = now;
- MUTEX_UNLOCK(&statusMutex);
- return -1;
+ if (strlen(interfaces) == 0) {
+ FREE(interfaces);
+ GE_LOG(ectx,
+ GE_ERROR | GE_USER | GE_BULK,
+ _("No network interfaces defined in configuration section `%s' under
`%s'!\n"),
+ "LOAD",
+ "INTERFACES");
+ return SYSERR;
}
- if (maxNetUpBPS == 0) {
- MUTEX_UNLOCK(&statusMutex);
- return -1;
+ MUTEX_LOCK(monitor->statusMutex);
+ for (i=0;i<monitor->ifcsSize;i++)
+ FREE(monitor->ifcs[i].name);
+ numInterfaces = 1;
+ for (i=strlen(interfaces)-1;i>=0;i--)
+ if (interfaces[i] == ',')
+ numInterfaces++;
+ GROW(monitor->ifcs,
+ monitor->ifcsSize,
+ numInterfaces);
+ for (i=strlen(interfaces)-1;i>=0;i--) {
+ if (interfaces[i] == ',') {
+ monitor->ifcs[--numInterfaces].name = STRDUP(&interfaces[i+1]);
+ numInterfaces++;
+ interfaces[i] = '\0';
+ }
}
- if (now - lastCall < cronSECONDS) {
- /* increase last load proportional to difference in
- data transmitted and in relation to the limit */
- ret = lastValue + 100 * (currentLoadSum - lastSum) / maxNetUpBPS;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
+ monitor->ifcs[--numInterfaces].name = STRDUP(interfaces);
+ GE_ASSERT(ectx, numInterfaces == 0);
+ for (i=0;i<monitor->ifcsSize;i++) {
+ monitor->ifcs[i].last_in = 0;
+ monitor->ifcs[i].last_out = 0;
}
- currentLoadSum -= lastSum;
- lastSum += currentLoadSum;
- currentLoadSum += overload;
- maxExpect = ( (now - lastCall) * maxNetUpBPS ) / cronSECONDS;
- lastCall = now;
- if (currentLoadSum < maxExpect)
- overload = 0;
- else
- overload = currentLoadSum - maxExpect;
- lastValue = currentLoadSum * 100 / maxExpect;
- ret = lastValue;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
+ FREE(interfaces);
+ monitor->useBasicMethod = basic;
+ GC_get_configuration_value_number(cfg,
+ "LOAD",
+ "MAXNETDOWNBPSTOTAL",
+ 0,
+ (unsigned long long)-1,
+ 50000,
+ &monitor->maxNetDownBPS);
+ GC_get_configuration_value_number(cfg,
+ "LOAD",
+ "MAXNETUPBPSTOTAL",
+ 0,
+ (unsigned long long)-1,
+ 50000,
+ &monitor->maxNetUpBPS);
+ MUTEX_UNLOCK(monitor->statusMutex);
+ return OK;
}
/**
@@ -714,7 +341,8 @@
* @return the network load as a percentage of allowed
* (100 is equivalent to full load)
*/
-int getNetworkLoadDown() {
+int os_network_monitor_get_load(struct LoadMonitor * monitor,
+ NetworkDirection dir) {
static unsigned long long overload;
static unsigned long long lastSum;
static cron_t lastCall;
@@ -724,12 +352,16 @@
unsigned long long currentLoadSum;
int i;
int ret;
+ int weight;
- MUTEX_LOCK(&statusMutex);
- currentLoadSum = globalTrafficBetweenProc.last_in;
- for (i=0;i<ifcsSize;i++)
- currentLoadSum += ifcs[i].last_in;
- cronTime(&now);
+ MUTEX_LOCK(monitor->statusMutex);
+ now = get_time();
+ if ( (monitor->useBasicMethod == NO) &&
+ (now - lastCall > 10 * cronSECONDS) )
+ updateInterfaceTraffic(monitor);
+ currentLoadSum = monitor->globalTrafficBetweenProc.last_in;
+ for (i=0;i<monitor->ifcsSize;i++)
+ currentLoadSum += monitor->ifcs[i].last_in;
if ( (lastSum > currentLoadSum) ||
(lastSum == 0) ||
(now < lastCall) ) {
@@ -738,24 +370,26 @@
this datapoint. So we return -1 -- AND reset lastSum / lastCall. */
lastSum = currentLoadSum;
lastCall = now;
- MUTEX_UNLOCK(&statusMutex);
+ MUTEX_UNLOCK(monitor->statusMutex);
return -1;
}
- if (maxNetDownBPS == 0) {
- MUTEX_UNLOCK(&statusMutex);
+ if (monitor->maxNetDownBPS == 0) {
+ MUTEX_UNLOCK(monitor->statusMutex);
return -1;
}
- if (now - lastCall < cronSECONDS) {
- /* increase last load proportional to difference in
- data transmitted and in relation to the limit */
- ret = lastValue + 100 * (currentLoadSum - lastSum) / maxNetDownBPS;
- MUTEX_UNLOCK(&statusMutex);
+
+ maxExpect = (now - lastCall) * monitor->maxNetDownBPS / cronSECONDS;
+ if (now - lastCall < 5 * cronSECONDS) {
+ /* return weighted average between last return value and
+ load in the last interval */
+ weight = (now - lastCall) * 100 / (5 * cronSECONDS); /* how close are we
to lastCall? */
+ ret = (lastValue * (100-weight) + weight * (currentLoadSum - lastSum) /
maxExpect) / 2;
+ MUTEX_UNLOCK(monitor->statusMutex);
return ret;
}
currentLoadSum -= lastSum;
lastSum += currentLoadSum;
currentLoadSum += overload;
- maxExpect = ( (now - lastCall) * maxNetDownBPS ) / cronSECONDS;
lastCall = now;
if (currentLoadSum < maxExpect)
overload = 0;
@@ -763,111 +397,60 @@
overload = currentLoadSum - maxExpect;
lastValue = currentLoadSum * 100 / maxExpect;
ret = lastValue;
- MUTEX_UNLOCK(&statusMutex);
+ MUTEX_UNLOCK(monitor->statusMutex);
return ret;
}
-/**
- * Get the load of the CPU relative to what is allowed.
- * @return the CPU load as a percentage of allowed
- * (100 is equivalent to full load)
- */
-int getCPULoad() {
- static int lastRet = -1;
- static cron_t lastCall;
- int ret;
- cron_t now;
+struct LoadMonitor *
+os_network_monitor_create(struct GE_Context * ectx,
+ struct GC_Configuration * cfg) {
+ struct LoadMonitor * monitor;
- if (initialized_ == NO) {
- lastRet = -1;
- return -1;
- }
- MUTEX_LOCK(&statusMutex);
- ret = (100 * currentLoad) / maxCPULoad;
-
- cronTime(&now);
- if ( (lastRet != -1) &&
- (now - lastCall < 250 * cronMILLIS) ) {
- /* use smoothing, but do NOT update lastRet at frequencies higher
- than 250ms; this makes the smoothing (mostly) independent from
- the frequency at which getCPULoad is called. */
- ret = (ret + 7 * lastRet)/8;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
- }
-
- /* for CPU, we don't do the 'fast increase' since CPU is much
- more jitterish to begin with */
- if (lastRet != -1)
- ret = (ret + 7 * lastRet)/8;
- lastRet = ret;
- lastCall = now;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
-}
-
-/**
- * The following method is called in order to initialize the status calls
- * routines. After that it is safe to call each of the status calls separately
- * @return OK on success and SYSERR on error (or calls errexit).
- */
-void initStatusCalls() {
+ monitor = MALLOC(sizeof(struct LoadMonitor));
+ memset(monitor,
+ 0,
+ sizeof(struct LoadMonitor));
+ monitor->ectx = ectx;
+ monitor->cfg = cfg;
#ifdef LINUX
- proc_stat = fopen("/proc/stat", "r");
- if (NULL == proc_stat)
- LOG_FILE_STRERROR(LOG_ERROR,
- "fopen",
- "/proc/stat");
- proc_net_dev = fopen(PROC_NET_DEV, "r");
- if (NULL == proc_net_dev)
- LOG_FILE_STRERROR(LOG_ERROR,
- "fopen",
- PROC_NET_DEV);
+ monitor->proc_net_dev = fopen(PROC_NET_DEV, "r");
+ if (NULL == monitor->proc_net_dev)
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_ERROR | GE_ADMIN | GE_USER | GE_BULK,
+ "fopen",
+ PROC_NET_DEV);
#endif
- MUTEX_CREATE_RECURSIVE(&statusMutex);
- initialized_ = YES;
- resetBetweenProc();
- registerConfigurationUpdateCallback(&resetStatusCalls);
- resetStatusCalls();
- cronLoadUpdate(NULL);
- addCronJob(&cronLoadUpdate,
- 10 * cronSECONDS,
- 10 * cronSECONDS,
- NULL);
- getNetworkLoadUp();
- getNetworkLoadDown();
+ monitor->statusMutex = MUTEX_CREATE(NO);
+ if (OK != resetStatusCalls(monitor,
+ cfg,
+ ectx,
+ NULL,
+ NULL)) {
+ os_network_monitor_destroy(monitor);
+ return NULL;
+ }
+ GC_attach_change_listener(cfg,
+ &resetStatusCalls,
+ monitor);
+ return monitor;
}
-/**
- * Shutdown the status calls module.
- */
-void doneStatusCalls() {
+void os_network_monitor_destroy(struct LoadMonitor * monitor) {
int i;
- if (initialized_ == NO)
- return;
- unregisterConfigurationUpdateCallback(&resetStatusCalls);
- delCronJob(&cronLoadUpdate,
- 10 * cronSECONDS,
- NULL);
- initialized_ = NO;
+ GC_detach_change_listener(monitor->cfg,
+ &resetStatusCalls,
+ monitor);
#ifdef LINUX
- if (proc_stat != NULL) {
- fclose(proc_stat);
- proc_stat = NULL;
- }
- if (proc_net_dev != NULL) {
- fclose(proc_net_dev);
- proc_net_dev = NULL;
- }
+ if (monitor->proc_net_dev != NULL)
+ fclose(monitor->proc_net_dev);
#endif
- for (i=0;i<ifcsSize;i++)
- FREE(ifcs[i].name);
- GROW(ifcs,
- ifcsSize,
+ for (i=0;i<monitor->ifcsSize;i++)
+ FREE(monitor->ifcs[i].name);
+ GROW(monitor->ifcs,
+ monitor->ifcsSize,
0);
- MUTEX_DESTROY(&statusMutex);
+ MUTEX_DESTROY(monitor->statusMutex);
}
-
/* end of statuscalls.c */
Modified: GNUnet/src/util/threads/Makefile.am
===================================================================
--- GNUnet/src/util/threads/Makefile.am 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/threads/Makefile.am 2006-06-24 20:37:52 UTC (rev 3037)
@@ -9,7 +9,8 @@
mutex.c \
pthread.c \
semaphore.c \
- shutdown.c
+ shutdown.c \
+ time.c
check_PROGRAMS = \
semaphoretest \
Added: GNUnet/src/util/threads/time.c
===================================================================
--- GNUnet/src/util/threads/time.c 2006-06-24 16:34:56 UTC (rev 3036)
+++ GNUnet/src/util/threads/time.c 2006-06-24 20:37:52 UTC (rev 3037)
@@ -0,0 +1,46 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2006 Christian Grothoff (and other contributing authors)
+
+ GNUnet 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, or (at your
+ option) any later version.
+
+ GNUnet 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 GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file util/threads/time.c
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util_threads.h"
+
+/**
+ * Get the current time (works just as "time", just that we use the
+ * unit of time that the cron-jobs use (and is 64 bit)).
+ *
+ * @return the current time
+ */
+cron_t get_time() {
+ struct timeval tv;
+#ifndef WINDOWS
+ struct timezone tz; /* man page says it's obsolete, but
+ I'd rather not pass a NULL pointer */
+
+ gettimeofday(&tv, &tz);
+#else
+ gettimeofday(&tv, NULL);
+#endif
+ return (((cron_t)tv.tv_sec) * 1000) + (tv.tv_usec / 1000 / 1000);
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r3037 - in GNUnet/src: include util util/network util/os util/threads,
grothoff <=