Commit 169238e9 authored by Havoc Pennington's avatar Havoc Pennington

2003-03-14 Havoc Pennington <hp@pobox.com>

	* bus/dispatch.c (bus_dispatch_test): do test using debug-pipe
	transport, tests more of the real codepath. Set up clients
	with bus_setup_debug_client.

	* bus/test.c (bus_setup_debug_client): function to set up debug
	"clients" on the main loop

	* dbus/dbus-transport.c (_dbus_transport_open): add debug-pipe
	support

	* dbus/dbus-server.c (dbus_server_listen): add debug-pipe
	server type

	* dbus/dbus-server-debug.c: support a debug server based on pipes

	* dbus/dbus-sysdeps.c (_dbus_full_duplex_pipe): new function
	(_dbus_close): new function

	* configure.in: check for socketpair
parent 4c95a978
2003-03-14 Havoc Pennington <hp@pobox.com>
* bus/dispatch.c (bus_dispatch_test): do test using debug-pipe
transport, tests more of the real codepath. Set up clients
with bus_setup_debug_client.
* bus/test.c (bus_setup_debug_client): function to set up debug
"clients" on the main loop
* dbus/dbus-transport.c (_dbus_transport_open): add debug-pipe
support
* dbus/dbus-server.c (dbus_server_listen): add debug-pipe
server type
* dbus/dbus-server-debug.c: support a debug server based on pipes
* dbus/dbus-sysdeps.c (_dbus_full_duplex_pipe): new function
(_dbus_close): new function
* configure.in: check for socketpair
2003-03-14 Havoc Pennington <hp@redhat.com>
* dbus/dbus-memory.c: add a "detect buffer overwrites on free"
......
......@@ -379,7 +379,7 @@ bus_dispatch_remove_connection (DBusConnection *connection)
static void
flush_bus (BusContext *context)
{
{
while (bus_loop_iterate (FALSE))
;
}
......@@ -435,23 +435,28 @@ bus_dispatch_test (const DBusString *test_data_dir)
DBusResultCode result;
dbus_error_init (&error);
context = bus_context_new ("debug:name=test-server",
context = bus_context_new ("debug-pipe:name=test-server",
activation_dirs,
&error);
if (context == NULL)
_dbus_assert_not_reached ("could not alloc context");
foo = dbus_connection_open ("debug:name=test-server", &result);
foo = dbus_connection_open ("debug-pipe:name=test-server", &result);
if (foo == NULL)
_dbus_assert_not_reached ("could not alloc connection");
bar = dbus_connection_open ("debug:name=test-server", &result);
bar = dbus_connection_open ("debug-pipe:name=test-server", &result);
if (bar == NULL)
_dbus_assert_not_reached ("could not alloc connection");
baz = dbus_connection_open ("debug:name=test-server", &result);
baz = dbus_connection_open ("debug-pipe:name=test-server", &result);
if (baz == NULL)
_dbus_assert_not_reached ("could not alloc connection");
if (!bus_setup_debug_client (foo) ||
!bus_setup_debug_client (bar) ||
!bus_setup_debug_client (baz))
_dbus_assert_not_reached ("could not set up connection");
if (!check_hello_message (context, foo))
_dbus_assert_not_reached ("hello message failed");
......
......@@ -50,6 +50,4 @@ void bus_loop_run (void);
void bus_loop_quit (void);
dbus_bool_t bus_loop_iterate (dbus_bool_t block);
#endif /* BUS_LOOP_H */
......@@ -21,3 +21,97 @@
*
*/
#include <config.h>
#ifdef DBUS_BUILD_TESTS
#include "test.h"
#include "loop.h"
/* The "debug client" watch/timeout handlers don't dispatch messages,
* as we manually pull them in order to verify them. This is why they
* are different from the real handlers in connection.c
*/
static void
connection_watch_callback (DBusWatch *watch,
unsigned int condition,
void *data)
{
DBusConnection *connection = data;
dbus_connection_ref (connection);
dbus_connection_handle_watch (connection, watch, condition);
dbus_connection_unref (connection);
}
static dbus_bool_t
add_connection_watch (DBusWatch *watch,
DBusConnection *connection)
{
return bus_loop_add_watch (watch, connection_watch_callback, connection,
NULL);
}
static void
remove_connection_watch (DBusWatch *watch,
DBusConnection *connection)
{
bus_loop_remove_watch (watch, connection_watch_callback, connection);
}
static void
connection_timeout_callback (DBusTimeout *timeout,
void *data)
{
DBusConnection *connection = data;
dbus_connection_ref (connection);
dbus_timeout_handle (timeout);
dbus_connection_unref (connection);
}
static dbus_bool_t
add_connection_timeout (DBusTimeout *timeout,
DBusConnection *connection)
{
return bus_loop_add_timeout (timeout, connection_timeout_callback, connection, NULL);
}
static void
remove_connection_timeout (DBusTimeout *timeout,
DBusConnection *connection)
{
bus_loop_remove_timeout (timeout, connection_timeout_callback, connection);
}
dbus_bool_t
bus_setup_debug_client (DBusConnection *connection)
{
if (!dbus_connection_set_watch_functions (connection,
(DBusAddWatchFunction) add_connection_watch,
(DBusRemoveWatchFunction) remove_connection_watch,
connection,
NULL))
{
dbus_connection_disconnect (connection);
return FALSE;
}
if (!dbus_connection_set_timeout_functions (connection,
(DBusAddTimeoutFunction) add_connection_timeout,
(DBusRemoveTimeoutFunction) remove_connection_timeout,
connection, NULL))
{
dbus_connection_disconnect (connection);
return FALSE;
}
return TRUE;
}
#endif
......@@ -33,6 +33,8 @@
dbus_bool_t bus_dispatch_test (const DBusString *test_data_dir);
dbus_bool_t bus_setup_debug_client (DBusConnection *connection);
#endif
#endif /* BUS_TEST_H */
......@@ -134,7 +134,7 @@ AC_C_BIGENDIAN
AC_CHECK_LIB(socket,socket)
AC_CHECK_LIB(nsl,gethostbyname)
AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep poll setenv)
AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep poll setenv socketpair)
AC_CACHE_CHECK([for posix getpwnam_r],
ac_cv_func_posix_getpwnam_r,
......
......@@ -44,6 +44,8 @@ libdbus_1_la_SOURCES= \
dbus-server-protected.h \
dbus-server-debug.c \
dbus-server-debug.h \
dbus-server-debug-pipe.c \
dbus-server-debug-pipe.h \
dbus-server-unix.c \
dbus-server-unix.h \
dbus-sha.c \
......
......@@ -428,8 +428,9 @@ sha1_compute_hash (DBusAuth *auth,
return retval;
}
/* http://www.ietf.org/rfc/rfc2831.txt suggests at least 64 bits of
* entropy, we use 128
/** http://www.ietf.org/rfc/rfc2831.txt suggests at least 64 bits of
* entropy, we use 128. This is the number of bytes in the random
* challenge.
*/
#define N_CHALLENGE_BYTES (128/8)
......
......@@ -77,11 +77,17 @@ static dbus_bool_t inited = FALSE;
static int fail_counts = -1;
static size_t fail_size = 0;
static dbus_bool_t guards = FALSE;
/** value stored in guard padding for debugging buffer overrun */
#define GUARD_VALUE 0xdeadbeef
/** size of the information about the block stored in guard mode */
#define GUARD_INFO_SIZE 8
/** size of the GUARD_VALUE-filled padding after the header info */
#define GUARD_START_PAD 16
/** size of the GUARD_VALUE-filled padding at the end of the block */
#define GUARD_END_PAD 16
/** size of stuff at start of block */
#define GUARD_START_OFFSET (GUARD_START_PAD + GUARD_INFO_SIZE)
/** total extra size over the requested allocation for guard stuff */
#define GUARD_EXTRA_SIZE (GUARD_START_OFFSET + GUARD_END_PAD)
#endif
......@@ -107,6 +113,9 @@ initialize_malloc_debug (void)
}
}
/**
* Where the block came from.
*/
typedef enum
{
SOURCE_UNKNOWN,
......
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-server-debug-pipe.c In-proc debug server implementation
*
* Copyright (C) 2003 CodeFactory AB
* Copyright (C) 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "dbus-internals.h"
#include "dbus-server-debug-pipe.h"
#include "dbus-transport-unix.h"
#include "dbus-connection-internal.h"
#include "dbus-hash.h"
#ifdef DBUS_BUILD_TESTS
/**
* @defgroup DBusServerDebugPipe DBusServerDebugPipe
* @ingroup DBusInternals
* @brief In-process pipe debug server used in unit tests.
*
* Types and functions related to DBusServerDebugPipe.
* This is used for unit testing.
*
* @{
*/
/**
* Opaque object representing a debug server implementation.
*/
typedef struct DBusServerDebugPipe DBusServerDebugPipe;
/**
* Implementation details of DBusServerDebugPipe. All members
* are private.
*/
struct DBusServerDebugPipe
{
DBusServer base; /**< Parent class members. */
char *name; /**< Server name. */
dbus_bool_t disconnected; /**< TRUE if disconnect has been called */
};
static DBusHashTable *server_pipe_hash;
static void
debug_finalize (DBusServer *server)
{
_dbus_server_finalize_base (server);
dbus_free (server);
}
static void
debug_handle_watch (DBusServer *server,
DBusWatch *watch,
unsigned int flags)
{
}
static void
debug_disconnect (DBusServer *server)
{
((DBusServerDebugPipe*)server)->disconnected = TRUE;
}
static DBusServerVTable debug_vtable = {
debug_finalize,
debug_handle_watch,
debug_disconnect
};
/**
* Creates a new debug server using an in-process pipe
*
* @param server_name the name of the server.
* @param result address where a result code can be returned.
* @returns a new server, or #NULL on failure.
*/
DBusServer*
_dbus_server_debug_pipe_new (const char *server_name,
DBusResultCode *result)
{
DBusServerDebugPipe *debug_server;
if (!server_pipe_hash)
{
server_pipe_hash = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, NULL);
if (!server_pipe_hash)
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
return NULL;
}
}
if (_dbus_hash_table_lookup_string (server_pipe_hash, server_name) != NULL)
{
dbus_set_result (result, DBUS_RESULT_ADDRESS_IN_USE);
return NULL;
}
debug_server = dbus_new0 (DBusServerDebugPipe, 1);
if (debug_server == NULL)
return NULL;
debug_server->name = _dbus_strdup (server_name);
if (debug_server->name == NULL)
{
dbus_free (debug_server->name);
dbus_free (debug_server);
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
}
if (!_dbus_server_init_base (&debug_server->base,
&debug_vtable))
{
dbus_free (debug_server->name);
dbus_free (debug_server);
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
return NULL;
}
if (!_dbus_hash_table_insert_string (server_pipe_hash,
debug_server->name,
debug_server))
{
_dbus_server_finalize_base (&debug_server->base);
dbus_free (debug_server->name);
dbus_free (debug_server);
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
return NULL;
}
dbus_set_result (result, DBUS_RESULT_SUCCESS);
return (DBusServer *)debug_server;
}
/**
* Creates the client-side transport for
* a debug-pipe connection connected to the
* given debug-pipe server name.
*
* @param server_name name of server to connect to
* @param result return location for result
* @returns #NULL on no memory or transport
*/
DBusTransport*
_dbus_transport_debug_pipe_new (const char *server_name,
DBusResultCode *result)
{
DBusTransport *client_transport;
DBusTransport *server_transport;
DBusConnection *connection;
int client_fd, server_fd;
DBusServer *server;
server = _dbus_hash_table_lookup_string (server_pipe_hash,
server_name);
if (server == NULL ||
((DBusServerDebugPipe*)server)->disconnected)
{
dbus_set_result (result, DBUS_RESULT_BAD_ADDRESS);
return NULL;
}
if (!_dbus_full_duplex_pipe (&client_fd, &server_fd,
NULL))
{
_dbus_verbose ("failed to create full duplex pipe\n");
dbus_set_result (result, DBUS_RESULT_FAILED);
return NULL;
}
_dbus_fd_set_close_on_exec (client_fd);
_dbus_fd_set_close_on_exec (server_fd);
client_transport = _dbus_transport_new_for_fd (client_fd,
FALSE);
if (client_transport == NULL)
{
_dbus_close (client_fd, NULL);
_dbus_close (server_fd, NULL);
return NULL;
}
client_fd = -1;
server_transport = _dbus_transport_new_for_fd (server_fd,
TRUE);
if (server_transport == NULL)
{
_dbus_transport_unref (client_transport);
_dbus_close (server_fd, NULL);
return NULL;
}
server_fd = -1;
connection = _dbus_connection_new_for_transport (server_transport);
_dbus_transport_unref (server_transport);
server_transport = NULL;
if (connection == NULL)
{
_dbus_transport_unref (client_transport);
return NULL;
}
/* See if someone wants to handle this new connection,
* self-referencing for paranoia
*/
if (server->new_connection_function)
{
dbus_server_ref (server);
(* server->new_connection_function) (server, connection,
server->new_connection_data);
dbus_server_unref (server);
}
/* If no one grabbed a reference, the connection will die,
* and the client transport will get an immediate disconnect
*/
dbus_connection_unref (connection);
return client_transport;
}
/** @} */
#endif /* DBUS_BUILD_TESTS */
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-server-debug-pipe.h In-proc debug server implementation
*
* Copyright (C) 2003 CodeFactory AB
* Copyright (C) 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef DBUS_SERVER_DEBUG_PIPE_H
#define DBUS_SERVER_DEBUG_PIPE_H
#include <dbus/dbus-internals.h>
#include <dbus/dbus-server-protected.h>
#include <dbus/dbus-transport.h>
DBUS_BEGIN_DECLS;
DBusServer* _dbus_server_debug_pipe_new (const char *server_name,
DBusResultCode *result);
DBusTransport* _dbus_transport_debug_pipe_new (const char *server_name,
DBusResultCode *result);
DBUS_END_DECLS;
#endif /* DBUS_SERVER_DEBUG_PIPE_H */
......@@ -25,6 +25,7 @@
#include "dbus-server-unix.h"
#ifdef DBUS_BUILD_TESTS
#include "dbus-server-debug.h"
#include "dbus-server-debug-pipe.h"
#endif
#include "dbus-address.h"
......@@ -272,6 +273,18 @@ dbus_server_listen (const char *address,
server = _dbus_server_debug_new (name, result);
if (server)
break;
}
else if (strcmp (method, "debug-pipe") == 0)
{
const char *name = dbus_address_entry_get_value (entries[i], "name");
if (name == NULL)
goto bad_address;
server = _dbus_server_debug_pipe_new (name, result);
if (server)
break;
}
......
......@@ -2754,4 +2754,78 @@ _dbus_stat (const DBusString *filename,
return TRUE;
}
/**
* Creates a full-duplex pipe (as in socketpair()).
* Sets both ends of the pipe nonblocking.
*
* @param fd1 return location for one end
* @param fd2 return location for the other end
* @param error error return
* @returns #FALSE on failure (if error is set)
*/
dbus_bool_t
_dbus_full_duplex_pipe (int *fd1,
int *fd2,
DBusError *error)
{
#ifdef HAVE_SOCKETPAIR
int fds[2];
if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Could not create full-duplex pipe");
return FALSE;
}
if (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
!_dbus_set_fd_nonblocking (fds[1], NULL))
{
dbus_set_error (error, _dbus_error_from_errno (errno),
"Could not set full-duplex pipe nonblocking");
close (fds[0]);
close (fds[1]);
return FALSE;
}
*fd1 = fds[0];
*fd2 = fds[1];
return TRUE;
#else
_dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
dbus_set_error (error, DBUS_ERROR_FAILED,
"_dbus_full_duplex_pipe() not implemented on this OS");
return FALSE;
#endif
}
/**
* Closes a file descriptor.
*
* @param fd the file descriptor
* @param error error object
* @returns #FALSE if error set
*/
dbus_bool_t
_dbus_close (int fd,
DBusError *error)
{
again:
if (close (fd) < 0)
{
if (errno == EINTR)
goto again;
dbus_set_error (error, _dbus_error_from_errno (errno),
"Could not close fd %d", fd);
return FALSE;
}
return TRUE;
}
/** @} end of sysdeps */
......@@ -196,9 +196,14 @@ typedef struct
unsigned long ctime;
} DBusStat;
dbus_bool_t _dbus_stat (const DBusString *filename,
DBusStat *statbuf,
DBusError *error);
dbus_bool_t _dbus_stat (const DBusString *filename,
DBusStat *statbuf,
DBusError *error);
dbus_bool_t _dbus_full_duplex_pipe (int *fd1,
int *fd2,
DBusError *error);
dbus_bool_t _dbus_close (int fd,
DBusError *error);
DBUS_END_DECLS;
......
......@@ -888,7 +888,7 @@ unix_disconnect (DBusTransport *transport)
free_watches (transport);
close (unix_transport->fd);
_dbus_close (unix_transport->fd, NULL);
unix_transport->fd = -1;
}
......@@ -1161,7 +1161,7 @@ _dbus_transport_new_for_domain_socket (const char *path,
if (transport == NULL)
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
close (fd);
_dbus_close (fd, NULL);
fd = -1;
}
......@@ -1199,7 +1199,7 @@ _dbus_transport_new_for_tcp_socket (const char *host,
if (transport == NULL)
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
close (fd);
_dbus_close (fd, NULL);
fd = -1;
}
......
......@@ -29,6 +29,7 @@
#include "dbus-address.h"
#ifdef DBUS_BUILD_TESTS
#include "dbus-transport-debug.h"
#include "dbus-server-debug-pipe.h"
#endif
/**
......@@ -229,7 +230,16 @@ _dbus_transport_open (const char *address,
transport = _dbus_transport_debug_client_new (name, result);
}
#endif
else if (strcmp (method, "debug-pipe") == 0)
{
const char *name = dbus_address_entry_get_value (entries[i], "name");
if (name == NULL)
goto bad_address;
transport = _dbus_transport_debug_pipe_new (name, result);
}
#endif
else
goto bad_address;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment