Andreas Otto wrote:
Dear APR Support Team,
some time ago I made the strategic decision to port my software:
http://libmsgque.sourceforge.net/
to APR by able to use all of the nice features.
Some days ago I finally start to do this job ... but today I got a massive
disappointment ...
You ask why ?
It's the UNIX Domain Socket issue !!!
well Unix-Domains are very beautiful in terms of usability
you only have to create the "sockaddr_un" as part of "sockaddr"
and you can use the same code you allready written for
network sockets to use local sockets
The main advantages are:
1. 50% faster as network sockets (on linux)
2. absolute secure -> no network access
now the problem:
APR does not support Unix Domain Sockets
Perhaps it will in the future.
Here is a patch that allows to do that.
The apr_sockadr_local_get could be included
inside apr_sockaddr_info_get and use hostname
for filename.
Not sure if some addr functions need some extra
check for AF_UNIX, since they'll probably
fail or return some junk. Nevertheless
I doubt they are useful anyhow for domain sockets.
I've tested the API, and bind/connect/accept
works fine. However probably there will be
needed some unlik callback on bind.
Regards
--
^(TM)
Index: network_io/unix/sockaddr.c
===================================================================
--- network_io/unix/sockaddr.c (revision 744613)
+++ network_io/unix/sockaddr.c (working copy)
@@ -1023,3 +1023,27 @@
#endif /* APR_HAVE_IPV6 */
return 0; /* no match */
}
+
+APR_DECLARE(apr_status_t) apr_sockaddr_local_get(apr_sockaddr_t **sa,
+ const char *filename,
+ apr_pool_t *p)
+{
+#if APR_HAVE_SOCKADDR_UN
+ *sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
+ (*sa)->pool = p;
+ apr_cpystrn((*sa)->sa.unx.sun_path, filename,
+ sizeof((*sa)->sa.unx.sun_path));
+
+ (*sa)->family = APR_UNIX;
+ (*sa)->sa.sin.sin_family = APR_UNIX;
+ (*sa)->salen = sizeof(struct sockaddr_un);
+ (*sa)->addr_str_len = sizeof((*sa)->sa.unx.sun_path);
+ (*sa)->ipaddr_ptr = &((*sa)->sa.unx.sun_path[0]);
+ (*sa)->ipaddr_len = (*sa)->addr_str_len;
+
+ return APR_SUCCESS;
+#else
+ *sa = NULL;
+ return APR_ENOTIMPL;
+#endif
+}
Index: network_io/unix/sockets.c
===================================================================
--- network_io/unix/sockets.c (revision 744613)
+++ network_io/unix/sockets.c (working copy)
@@ -81,9 +81,10 @@
}
apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type,
- int protocol, apr_pool_t *cont)
+ int oprotocol, apr_pool_t *cont)
{
int family = ofamily;
+ int protocol = oprotocol;
if (family == APR_UNSPEC) {
#if APR_HAVE_IPV6
@@ -92,7 +93,11 @@
family = APR_INET;
#endif
}
-
+#if APR_HAVE_SOCKADDR_UN
+ if (family == APR_UNIX) {
+ protocol = 0;
+ }
+#endif
alloc_socket(new, cont);
#ifndef BEOS_R5
@@ -128,7 +133,7 @@
if ((*new)->socketdes < 0) {
return errno;
}
- set_socket_vars(*new, family, type, protocol);
+ set_socket_vars(*new, family, type, oprotocol);
(*new)->timeout = -1;
(*new)->inherit = 0;
@@ -225,6 +230,12 @@
(*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr;
}
#endif
+#if APR_HAVE_SOCKADDR_UN
+ else if (sock->local_addr->sa.sin.sin_family == AF_UNIX) {
+ (*new)->local_addr->ipaddr_ptr = &((*new)->local_addr->sa.unx.sun_path[0]);
+ }
+#endif
+
(*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port);
if (sock->local_port_unknown) {
/* not likely for a listening socket, but theoretically possible :) */
Index: include/apr.h.in
===================================================================
--- include/apr.h.in (revision 744613)
+++ include/apr.h.in (working copy)
@@ -208,6 +208,7 @@
#define APR_HAVE_INET_ADDR @have_inet_addr@
#define APR_HAVE_INET_NETWORK @have_inet_network@
#define APR_HAVE_IPV6 @have_ipv6@
+#define APR_HAVE_SOCKADDR_UN @have_sockaddr_un@
#define APR_HAVE_MEMMOVE @have_memmove@
#define APR_HAVE_SETRLIMIT @have_setrlimit@
#define APR_HAVE_SIGACTION @have_sigaction@
Index: include/apr.hw
===================================================================
--- include/apr.hw (revision 744613)
+++ include/apr.hw (working copy)
@@ -278,6 +278,7 @@
#define APR_HAVE_INET_ADDR 1
#define APR_HAVE_INET_NETWORK 0
#define APR_HAVE_IPV6 0
+#define APR_HAVE_SOCKADDR_UN 0
#define APR_HAVE_MEMMOVE 1
#define APR_HAVE_SETRLIMIT 0
#define APR_HAVE_SIGACTION 0
Index: include/apr_network_io.h
===================================================================
--- include/apr_network_io.h (revision 744613)
+++ include/apr_network_io.h (working copy)
@@ -30,6 +30,9 @@
#if APR_HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
+#if APR_HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
#ifdef __cplusplus
extern "C" {
@@ -111,6 +114,7 @@
#define APR_IPV4_ADDR_OK 0x01 /**< @see apr_sockaddr_info_get() */
#define APR_IPV6_ADDR_OK 0x02 /**< @see apr_sockaddr_info_get() */
+#define APR_UNIX_ADDR_OK 0x04 /**< @see apr_sockaddr_info_get() */
#if (!APR_HAVE_IN_ADDR)
/**
@@ -154,6 +158,14 @@
#define APR_INET6 AF_INET6
#endif
+#if defined(AF_UNIX)
+#define APR_UNIX AF_UNIX
+#elif defined(AF_LOCAL)
+#define APR_UNIX AF_LOCAL
+#else
+#define APR_UNIX APR_UNSPEC
+#endif
+
/**
* @defgroup IP_Proto IP Protocol Definitions for use when creating sockets
* @{
@@ -245,6 +257,10 @@
* dependent on whether APR_HAVE_IPV6 is defined. */
struct sockaddr_storage sas;
#endif
+#if APR_HAVE_SOCKADDR_UN
+ /** Unix domain socket sockaddr structure */
+ struct sockaddr_un unx;
+#endif
} sa;
};
@@ -377,7 +393,18 @@
apr_int32_t flags,
apr_pool_t *p);
+
/**
+ * Create domain socket apr_sockaddr_t.
+ * @param sa The new apr_sockaddr_t.
+ * @param filename The socket file name.
+ * @param p The pool for the apr_sockaddr_t and associated storage.
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_local_get(apr_sockaddr_t **sa,
+ const char *filename,
+ apr_pool_t *p);
+
+/**
* Look up the host name from an apr_sockaddr_t.
* @param hostname The hostname.
* @param sa The apr_sockaddr_t.
Index: include/apr.hnw
===================================================================
--- include/apr.hnw (revision 744613)
+++ include/apr.hnw (working copy)
@@ -178,6 +178,7 @@
#else
#define APR_HAVE_IPV6 0
#endif
+#define APR_HAVE_SOCKADDR_UN 0
#define APR_HAVE_MEMCHR 1
#define APR_HAVE_MEMMOVE 1
#define APR_HAVE_SETRLIMIT 0
Index: configure.in
===================================================================
--- configure.in (revision 744613)
+++ configure.in (working copy)
@@ -2294,6 +2294,7 @@
APR_CHECK_WORKING_GETNAMEINFO
APR_CHECK_SOCKADDR_IN6
APR_CHECK_SOCKADDR_STORAGE
+APR_CHECK_SOCKADDR_UN
have_ipv6="0"
if test "$user_disabled_ipv6" = 1; then
Index: build/apr_network.m4
===================================================================
--- build/apr_network.m4 (revision 744613)
+++ build/apr_network.m4 (working copy)
@@ -788,6 +788,36 @@
fi
])
+dnl Check for presence of struct sockaddr_un.
+AC_DEFUN([APR_CHECK_SOCKADDR_UN], [
+AC_CACHE_CHECK(for sockaddr_un, ac_cv_define_sockaddr_un,[
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+],[
+struct sockaddr_un sa;
+],[
+ ac_cv_define_sockaddr_un=yes
+],[
+ ac_cv_define_sockaddr_un=no
+])
+])
+
+if test "$ac_cv_define_sockaddr_un" = "yes"; then
+ have_sockaddr_un=1
+else
+ have_sockaddr_un=0
+fi
+AC_SUBST(have_sockaddr_un)
+])
+
dnl
dnl APR_H_ERRNO_COMPILE_CHECK
dnl