Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_bind_exclusive.c
Go to the documentation of this file.
1
15
16#include "nilorea/n_log.h"
17#include "nilorea/n_network.h"
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
28static int check_exclusive(int udp) {
29 NETWORK* first = NULL;
30 NETWORK* second = NULL;
31 char port[16] = "";
32 const char* what = udp ? "netw_bind_udp" : "netw_make_listening";
33 int p, ok = 0;
34
35 /* Take a free port by trying a range, rather than asking for 0: the NETWORK keeps the
36 * port string it was GIVEN, so an ephemeral bind would not report back which one it got
37 * and the second bind would have nothing to aim at. */
38 for (p = 34100; p < 34100 + 200; p++) {
39 snprintf(port, sizeof(port), "%d", p);
40 ok = udp ? (netw_bind_udp(&first, "127.0.0.1", port, NETWORK_IPV4) == TRUE)
41 : (netw_make_listening(&first, "127.0.0.1", port, 8, NETWORK_IPV4) == TRUE);
42 if (ok && first)
43 break;
44 first = NULL;
45 }
46 if (!ok || !first) {
47 n_log(LOG_ERR, "%s: could not take any port in the test range", what);
48 return 1;
49 }
50
51 second = NULL;
52 ok = udp ? (netw_bind_udp(&second, "127.0.0.1", port, NETWORK_IPV4) == TRUE)
53 : (netw_make_listening(&second, "127.0.0.1", port, 8, NETWORK_IPV4) == TRUE);
54 if (second)
55 netw_close(&second);
56 netw_close(&first);
57
58 if (!udp) {
59 /* TCP: exclusive on every platform. This is the contract that matters for a
60 * listener a user was told is running. */
61 if (ok) {
63 "%s: the SECOND bind to port %s SUCCEEDED. The port is being shared, so a "
64 "listener can be started over one another process already owns.",
65 what, port);
66 return 1;
67 }
68 n_log(LOG_INFO, "%s: a second bind to port %s was refused, as it must be", what, port);
69 return 0;
70 }
71
72 /* UDP is not the same question, and asserting it were would be asserting something
73 * POSIX does not offer. SO_REUSEADDR on a datagram socket deliberately PERMITS several
74 * sockets on one port (that is how multicast and broadcast receivers work), so a second
75 * bind succeeding on POSIX is correct behaviour rather than a defect. What is worth
76 * holding is the Windows side, where the option is not set and the second bind is
77 * refused, because that is where it would otherwise mean a process silently binding
78 * over one already holding the port. */
79#ifdef __windows__
80 if (ok) {
82 "%s: the second UDP bind to port %s SUCCEEDED on Windows, where the port "
83 "should be exclusive",
84 what, port);
85 return 1;
86 }
87 n_log(LOG_INFO, "%s: a second UDP bind to port %s was refused, as it must be on Windows", what, port);
88#else
90 "%s: a second UDP bind to port %s %s, which is what POSIX SO_REUSEADDR means "
91 "for datagram sockets (shared receivers); the exclusivity that matters is "
92 "asserted for TCP above and for UDP on Windows",
93 what, port, ok ? "succeeded" : "was refused");
94#endif
95 return 0;
96}
97
98int main(void) {
99 int rc = 0;
101 rc |= check_exclusive(0);
102 rc |= check_exclusive(1);
103 if (rc == 0)
104 printf(
105 "ex_bind_exclusive: a TCP listener's port is exclusive; UDP is exclusive on Windows "
106 "and shareable on POSIX, which is what SO_REUSEADDR means there\n");
107 else
108 printf("ex_bind_exclusive: FAILED\n");
109 return rc;
110}
int main(void)
static int check_exclusive(int udp)
Bind a listener, then try to bind the same port again; the second must fail.
char * port
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_ERR
error conditions
Definition n_log.h:100
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
Definition n_log.c:123
#define LOG_INFO
informational
Definition n_log.h:106
int netw_bind_udp(NETWORK **netw, char *addr, char *port, int ip_version)
Create a UDP bound socket for receiving datagrams.
Definition n_network.c:3626
int netw_make_listening(NETWORK **netw, char *addr, char *port, int nbpending, int ip_version)
Make a NETWORK be a Listening network.
Definition n_network.c:3493
#define NETWORK_IPV4
Flag to force IPV4.
Definition n_network.h:50
int netw_close(NETWORK **netw)
Closing a specified Network, destroy queues, free the structure.
Definition n_network.c:3258
Structure of a NETWORK.
Definition n_network.h:375
Generic log system.
Network Engine.