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,

Reply via email to