blob: a4ea5981b4171cc8a04c5173c8d0de389c46d6d9 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "platform/impl/socket_address_posix.h"
#include <cstring>
#include <vector>
#include "util/osp_logging.h"
namespace openscreen {
SocketAddressPosix::SocketAddressPosix(const struct sockaddr& address) {
if (address.sa_family == AF_INET) {
memcpy(&internal_address_, &address, sizeof(struct sockaddr_in));
RecomputeEndpoint(IPAddress::Version::kV4);
} else if (address.sa_family == AF_INET6) {
memcpy(&internal_address_, &address, sizeof(struct sockaddr_in6));
RecomputeEndpoint(IPAddress::Version::kV6);
} else {
// Not IPv4 or IPv6.
OSP_NOTREACHED();
}
}
SocketAddressPosix::SocketAddressPosix(const IPEndpoint& endpoint)
: endpoint_(endpoint) {
if (endpoint.address.IsV4()) {
internal_address_.v4.sin_family = AF_INET;
internal_address_.v4.sin_port = htons(endpoint.port);
endpoint.address.CopyToV4(
reinterpret_cast<uint8_t*>(&internal_address_.v4.sin_addr.s_addr));
} else {
OSP_DCHECK(endpoint.address.IsV6());
internal_address_.v6.sin6_family = AF_INET6;
internal_address_.v6.sin6_flowinfo = 0;
internal_address_.v6.sin6_scope_id = 0;
internal_address_.v6.sin6_port = htons(endpoint.port);
endpoint.address.CopyToV6(
reinterpret_cast<uint8_t*>(&internal_address_.v6.sin6_addr));
}
}
struct sockaddr* SocketAddressPosix::address() {
switch (version()) {
case IPAddress::Version::kV4:
return reinterpret_cast<struct sockaddr*>(&internal_address_.v4);
case IPAddress::Version::kV6:
return reinterpret_cast<struct sockaddr*>(&internal_address_.v6);
default:
OSP_NOTREACHED();
}
}
const struct sockaddr* SocketAddressPosix::address() const {
switch (version()) {
case IPAddress::Version::kV4:
return reinterpret_cast<const struct sockaddr*>(&internal_address_.v4);
case IPAddress::Version::kV6:
return reinterpret_cast<const struct sockaddr*>(&internal_address_.v6);
default:
OSP_NOTREACHED();
}
}
socklen_t SocketAddressPosix::size() const {
switch (version()) {
case IPAddress::Version::kV4:
return sizeof(struct sockaddr_in);
case IPAddress::Version::kV6:
return sizeof(struct sockaddr_in6);
default:
OSP_NOTREACHED();
}
}
void SocketAddressPosix::RecomputeEndpoint() {
RecomputeEndpoint(endpoint_.address.version());
}
void SocketAddressPosix::RecomputeEndpoint(IPAddress::Version version) {
switch (version) {
case IPAddress::Version::kV4:
endpoint_.address = IPAddress(IPAddress::Version::kV4,
reinterpret_cast<const uint8_t*>(
&internal_address_.v4.sin_addr.s_addr));
endpoint_.port = ntohs(internal_address_.v4.sin_port);
break;
case IPAddress::Version::kV6:
endpoint_.address = IPAddress(IPAddress::Version::kV6,
internal_address_.v6.sin6_addr.s6_addr);
endpoint_.port = ntohs(internal_address_.v6.sin6_port);
break;
}
}
} // namespace openscreen