mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-01-13 07:20:27 +01:00
2002-12-12 Havoc Pennington <hp@pobox.com>
* dbus/dbus-transport-unix.c, dbus/dbus-server-unix.c: use the below new interfaces and include fewer system headers. * dbus/dbus-sysdeps.c (_dbus_read): new function (_dbus_write): new function (_dbus_write_two): new function (_dbus_connect_unix_socket): new function (_dbus_listen_unix_socket): new function * dbus/dbus-message-internal.h: change interfaces to use DBusString
This commit is contained in:
parent
d4b870e7f9
commit
271fa7fc33
10 changed files with 485 additions and 231 deletions
14
ChangeLog
14
ChangeLog
|
|
@ -1,3 +1,17 @@
|
|||
2002-12-12 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* dbus/dbus-transport-unix.c, dbus/dbus-server-unix.c: use the
|
||||
below new interfaces and include fewer system headers.
|
||||
|
||||
* dbus/dbus-sysdeps.c (_dbus_read): new function
|
||||
(_dbus_write): new function
|
||||
(_dbus_write_two): new function
|
||||
(_dbus_connect_unix_socket): new function
|
||||
(_dbus_listen_unix_socket): new function
|
||||
|
||||
* dbus/dbus-message-internal.h: change interfaces to use
|
||||
DBusString
|
||||
|
||||
2002-12-11 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* dbus/dbus-types.h: add dbus_unichar
|
||||
|
|
|
|||
|
|
@ -30,10 +30,8 @@ DBUS_BEGIN_DECLS;
|
|||
typedef struct DBusMessageLoader DBusMessageLoader;
|
||||
|
||||
void _dbus_message_get_network_data (DBusMessage *message,
|
||||
const unsigned char **header,
|
||||
int *header_len,
|
||||
const unsigned char **body,
|
||||
int *body_len);
|
||||
const DBusString **header,
|
||||
const DBusString **body);
|
||||
|
||||
void _dbus_message_lock (DBusMessage *message);
|
||||
|
||||
|
|
@ -41,11 +39,10 @@ void _dbus_message_lock (DBusMessage *message);
|
|||
DBusMessageLoader* _dbus_message_loader_new (void);
|
||||
void _dbus_message_loader_ref (DBusMessageLoader *loader);
|
||||
void _dbus_message_loader_unref (DBusMessageLoader *loader);
|
||||
dbus_bool_t _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
|
||||
unsigned char **buffer,
|
||||
int *buffer_len);
|
||||
void _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
|
||||
DBusString **buffer);
|
||||
void _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
|
||||
unsigned char *buffer,
|
||||
DBusString *buffer,
|
||||
int bytes_read);
|
||||
|
||||
DBusMessage* _dbus_message_loader_pop_message (DBusMessageLoader *loader);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,13 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The largest-length message we allow
|
||||
*
|
||||
* @todo match this up with whatever the protocol spec says.
|
||||
*/
|
||||
#define _DBUS_MAX_MESSAGE_LENGTH (_DBUS_INT_MAX/16)
|
||||
|
||||
/**
|
||||
* @brief Internals of DBusMessage
|
||||
*
|
||||
|
|
@ -49,14 +56,12 @@ struct DBusMessage
|
|||
{
|
||||
int refcount; /**< Reference count */
|
||||
|
||||
unsigned char *header; /**< Header network data, stored
|
||||
* separately from body so we can
|
||||
* independently realloc it.
|
||||
*/
|
||||
int header_len; /**< Length of header data. */
|
||||
DBusString header; /**< Header network data, stored
|
||||
* separately from body so we can
|
||||
* independently realloc it.
|
||||
*/
|
||||
|
||||
unsigned char *body; /**< Body network data. */
|
||||
int body_len; /**< Length of body data. */
|
||||
DBusString body; /**< Body network data. */
|
||||
|
||||
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
|
||||
};
|
||||
|
|
@ -69,23 +74,17 @@ struct DBusMessage
|
|||
*
|
||||
* @param message the message.
|
||||
* @param header return location for message header data.
|
||||
* @param header_len return location for header length in bytes.
|
||||
* @param body return location for message body data.
|
||||
* @param body_len return location for body length in bytes.
|
||||
*/
|
||||
void
|
||||
_dbus_message_get_network_data (DBusMessage *message,
|
||||
const unsigned char **header,
|
||||
int *header_len,
|
||||
const unsigned char **body,
|
||||
int *body_len)
|
||||
const DBusString **header,
|
||||
const DBusString **body)
|
||||
{
|
||||
_dbus_assert (message->locked);
|
||||
|
||||
*header = message->header;
|
||||
*header_len = message->header_len;
|
||||
*body = message->body;
|
||||
*body_len = message->body_len;
|
||||
*header = &message->header;
|
||||
*body = &message->body;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -143,11 +142,25 @@ dbus_message_new (void)
|
|||
|
||||
message->refcount = 1;
|
||||
|
||||
if (!_dbus_string_init (&message->header, _DBUS_MAX_MESSAGE_LENGTH))
|
||||
{
|
||||
dbus_free (message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_dbus_string_init (&message->body, _DBUS_MAX_MESSAGE_LENGTH))
|
||||
{
|
||||
_dbus_string_free (&message->header);
|
||||
dbus_free (message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We need to decide what a message contains. ;-) */
|
||||
message->header = _dbus_strdup ("H");
|
||||
message->header_len = 2;
|
||||
message->body = _dbus_strdup ("Body");
|
||||
message->body_len = 5;
|
||||
/* (not bothering to check failure of these appends) */
|
||||
_dbus_string_append (&message->header, "H");
|
||||
_dbus_string_append_byte (&message->header, '\0');
|
||||
_dbus_string_append (&message->body, "Body");
|
||||
_dbus_string_append_byte (&message->body, '\0');
|
||||
|
||||
return message;
|
||||
}
|
||||
|
|
@ -180,6 +193,8 @@ dbus_message_unref (DBusMessage *message)
|
|||
message->refcount -= 1;
|
||||
if (message->refcount == 0)
|
||||
{
|
||||
_dbus_string_free (&message->header);
|
||||
_dbus_string_free (&message->body);
|
||||
|
||||
dbus_free (message);
|
||||
}
|
||||
|
|
@ -212,12 +227,9 @@ dbus_message_unref (DBusMessage *message)
|
|||
struct DBusMessageLoader
|
||||
{
|
||||
int refcount; /**< Reference count. */
|
||||
|
||||
DBusString data; /**< Buffered data */
|
||||
|
||||
int allocated; /**< Allocated size of "data" */
|
||||
int length; /**< Used size of "data" */
|
||||
|
||||
unsigned char *data; /**< Buffered data. */
|
||||
|
||||
DBusList *messages; /**< Complete messages. */
|
||||
|
||||
unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
|
||||
|
|
@ -251,14 +263,15 @@ _dbus_message_loader_new (void)
|
|||
return NULL;
|
||||
|
||||
loader->refcount = 1;
|
||||
|
||||
/* Header, plus room for averagish other fields */
|
||||
loader->allocated = INITIAL_LOADER_DATA_LEN;
|
||||
loader->data = dbus_malloc (loader->allocated);
|
||||
if (loader->data == NULL)
|
||||
loader->allocated = 0;
|
||||
|
||||
loader->length = 0;
|
||||
|
||||
if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
|
||||
{
|
||||
dbus_free (loader);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* preallocate the buffer for speed, ignore failure */
|
||||
(void) _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
|
@ -290,7 +303,7 @@ _dbus_message_loader_unref (DBusMessageLoader *loader)
|
|||
(DBusForeachFunction) dbus_message_unref,
|
||||
NULL);
|
||||
_dbus_list_clear (&loader->messages);
|
||||
dbus_free (loader->data);
|
||||
_dbus_string_free (&loader->data);
|
||||
dbus_free (loader);
|
||||
}
|
||||
}
|
||||
|
|
@ -309,50 +322,17 @@ _dbus_message_loader_unref (DBusMessageLoader *loader)
|
|||
* or reallocs.
|
||||
*
|
||||
* @param loader the message loader.
|
||||
* @param buffer address to store the buffer.
|
||||
* @param buffer_len address to store the buffer length.
|
||||
* @returns #FALSE if no buffer can be allocated.
|
||||
* @param buffer the buffer
|
||||
*/
|
||||
dbus_bool_t
|
||||
void
|
||||
_dbus_message_loader_get_buffer (DBusMessageLoader *loader,
|
||||
unsigned char **buffer,
|
||||
int *buffer_len)
|
||||
DBusString **buffer)
|
||||
{
|
||||
_dbus_assert (!loader->buffer_outstanding);
|
||||
|
||||
#define MIN_BUFSIZE INITIAL_LOADER_DATA_LEN
|
||||
|
||||
if ((loader->length + MIN_BUFSIZE) >= loader->allocated)
|
||||
{
|
||||
unsigned char *buf;
|
||||
int new_allocated;
|
||||
|
||||
/* double (and add MIN_BUFSIZE, in case allocated == 0) */
|
||||
new_allocated = MIN_BUFSIZE + loader->allocated * 2;
|
||||
|
||||
if (new_allocated <= loader->allocated)
|
||||
{
|
||||
/* ugh, overflow. Maybe someone is trying to screw us. */
|
||||
/* (we could overflow so far that new_allocated > loader->allocated
|
||||
* but nothing should break in that case)
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
buf = dbus_realloc (loader->data, new_allocated);
|
||||
if (buf == NULL)
|
||||
return FALSE;
|
||||
|
||||
loader->data = buf;
|
||||
loader->allocated = new_allocated;
|
||||
}
|
||||
|
||||
*buffer = loader->data + loader->length;
|
||||
*buffer_len = loader->allocated - loader->length;
|
||||
*buffer = &loader->data;
|
||||
|
||||
loader->buffer_outstanding = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -367,24 +347,23 @@ _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
|
|||
*/
|
||||
void
|
||||
_dbus_message_loader_return_buffer (DBusMessageLoader *loader,
|
||||
unsigned char *buffer,
|
||||
DBusString *buffer,
|
||||
int bytes_read)
|
||||
{
|
||||
_dbus_assert (loader->buffer_outstanding);
|
||||
_dbus_assert (buffer == &loader->data);
|
||||
|
||||
/* FIXME fake implementation just creates a message for every 7
|
||||
* bytes. The real implementation will pass ownership of
|
||||
* loader->data to new messages, to avoid memcpy. We can also
|
||||
* loader->data bytes to new messages, to avoid memcpy. We can also
|
||||
* smart-realloc loader->data to shrink it if it's too big, though
|
||||
* _dbus_message_loader_get_buffer() could strategically arrange for
|
||||
* that to usually not happen.
|
||||
*/
|
||||
|
||||
loader->length += bytes_read;
|
||||
|
||||
loader->buffer_outstanding = FALSE;
|
||||
|
||||
while (loader->length >= 7)
|
||||
while (_dbus_string_get_length (&loader->data) >= 7)
|
||||
{
|
||||
DBusMessage *message;
|
||||
|
||||
|
|
@ -394,10 +373,9 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
|
|||
|
||||
_dbus_list_append (&loader->messages, message);
|
||||
|
||||
memmove (loader->data, loader->data + 7,
|
||||
loader->length - 7);
|
||||
loader->length -= 7;
|
||||
|
||||
_dbus_string_delete (&loader->data,
|
||||
0, 7);
|
||||
|
||||
_dbus_verbose ("Loaded message %p\n", message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,6 @@
|
|||
#include "dbus-connection-internal.h"
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/**
|
||||
* @defgroup DBusServerUnix DBusServer implementations for UNIX
|
||||
|
|
@ -132,14 +128,13 @@ unix_handle_watch (DBusServer *server,
|
|||
|
||||
listen_fd = dbus_watch_get_fd (watch);
|
||||
|
||||
retry:
|
||||
client_fd = accept (listen_fd, NULL, NULL);
|
||||
client_fd = _dbus_accept_unix_socket (listen_fd);
|
||||
|
||||
if (client_fd < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
else if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
/* EINTR handled for us */
|
||||
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
_dbus_verbose ("No client available to accept after all\n");
|
||||
else
|
||||
_dbus_verbose ("Failed to accept a client connection: %s\n",
|
||||
|
|
@ -247,46 +242,10 @@ _dbus_server_new_for_domain_socket (const char *path,
|
|||
{
|
||||
DBusServer *server;
|
||||
int listen_fd;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
listen_fd = socket (AF_LOCAL, SOCK_STREAM, 0);
|
||||
|
||||
listen_fd = _dbus_listen_unix_socket (path, result);
|
||||
if (listen_fd < 0)
|
||||
{
|
||||
dbus_set_result (result, _dbus_result_from_errno (errno));
|
||||
_dbus_verbose ("Failed to create socket \"%s\": %s\n",
|
||||
path, _dbus_strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_dbus_set_fd_nonblocking (listen_fd, result))
|
||||
{
|
||||
close (listen_fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_DBUS_ZERO (addr);
|
||||
addr.sun_family = AF_LOCAL;
|
||||
strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
|
||||
addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
|
||||
|
||||
if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
|
||||
{
|
||||
dbus_set_result (result, _dbus_result_from_errno (errno));
|
||||
_dbus_verbose ("Failed to bind socket \"%s\": %s\n",
|
||||
path, _dbus_strerror (errno));
|
||||
close (listen_fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (listen (listen_fd, 30 /* backlog */) < 0)
|
||||
{
|
||||
dbus_set_result (result, _dbus_result_from_errno (errno));
|
||||
_dbus_verbose ("Failed to listen on socket \"%s\": %s\n",
|
||||
path, _dbus_strerror (errno));
|
||||
close (listen_fd);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
server = _dbus_server_new_for_fd (listen_fd);
|
||||
if (server == NULL)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "dbus-internals.h"
|
||||
#include "dbus-string.h"
|
||||
/* we allow a system header here, for speed/convenience */
|
||||
#include <string.h>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@
|
|||
#ifndef DBUS_STRING_H
|
||||
#define DBUS_STRING_H
|
||||
|
||||
#include <dbus/dbus-internals.h>
|
||||
#include <config.h>
|
||||
|
||||
#include <dbus/dbus-memory.h>
|
||||
#include <dbus/dbus-types.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,22 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "dbus-internals.h"
|
||||
#include "dbus-sysdeps.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#ifdef HAVE_WRITEV
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup DBusInternalsUtils
|
||||
|
|
@ -54,6 +64,324 @@ _dbus_getenv (const char *varname)
|
|||
return getenv (varname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Thin wrapper around the read() system call that appends
|
||||
* the data it reads to the DBusString buffer. It appends
|
||||
* up to the given count, and returns the same value
|
||||
* and same errno as read(). The only exception is that
|
||||
* _dbus_read() handles EINTR for you.
|
||||
*
|
||||
* @param fd the file descriptor to read from
|
||||
* @param buffer the buffer to append data to
|
||||
* @param count the amount of data to read
|
||||
* @returns the number of bytes read or -1
|
||||
*/
|
||||
int
|
||||
_dbus_read (int fd,
|
||||
DBusString *buffer,
|
||||
int count)
|
||||
{
|
||||
int bytes_read;
|
||||
int start;
|
||||
char *data;
|
||||
|
||||
_dbus_assert (count >= 0);
|
||||
|
||||
start = _dbus_string_get_length (buffer);
|
||||
|
||||
if (!_dbus_string_lengthen (buffer, count))
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_dbus_string_get_data_len (buffer, &data, start, count);
|
||||
|
||||
again:
|
||||
|
||||
bytes_read = read (fd, data, count);
|
||||
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
else
|
||||
{
|
||||
/* put length back (note that this doesn't actually realloc anything) */
|
||||
_dbus_string_set_length (buffer, start);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* put length back (doesn't actually realloc) */
|
||||
_dbus_string_set_length (buffer, start + bytes_read);
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thin wrapper around the write() system call that writes a part of a
|
||||
* DBusString and handles EINTR for you.
|
||||
*
|
||||
* @param fd the file descriptor to write
|
||||
* @param buffer the buffer to write data from
|
||||
* @param start the first byte in the buffer to write
|
||||
* @param len the number of bytes to try to write
|
||||
* @returns the number of bytes written or -1 on error
|
||||
*/
|
||||
int
|
||||
_dbus_write (int fd,
|
||||
const DBusString *buffer,
|
||||
int start,
|
||||
int len)
|
||||
{
|
||||
const char *data;
|
||||
int bytes_written;
|
||||
|
||||
_dbus_string_get_const_data_len (buffer, &data, start, len);
|
||||
|
||||
again:
|
||||
|
||||
bytes_written = write (fd, data, len);
|
||||
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like _dbus_write() but will use writev() if possible
|
||||
* to write both buffers in sequence. The return value
|
||||
* is the number of bytes written in the first buffer,
|
||||
* plus the number written in the second. If the first
|
||||
* buffer is written successfully and an error occurs
|
||||
* writing the second, the number of bytes in the first
|
||||
* is returned (i.e. the error is ignored), on systems that
|
||||
* don't have writev. Handles EINTR for you.
|
||||
* The second buffer may be #NULL.
|
||||
*
|
||||
* @param fd the file descriptor
|
||||
* @param buffer1 first buffer
|
||||
* @param start1 first byte to write in first buffer
|
||||
* @param len1 number of bytes to write from first buffer
|
||||
* @param buffer2 second buffer, or #NULL
|
||||
* @param start2 first byte to write in second buffer
|
||||
* @param len2 number of bytes to write in second buffer
|
||||
* @returns total bytes written from both buffers, or -1 on error
|
||||
*/
|
||||
int
|
||||
_dbus_write_two (int fd,
|
||||
const DBusString *buffer1,
|
||||
int start1,
|
||||
int len1,
|
||||
const DBusString *buffer2,
|
||||
int start2,
|
||||
int len2)
|
||||
{
|
||||
_dbus_assert (buffer1 != NULL);
|
||||
_dbus_assert (start1 >= 0);
|
||||
_dbus_assert (start2 >= 0);
|
||||
_dbus_assert (len1 >= 0);
|
||||
_dbus_assert (len2 >= 0);
|
||||
|
||||
#ifdef HAVE_WRITEV
|
||||
{
|
||||
struct iovec vectors[2];
|
||||
const char *data1;
|
||||
const char *data2;
|
||||
int bytes_written;
|
||||
|
||||
_dbus_string_get_const_data_len (buffer1, &data1, start1, len1);
|
||||
|
||||
if (buffer2 != NULL)
|
||||
_dbus_string_get_const_data_len (buffer2, &data2, start2, len2);
|
||||
else
|
||||
{
|
||||
data2 = NULL;
|
||||
start2 = 0;
|
||||
len2 = 0;
|
||||
}
|
||||
|
||||
vectors[0].iov_base = (char*) data1;
|
||||
vectors[0].iov_len = len1;
|
||||
vectors[1].iov_base = (char*) data2;
|
||||
vectors[1].iov_len = len2;
|
||||
|
||||
again:
|
||||
|
||||
bytes_written = writev (fd,
|
||||
vectors,
|
||||
data2 ? 2 : 1);
|
||||
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
#else /* HAVE_WRITEV */
|
||||
{
|
||||
int ret1;
|
||||
|
||||
ret1 = _dbus_write (fd, buffer1, start1, len1);
|
||||
if (ret1 == len1 && buffer2 != NULL)
|
||||
{
|
||||
ret2 = _dbus_write (fd, buffer2, start2, len2);
|
||||
if (ret2 < 0)
|
||||
ret2 = 0; /* we can't report an error as the first write was OK */
|
||||
|
||||
return ret1 + ret2;
|
||||
}
|
||||
else
|
||||
return ret1;
|
||||
}
|
||||
#endif /* !HAVE_WRITEV */
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket and connects it to the UNIX domain socket at the
|
||||
* given path. The connection fd is returned, and is set up as
|
||||
* nonblocking.
|
||||
*
|
||||
* @param path the path to UNIX domain socket
|
||||
* @param result return location for error code
|
||||
* @returns connection file descriptor or -1 on error
|
||||
*/
|
||||
int
|
||||
_dbus_connect_unix_socket (const char *path,
|
||||
DBusResultCode *result)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
fd = socket (AF_LOCAL, SOCK_STREAM, 0);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
dbus_set_result (result,
|
||||
_dbus_result_from_errno (errno));
|
||||
|
||||
_dbus_verbose ("Failed to create socket: %s\n",
|
||||
_dbus_strerror (errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
_DBUS_ZERO (addr);
|
||||
addr.sun_family = AF_LOCAL;
|
||||
strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
|
||||
addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
|
||||
|
||||
if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
|
||||
{
|
||||
dbus_set_result (result,
|
||||
_dbus_result_from_errno (errno));
|
||||
|
||||
_dbus_verbose ("Failed to connect to socket %s: %s\n",
|
||||
path, _dbus_strerror (errno));
|
||||
|
||||
close (fd);
|
||||
fd = -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_dbus_set_fd_nonblocking (fd, result))
|
||||
{
|
||||
close (fd);
|
||||
fd = -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket and binds it to the given path,
|
||||
* then listens on the socket. The socket is
|
||||
* set to be nonblocking.
|
||||
*
|
||||
* @param path the socket name
|
||||
* @param result return location for errors
|
||||
* @returns the listening file descriptor or -1 on error
|
||||
*/
|
||||
int
|
||||
_dbus_listen_unix_socket (const char *path,
|
||||
DBusResultCode *result)
|
||||
{
|
||||
int listen_fd;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
listen_fd = socket (AF_LOCAL, SOCK_STREAM, 0);
|
||||
|
||||
if (listen_fd < 0)
|
||||
{
|
||||
dbus_set_result (result, _dbus_result_from_errno (errno));
|
||||
_dbus_verbose ("Failed to create socket \"%s\": %s\n",
|
||||
path, _dbus_strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
_DBUS_ZERO (addr);
|
||||
addr.sun_family = AF_LOCAL;
|
||||
strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
|
||||
addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
|
||||
|
||||
if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
|
||||
{
|
||||
dbus_set_result (result, _dbus_result_from_errno (errno));
|
||||
_dbus_verbose ("Failed to bind socket \"%s\": %s\n",
|
||||
path, _dbus_strerror (errno));
|
||||
close (listen_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen (listen_fd, 30 /* backlog */) < 0)
|
||||
{
|
||||
dbus_set_result (result, _dbus_result_from_errno (errno));
|
||||
_dbus_verbose ("Failed to listen on socket \"%s\": %s\n",
|
||||
path, _dbus_strerror (errno));
|
||||
close (listen_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_dbus_set_fd_nonblocking (listen_fd, result))
|
||||
{
|
||||
close (listen_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return listen_fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a connection on a listening UNIX socket.
|
||||
* Specific to UNIX domain sockets because we might
|
||||
* add extra args to this function later to get client
|
||||
* credentials. Handles EINTR for you.
|
||||
*
|
||||
* @param listen_fd the listen file descriptor
|
||||
* @returns the connection fd of the client, or -1 on error
|
||||
*/
|
||||
int
|
||||
_dbus_accept_unix_socket (int listen_fd)
|
||||
{
|
||||
int client_fd;
|
||||
|
||||
retry:
|
||||
client_fd = accept (listen_fd, NULL, NULL);
|
||||
|
||||
if (client_fd < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return client_fd;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
*/
|
||||
#include <string.h>
|
||||
|
||||
/* and it would just be annoying to abstract this */
|
||||
#include <errno.h>
|
||||
|
||||
DBUS_BEGIN_DECLS;
|
||||
|
||||
/* The idea of this file is to encapsulate everywhere that we're
|
||||
|
|
@ -46,6 +49,29 @@ void _dbus_abort (void);
|
|||
|
||||
const char* _dbus_getenv (const char *varname);
|
||||
|
||||
|
||||
int _dbus_read (int fd,
|
||||
DBusString *buffer,
|
||||
int count);
|
||||
int _dbus_write (int fd,
|
||||
const DBusString *buffer,
|
||||
int start,
|
||||
int len);
|
||||
int _dbus_write_two (int fd,
|
||||
const DBusString *buffer1,
|
||||
int start1,
|
||||
int len1,
|
||||
const DBusString *buffer2,
|
||||
int start2,
|
||||
int len2);
|
||||
|
||||
int _dbus_connect_unix_socket (const char *path,
|
||||
DBusResultCode *result);
|
||||
int _dbus_listen_unix_socket (const char *path,
|
||||
DBusResultCode *result);
|
||||
int _dbus_accept_unix_socket (int listen_fd);
|
||||
|
||||
|
||||
DBUS_END_DECLS;
|
||||
|
||||
#endif /* DBUS_SYSDEPS_H */
|
||||
|
|
|
|||
|
|
@ -28,13 +28,7 @@
|
|||
#include "dbus-watch.h"
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_WRITEV
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup DBusTransportUnix DBusTransport implementations for UNIX
|
||||
|
|
@ -99,15 +93,13 @@ do_writing (DBusTransport *transport)
|
|||
DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
|
||||
|
||||
total = 0;
|
||||
|
||||
again:
|
||||
|
||||
while (_dbus_connection_have_messages_to_send (transport->connection))
|
||||
{
|
||||
int bytes_written;
|
||||
DBusMessage *message;
|
||||
const unsigned char *header;
|
||||
const unsigned char *body;
|
||||
const DBusString *header;
|
||||
const DBusString *body;
|
||||
int header_len, body_len;
|
||||
|
||||
if (total > unix_transport->max_bytes_written_per_iteration)
|
||||
|
|
@ -122,42 +114,37 @@ do_writing (DBusTransport *transport)
|
|||
_dbus_message_lock (message);
|
||||
|
||||
_dbus_message_get_network_data (message,
|
||||
&header, &header_len,
|
||||
&body, &body_len);
|
||||
&header, &body);
|
||||
|
||||
header_len = _dbus_string_get_length (header);
|
||||
body_len = _dbus_string_get_length (body);
|
||||
|
||||
if (unix_transport->message_bytes_written < header_len)
|
||||
{
|
||||
#ifdef HAVE_WRITEV
|
||||
struct iovec vectors[2];
|
||||
|
||||
vectors[0].iov_base = header + unix_transport->message_bytes_written;
|
||||
vectors[0].iov_len = header_len - unix_transport->message_bytes_written;
|
||||
vectors[1].iov_base = body;
|
||||
vectors[1].iov_len = body_len;
|
||||
|
||||
bytes_written = writev (unix_transport->fd,
|
||||
vectors, _DBUS_N_ELEMENTS (vectors));
|
||||
#else
|
||||
bytes_written = write (unix_transport->fd,
|
||||
header + unix_transport->message_bytes_written,
|
||||
header_len - unix_transport->message_bytes_written);
|
||||
#endif
|
||||
bytes_written =
|
||||
_dbus_write_two (unix_transport->fd,
|
||||
header,
|
||||
unix_transport->message_bytes_written,
|
||||
header_len - unix_transport->message_bytes_written,
|
||||
body,
|
||||
0, body_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes_written = write (unix_transport->fd,
|
||||
body +
|
||||
(unix_transport->message_bytes_written - header_len),
|
||||
body_len -
|
||||
(unix_transport->message_bytes_written - body_len));
|
||||
bytes_written =
|
||||
_dbus_write (unix_transport->fd,
|
||||
body,
|
||||
(unix_transport->message_bytes_written - header_len),
|
||||
body_len -
|
||||
(unix_transport->message_bytes_written - header_len));
|
||||
}
|
||||
|
||||
if (bytes_written < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
else if (errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK)
|
||||
/* EINTR already handled for us */
|
||||
|
||||
if (errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK)
|
||||
goto out;
|
||||
else
|
||||
{
|
||||
|
|
@ -194,15 +181,15 @@ static void
|
|||
do_reading (DBusTransport *transport)
|
||||
{
|
||||
DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
|
||||
unsigned char *buffer;
|
||||
DBusString *buffer;
|
||||
int buffer_len;
|
||||
int bytes_read;
|
||||
int total;
|
||||
|
||||
total = 0;
|
||||
|
||||
again:
|
||||
|
||||
again:
|
||||
|
||||
if (total > unix_transport->max_bytes_read_per_iteration)
|
||||
{
|
||||
_dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
|
||||
|
|
@ -210,23 +197,24 @@ do_reading (DBusTransport *transport)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!_dbus_message_loader_get_buffer (transport->loader,
|
||||
&buffer, &buffer_len))
|
||||
goto out; /* no memory for a buffer */
|
||||
_dbus_message_loader_get_buffer (transport->loader,
|
||||
&buffer);
|
||||
|
||||
buffer_len = _dbus_string_get_length (buffer);
|
||||
|
||||
bytes_read = read (unix_transport->fd,
|
||||
buffer, buffer_len);
|
||||
bytes_read = _dbus_read (unix_transport->fd,
|
||||
buffer, unix_transport->max_bytes_read_per_iteration);
|
||||
|
||||
_dbus_message_loader_return_buffer (transport->loader,
|
||||
buffer,
|
||||
bytes_read < 0 ? 0 : bytes_read);
|
||||
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
else if (errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK)
|
||||
{
|
||||
/* EINTR already handled for us */
|
||||
|
||||
if (errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK)
|
||||
goto out;
|
||||
else
|
||||
{
|
||||
|
|
@ -519,49 +507,10 @@ _dbus_transport_new_for_domain_socket (const char *path,
|
|||
{
|
||||
int fd;
|
||||
DBusTransport *transport;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
transport = NULL;
|
||||
|
||||
fd = socket (AF_LOCAL, SOCK_STREAM, 0);
|
||||
|
||||
fd = _dbus_connect_unix_socket (path, result);
|
||||
if (fd < 0)
|
||||
{
|
||||
dbus_set_result (result,
|
||||
_dbus_result_from_errno (errno));
|
||||
|
||||
_dbus_verbose ("Failed to create socket: %s\n",
|
||||
_dbus_strerror (errno));
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
_DBUS_ZERO (addr);
|
||||
addr.sun_family = AF_LOCAL;
|
||||
strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
|
||||
addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
|
||||
|
||||
if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
|
||||
{
|
||||
dbus_set_result (result,
|
||||
_dbus_result_from_errno (errno));
|
||||
|
||||
_dbus_verbose ("Failed to connect to socket %s: %s\n",
|
||||
path, _dbus_strerror (errno));
|
||||
|
||||
close (fd);
|
||||
fd = -1;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_dbus_set_fd_nonblocking (fd, result))
|
||||
{
|
||||
close (fd);
|
||||
fd = -1;
|
||||
|
||||
goto out;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
transport = _dbus_transport_new_for_fd (fd);
|
||||
if (transport == NULL)
|
||||
|
|
@ -569,10 +518,8 @@ _dbus_transport_new_for_domain_socket (const char *path,
|
|||
dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
|
||||
close (fd);
|
||||
fd = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
return transport;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
#include <dbus/dbus-list.h>
|
||||
#undef DBUS_COMPILATION
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Cheesy main loop used in test programs. Any real app would use the
|
||||
* GLib or Qt or other non-sucky main loops.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue