Procházet zdrojové kódy

udpgw: add option to use unique local ports for each remote IP address (by default we use unique local port for
remote IP,port pair)

ambrop7 před 14 roky
rodič
revize
254e9d3e52
1 změnil soubory, kde provedl 27 přidání a 8 odebrání
  1. 27 8
      udpgw/udpgw.c

+ 27 - 8
udpgw/udpgw.c

@@ -124,6 +124,7 @@ struct {
     int client_socket_sndbuf;
     int local_udp_num_ports;
     char *local_udp_addr;
+    int unique_local_ports;
 } options;
 
 // MTUs
@@ -336,6 +337,7 @@ void print_help (const char *name)
         "        [--max-connections-for-client <number>]\n"
         "        [--client-socket-sndbuf <bytes / 0>]\n"
         "        [--local-udp-addrs <addr> <num_ports>]\n"
+        "        [--unique-local-ports]\n"
         "Address format is a.b.c.d:port (IPv4) or [addr]:port (IPv6).\n",
         name
     );
@@ -369,6 +371,7 @@ int parse_arguments (int argc, char *argv[])
     options.max_connections_for_client = DEFAULT_MAX_CONNECTIONS_FOR_CLIENT;
     options.client_socket_sndbuf = CLIENT_DEFAULT_SOCKET_SEND_BUFFER;
     options.local_udp_num_ports = -1;
+    options.unique_local_ports = 0;
     
     int i;
     for (i = 1; i < argc; i++) {
@@ -515,6 +518,9 @@ int parse_arguments (int argc, char *argv[])
             }
             i += 2;
         }
+        else if (!strcmp(arg, "--unique-local-ports")) {
+            options.unique_local_ports = 1;
+        }
         else {
             fprintf(stderr, "unknown option: %s\n", arg);
             return 0;
@@ -546,6 +552,11 @@ int process_arguments (void)
             BLog(BLOG_ERROR, "local udp addr: BAddr_Parse failed");
             return 0;
         }
+        
+        if (local_udp_addr.type != BADDR_TYPE_IPV4) {
+            BLog(BLOG_ERROR, "local udp addr: must be an IPv4 address");
+            return 0;
+        }
     }
     
     return 1;
@@ -810,6 +821,7 @@ void client_recv_if_handler_send (struct client *client, uint8_t *data, int data
 uint8_t * build_port_usage_array_and_find_least_used_connection (BAddr remote_addr, struct connection **out_con)
 {
     ASSERT(options.local_udp_num_ports >= 0)
+    ASSERT(remote_addr.type == BADDR_TYPE_IPV4)
     
     // allocate port usage array
     uint8_t *port_usage = BAllocSize(bsize_fromint(options.local_udp_num_ports));
@@ -836,13 +848,21 @@ uint8_t * build_port_usage_array_and_find_least_used_connection (BAddr remote_ad
                 continue;
             }
             
-            if (BAddr_Compare(&con->addr, &remote_addr)) {
-                port_usage[con->local_port_index] = 1;
-                
-                if (!PacketPassFairQueueFlow_IsBusy(&con->send_qflow)) {
-                    if (!least_con || con->last_use_time < least_con->last_use_time) {
-                        least_con = con;
-                    }
+            if (options.unique_local_ports) {
+                if (con->addr.ipv4.ip != remote_addr.ipv4.ip) {
+                    continue;
+                }
+            } else {
+                if (!BAddr_Compare(&con->addr, &remote_addr)) {
+                    continue;
+                }
+            }
+            
+            port_usage[con->local_port_index] = 1;
+            
+            if (!PacketPassFairQueueFlow_IsBusy(&con->send_qflow)) {
+                if (!least_con || con->last_use_time < least_con->last_use_time) {
+                    least_con = con;
                 }
             }
         }
@@ -941,7 +961,6 @@ void connection_init (struct client *client, uint16_t conid, BAddr addr, const u
         
         ASSERT(least_con->local_port_index >= 0)
         ASSERT(least_con->local_port_index < options.local_udp_num_ports)
-        ASSERT(BAddr_Compare(&least_con->addr, &addr))
         ASSERT(!PacketPassFairQueueFlow_IsBusy(&least_con->send_qflow))
         
         int i = least_con->local_port_index;