summaryrefslogtreecommitdiff
path: root/src/network/core
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-04-03 01:24:52 +0000
committerrubidium <rubidium@openttd.org>2009-04-03 01:24:52 +0000
commit632d74c6b1a17f3bc3419158dfc1bb5a2e5f77b5 (patch)
tree3d2dcf19488a31930bdb82d46f8ddc4b53aba59a /src/network/core
parentba5aafb9bba4887b502dba32e56747fe10af604e (diff)
downloadopenttd-632d74c6b1a17f3bc3419158dfc1bb5a2e5f77b5.tar.xz
(svn r15922) -Codechange: unify the ways to listen on a socket
Diffstat (limited to 'src/network/core')
-rw-r--r--src/network/core/address.cpp58
-rw-r--r--src/network/core/address.h12
-rw-r--r--src/network/core/udp.cpp29
-rw-r--r--src/network/core/udp.h2
4 files changed, 73 insertions, 28 deletions
diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp
index c1313fe74..68eb692b1 100644
--- a/src/network/core/address.cpp
+++ b/src/network/core/address.cpp
@@ -82,7 +82,7 @@ SOCKET NetworkAddress::Connect()
int e = getaddrinfo(this->GetHostname(), port_name, &hints, &ai);
if (e != 0) {
DEBUG(net, 0, "getaddrinfo failed: %s", gai_strerror(e));
- return false;
+ return INVALID_SOCKET;
}
SOCKET sock = INVALID_SOCKET;
@@ -111,4 +111,60 @@ SOCKET NetworkAddress::Connect()
return sock;
}
+SOCKET NetworkAddress::Listen(int family, int socktype)
+{
+ struct addrinfo *ai;
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof (hints));
+ hints.ai_family = family;
+ hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
+ hints.ai_socktype = socktype;
+
+ /* The port needs to be a string. Six is enough to contain all characters + '\0'. */
+ char port_name[6] = { '0' };
+ seprintf(port_name, lastof(port_name), "%u", this->GetPort());
+
+ int e = getaddrinfo(this->GetHostname(), port_name, &hints, &ai);
+ if (e != 0) {
+ DEBUG(net, 0, "getaddrinfo failed: %s", gai_strerror(e));
+ return INVALID_SOCKET;
+ }
+
+ SOCKET sock = INVALID_SOCKET;
+ for (struct addrinfo *runp = ai; runp != NULL; runp = runp->ai_next) {
+ sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
+ if (sock == INVALID_SOCKET) {
+ DEBUG(net, 1, "could not create socket: %s", strerror(errno));
+ continue;
+ }
+
+ if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
+
+ if (bind(sock, runp->ai_addr, runp->ai_addrlen) != 0) {
+ DEBUG(net, 1, "could not bind: %s", strerror(errno));
+ closesocket(sock);
+ sock = INVALID_SOCKET;
+ continue;
+ }
+
+ if (socktype != SOCK_DGRAM && listen(sock, 1) != 0) {
+ DEBUG(net, 1, "could not listen: %s", strerror(errno));
+ closesocket(sock);
+ sock = INVALID_SOCKET;
+ continue;
+ }
+
+ /* Connection succeeded */
+ if (!SetNonBlocking(sock)) DEBUG(net, 0, "Setting non-blocking mode failed");
+
+ this->address_length = runp->ai_addrlen;
+ assert(sizeof(this->address) >= runp->ai_addrlen);
+ memcpy(&this->address, runp->ai_addr, runp->ai_addrlen);
+ break;
+ }
+ freeaddrinfo (ai);
+
+ return sock;
+}
+
#endif /* ENABLE_NETWORK */
diff --git a/src/network/core/address.h b/src/network/core/address.h
index 3e8ca0343..c42805add 100644
--- a/src/network/core/address.h
+++ b/src/network/core/address.h
@@ -52,8 +52,8 @@ public:
* @param ip the unresolved hostname
* @param port the port
*/
- NetworkAddress(const char *hostname = NULL, uint16 port = 0) :
- hostname(hostname == NULL ? NULL : strdup(hostname)),
+ NetworkAddress(const char *hostname = "0.0.0.0", uint16 port = 0) :
+ hostname(strdup(hostname)),
address_length(0)
{
memset(&this->address, 0, sizeof(this->address));
@@ -159,6 +159,14 @@ public:
* @return the connected socket or INVALID_SOCKET.
*/
SOCKET Connect();
+
+ /**
+ * Make the given socket listen.
+ * @param family the type of 'protocol' (IPv4, IPv6)
+ * @param socktype the type of socket (TCP, UDP, etc)
+ * @return the listening socket or INVALID_SOCKET.
+ */
+ SOCKET Listen(int family, int socktype);
};
#endif /* ENABLE_NETWORK */
diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp
index 4818767d9..473d438ea 100644
--- a/src/network/core/udp.cpp
+++ b/src/network/core/udp.cpp
@@ -17,45 +17,26 @@
/**
* Start listening on the given host and port.
- * @param host the host (ip) to listen on
- * @param port the port to listen on
+ * @param address the host to listen on
* @param broadcast whether to allow broadcast sending/receiving
* @return true if the listening succeeded
*/
-bool NetworkUDPSocketHandler::Listen(const uint32 host, const uint16 port, const bool broadcast)
+bool NetworkUDPSocketHandler::Listen(NetworkAddress address, bool broadcast)
{
- struct sockaddr_in sin;
-
/* Make sure socket is closed */
this->Close();
- this->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (!this->IsConnected()) {
- DEBUG(net, 0, "[udp] failed to start UDP listener");
- return false;
- }
-
- SetNonBlocking(this->sock);
-
- sin.sin_family = AF_INET;
- /* Listen on all IPs */
- sin.sin_addr.s_addr = host;
- sin.sin_port = htons(port);
-
- if (bind(this->sock, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
- DEBUG(net, 0, "[udp] bind failed on %s:%i", inet_ntoa(*(struct in_addr *)&host), port);
- return false;
- }
+ this->sock = address.Listen(AF_INET, SOCK_DGRAM);
if (broadcast) {
/* Enable broadcast */
unsigned long val = 1;
#ifndef BEOS_NET_SERVER /* will work around this, some day; maybe. */
- setsockopt(this->sock, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val));
+ setsockopt(this->sock, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val));
#endif
}
- DEBUG(net, 1, "[udp] listening on port %s:%d", inet_ntoa(*(struct in_addr *)&host), port);
+ DEBUG(net, 1, "[udp] listening on port %s", address.GetAddressAsString());
return true;
}
diff --git a/src/network/core/udp.h b/src/network/core/udp.h
index dd019b3bb..61f0f8f8e 100644
--- a/src/network/core/udp.h
+++ b/src/network/core/udp.h
@@ -125,7 +125,7 @@ public:
/** On destructing of this class, the socket needs to be closed */
virtual ~NetworkUDPSocketHandler() { this->Close(); }
- bool Listen(uint32 host, uint16 port, bool broadcast);
+ bool Listen(NetworkAddress address, bool broadcast);
void Close();
void SendPacket(Packet *p, NetworkAddress *recv);