Commit 5ebb5748 authored by Anders Carlsson's avatar Anders Carlsson

2003-01-30 Anders Carlsson <andersca@codefactory.se>

	* dbus/Makefile.am:
	Add dbus-address.[ch]

	* dbus/dbus-address.c: (dbus_address_entry_free),
	(dbus_address_entries_free), (create_entry),
	(dbus_address_entry_get_method), (dbus_address_entry_get_value),
	(dbus_parse_address), (_dbus_address_test):
	* dbus/dbus-address.h:
	New files for dealing with address parsing.

	* dbus/dbus-connection.c:
	Document timeout functions.

	* dbus/dbus-message.c:
	Document dbus_message_new_from_message.

	* dbus/dbus-server-debug.c:
	Document.

	* dbus/dbus-server.c: (dbus_server_listen):
	Parse address and use correct server implementation.

	* dbus/dbus-string.c: (_dbus_string_find_to), (_dbus_string_test):
	* dbus/dbus-string.h:
	New function with test.

	* dbus/dbus-test.c: (dbus_internal_symbol_do_not_use_run_tests):
	* dbus/dbus-test.h:
	Add address tests.

	* dbus/dbus-transport-debug.c:
	Document.

	* dbus/dbus-transport.c: (_dbus_transport_open):
	Parse address and use correct transport implementation.
