(svn r15921) -Fix: some OSes don't like sizeof(sockaddr_storage) but want sizeof(sockaddr) or whatever is 'valid' for the given protocol

This commit is contained in:
rubidium 2009-04-03 00:33:00 +00:00
parent c7b6469dab
commit ba5aafb9bb
4 changed files with 36 additions and 25 deletions

View File

@ -15,8 +15,10 @@
const char *NetworkAddress::GetHostname() const char *NetworkAddress::GetHostname()
{ {
if (this->hostname == NULL) { if (this->hostname == NULL) {
assert(this->address_length != 0);
char buf[NETWORK_HOSTNAME_LENGTH] = { '\0' }; char buf[NETWORK_HOSTNAME_LENGTH] = { '\0' };
getnameinfo((struct sockaddr *)&this->address, sizeof(this->address), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST); getnameinfo((struct sockaddr *)&this->address, this->address_length, buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
this->hostname = strdup(buf); this->hostname = strdup(buf);
} }
return this->hostname; return this->hostname;
@ -56,9 +58,9 @@ const char *NetworkAddress::GetAddressAsString()
const sockaddr_storage *NetworkAddress::GetAddress() const sockaddr_storage *NetworkAddress::GetAddress()
{ {
if (!this->resolved) { if (!this->IsResolved()) {
((struct sockaddr_in *)&this->address)->sin_addr.s_addr = NetworkResolveHost(this->hostname); ((struct sockaddr_in *)&this->address)->sin_addr.s_addr = NetworkResolveHost(this->hostname);
this->resolved = true; this->address_length = sizeof(sockaddr);
} }
return &this->address; return &this->address;
} }
@ -90,11 +92,18 @@ SOCKET NetworkAddress::Connect()
if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed"); if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
if (connect(sock, runp->ai_addr, runp->ai_addrlen) != 0) continue; if (connect(sock, runp->ai_addr, runp->ai_addrlen) != 0) {
closesocket(sock);
sock = INVALID_SOCKET;
continue;
}
/* Connection succeeded */ /* Connection succeeded */
if (!SetNonBlocking(sock)) DEBUG(net, 0, "Setting non-blocking mode failed"); 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; break;
} }
freeaddrinfo (ai); freeaddrinfo (ai);

View File

@ -16,8 +16,8 @@
*/ */
class NetworkAddress { class NetworkAddress {
private: private:
bool resolved; ///< Has the IP address been resolved
char *hostname; ///< The hostname, NULL if there isn't one char *hostname; ///< The hostname, NULL if there isn't one
size_t address_length; ///< The length of the resolved address
sockaddr_storage address; ///< The resolved address sockaddr_storage address; ///< The resolved address
public: public:
@ -27,8 +27,8 @@ public:
* @param port the port * @param port the port
*/ */
NetworkAddress(in_addr_t ip, uint16 port) : NetworkAddress(in_addr_t ip, uint16 port) :
resolved(true), hostname(NULL),
hostname(NULL) address_length(sizeof(sockaddr))
{ {
memset(&this->address, 0, sizeof(this->address)); memset(&this->address, 0, sizeof(this->address));
this->address.ss_family = AF_INET; this->address.ss_family = AF_INET;
@ -40,9 +40,9 @@ public:
* Create a network address based on a resolved IP and port * Create a network address based on a resolved IP and port
* @param address the IP address with port * @param address the IP address with port
*/ */
NetworkAddress(struct sockaddr_storage &address) : NetworkAddress(struct sockaddr_storage &address, size_t address_length) :
resolved(true),
hostname(NULL), hostname(NULL),
address_length(address_length),
address(address) address(address)
{ {
} }
@ -53,8 +53,8 @@ public:
* @param port the port * @param port the port
*/ */
NetworkAddress(const char *hostname = NULL, uint16 port = 0) : NetworkAddress(const char *hostname = NULL, uint16 port = 0) :
resolved(false), hostname(hostname == NULL ? NULL : strdup(hostname)),
hostname(hostname == NULL ? NULL : strdup(hostname)) address_length(0)
{ {
memset(&this->address, 0, sizeof(this->address)); memset(&this->address, 0, sizeof(this->address));
this->address.ss_family = AF_INET; this->address.ss_family = AF_INET;
@ -66,8 +66,8 @@ public:
* @param address the address to clone * @param address the address to clone
*/ */
NetworkAddress(const NetworkAddress &address) : NetworkAddress(const NetworkAddress &address) :
resolved(address.resolved),
hostname(address.hostname == NULL ? NULL : strdup(address.hostname)), hostname(address.hostname == NULL ? NULL : strdup(address.hostname)),
address_length(address.address_length),
address(address.address) address(address.address)
{ {
} }
@ -97,6 +97,17 @@ public:
*/ */
const sockaddr_storage *GetAddress(); const sockaddr_storage *GetAddress();
/**
* Get the (valid) length of the address.
* @return the length
*/
size_t GetAddressLength()
{
/* Resolve it if we didn't do it already */
if (!this->IsResolved()) this->GetAddress();
return this->address_length;
}
/** /**
* Get the port * Get the port
* @return the port * @return the port
@ -115,7 +126,7 @@ public:
*/ */
bool IsResolved() const bool IsResolved() const
{ {
return this->resolved; return this->address_length != 0;
} }
/** /**

View File

@ -89,7 +89,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv)
p->PrepareToSend(); p->PrepareToSend();
/* Send the buffer */ /* Send the buffer */
res = sendto(this->sock, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv->GetAddress(), sizeof(*recv->GetAddress())); res = sendto(this->sock, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv->GetAddress(), recv->GetAddressLength());
/* Check for any errors, but ignore it otherwise */ /* Check for any errors, but ignore it otherwise */
if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR()); if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR());
@ -119,7 +119,7 @@ void NetworkUDPSocketHandler::ReceivePackets()
/* We got some bytes for the base header of the packet. */ /* We got some bytes for the base header of the packet. */
if (nbytes > 2) { if (nbytes > 2) {
NetworkAddress address(client_addr); NetworkAddress address(client_addr, client_len);
p.PrepareToRead(); p.PrepareToRead();
/* If the size does not match the packet must be corrupted. /* If the size does not match the packet must be corrupted.

View File

@ -1090,24 +1090,15 @@ static void NetworkGenerateUniqueId()
void NetworkStartDebugLog(NetworkAddress address) void NetworkStartDebugLog(NetworkAddress address)
{ {
extern SOCKET _debug_socket; // Comes from debug.c extern SOCKET _debug_socket; // Comes from debug.c
SOCKET s;
DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", address.GetHostname(), address.GetPort()); DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", address.GetHostname(), address.GetPort());
s = socket(AF_INET, SOCK_STREAM, 0); SOCKET s = address.Connect();
if (s == INVALID_SOCKET) { if (s == INVALID_SOCKET) {
DEBUG(net, 0, "Failed to open socket for redirection DEBUG()"); DEBUG(net, 0, "Failed to open socket for redirection DEBUG()");
return; return;
} }
if (!SetNoDelay(s)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
if (connect(s, (struct sockaddr *)address.GetAddress(), sizeof(*address.GetAddress())) != 0) {
DEBUG(net, 0, "Failed to redirection DEBUG() to %s", address.GetAddressAsString());
return;
}
if (!SetNonBlocking(s)) DEBUG(net, 0, "Setting non-blocking mode failed");
_debug_socket = s; _debug_socket = s;
DEBUG(net, 0, "DEBUG() is now redirected"); DEBUG(net, 0, "DEBUG() is now redirected");