Adds: apr_bucket_socket_get_peer() and has the bucket read call recvfrom().
Based on an earlier patch from Issac Goldstand.
Index: include/apr_buckets.h
===================================================================
--- include/apr_buckets.h (revision 594215)
+++ include/apr_buckets.h (working copy)
@@ -553,6 +553,17 @@
void (*free_func)(void *data);
};
+
+typedef struct apr_bucket_socket apr_bucket_socket;
+/**
+ * A bucket referring to data allocated off the heap.
+ */
+struct apr_bucket_socket {
+ apr_socket_t *s;
+ apr_sockaddr_t *peer;
+};
+
+
/** @see apr_bucket_pool */
typedef struct apr_bucket_pool apr_bucket_pool;
/**
@@ -1402,6 +1413,9 @@
APU_DECLARE(apr_bucket *) apr_bucket_socket_make(apr_bucket *b,
apr_socket_t *thissock);
+
+APU_DECLARE(apr_sockaddr_t*) apr_bucket_socket_get_peer(apr_bucket *b);
+
/**
* Create a bucket referring to a pipe.
* @param thispipe The pipe to put in the bucket
Index: buckets/apr_buckets_socket.c
===================================================================
--- buckets/apr_buckets_socket.c (revision 594215)
+++ buckets/apr_buckets_socket.c (working copy)
@@ -19,10 +19,12 @@
static apr_status_t socket_bucket_read(apr_bucket *a, const char **str,
apr_size_t *len, apr_read_type_e block)
{
- apr_socket_t *p = a->data;
+ apr_bucket_socket *baton = a->data;
+ apr_socket_t *p = baton->s;
char *buf;
apr_status_t rv;
apr_interval_time_t timeout;
+ int sd_type;
if (block == APR_NONBLOCK_READ) {
apr_socket_timeout_get(p, &timeout);
@@ -33,7 +35,21 @@
*len = APR_BUCKET_BUFF_SIZE;
buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */
- rv = apr_socket_recv(p, buf, len);
+ apr_socket_type_get(p, &sd_type);
+ if (sd_type == SOCK_STREAM) {
+ rv = apr_socket_recv(p, buf, len);
+ } else {
+ /* Is socket connected? */
+ if (apr_socket_addr_get(&baton->peer, APR_REMOTE, p) != APR_SUCCESS) {
+ rv = apr_socket_recv(p, buf, len);
+ } else {
+ if (!baton->peer) {
+ baton->peer = apr_bucket_alloc(sizeof(*baton->peer), a->list);
+ }
+ /* Caller is responsible for detecting peer on his own if needed */
+ rv = apr_socket_recvfrom(baton->peer, p, 0, buf, len);
+ }
+ }
if (block == APR_NONBLOCK_READ) {
apr_socket_timeout_set(p, timeout);
@@ -77,6 +93,8 @@
APU_DECLARE(apr_bucket *) apr_bucket_socket_make(apr_bucket *b, apr_socket_t
*p)
{
+ apr_bucket_socket *baton;
+ baton = apr_bucket_alloc(sizeof(*baton), b->list);
/*
* XXX: We rely on a cleanup on some pool or other to actually
* destroy the socket. We should probably explicitly call apr to
@@ -85,11 +103,16 @@
* Note that typically the socket is allocated from the connection pool
* so it will disappear when the connection is finished.
*/
+ baton->s = p;
+ baton->peer = NULL;
+
b->type = &apr_bucket_type_socket;
b->length = (apr_size_t)(-1);
b->start = -1;
- b->data = p;
+ b->data = baton;
+ apr_socket_addr_get(&baton->peer, APR_REMOTE, p);
+
return b;
}
@@ -104,6 +127,13 @@
return apr_bucket_socket_make(b, p);
}
+APU_DECLARE(apr_sockaddr_t*) apr_bucket_socket_get_peer(apr_bucket *b)
+{
+ apr_bucket_socket *baton = b->data;
+ return baton->peer;
+}
+
+
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_socket = {
"SOCKET", 5, APR_BUCKET_DATA,
apr_bucket_destroy_noop,