2 * Copyright 2002-2006,2008, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Scott T. Mansfield, thephantom@mac.com
7 * Oliver Tappe, zooey@hirschkaefer.de
11 NetAddress.cpp -- Implementation of the BNetAddress class.
13 * In all accessors, non-struct output values are converted from network to
15 * In all mutators, non-struct input values are converted from host to
17 * No trouts were harmed during the development of this class.
20 #include <r5_compatibility.h>
22 #include <ByteOrder.h>
23 #include <NetAddress.h>
26 #include <arpa/inet.h>
28 #include <netinet/in.h>
33 BNetAddress::BNetAddress(const char* hostname
, unsigned short port
)
37 SetTo(hostname
, port
);
41 BNetAddress::BNetAddress(const struct sockaddr_in
& addr
)
49 BNetAddress::BNetAddress(in_addr addr
, int port
)
57 BNetAddress::BNetAddress(uint32 addr
, int port
)
65 BNetAddress::BNetAddress(const char* hostname
, const char* protocol
,
70 SetTo(hostname
, protocol
, service
);
74 BNetAddress::BNetAddress(const BNetAddress
& other
)
80 BNetAddress::BNetAddress(BMessage
* archive
)
83 if (archive
->FindInt16("bnaddr_family", &int16value
) != B_OK
)
88 if (archive
->FindInt16("bnaddr_port", &int16value
) != B_OK
)
93 if (archive
->FindInt32("bnaddr_addr", &fAddress
) != B_OK
)
100 BNetAddress::~BNetAddress()
106 BNetAddress::operator=(const BNetAddress
& other
)
109 fFamily
= other
.fFamily
;
111 fAddress
= other
.fAddress
;
118 *=--------------------------------------------------------------------------=*
123 * hostname: Host name associated with this instance (default: NULL).
124 * In this particular implementation, hostname will be an
125 * ASCII-fied representation of an IP address.
127 * port: Port number associated with this instance
128 * (default: NULL). Will be converted to host byte order
129 * here, so it is not necessary to call ntohs() after
130 * calling this method.
133 * B_OK for success, B_NO_INIT if instance was not properly constructed.
136 * Hostname and/or port can be NULL; although having them both NULL would
137 * be a pointless waste of CPU cycles. ;-)
139 * The hostname output parameter can be a variety of things, but in this
140 * method we convert the IP address to a string. See the relevant
141 * documentation about inet_ntoa() for details.
143 * Make sure hostname is large enough or you will step on someone
144 * else's toes. (Can you say "buffer overflow exploit" boys and girls?)
145 * You can generally be safe using the MAXHOSTNAMELEN define, which
146 * defaults to 64 bytes--don't forget to leave room for the NULL!
149 BNetAddress::GetAddr(char* hostname
, unsigned short* port
) const
155 *port
= ntohs(fPort
);
157 if (hostname
!= NULL
) {
159 addr
.s_addr
= fAddress
;
161 char* text
= inet_ntoa(addr
);
163 strcpy(hostname
, text
);
171 *=--------------------------------------------------------------------------=*
176 * sa: sockaddr_in struct to be filled.
179 * B_OK for success, B_NO_INIT if instance was not properly constructed.
182 * This method fills in the sin_addr, sin_family, and sin_port fields of
183 * the output parameter, all other fields are untouched so we can work
184 * with both POSIX and non-POSIX versions of said struct. The port and
185 * address values added to the output parameter are in network byte order.
187 status_t
BNetAddress::GetAddr(struct sockaddr_in
& sa
) const
193 sa
.sin_addr
.s_addr
= fAddress
;
194 if (check_r5_compatibility()) {
195 r5_sockaddr_in
* r5Addr
= (r5_sockaddr_in
*)&sa
;
196 if (fFamily
== AF_INET
)
197 r5Addr
->sin_family
= R5_AF_INET
;
199 r5Addr
->sin_family
= fFamily
;
201 sa
.sin_family
= fFamily
;
208 *=--------------------------------------------------------------------------=*
213 * addr: in_addr struct to fill.
214 * port: optional port number to fill.
217 * B_OK for success, B_NO_INIT if instance was not properly constructed.
220 * Output port will be in host byte order, but addr will be in the usual
221 * network byte order (ready to be used by other network functions).
223 status_t
BNetAddress::GetAddr(in_addr
& addr
, unsigned short* port
) const
228 addr
.s_addr
= fAddress
;
231 *port
= ntohs(fPort
);
238 *=--------------------------------------------------------------------------=*
240 * Determine whether or not this instance is properly initialized.
243 * B_OK if this instance is initialized, B_ERROR if not.
245 status_t
BNetAddress::InitCheck() const
247 return fInit
== B_OK
? B_OK
: B_ERROR
;
251 status_t
BNetAddress::InitCheck()
253 return const_cast<const BNetAddress
*>(this)->InitCheck();
258 *=--------------------------------------------------------------------------=*
260 * Serialize this instance into the passed BMessage parameter.
263 * deep: [ignored] default==true.
266 * into: BMessage object to serialize into.
269 * B_OK/BERROR on success/failure. Returns B_NO_INIT if instance not
270 * properly initialized.
272 status_t
BNetAddress::Archive(BMessage
* into
, bool deep
) const
277 if (into
->AddInt16("bnaddr_family", fFamily
) != B_OK
)
280 if (into
->AddInt16("bnaddr_port", fPort
) != B_OK
)
283 if (into
->AddInt32("bnaddr_addr", fAddress
) != B_OK
)
291 *=--------------------------------------------------------------------------=*
293 * Un-serialize and instantiate from the passed BMessage parameter.
296 * archive: Archived BMessage object for (de)serialization.
299 * NULL if a BNetAddress instance can not be initialized, otherwise
300 * a new BNetAddress object instantiated from the BMessage parameter.
303 BNetAddress::Instantiate(BMessage
* archive
)
305 if (!validate_instantiation(archive
, "BNetAddress"))
308 BNetAddress
* address
= new (std::nothrow
) BNetAddress(archive
);
312 if (address
->InitCheck() != B_OK
) {
322 *=--------------------------------------------------------------------------=*
324 * Set hostname and port network address data.
327 * hostname: Can be one of three things:
328 * 1. An ASCII-string representation of an IP address.
329 * 2. A canonical hostname.
330 * 3. NULL. If NULL, then by default the address will be
331 * set to INADDR_ANY (0.0.0.0).
335 * B_OK/B_ERROR for success/failure.
338 BNetAddress::SetTo(const char* hostname
, unsigned short port
)
340 if (hostname
== NULL
)
343 in_addr_t addr
= INADDR_ANY
;
345 // Try like all git-out to set the address from the given hostname.
347 // See if the string is an ASCII-fied IP address.
348 addr
= inet_addr(hostname
);
349 if (addr
== INADDR_ANY
|| addr
== (in_addr_t
)-1) {
350 // See if we can resolve the hostname to an IP address.
351 struct hostent
* host
= gethostbyname(hostname
);
353 addr
= *(int*)host
->h_addr_list
[0];
367 Set from passed in sockaddr_in address.
373 BNetAddress::SetTo(const struct sockaddr_in
& addr
)
375 fPort
= addr
.sin_port
;
376 fAddress
= addr
.sin_addr
.s_addr
;
378 if (check_r5_compatibility()) {
379 const r5_sockaddr_in
* r5Addr
= (const r5_sockaddr_in
*)&addr
;
380 if (r5Addr
->sin_family
== R5_AF_INET
)
383 fFamily
= r5Addr
->sin_family
;
385 fFamily
= addr
.sin_family
;
392 Set from passed in address and port.
394 \param addr IP address in network form.
395 \param port Optional port number.
400 BNetAddress::SetTo(in_addr addr
, int port
)
403 fPort
= htons((short)port
);
404 fAddress
= addr
.s_addr
;
411 Set from passed in address and port.
413 \param addr IP address in network form.
414 \param port Optional port number.
419 BNetAddress::SetTo(uint32 addr
, int port
)
422 fPort
= htons((short)port
);
430 *=--------------------------------------------------------------------------=*
432 * Set from passed in hostname and protocol/service information.
435 * hostname: Can be one of three things:
436 * 1. An ASCII-string representation of an IP address.
437 * 2. A canonical hostname.
438 * 3. NULL. If NULL, then by default the address will be
439 * set to INADDR_ANY (0.0.0.0).
440 * protocol: Datagram type, typically "TCP" or "UDP"
441 * service: The name of the service, such as http, ftp, et al. This
442 * must be one of the official service names listed in
443 * /etc/services -- but you already knew that because
444 * you're doing network/sockets programming, RIIIGHT???.
447 * B_OK/B_ERROR on success/failure.
450 * The protocol and service input parameters must be one of the official
451 * types listed in /etc/services. We use these two parameters to
452 * determine the port number (see getservbyname(3)). This method will
453 * fail if the aforementioned precondition is not met.
456 BNetAddress::SetTo(const char* hostname
, const char* protocol
,
459 struct servent
* serviceEntry
= getservbyname(service
, protocol
);
460 if (serviceEntry
== NULL
)
463 return SetTo(hostname
, serviceEntry
->s_port
);
467 // #pragma mark - FBC
470 void BNetAddress::_ReservedBNetAddressFBCCruft1() {}
471 void BNetAddress::_ReservedBNetAddressFBCCruft2() {}
472 void BNetAddress::_ReservedBNetAddressFBCCruft3() {}
473 void BNetAddress::_ReservedBNetAddressFBCCruft4() {}
474 void BNetAddress::_ReservedBNetAddressFBCCruft5() {}
475 void BNetAddress::_ReservedBNetAddressFBCCruft6() {}