diff options
Diffstat (limited to 'opentracker.c')
| -rw-r--r-- | opentracker.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/opentracker.c b/opentracker.c index a546fc5..f579b92 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -320,8 +320,17 @@ static void *server_mainloop(void *args) { | |||
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | 322 | ||
| 323 | /* A group of sockets sharing one address only spreads datagrams if every | ||
| 324 | member asked for it before binding, the first one included, so whether | ||
| 325 | this entry will have workers has to be known here. */ | ||
| 326 | static socket_sharing listen_sharing_for(const ot_listen *entry) { | ||
| 327 | if (entry->proto == FLAG_UDP && entry->workers > 1 && socket_can_balance()) | ||
| 328 | return SOCKET_BALANCED; | ||
| 329 | return entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE; | ||
| 330 | } | ||
| 331 | |||
| 323 | static void listen_bind_one(ot_listen *entry) { | 332 | static void listen_bind_one(ot_listen *entry) { |
| 324 | socket_sharing sharing = entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE; | 333 | socket_sharing sharing = listen_sharing_for(entry); |
| 325 | 334 | ||
| 326 | #ifdef _DEBUG | 335 | #ifdef _DEBUG |
| 327 | { | 336 | { |
| @@ -370,6 +379,10 @@ static void listen_bind_all(void) { | |||
| 370 | listen_bind_one(entries + i); | 379 | listen_bind_one(entries + i); |
| 371 | } | 380 | } |
| 372 | 381 | ||
| 382 | /* The socket the event loop was using becomes the first worker's. Where the | ||
| 383 | kernel spreads datagrams, every further worker binds one of its own, so | ||
| 384 | none of them share a receive queue. | ||
| 385 | All others read from the first */ | ||
| 373 | static void listen_start_udp_workers(void) { | 386 | static void listen_start_udp_workers(void) { |
| 374 | size_t count, i; | 387 | size_t count, i; |
| 375 | ot_listen *entries = config_listen_entries(&count); | 388 | ot_listen *entries = config_listen_entries(&count); |
| @@ -377,14 +390,30 @@ static void listen_start_udp_workers(void) { | |||
| 377 | udp_init(); | 390 | udp_init(); |
| 378 | 391 | ||
| 379 | for (i = 0; i < count; ++i) { | 392 | for (i = 0; i < count; ++i) { |
| 380 | ot_listen *entry = entries + i; | 393 | ot_listen *entry = entries + i; |
| 394 | int balance = listen_sharing_for(entry) == SOCKET_BALANCED; | ||
| 395 | int worker; | ||
| 381 | 396 | ||
| 382 | if (entry->proto != FLAG_UDP || entry->workers <= 0) | 397 | if (entry->proto != FLAG_UDP || entry->workers <= 0) |
| 383 | continue; | 398 | continue; |
| 384 | 399 | ||
| 385 | socket_set_blocking((int)entry->sock, 1); | 400 | socket_set_blocking((int)entry->sock, 1); |
| 386 | event_del((int)entry->sock); | 401 | event_del((int)entry->sock); |
| 387 | udp_workers_install(entry->sock, (unsigned int)entry->workers); | 402 | udp_worker_install(entry->sock); |
| 403 | |||
| 404 | for (worker = 1; worker < entry->workers; ++worker) { | ||
| 405 | int64_t sock = entry->sock; | ||
| 406 | |||
| 407 | if (balance) { | ||
| 408 | sock = socket_udp_bind(entry->ip, entry->port, SOCKET_BALANCED); | ||
| 409 | if (sock == -1) { | ||
| 410 | fprintf(stderr, "Warning: could not bind another socket for udp worker %d: %s. Sharing the first instead.\n", worker, strerror(errno)); | ||
| 411 | sock = entry->sock; | ||
| 412 | } else | ||
| 413 | socket_set_blocking((int)sock, 1); | ||
| 414 | } | ||
| 415 | udp_worker_install(sock); | ||
| 416 | } | ||
| 388 | } | 417 | } |
| 389 | } | 418 | } |
| 390 | 419 | ||
