From 5025a9931265fe959126155737a04ec8f8f686aa Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 8 Nov 2008 16:58:55 +0000 Subject: [PATCH] Implement sk_addr_dup(). git-svn-id: svn://svn.tartarus.org/sgt/putty@8294 cda61777-01e9-0310-a592-d414129be87e --- network.h | 6 ++++++ unix/uxnet.c | 13 ++++++++++++- windows/winnet.c | 12 ++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/network.h b/network.h index 41d0d442..af83e653 100644 --- 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() */ diff --git a/unix/uxnet.c b/unix/uxnet.c index 98453db6..46c87498 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -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; } diff --git a/windows/winnet.c b/windows/winnet.c index 93eb40c5..38489163 100644 --- a/windows/winnet.c +++ b/windows/winnet.c @@ -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; } -- 2.11.0