blob: 09bd5388e26f582684cb37ccd8882732a1993fcb [file] [log] [blame]
// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/network/socket_address_parser.h"
#include "base/basictypes.h"
#include "base/logging.h"
#include "net/base/ip_address.h"
#include "starboard/memory.h"
#include "url/third_party/mozilla/url_parse.h"
#include "url/url_canon.h"
#include "url/url_canon_ip.h"
namespace cobalt {
namespace network {
bool ParseSocketAddress(const char* spec, const url::Component& host_component,
SbSocketAddress* out_socket_address) {
DCHECK(out_socket_address);
unsigned char address_v4[net::IPAddress::kIPv4AddressSize];
int num_ipv4_components = 0;
// IPv4AddressToNumber will return either IPV4, BROKEN, or NEUTRAL. If the
// input IP address is IPv6, then NEUTRAL will be returned, and a different
// function will be used to covert the hostname to IPv6 address.
// If the return value is IPV4, then address will be in network byte order.
url::CanonHostInfo::Family family = url::IPv4AddressToNumber(
spec, host_component, address_v4, &num_ipv4_components);
switch (family) {
case url::CanonHostInfo::IPV4:
if (num_ipv4_components != net::IPAddress::kIPv4AddressSize) {
return false;
}
memset(out_socket_address, 0, sizeof(SbSocketAddress));
out_socket_address->type = kSbSocketAddressTypeIpv4;
DCHECK_GE(sizeof(address_v4),
static_cast<std::size_t>(num_ipv4_components));
memcpy(out_socket_address->address, address_v4,
num_ipv4_components);
return true;
case url::CanonHostInfo::NEUTRAL:
#if SB_API_VERSION >= 12
if (!SbSocketIsIpv6Supported()) {
return false;
}
#endif
#if SB_API_VERSION >= 12 || SB_HAS(IPV6)
unsigned char address_v6[net::IPAddress::kIPv6AddressSize];
if (!url::IPv6AddressToNumber(spec, host_component, address_v6)) {
break;
}
memset(out_socket_address, 0, sizeof(SbSocketAddress));
out_socket_address->type = kSbSocketAddressTypeIpv6;
static_assert(sizeof(address_v6) == net::IPAddress::kIPv6AddressSize, "");
memcpy(out_socket_address->address, address_v6, sizeof(address_v6));
return true;
#else
return false;
#endif
case url::CanonHostInfo::BROKEN:
break;
case url::CanonHostInfo::IPV6:
NOTREACHED() << "Invalid return value from IPv4AddressToNumber.";
break;
default:
NOTREACHED() << "Unexpected return value from IPv4AddressToNumber: "
<< family;
break;
}
return false;
}
} // namespace network
} // namespace cobalt