1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "platform/impl/socket_address_posix.h"
6 
7 #include <cstring>
8 #include <vector>
9 
10 #include "util/osp_logging.h"
11 
12 namespace openscreen {
13 
SocketAddressPosix(const struct sockaddr & address)14 SocketAddressPosix::SocketAddressPosix(const struct sockaddr& address) {
15   if (address.sa_family == AF_INET) {
16     memcpy(&internal_address_, &address, sizeof(struct sockaddr_in));
17     RecomputeEndpoint(IPAddress::Version::kV4);
18   } else if (address.sa_family == AF_INET6) {
19     memcpy(&internal_address_, &address, sizeof(struct sockaddr_in6));
20     RecomputeEndpoint(IPAddress::Version::kV6);
21   } else {
22     // Not IPv4 or IPv6.
23     OSP_NOTREACHED();
24   }
25 }
26 
SocketAddressPosix(const IPEndpoint & endpoint)27 SocketAddressPosix::SocketAddressPosix(const IPEndpoint& endpoint)
28     : endpoint_(endpoint) {
29   if (endpoint.address.IsV4()) {
30     internal_address_.v4.sin_family = AF_INET;
31     internal_address_.v4.sin_port = htons(endpoint.port);
32     endpoint.address.CopyToV4(
33         reinterpret_cast<uint8_t*>(&internal_address_.v4.sin_addr.s_addr));
34   } else {
35     OSP_DCHECK(endpoint.address.IsV6());
36 
37     internal_address_.v6.sin6_family = AF_INET6;
38     internal_address_.v6.sin6_flowinfo = 0;
39     internal_address_.v6.sin6_scope_id = 0;
40     internal_address_.v6.sin6_port = htons(endpoint.port);
41     endpoint.address.CopyToV6(
42         reinterpret_cast<uint8_t*>(&internal_address_.v6.sin6_addr));
43   }
44 }
45 
address()46 struct sockaddr* SocketAddressPosix::address() {
47   switch (version()) {
48     case IPAddress::Version::kV4:
49       return reinterpret_cast<struct sockaddr*>(&internal_address_.v4);
50     case IPAddress::Version::kV6:
51       return reinterpret_cast<struct sockaddr*>(&internal_address_.v6);
52     default:
53       OSP_NOTREACHED();
54   }
55 }
56 
address() const57 const struct sockaddr* SocketAddressPosix::address() const {
58   switch (version()) {
59     case IPAddress::Version::kV4:
60       return reinterpret_cast<const struct sockaddr*>(&internal_address_.v4);
61     case IPAddress::Version::kV6:
62       return reinterpret_cast<const struct sockaddr*>(&internal_address_.v6);
63     default:
64       OSP_NOTREACHED();
65   }
66 }
67 
size() const68 socklen_t SocketAddressPosix::size() const {
69   switch (version()) {
70     case IPAddress::Version::kV4:
71       return sizeof(struct sockaddr_in);
72     case IPAddress::Version::kV6:
73       return sizeof(struct sockaddr_in6);
74     default:
75       OSP_NOTREACHED();
76   }
77 }
78 
RecomputeEndpoint()79 void SocketAddressPosix::RecomputeEndpoint() {
80   RecomputeEndpoint(endpoint_.address.version());
81 }
82 
RecomputeEndpoint(IPAddress::Version version)83 void SocketAddressPosix::RecomputeEndpoint(IPAddress::Version version) {
84   switch (version) {
85     case IPAddress::Version::kV4:
86       endpoint_.address = IPAddress(IPAddress::Version::kV4,
87                                     reinterpret_cast<const uint8_t*>(
88                                         &internal_address_.v4.sin_addr.s_addr));
89       endpoint_.port = ntohs(internal_address_.v4.sin_port);
90       break;
91     case IPAddress::Version::kV6:
92       endpoint_.address = IPAddress(IPAddress::Version::kV6,
93                                     internal_address_.v6.sin6_addr.s6_addr);
94       endpoint_.port = ntohs(internal_address_.v6.sin6_port);
95       break;
96   }
97 }
98 
99 }  // namespace openscreen
100