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 #ifndef PLATFORM_IMPL_SOCKET_ADDRESS_POSIX_H_
6 #define PLATFORM_IMPL_SOCKET_ADDRESS_POSIX_H_
7 
8 #include <fcntl.h>
9 #include <netinet/in.h>
10 #include <netinet/ip.h>
11 #include <sys/socket.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 
15 #include <string>
16 
17 #include "platform/base/ip_address.h"
18 
19 namespace openscreen {
20 
21 class SocketAddressPosix {
22  public:
23   explicit SocketAddressPosix(const struct sockaddr& address);
24   explicit SocketAddressPosix(const IPEndpoint& endpoint);
25 
26   SocketAddressPosix(const SocketAddressPosix&) = default;
27   SocketAddressPosix(SocketAddressPosix&&) noexcept = default;
28   SocketAddressPosix& operator=(const SocketAddressPosix&) = default;
29   SocketAddressPosix& operator=(SocketAddressPosix&&) noexcept = default;
30 
31   struct sockaddr* address();
32   const struct sockaddr* address() const;
33   socklen_t size() const;
version()34   IPAddress::Version version() const { return endpoint_.address.version(); }
endpoint()35   IPEndpoint endpoint() const { return endpoint_; }
36 
37   // Recomputes |endpoint_| if |internal_address_| is written to directly, e.g.
38   // by a system call.
39   void RecomputeEndpoint();
40 
41  private:
42   void RecomputeEndpoint(IPAddress::Version version);
43 
44   // The way the sockaddr_* family works in POSIX is pretty unintuitive. The
45   // sockaddr_in and sockaddr_in6 structs can be reinterpreted as type
46   // sockaddr, however they don't have a common parent--the types are unrelated.
47   // Our solution for this is to wrap sockaddr_in* in a union, so that our code
48   // can be simplified since most platform APIs just take a sockaddr.
49   union SocketAddressIn {
50     struct sockaddr_in v4;
51     struct sockaddr_in6 v6;
52   };
53 
54   SocketAddressIn internal_address_;
55   IPEndpoint endpoint_;
56 };
57 
58 }  // namespace openscreen
59 
60 #endif  // PLATFORM_IMPL_SOCKET_ADDRESS_POSIX_H_
61