parent 7ba714ad
2003-01-30 Anders Carlsson <andersca@codefactory.se>
* dbus/Makefile.am:
Add dbus-address.[ch]
* dbus/dbus-address.c: (dbus_address_entry_free),
(dbus_address_entries_free), (create_entry),
(dbus_address_entry_get_method), (dbus_address_entry_get_value),
(dbus_parse_address), (_dbus_address_test):
* dbus/dbus-address.h:
New files for dealing with address parsing.
* dbus/dbus-connection.c:
Document timeout functions.
* dbus/dbus-message.c:
Document dbus_message_new_from_message.
* dbus/dbus-server-debug.c:
Document.
* dbus/dbus-server.c: (dbus_server_listen):
Parse address and use correct server implementation.
* dbus/dbus-string.c: (_dbus_string_find_to), (_dbus_string_test):
* dbus/dbus-string.h:
New function with test.
* dbus/dbus-test.c: (dbus_internal_symbol_do_not_use_run_tests):
* dbus/dbus-test.h:
Add address tests.
* dbus/dbus-transport-debug.c:
Document.
* dbus/dbus-transport.c: (_dbus_transport_open):
Parse address and use correct transport implementation.
2003-01-30 Havoc Pennington <hp@pobox.com>
* dbus/dbus-message.c: use message->byte_order instead of
......
......@@ -7,6 +7,7 @@ lib_LTLIBRARIES=libdbus-1.la
dbusinclude_HEADERS= \
dbus.h \
dbus-address.h \
dbus-connection.h \
dbus-errors.h \
dbus-macros.h \
......@@ -19,6 +20,7 @@ dbusinclude_HEADERS= \
dbus-types.h
libdbus_1_la_SOURCES= \
dbus-address.c \
dbus-auth.c \
dbus-auth.h \
dbus-connection.c \
......
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-address.c Server address parser.
*
* Copyright (C) 2003 CodeFactory AB
*
* 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 <config.h>
#include "dbus-address.h"
#include "dbus-internals.h"
#include "dbus-list.h"
/**
* @defgroup DBusAddress address parsing
* @ingroup DBus
* @brief Parsing addresses to DBus servers.
*
* @{
*/
struct DBusAddressEntry
{
DBusString method;
DBusList *keys;
DBusList *values;
};
static void
dbus_address_entry_free (DBusAddressEntry *entry)
{
DBusList *link;
_dbus_string_free (&entry->method);
link = _dbus_list_get_first_link (&entry->keys);
while (link != NULL)
{
_dbus_string_free (link->data);
dbus_free (link->data);
link = _dbus_list_get_next_link (&entry->keys, link);
}
link = _dbus_list_get_first_link (&entry->values);
while (link != NULL)
{
_dbus_string_free (link->data);
dbus_free (link->data);
link = _dbus_list_get_next_link (&entry->values, link);
}
dbus_free (entry);
}
/**
* Frees a #NULL-terminated array of address entries.
*
* @param entries the array.
*/
void
dbus_address_entries_free (DBusAddressEntry **entries)
{
int i;
for (i = 0; entries[i] != NULL; i++)
dbus_address_entry_free (entries[i]);
dbus_free (entries);
}
static DBusAddressEntry *
create_entry (void)
{
DBusAddressEntry *entry;
entry = dbus_new0 (DBusAddressEntry, 1);
if (entry == NULL)
return NULL;
if (!_dbus_string_init (&entry->method, _DBUS_INT_MAX))
dbus_free (entry);
return entry;
}
/**
* Returns the method string of an address entry.
*
* @param entry the entry.
* @returns a string describing the method. This string
* must not be freed.
*/
const char *
dbus_address_entry_get_method (DBusAddressEntry *entry)
{
const char *method;
_dbus_string_get_const_data (&entry->method, &method);
return method;
}
/**
* Returns a value from a key of an entry.
*
* @param entry the entry.
* @param key the key.
* @returns the key value. This string must not be fred.
*/
const char *
dbus_address_entry_get_value (DBusAddressEntry *entry,
const char *key)
{
DBusList *values, *keys;
keys = _dbus_list_get_first_link (&entry->keys);
values = _dbus_list_get_first_link (&entry->values);
while (keys != NULL)
{
_dbus_assert (values != NULL);
if (_dbus_string_equal_c_str (keys->data, key))
{
const char *str;
_dbus_string_get_const_data (values->data, &str);
return str;
}
keys = _dbus_list_get_next_link (&entry->keys, keys);
values = _dbus_list_get_next_link (&entry->values, values);
}
return NULL;
}
/**
* Parses an address string of the form:
*
* method:key=value,key=value;method:key=value
*
* @param address the address.
* @param entry return location to an array of entries.
* @param array_len return location for array length.
* @param result return location for result code.
* @returns #TRUE on success, #FALSE otherwise.
*/
dbus_bool_t
dbus_parse_address (const char *address,
DBusAddressEntry ***entry,
int *array_len,
DBusResultCode *result)
{
DBusString str;
int pos, end_pos, len, i;
DBusList *entries, *link;
DBusAddressEntry **entry_array;
_dbus_string_init_const (&str, address);
entries = NULL;
pos = 0;
len = _dbus_string_get_length (&str);
while (pos < len)
{
DBusAddressEntry *entry;
int found_pos;
entry = create_entry ();
if (!entry)
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
goto error;
}
/* Append the entry */
if (!_dbus_list_append (&entries, entry))
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
dbus_address_entry_free (entry);
goto error;
}
/* Look for a semi-colon */
if (!_dbus_string_find (&str, pos, ";", &end_pos))
end_pos = len;
/* Look for the colon : */
if (!_dbus_string_find_to (&str, pos, end_pos, ":", &found_pos))
{
dbus_set_result (result, DBUS_RESULT_BAD_ADDRESS);
goto error;
}
if (!_dbus_string_copy_len (&str, pos, found_pos - pos, &entry->method, 0))
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
goto error;
}
pos = found_pos + 1;
while (pos < end_pos)
{
int comma_pos, equals_pos;
if (!_dbus_string_find_to (&str, pos, end_pos, ",", &comma_pos))
comma_pos = end_pos;
if (!_dbus_string_find (&str, pos, "=", &equals_pos) ||
equals_pos == pos || equals_pos + 1 == end_pos)
{
dbus_set_result (result, DBUS_RESULT_BAD_ADDRESS);
goto error;
}
else
{
DBusString *key;
DBusString *value;
key = dbus_new0 (DBusString, 1);
if (!key)
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
goto error;
}
value = dbus_new0 (DBusString, 1);
if (!value)
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
dbus_free (key);
goto error;
}
if (!_dbus_string_init (key, _DBUS_INT_MAX))
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
dbus_free (key);
dbus_free (value);
goto error;
}
if (!_dbus_string_init (value, _DBUS_INT_MAX))
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
_dbus_string_free (key);
dbus_free (key);
dbus_free (value);
goto error;
}
if (!_dbus_string_copy_len (&str, pos, equals_pos - pos, key, 0))
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
_dbus_string_free (key);
_dbus_string_free (value);
dbus_free (key);
dbus_free (value);
goto error;
}
if (!_dbus_string_copy_len (&str, equals_pos + 1, comma_pos - equals_pos - 1, value, 0))
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
_dbus_string_free (key);
_dbus_string_free (value);
dbus_free (key);
dbus_free (value);
goto error;
}
if (!_dbus_list_append (&entry->keys, key))
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
_dbus_string_free (key);
_dbus_string_free (value);
dbus_free (key);
dbus_free (value);
goto error;
}
if (!_dbus_list_append (&entry->values, value))
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
_dbus_string_free (value);
dbus_free (value);
goto error;
}
}
pos = comma_pos + 1;
}
pos = end_pos + 1;
}
*array_len = _dbus_list_get_length (&entries);
entry_array = dbus_new (DBusAddressEntry *, *array_len + 1);
if (!entry_array)
{
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
goto error;
}
entry_array [*array_len] = NULL;
link = _dbus_list_get_first_link (&entries);
i = 0;
while (link != NULL)
{
entry_array[i] = link->data;
i++;
link = _dbus_list_get_next_link (&entries, link);
}
_dbus_list_clear (&entries);
*entry = entry_array;
dbus_set_result (result, DBUS_RESULT_SUCCESS);
return TRUE;
error:
link = _dbus_list_get_first_link (&entries);
while (link != NULL)
{
dbus_address_entry_free (link->data);
link = _dbus_list_get_next_link (&entries, link);
}
return FALSE;
}
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
dbus_bool_t
_dbus_address_test (void)
{
DBusAddressEntry **entries;
int len;
DBusResultCode result;
if (!dbus_parse_address ("unix:path=/tmp/foo;debug:name=test,sliff=sloff;",
&entries, &len, &result))
_dbus_assert_not_reached ("could not parse address");
_dbus_assert (len == 2);
_dbus_assert (strcmp (dbus_address_entry_get_value (entries[0], "path"), "/tmp/foo") == 0);
_dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "name"), "test") == 0);
_dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "sliff"), "sloff") == 0);
dbus_address_entries_free (entries);
/* Different possible errors */
if (dbus_parse_address ("foo", &entries, &len, &result))
_dbus_assert_not_reached ("Parsed incorrect address.");
if (dbus_parse_address ("foo:bar", &entries, &len, &result))
_dbus_assert_not_reached ("Parsed incorrect address.");
if (dbus_parse_address ("foo:bar,baz", &entries, &len, &result))
_dbus_assert_not_reached ("Parsed incorrect address.");
if (dbus_parse_address ("foo:bar=foo,baz", &entries, &len, &result))
_dbus_assert_not_reached ("Parsed incorrect address.");
if (dbus_parse_address ("foo:bar=foo;baz", &entries, &len, &result))
_dbus_assert_not_reached ("Parsed incorrect address.");
if (dbus_parse_address ("foo:=foo", &entries, &len, &result))
_dbus_assert_not_reached ("Parsed incorrect address.");
if (dbus_parse_address ("foo:foo=", &entries, &len, &result))
_dbus_assert_not_reached ("Parsed incorrect address.");
return TRUE;
}
#endif
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-address.h Server address parser.
*
* Copyright (C) 2003 CodeFactory AB
*
* 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
*
*/
#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
#endif
#ifndef DBUS_ADDRESS_H
#define DBUS_ADDRESS_H
#include <dbus/dbus-types.h>
#include <dbus/dbus-errors.h>
typedef struct DBusAddressEntry DBusAddressEntry;
dbus_bool_t dbus_parse_address (const char *address,
DBusAddressEntry ***entry,
int *array_len,
DBusResultCode *result);
const char *dbus_address_entry_get_value (DBusAddressEntry *entry,
const char *key);
const char *dbus_address_entry_get_method (DBusAddressEntry *entry);
void dbus_address_entries_free (DBusAddressEntry **entries);
#endif /* DBUS_ADDRESS_H */
......@@ -223,6 +223,16 @@ _dbus_connection_remove_watch (DBusConnection *connection,
watch);
}
/**
* Adds a timeout using the connection's DBusAddTimeoutFunction if
* available. Otherwise records the timeout to be added when said
* function is available. Also re-adds the timeout if the
* DBusAddTimeoutFunction changes. May fail due to lack of memory.
*
* @param connection the connection.
* @param timeout the timeout to add.
* @returns #TRUE on success.
*/
dbus_bool_t
_dbus_connection_add_timeout (DBusConnection *connection,
DBusTimeout *timeout)
......@@ -234,6 +244,14 @@ _dbus_connection_add_timeout (DBusConnection *connection,
return FALSE;
}
/**
* Removes a timeout using the connection's DBusRemoveTimeoutFunction
* if available. It's an error to call this function on a timeout
* that was not previously added.
*
* @param connection the connection.
* @param timeout the timeout to remove.
*/
void
_dbus_connection_remove_timeout (DBusConnection *connection,
DBusTimeout *timeout)
......
......@@ -774,6 +774,12 @@ dbus_message_new_reply (const char *name,
return message;
}
/**
* Creates a new message that is an exact replica of the message
* specified, except that its refcount is set to 1.
*
* @param message the message.
* @returns the new message.
DBusMessage *
dbus_message_new_from_message (const DBusMessage *message)
{
......@@ -1628,6 +1634,10 @@ dbus_message_get_sender (DBusMessage *message)
* _DBUS_INT_MAX; and add 16 for paranoia, since a message
* over 128M is pretty nuts anyhow.
*/
/**
* The maximum sane message size.
*/
#define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
/**
......
......@@ -40,8 +40,14 @@
* @{
*/
/**
* Default timeout interval when reading or writing.
*/
#define DEFAULT_INTERVAL 10
/**
* Opaque object representing a debug server implementation.
*/
typedef struct DBusServerDebug DBusServerDebug;
/**
......@@ -83,6 +89,12 @@ static DBusServerVTable debug_vtable = {
debug_disconnect
};
/**
* Looks up a server by its name.
*
* @param server_name the server name.
* @returns the server, or #NULL if none exists.
*/
DBusServer*
_dbus_server_debug_lookup (const char *server_name)
{
......@@ -92,6 +104,13 @@ _dbus_server_debug_lookup (const char *server_name)
return _dbus_hash_table_lookup_string (server_hash, server_name);
}
/**
* Creates a new debug server.
*
* @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_new (const char *server_name,
DBusResultCode *result)
......@@ -200,6 +219,14 @@ handle_new_client (void *data)
dbus_connection_unref (connection);
}
/**
* Tells the server to accept a transport so the transport
* can send messages to it.
*
* @param server the server
* @param transport the transport
* @returns #TRUE on success.
*/
dbus_bool_t
_dbus_server_debug_accept_transport (DBusServer *server,
DBusTransport *transport)
......
......@@ -25,6 +25,7 @@
#ifdef DBUS_BUILD_TESTS
#include "dbus-server-debug.h"
#endif
#include "dbus-address.h"
/**
* @defgroup DBusServer DBusServer
......@@ -134,6 +135,13 @@ _dbus_server_remove_watch (DBusServer *server,
_dbus_watch_list_remove_watch (server->watches, watch);
}
/**
* Adds a timeout for this server, chaining out to application-provided
* timeout handlers.
*
* @param server the server.
* @param timeout the timeout to add.
*/
dbus_bool_t
_dbus_server_add_timeout (DBusServer *server,
DBusTimeout *timeout)
......@@ -141,6 +149,12 @@ _dbus_server_add_timeout (DBusServer *server,
return _dbus_timeout_list_add_timeout (server->timeouts, timeout);
}
/**
* Removes a timeout previously added with _dbus_server_add_timeout().
*
* @param server the server.
* @param timeout the timeout to remove.
*/
void
_dbus_server_remove_timeout (DBusServer *server,
DBusTimeout *timeout)
......@@ -187,15 +201,53 @@ dbus_server_listen (const char *address,
DBusResultCode *result)
{
DBusServer *server;
DBusAddressEntry **entries;
int len, i;
if (!dbus_parse_address (address, &entries, &len, result))
return NULL;
#if 1
/* For now just pretend the address is a unix domain socket path */
server = _dbus_server_new_for_domain_socket (address, result);
#else
server = _dbus_server_debug_new (address, result);
#endif
server = NULL;
for (i = 0; i < len; i++)
{
const char *method = dbus_address_entry_get_method (entries[i]);
if (strcmp (method, "unix") == 0)
{
const char *path = dbus_address_entry_get_value (entries[i], "path");
if (path == NULL)
goto bad_address;
server = _dbus_server_new_for_domain_socket (path, result);
if (server)
break;
}
else if (strcmp (method, "debug") == 0)
{
const char *name = dbus_address_entry_get_value (entries[i], "name");
if (name == NULL)
goto bad_address;
server = _dbus_server_debug_new (name, result);
if (server)
break;
}
else goto bad_address;
}
dbus_address_entries_free (entries);
return server;
bad_address:
dbus_address_entries_free (entries);
dbus_set_result (result, DBUS_RESULT_BAD_ADDRESS);
return NULL;
}
/**
......
......@@ -1221,6 +1221,78 @@ _dbus_string_find (const DBusString *str,
return FALSE;
}
/**
* Finds the given substring in the string,
* up to a certain position,
* returning #TRUE and filling in the byte index
* where the substring was found, if it was found.
* Returns #FALSE if the substring wasn't found.
* Sets *start to the length of the string if the substring
* is not found.
*
* @param str the string
* @param start where to start looking
* @param end where to stop looking
* @param substr the substring
* @param found return location for where it was found, or #NULL
* @returns #TRUE if found
*/
dbus_bool_t
_dbus_string_find_to (const DBusString *str,
int start,
int end,
const char *substr,
int *found)
{
int i;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (substr != NULL);
_dbus_assert (start <= real->len);
_dbus_assert (end <= real->len);
_dbus_assert (start < end);