Browse Source

fix: sockaddr comparison issue (#749)

lfeng 5 months ago
parent
commit
1778d4a155
3 changed files with 25 additions and 3 deletions
  1. 20 0
      base/hsocket.c
  2. 1 0
      base/hsocket.h
  3. 4 3
      event/rudp.c

+ 20 - 0
base/hsocket.c

@@ -170,6 +170,26 @@ const char* sockaddr_str(sockaddr_u* addr, char* buf, int len) {
     return buf;
 }
 
+int sockaddr_compare(const sockaddr_u* addr1, const sockaddr_u* addr2) {
+    if (addr1->sa.sa_family != addr2->sa.sa_family)
+        return addr1->sa.sa_family - addr2->sa.sa_family;
+    if (addr1->sa.sa_family == AF_INET) {
+        if (addr1->sin.sin_family != addr2->sin.sin_family)
+            return addr1->sin.sin_family - addr2->sin.sin_family;
+        if (addr1->sin.sin_port != addr2->sin.sin_port)
+            return addr1->sin.sin_port - addr2->sin.sin_port;
+        return memcmp(&addr1->sin.sin_addr, &addr2->sin.sin_addr, sizeof(struct in_addr));
+    }
+    else if (addr1->sa.sa_family == AF_INET6) {
+        if (addr1->sin6.sin6_family != addr2->sin6.sin6_family)
+            return addr1->sin6.sin6_family - addr2->sin6.sin6_family;
+        if (addr1->sin6.sin6_port != addr2->sin6.sin6_port)
+            return addr1->sin6.sin6_port - addr2->sin6.sin6_port;
+        return memcmp(&addr1->sin6.sin6_addr, &addr2->sin6.sin6_addr, sizeof(struct in_addr));
+    }
+    return memcmp(addr1, addr2, sizeof(sockaddr_u));
+}
+
 static int sockaddr_bind(sockaddr_u* localaddr, int type) {
     // socket -> setsockopt -> bind
 #ifdef SOCK_CLOEXEC

+ 1 - 0
base/hsocket.h

@@ -121,6 +121,7 @@ HV_EXPORT void sockaddr_set_port(sockaddr_u* addr, int port);
 HV_EXPORT int sockaddr_set_ipport(sockaddr_u* addr, const char* host, int port);
 HV_EXPORT socklen_t sockaddr_len(sockaddr_u* addr);
 HV_EXPORT const char* sockaddr_str(sockaddr_u* addr, char* buf, int len);
+HV_EXPORT int sockaddr_compare(const sockaddr_u* addr1, const sockaddr_u* addr2);
 
 //#define INET_ADDRSTRLEN   16
 //#define INET6_ADDRSTRLEN  46

+ 4 - 3
event/rudp.c

@@ -3,6 +3,7 @@
 #if WITH_RUDP
 
 #include "hevent.h"
+#include "hsocket.h"
 
 void rudp_entry_free(rudp_entry_t* entry) {
 #if WITH_KCP
@@ -38,7 +39,7 @@ bool rudp_insert(rudp_t* rudp, rudp_entry_t* entry) {
     while (*n) {
         parent = *n;
         e = rb_entry(*n, rudp_entry_t, rb_node);
-        cmp = memcmp(&entry->addr, &e->addr, sizeof(sockaddr_u));
+        cmp = sockaddr_compare(&entry->addr, &e->addr);
         if (cmp < 0) {
             n = &(*n)->rb_left;
         } else if (cmp > 0) {
@@ -63,7 +64,7 @@ rudp_entry_t* rudp_search(rudp_t* rudp, struct sockaddr* addr) {
     bool exists = false;
     while (n) {
         e = rb_entry(n, rudp_entry_t, rb_node);
-        cmp = memcmp(addr, &e->addr, sizeof(sockaddr_u));
+        cmp = sockaddr_compare((sockaddr_u*)addr, &e->addr);
         if (cmp < 0) {
             n = n->rb_left;
         } else if (cmp > 0) {
@@ -99,7 +100,7 @@ rudp_entry_t* rudp_get(rudp_t* rudp, struct sockaddr* addr) {
     while (*n) {
         parent = *n;
         e = rb_entry(*n, rudp_entry_t, rb_node);
-        cmp = memcmp(addr, &e->addr, sizeof(sockaddr_u));
+        cmp = sockaddr_compare((sockaddr_u*)addr, &e->addr);
         if (cmp < 0) {
             n = &(*n)->rb_left;
         } else if (cmp > 0) {