Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

InetAddress.cxx

00001 /*
00002  * Copyright 1991-2002 Eric M. Hopper <hopper@omnifarious.org>
00003  * 
00004  *     This program is free software; you can redistribute it and/or modify it
00005  *     under the terms of the GNU Lesser General Public License as published
00006  *     by the Free Software Foundation; either version 2 of the License, or
00007  *     (at your option) any later version.
00008  * 
00009  *     This program is distributed in the hope that it will be useful, but
00010  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *     Lesser General Public License for more details.
00013  * 
00014  *     You should have received a copy of the GNU Lesser General Public
00015  *     License along with this program; if not, write to the Free Software
00016  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 /* $Header: /home/hopper/src/cvs/C++/EHnet++/InetAddress.cxx,v 1.8 2002/08/29 00:58:04 hopper Exp $ */
00020 
00021  // For log, see ./ChangeLog
00022  //
00023  // $Revision: 1.8 $
00024  //
00025  // Revision 1.2  1996/02/12 00:32:36  hopper
00026  // Fixed to use the new C++ standard library string class instead of all the
00027  // 'NetString' silliness.
00028  //
00029  // Revision 1.1.1.1  1995/07/23 17:45:29  hopper
00030  // Imported sources
00031  //
00032  // Revision 0.3  1995/01/06  15:56:26  hopper
00033  // Merged 0.2 and 0.2.0.6
00034  //
00035  // Revision 0.2.0.6  1995/01/06  15:54:48  hopper
00036  // Added stuff to make this work (hopefully) under OS/2.
00037  //
00038  // Revision 0.2.0.5  1994/08/12  17:05:40  hopper
00039  // Changed to use NetString class. The NetString class handles all library
00040  // dependencies.
00041  //
00042  // Revision 0.2.0.4  1994/07/18  03:30:08  hopper
00043  // Added a #pragma implementation line so it would work better with gcc 2.6.0
00044  //
00045  // Revision 0.2.0.3  1994/05/26  04:22:19  hopper
00046  // Made even more changes to make this work with RWCString class.
00047  // Used htons, ntohs, htonl, and ntohl in a more consistent fashion. I'm on a
00048  // big endian machine now!
00049  //
00050  // Revision 0.2.0.2  1994/05/08  18:33:06  hopper
00051  // Changed to work better with Rogue Wave classes.
00052  //
00053  // Revision 0.2.0.1  1994/05/08  17:58:23  hopper
00054  // Head of WinterFire branch. Changed all instances of String with
00055  // RWCString.
00056  //
00057  // Revision 0.2  1994/05/08  16:10:57  hopper
00058  // Shifted declarations and definitions to work better with new libraries.
00059  //
00060  // Revision 0.1  1994/05/03  03:23:38  hopper
00061  // Initial revision.
00062  //
00063 
00064 #ifdef __GNUG__
00065 #  pragma implementation "InetAddress.h"
00066 #endif
00067 
00068 #include <EHnet++/InetAddress.h>
00069 #include <cctype>
00070 #include <sys/socket.h>
00071 #include <cstdlib>
00072 
00073 namespace strmod {
00074 namespace ehnet {
00075 
00076 ::std::string InetAddress::AsString()
00077 {
00078    ::std::string portnum = ToDec(port);
00079    ::std::string temp = hostname;
00080 
00081    /* I've seen a few alternative repesentations.  I guess the most common
00082       is the same as this, except with no "port ". */
00083 
00084    temp += " port ";
00085    temp += portnum;
00086 
00087    return(temp);
00088 }
00089 
00090 ::std::string InetAddress::GetHostname(bool forcelookup)
00091 {
00092    if (forcelookup) {
00093       hostname = IaddrToName(inaddr);
00094       return(hostname);
00095    } else {
00096       return(GetHostname());
00097    }
00098 }
00099 
00100 const InetAddress &InetAddress::operator =(const InetAddress &b)
00101 {
00102    /* If we're not ourselves, copy all the data over from the other
00103       InetAddress. */
00104    if (this != &b) {
00105       hostname = b.hostname;
00106       port = b.port;
00107       inaddr = b.inaddr;
00108    }
00109 
00110    return(*this);
00111 }
00112 
00113 const InetAddress &InetAddress::operator =(const sockaddr_in &iadr)
00114 {
00115    /* Make sure we're not being set to our own inaddr, so the = won't be
00116       disastrous. */
00117    if (&inaddr != &iadr) {
00118       inaddr = iadr;
00119    }
00120 
00121    /* Make sure we look a lot like the OS thinks an inaddr should look. */
00122    inaddr.sin_family = AF_INET;
00123    memset(inaddr.sin_zero, '\0', sizeof(inaddr.sin_zero));
00124 
00125    /* Cache the hostname and port info.  We could instead do this every time
00126       someone asks, but it would be kind of wasteful. */
00127    port = ntohs(iadr.sin_port);
00128    hostname = IaddrToName(inaddr);
00129 
00130    return(*this);
00131 }
00132 
00133 InetAddress::InetAddress(const ::std::string &h_name, U2Byte prt) :
00134         hostname(h_name), port(prt)
00135 {
00136    const char *c_hostname;
00137 
00138    c_hostname = h_name.c_str();
00139    memset(&inaddr, '\0', sizeof(inaddr));
00140    inaddr.sin_family = AF_INET;
00141    inaddr.sin_port = htons(port);
00142    U4Byte saddr = 0;
00143 
00144    if (ParseNumeric(c_hostname, saddr)) {
00145       /* If the address made sense as a <num>.<num>.<num>.<num> address,
00146          attempt to look up a 'real' hostname for this address. */
00147       hostname = IaddrToName(inaddr);
00148       inaddr.sin_addr.s_addr = saddr;
00149    } else if (NameToIaddr(c_hostname, saddr)) {
00150       /* Otherwise, if we were able to translate the name into an actual
00151          internet address, then the hostname is the name passed in. See note
00152          after function. */
00153       hostname = h_name;
00154       inaddr.sin_addr.s_addr = saddr;
00155    } else {
00156       /* This doesn't seem like any address we can translate to an internet
00157          address. */
00158       InvalidateAddress();
00159    }
00160 }
00161 /* **Note about above function**
00162    This is, perhaps, not the right way to do things because the passed in
00163    name could simply be an alias.  I think this way causes fewer surprises
00164    for the programmer using this class, and there ARE ways to force lookup
00165    of the alias, namely by calling GetHostname(true) to force a lookup. */
00166 
00167 InetAddress::InetAddress(U2Byte prt) : port(prt)
00168 {
00169    memset(&inaddr, '\0', sizeof(inaddr));
00170    inaddr.sin_family = AF_INET;
00171    inaddr.sin_port = htons(port);
00172    inaddr.sin_addr.s_addr = INADDR_ANY;
00173    hostname = IaddrToName(inaddr);
00174 }
00175 
00176 InetAddress::InetAddress(const InetAddress &b) : hostname(b.hostname),
00177                                                  port(b.port),
00178                                                  inaddr(b.inaddr)
00179 {
00180 }
00181 
00182 InetAddress::InetAddress(const sockaddr_in &iadr) : port(0)
00183 {
00184    memset(&inaddr, '\0', sizeof(inaddr));
00185    *this = iadr;
00186 }
00187 
00188 void InetAddress::InvalidateAddress()
00189 {
00190    hostname = ::std::string("invalid.host.name");
00191 
00192    inaddr.sin_addr.s_addr = INADDR_ANY;
00193 }
00194 
00195 bool InetAddress::ParseNumeric(const char *numeric_addr, U4Byte &num)
00196 {
00197    if (isdigit(numeric_addr[0])) {
00198       unsigned long num1, num2, num3, num4;
00199       int i;
00200 
00201       i = 0;
00202       if (!AsciiToQInum(numeric_addr, i, num1, true))
00203          return(false);
00204       if (!AsciiToQInum(numeric_addr, i, num2, true))
00205          return(false);
00206       if (!AsciiToQInum(numeric_addr, i, num3, true))
00207          return(false);
00208       if (!AsciiToQInum(numeric_addr, i, num4, false))
00209          return(false);
00210       num = htonl((((((num1 << 8) | num2) << 8) | num3) << 8) | num4);
00211       return(true);
00212    } else {
00213       return(false);
00214    }
00215 }
00216 
00217 bool InetAddress::AsciiToQInum(const char *s, int &i,
00218                                unsigned long &num, bool endsindot)
00219 {
00220    int mynum;
00221 
00222    if (!isdigit(s[i])) {
00223       return(false);
00224    }
00225 
00226    mynum = atoi(s + i);
00227    if (mynum < 0 || mynum > 255) {
00228       return(false);
00229    }
00230    while (s[i] != '\0' && isdigit(s[i]))
00231       i++;
00232    if (endsindot) {
00233       if (s[i] != '.') {
00234          return(false);
00235       } else {
00236          i++;
00237       }
00238    } else {
00239       if (s[i] != '\0') {
00240          return(false);
00241       }
00242    }
00243    num = mynum;
00244    return(true);
00245 }
00246 
00247 ::std::string InetAddress::ToDec(U2Byte num)
00248 {
00249    U2Byte top = 10000;
00250    ::std::string temp;
00251 
00252    while (top > 0 && (num / top) < 1)
00253       top /= 10;
00254    if (top <= 0)
00255       temp += '0';
00256    else {
00257       while (top > 0) {
00258          temp += '0' + ((num / top) % 10);
00259          top /= 10;
00260       }
00261    }
00262    return(temp);
00263 }
00264 
00265 } // end namespace ehnet
00266 } // end namespace lcore

Generated on Wed Jan 29 00:32:44 2003 for libNet by doxygen1.3-rc1