| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_LIB_INET_IP_PORT_H_ |
| #define SRC_LIB_INET_IP_PORT_H_ |
| |
| #include <arpa/inet.h> |
| #include <endian.h> |
| |
| #include <ostream> |
| |
| namespace inet { |
| |
| // Represents an IP port number. |
| // |
| // Ports are not treated as 16-bit integers by the network stack, meaning that, |
| // on little-endian targets, the two bytes will be reversed. For example, the |
| // mDNS multicast port is 5353 decimal or 14E9 hex. On arrival on a little- |
| // endian machine, the bytes are laid down in the order 14, E9 resulting in |
| // the integer value E914. |
| // |
| // This class exists primarily to alleviate the confusion this causes. |
| // |
| // The types |in_port_t| and |uint16_t| are interpreted differently, in spite |
| // of the fact that they have the same underlying type (hence the From_* |
| // static methods rather than constructors). |in_port_t| is assumed to be |
| // big-endian (in network order) consistent with the way the network stack |
| // produces and consumes port values. |uint16_t| is assumed to be host-endian. |
| // This means that creating an |IpPort| constant from a |uint16_t| literal |
| // should be done using |From_uint16_t|. |
| // |
| // An |ostream| operator<< overload is provided so |IpPort| values are |
| // represented properly as text. It just writes |value.as_uint16_t()|. |
| class IpPort { |
| public: |
| // Creates an |IpPort| from an |in_port_t|. This assumes that the value is |
| // big-endian (network order). Use this method when creating an |IpPort| |
| // from |in_port_t| values produced by the network stack. |
| static IpPort From_in_port_t(in_port_t port) { return IpPort(port); } |
| |
| // Creates an |IpPort| from a |uint16_t|. This assumes that the value is |
| // host-endian. Use this method when creating |IpPort| from host-endian |
| // |uint16_t| values, such as literals. |
| static IpPort From_uint16_t(uint16_t port_as_uint16_t) { |
| return IpPort(htobe16(port_as_uint16_t)); |
| } |
| |
| // Creates an invalid IpPort. |
| IpPort(); |
| |
| // Creates a port from two bytes in network order. |
| IpPort(uint8_t b0, uint8_t b1); |
| |
| bool is_valid() const { return value_ != 0; } |
| |
| // Returns an |in_port_t| value for the port. This value is big-endian |
| // (network order), suitable for consumption by the network stack. |
| in_port_t as_in_port_t() const { return value_; } |
| |
| // Returns a |uint16_t| value for the port. This value is host-endian, |
| // suitable for displaying to humans, etc. |
| uint16_t as_uint16_t() const { return be16toh(value_); } |
| |
| explicit operator bool() const { return is_valid(); } |
| |
| bool operator==(const IpPort& other) const { return as_in_port_t() == other.as_in_port_t(); } |
| |
| bool operator!=(const IpPort& other) const { return as_in_port_t() != other.as_in_port_t(); } |
| |
| private: |
| explicit IpPort(in_port_t port) : value_(port) {} |
| |
| in_port_t value_; // big-endian |
| }; |
| |
| std::ostream& operator<<(std::ostream& os, IpPort value); |
| |
| } // namespace inet |
| |
| #endif // SRC_LIB_INET_IP_PORT_H_ |