summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-04 03:21:31 +0000
committermbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-04 03:21:31 +0000
commit76ff86af64d9260bc6042b3ab80adf78cc1a1582 (patch)
treea8c81194db224fcef75c6696a9c06def27171ad8
parent211486bd44160962954c2b10874323f4ac6c838e (diff)
downloadchromium_src-76ff86af64d9260bc6042b3ab80adf78cc1a1582.zip
chromium_src-76ff86af64d9260bc6042b3ab80adf78cc1a1582.tar.gz
chromium_src-76ff86af64d9260bc6042b3ab80adf78cc1a1582.tar.bz2
Add an IPEndPoint class as a simple class for dealing with struct sockaddr.
BUG=none TEST=ip_endpoint_unittest Review URL: http://codereview.chromium.org/6592096 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76868 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/base/ip_endpoint.cc102
-rw-r--r--net/base/ip_endpoint.h53
-rw-r--r--net/base/ip_endpoint_unittest.cc141
-rw-r--r--net/net.gyp3
4 files changed, 299 insertions, 0 deletions
diff --git a/net/base/ip_endpoint.cc b/net/base/ip_endpoint.cc
new file mode 100644
index 0000000..116af2b
--- /dev/null
+++ b/net/base/ip_endpoint.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2011 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 "net/base/ip_endpoint.h"
+
+#include "base/logging.h"
+#if defined(OS_WIN)
+#include <winsock2.h>
+#elif defined(OS_POSIX)
+#include <netinet/in.h>
+#endif
+
+namespace net {
+
+const size_t kIPv4AddressSize = 4;
+const size_t kIPv6AddressSize = 16;
+
+IPEndPoint::IPEndPoint() : port_(0) {}
+
+IPEndPoint::IPEndPoint(const IPAddressNumber& address, int port)
+ : address_(address),
+ port_(port) {}
+
+IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) {
+ address_ = endpoint.address_;
+ port_ = endpoint.port_;
+}
+
+bool IPEndPoint::ToSockaddr(struct sockaddr* address,
+ size_t* address_length) const {
+ DCHECK(address);
+ DCHECK(address_length);
+ switch (address_.size()) {
+ case kIPv4AddressSize: {
+ if (*address_length < sizeof(struct sockaddr_in))
+ return false;
+ *address_length = sizeof(struct sockaddr_in);
+ struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(address);
+ memset(addr, 0, sizeof(struct sockaddr_in));
+ addr->sin_family = AF_INET;
+ addr->sin_port = htons(port_);
+ memcpy(&addr->sin_addr, &address_[0], kIPv4AddressSize);
+ break;
+ }
+ case kIPv6AddressSize: {
+ if (*address_length < sizeof(struct sockaddr_in6))
+ return false;
+ *address_length = sizeof(struct sockaddr_in6);
+ struct sockaddr_in6* addr6 =
+ reinterpret_cast<struct sockaddr_in6*>(address);
+ memset(addr6, 0, sizeof(struct sockaddr_in6));
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_port = htons(port_);
+ memcpy(&addr6->sin6_addr, &address_[0], kIPv6AddressSize);
+ break;
+ }
+ default: {
+ NOTREACHED() << "Bad IP address";
+ break;
+ }
+ }
+ return true;
+}
+
+bool IPEndPoint::FromSockAddr(const struct sockaddr* address,
+ size_t address_length) {
+ DCHECK(address);
+ switch (address->sa_family) {
+ case AF_INET: {
+ const struct sockaddr_in* addr =
+ reinterpret_cast<const struct sockaddr_in*>(address);
+ port_ = ntohs(addr->sin_port);
+ const char* bytes = reinterpret_cast<const char*>(&addr->sin_addr);
+ address_.assign(&bytes[0], &bytes[kIPv4AddressSize]);
+ break;
+ }
+ case AF_INET6: {
+ const struct sockaddr_in6* addr =
+ reinterpret_cast<const struct sockaddr_in6*>(address);
+ port_ = ntohs(addr->sin6_port);
+ const char* bytes = reinterpret_cast<const char*>(&addr->sin6_addr);
+ address_.assign(&bytes[0], &bytes[kIPv6AddressSize]);
+ break;
+ }
+ default: {
+ NOTREACHED() << "Bad IP address";
+ break;
+ }
+ }
+ return true;
+}
+
+bool IPEndPoint::operator<(const IPEndPoint& that) const {
+ return address_ < that.address_ || port_ < that.port_;
+}
+
+bool IPEndPoint::operator==(const IPEndPoint& that) const {
+ return address_ == that.address_ && port_ == that.port_;
+}
+
+} // namespace net
diff --git a/net/base/ip_endpoint.h b/net/base/ip_endpoint.h
new file mode 100644
index 0000000..66aea71
--- /dev/null
+++ b/net/base/ip_endpoint.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2011 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.
+
+#ifndef NET_BASE_IP_ENDPOINT_H_
+#define NET_BASE_IP_ENDPOINT_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "net/base/net_util.h"
+
+struct sockaddr;
+
+namespace net {
+
+// An IPEndPoint represents the address of a transport endpoint:
+// * IP address (either v4 or v6)
+// * Port
+class IPEndPoint {
+ public:
+ IPEndPoint();
+ IPEndPoint(const IPAddressNumber& address, int port);
+ IPEndPoint(const IPEndPoint& endpoint);
+
+ const IPAddressNumber& address() const { return address_; }
+ int port() const { return port_; }
+
+ // Convert to a provided sockaddr struct.
+ // |address| is the sockaddr to copy into. Should be at least
+ // sizeof(struct sockaddr_storage) bytes.
+ // |address_length| is an input/output parameter. On input, it is the
+ // size of data in |address| available. On output, it is the size of
+ // the address that was copied into |address|.
+ // Returns true on success, false on failure.
+ bool ToSockaddr(struct sockaddr* address, size_t* address_length) const;
+
+ // Convert from a sockaddr struct.
+ // |address| is the address.
+ // |address_length| is the length of |address|.
+ // Returns true on success, false on failure.
+ bool FromSockAddr(const struct sockaddr* address, size_t address_length);
+
+ bool operator<(const IPEndPoint& that) const;
+ bool operator==(const IPEndPoint& that) const;
+
+ private:
+ IPAddressNumber address_;
+ int port_;
+};
+
+} // namespace net
+
+#endif // NET_BASE_IP_ENDPOINT_H_
diff --git a/net/base/ip_endpoint_unittest.cc b/net/base/ip_endpoint_unittest.cc
new file mode 100644
index 0000000..b9fe48b
--- /dev/null
+++ b/net/base/ip_endpoint_unittest.cc
@@ -0,0 +1,141 @@
+// Copyright (c) 2011 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 "net/base/ip_endpoint.h"
+
+#include "net/base/net_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#if defined(OS_WIN)
+#include <winsock2.h>
+#elif defined(OS_POSIX)
+#include <netinet/in.h>
+#endif
+
+namespace net {
+
+namespace {
+
+struct TestData {
+ std::string host;
+ bool ipv6;
+ IPAddressNumber ip_address;
+} tests[] = {
+ { "127.0.00.1", false},
+ { "192.168.1.1", false },
+ { "::1", true },
+ { "2001:db8:0::42", true },
+};
+int test_count = ARRAYSIZE_UNSAFE(tests);
+
+class IPEndPointTest : public PlatformTest {
+ public:
+ virtual void SetUp() {
+ // This is where we populate the TestData.
+ for (int index = 0; index < test_count; ++index) {
+ EXPECT_TRUE(ParseIPLiteralToNumber(tests[index].host,
+ &tests[index].ip_address));
+ }
+ }
+};
+
+TEST_F(IPEndPointTest, Constructor) {
+ IPEndPoint endpoint;
+ EXPECT_EQ(0, endpoint.port());
+
+ for (int index = 0; index < test_count; ++index) {
+ IPEndPoint endpoint(tests[index].ip_address, 80);
+ EXPECT_EQ(80, endpoint.port());
+ EXPECT_EQ(tests[index].ip_address, endpoint.address());
+ }
+}
+
+TEST_F(IPEndPointTest, Assignment) {
+ for (int index = 0; index < test_count; ++index) {
+ IPEndPoint src(tests[index].ip_address, index);
+ IPEndPoint dest = src;
+
+ EXPECT_EQ(src.port(), dest.port());
+ EXPECT_EQ(src.address(), dest.address());
+ }
+}
+
+TEST_F(IPEndPointTest, Copy) {
+ for (int index = 0; index < test_count; ++index) {
+ IPEndPoint src(tests[index].ip_address, index);
+ IPEndPoint dest(src);
+
+ EXPECT_EQ(src.port(), dest.port());
+ EXPECT_EQ(src.address(), dest.address());
+ }
+}
+
+TEST_F(IPEndPointTest, ToFromSockaddr) {
+ for (int index = 0; index < test_count; ++index) {
+ IPEndPoint ip_endpoint(tests[index].ip_address, index);
+
+ // Convert to a sockaddr.
+ struct sockaddr_storage addr;
+ size_t addr_len = sizeof(addr);
+ struct sockaddr* sockaddr = reinterpret_cast<struct sockaddr*>(&addr);
+ EXPECT_TRUE(ip_endpoint.ToSockaddr(sockaddr, &addr_len));
+
+ // Basic verification.
+ size_t expected_size = tests[index].ipv6 ?
+ sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+ EXPECT_EQ(expected_size, addr_len);
+ EXPECT_EQ(ip_endpoint.port(), GetPortFromSockaddr(sockaddr, addr_len));
+
+ // And convert back to an IPEndPoint.
+ IPEndPoint ip_endpoint2;
+ EXPECT_TRUE(ip_endpoint2.FromSockAddr(sockaddr, addr_len));
+ EXPECT_EQ(ip_endpoint.port(), ip_endpoint2.port());
+ EXPECT_EQ(ip_endpoint.address(), ip_endpoint2.address());
+ }
+}
+
+TEST_F(IPEndPointTest, ToSockaddrBufTooSmall) {
+ for (int index = 0; index < test_count; ++index) {
+ IPEndPoint ip_endpoint(tests[index].ip_address, index);
+
+ struct sockaddr_storage addr;
+ size_t addr_len = index; // size is too small!
+ struct sockaddr* sockaddr = reinterpret_cast<struct sockaddr*>(&addr);
+ EXPECT_FALSE(ip_endpoint.ToSockaddr(sockaddr, &addr_len));
+ }
+}
+
+TEST_F(IPEndPointTest, Equality) {
+ for (int index = 0; index < test_count; ++index) {
+ IPEndPoint src(tests[index].ip_address, index);
+ IPEndPoint dest(src);
+ EXPECT_TRUE(src == dest);
+ }
+}
+
+TEST_F(IPEndPointTest, LessThan) {
+ // Vary by port.
+ IPEndPoint ip_endpoint1(tests[0].ip_address, 100);
+ IPEndPoint ip_endpoint2(tests[0].ip_address, 1000);
+ EXPECT_TRUE(ip_endpoint1 < ip_endpoint2);
+
+ // IPv4 vs IPv6
+ ip_endpoint1 = IPEndPoint(tests[0].ip_address, 80);
+ ip_endpoint2 = IPEndPoint(tests[2].ip_address, 80);
+ EXPECT_FALSE(ip_endpoint1 < ip_endpoint2);
+
+ // IPv4 vs IPv4
+ ip_endpoint1 = IPEndPoint(tests[0].ip_address, 80);
+ ip_endpoint2 = IPEndPoint(tests[1].ip_address, 80);
+ EXPECT_TRUE(ip_endpoint1 < ip_endpoint2);
+
+ // IPv6 vs IPv6
+ ip_endpoint1 = IPEndPoint(tests[2].ip_address, 80);
+ ip_endpoint2 = IPEndPoint(tests[3].ip_address, 80);
+ EXPECT_TRUE(ip_endpoint1 < ip_endpoint2);
+}
+
+} // namespace
+
+} // namespace net
diff --git a/net/net.gyp b/net/net.gyp
index f5f2dbb..1aff097 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -97,6 +97,8 @@
'base/host_resolver_proc.h',
'base/io_buffer.cc',
'base/io_buffer.h',
+ 'base/ip_endpoint.cc',
+ 'base/ip_endpoint.h',
'base/keygen_handler.cc',
'base/keygen_handler.h',
'base/keygen_handler_mac.cc',
@@ -865,6 +867,7 @@
'base/host_cache_unittest.cc',
'base/host_mapping_rules_unittest.cc',
'base/host_resolver_impl_unittest.cc',
+ 'base/ip_endpoint_unittest.cc',
'base/keygen_handler_unittest.cc',
'base/listen_socket_unittest.cc',
'base/listen_socket_unittest.h',