Implement sk_addr_dup().
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 8 Nov 2008 16:58:55 +0000 (16:58 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 8 Nov 2008 16:58:55 +0000 (16:58 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@8294 cda61777-01e9-0310-a592-d414129be87e

network.h
unix/uxnet.c
windows/winnet.c

index 41d0d44..af83e65 100644 (file)
--- a/network.h
+++ b/network.h
@@ -120,6 +120,12 @@ int sk_address_is_local(SockAddr addr);
 int sk_addrtype(SockAddr addr);
 void sk_addrcopy(SockAddr addr, char *buf);
 void sk_addr_free(SockAddr addr);
+/* sk_addr_dup generates another SockAddr which contains the same data
+ * as the original one and can be freed independently. May not actually
+ * physically _duplicate_ it: incrementing a reference count so that
+ * one more free is required before it disappears is an acceptable
+ * implementation. */
+SockAddr sk_addr_dup(SockAddr addr);
 
 /* NB, control of 'addr' is passed via sk_new, which takes responsibility
  * for freeing it, as for new_connection() */
index 98453db..46c8749 100644 (file)
@@ -88,6 +88,7 @@ struct Socket_tag {
 };
 
 struct SockAddr_tag {
+    int refcount;
     const char *error;
     enum { UNRESOLVED, UNIX, IP } superfamily;
 #ifndef NO_IPV6
@@ -193,6 +194,7 @@ SockAddr sk_namelookup(const char *host, char **canonicalname, int address_famil
     ret->superfamily = UNRESOLVED;
     *realhost = '\0';
     ret->error = NULL;
+    ret->refcount = 1;
 
 #ifndef NO_IPV6
     hints.ai_flags = AI_CANONNAME;
@@ -275,6 +277,7 @@ SockAddr sk_nonamelookup(const char *host)
 #else
     ret->addresses = NULL;
 #endif
+    ret->refcount = 1;
     return ret;
 }
 
@@ -412,7 +415,8 @@ void sk_addrcopy(SockAddr addr, char *buf)
 
 void sk_addr_free(SockAddr addr)
 {
-
+    if (--addr->refcount > 0)
+       return;
 #ifndef NO_IPV6
     if (addr->ais != NULL)
        freeaddrinfo(addr->ais);
@@ -422,6 +426,12 @@ void sk_addr_free(SockAddr addr)
     sfree(addr);
 }
 
+SockAddr sk_addr_dup(SockAddr addr)
+{
+    addr->refcount++;
+    return addr;
+}
+
 static Plug sk_tcp_plug(Socket sock, Plug p)
 {
     Actual_Socket s = (Actual_Socket) sock;
@@ -1415,5 +1425,6 @@ SockAddr platform_get_x11_unix_address(const char *display, int displaynum,
     ret->addresses = NULL;
     ret->naddresses = 0;
 #endif
+    ret->refcount = 1;
     return ret;
 }
index 93eb40c..3848916 100644 (file)
@@ -78,6 +78,7 @@ struct Socket_tag {
 };
 
 struct SockAddr_tag {
+    int refcount;
     char *error;
     int resolved;
 #ifndef NO_IPV6
@@ -444,6 +445,7 @@ SockAddr sk_namelookup(const char *host, char **canonicalname,
 #endif
     ret->addresses = NULL;
     ret->resolved = FALSE;
+    ret->refcount = 1;
     *realhost = '\0';
 
     if ((a = p_inet_addr(host)) == (unsigned long) INADDR_NONE) {
@@ -547,6 +549,7 @@ SockAddr sk_nonamelookup(const char *host)
 #endif
     ret->addresses = NULL;
     ret->naddresses = 0;
+    ret->refcount = 1;
     strncpy(ret->hostname, host, lenof(ret->hostname));
     ret->hostname[lenof(ret->hostname)-1] = '\0';
     return ret;
@@ -708,6 +711,8 @@ void sk_addrcopy(SockAddr addr, char *buf)
 
 void sk_addr_free(SockAddr addr)
 {
+    if (--addr->refcount > 0)
+       return;
 #ifndef NO_IPV6
     if (addr->ais && p_freeaddrinfo)
        p_freeaddrinfo(addr->ais);
@@ -717,6 +722,12 @@ void sk_addr_free(SockAddr addr)
     sfree(addr);
 }
 
+SockAddr sk_addr_dup(SockAddr addr)
+{
+    addr->refcount++;
+    return addr;
+}
+
 static Plug sk_tcp_plug(Socket sock, Plug p)
 {
     Actual_Socket s = (Actual_Socket) sock;
@@ -1677,5 +1688,6 @@ SockAddr platform_get_x11_unix_address(const char *display, int displaynum,
     SockAddr ret = snew(struct SockAddr_tag);
     memset(ret, 0, sizeof(struct SockAddr_tag));
     ret->error = "unix sockets not supported on this platform";
+    ret->refcount = 1;
     return ret;
 }