monotone

monotone Mtn Source Tree

Root/netxx/address.cxx

1/*
2 * Copyright (C) 2001-2004 Peter J Jones (pjones@pmade.org)
3 * All Rights Reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 * 3. Neither the name of the Author nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
23 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/** @file
34 * This file contains the implementation for the Netxx::Address class and
35 * some of the necessary helper functions.
36**/
37
38// common header
39#include "common.h"
40
41// Netxx includes
42#include "netxx/address.h"
43#include "netxx/types.h"
44#include "sockaddr.h"
45#include "resolve.h"
46
47// standard includes
48#include <cstdlib>
49
50//####################################################################
51namespace
52{
53 const char const_local_service[] = "local";
54
55 bool parse_uri (const char *uri, std::string &protocol, std::string &name, Netxx::port_type &port, std::string &path);
56 void make_uds (const char *filename, Netxx::Address::container_type &addrs);
57}
58//####################################################################
59Netxx::Address::Address (const char *uri, port_type default_port, bool use_ipv6)
60 : port_(0), ipv6_(use_ipv6)
61{
62# if defined(WIN32)
63WSADATA wsdata;
64
65if (WSAStartup(MAKEWORD(2,2), &wsdata) != 0) {
66 throw Exception("failed to load WinSock");
67}
68# endif
69
70 add_address(uri, default_port);
71}
72//####################################################################
73Netxx::Address::Address (bool use_ipv6)
74 : port_(0), ipv6_(use_ipv6)
75{
76# if defined(WIN32)
77WSADATA wsdata;
78
79if (WSAStartup(MAKEWORD(2,2), &wsdata) != 0) {
80 throw Exception("failed to load WinSock");
81}
82# endif
83}
84//####################################################################
85Netxx::Address::~Address (void)
86{
87# if defined(WIN32)
88WSACleanup();
89# endif
90}
91//####################################################################
92const char* Netxx::Address::get_protocol (void) const
93{
94 if (!protocol_.empty()) return protocol_.c_str();
95 return 0;
96}
97//####################################################################
98const char* Netxx::Address::get_name (void) const
99{
100 if (!name_.empty()) return name_.c_str();
101 return 0;
102}
103//####################################################################
104const char* Netxx::Address::get_path (void) const
105{
106 if (!path_.empty()) return path_.c_str();
107 return 0;
108}
109//####################################################################
110Netxx::port_type Netxx::Address::get_port (void) const
111{
112 return port_;
113}
114//####################################################################
115Netxx::Address::const_iterator Netxx::Address::begin (void) const
116{
117 return addrs_.begin();
118}
119//####################################################################
120Netxx::Address::const_iterator Netxx::Address::end (void) const
121{
122 return addrs_.end();
123}
124//####################################################################
125Netxx::size_type Netxx::Address::size (void) const
126{
127 return addrs_.size();
128}
129//####################################################################
130void Netxx::Address::add_address(const char *uri, port_type default_port)
131{
132 port_type tmp_port=0;
133 std::string protocol;
134
135 if (!parse_uri(uri, protocol, name_, tmp_port, path_)) {
136std::string error("can't parse URI: "); error += uri;
137throw NetworkException(error);
138 }
139
140 if (!protocol.empty() && std::strcmp(protocol.c_str(), const_local_service) == 0) {
141make_uds(name_.c_str(), addrs_);
142return;
143 }
144
145 if (!tmp_port && !protocol.empty()) tmp_port = resolve_service(protocol.c_str());
146 if (!tmp_port) tmp_port = default_port;
147
148 port_ = tmp_port;
149 protocol_ = protocol;
150 resolve_hostname(name_.c_str(), port_, ipv6_, addrs_);
151}
152//####################################################################
153void Netxx::Address::add_all_addresses (port_type port)
154{
155 { // new scope just for safety
156SockAddr saddr(AF_INET, port);
157sockaddr_in *sai = reinterpret_cast<sockaddr_in*>(saddr.get_sa());
158sai->sin_addr.s_addr = htons(INADDR_ANY);
159addrs_.push_back(Peer("localhost", port, sai, saddr.get_sa_size()));
160 }
161
162 port_ = port;
163
164# ifndef NETXX_NO_INET6
165 if (ipv6_) {
166SockAddr saddr(AF_INET6, port);
167sockaddr_in6 *sai6 = reinterpret_cast<sockaddr_in6*>(saddr.get_sa());
168sai6->sin6_addr= in6addr_any;
169addrs_.push_back(Peer("localhost", port, sai6, saddr.get_sa_size()));
170 }
171# endif
172}
173//####################################################################
174namespace
175{
176 //####################################################################
177 bool parse_uri (const char *uri, std::string &protocol, std::string &name, Netxx::port_type &port, std::string &path)
178 {
179const char *start_pos = uri, *stop_pos;
180
181#ifndef WIN32
182 // see if the URI is a Unix filepath
183 if (*uri == '/') {
184protocol = const_local_service;
185name = uri;
186return true;
187 }
188#endif
189
190// first look for the protocol seperator
191while (*uri != 0 && *uri != ':') ++uri;
192
193if (*uri == ':' && *(uri+1) == '/' && *(uri+2) == '/') {
194 // looks like we may have a protocol/service name
195
196 if (uri != start_pos) protocol.assign(start_pos, uri - start_pos);
197 start_pos = uri + 3;
198
199# ifndef WIN32
200// check to see if it is a local domain socket
201if (std::strcmp(protocol.c_str(), const_local_service) == 0) {
202 name = start_pos;
203 return true;
204}
205# endif
206}
207
208uri = start_pos;
209
210// now look for any path info
211while (*uri != 0 && *uri != '/') ++uri;
212
213if (*uri == '/') {
214 // grab the path info
215 path = uri;
216}
217
218stop_pos = uri;
219uri = start_pos;
220
221int colon_count = 0;
222while (*uri != 0 && uri != stop_pos) {
223 if (*uri == ':')
224 colon_count++;
225 ++uri;
226}
227if (colon_count > 1) {
228 // ipv6 hostname
229 name.assign(start_pos, stop_pos - start_pos);
230 return true;
231}
232
233stop_pos = uri;
234uri = start_pos;
235
236// check for a port number in the hostname
237while (*uri != 0 && uri != stop_pos && *uri != ':') ++uri;
238
239if (*uri == ':') {
240 std::string tmp_port(uri+1, stop_pos - uri - 1);
241 if (*(uri+1) != 0) port = static_cast<Netxx::port_type>(std::atoi(tmp_port.c_str()));
242}
243
244stop_pos = uri;
245uri = start_pos;
246
247// all we should have left is the hostname
248if (uri == stop_pos) return false;
249name.assign(uri, stop_pos - uri);
250return true;
251 }
252 //####################################################################
253 void make_uds (const char *filename, Netxx::Address::container_type &addrs)
254 {
255# ifndef WIN32
256
257Netxx::SockAddr saddr(AF_LOCAL);
258sockaddr_un *sau = reinterpret_cast<sockaddr_un*>(saddr.get_sa());
259
260std::strncpy(sau->sun_path, filename, sizeof(sau->sun_path) - 1);
261addrs.push_back(Netxx::Peer(filename, 0, sau, saddr.get_sa_size()));
262
263# endif
264 }
265 //####################################################################
266} // end anonymous namespace

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status