Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

pana_udp_transport.h

00001 /* BEGIN_COPYRIGHT                                                        */
00002 /*                                                                        */
00003 /* Open Diameter: Open-source software for the Diameter and               */
00004 /*                Diameter related protocols                              */
00005 /*                                                                        */
00006 /* Copyright (C) 2002-2004 Open Diameter Project                          */
00007 /*                                                                        */
00008 /* This library is free software; you can redistribute it and/or modify   */
00009 /* it under the terms of the GNU Lesser General Public License as         */
00010 /* published by the Free Software Foundation; either version 2.1 of the   */
00011 /* License, or (at your option) any later version.                        */
00012 /*                                                                        */
00013 /* This library is distributed in the hope that it will be useful,        */
00014 /* but WITHOUT ANY WARRANTY; without even the implied warranty of         */
00015 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      */
00016 /* Lesser General Public License for more details.                        */
00017 /*                                                                        */
00018 /* You should have received a copy of the GNU Lesser General Public       */
00019 /* License along with this library; if not, write to the Free Software    */
00020 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307    */
00021 /* USA.                                                                   */
00022 /*                                                                        */
00023 /* In addition, when you copy and redistribute some or the entire part of */
00024 /* the source code of this software with or without modification, you     */
00025 /* MUST include this copyright notice in each copy.                       */
00026 /*                                                                        */
00027 /* If you make any changes that are appeared to be useful, please send    */
00028 /* sources that include the changed part to                               */
00029 /* diameter-developers@lists.sourceforge.net so that we can reflect your  */
00030 /* changes to one unified version of this software.                       */
00031 /*                                                                        */
00032 /* END_COPYRIGHT                                                          */
00033 
00034 #ifndef __PANA_UDP_TRANSPORT_H__
00035 #define __PANA_UDP_TRANSPORT_H__
00036 
00037 #if defined(WIN32)
00038 #include "windows.h"
00039 #include "Iphlpapi.h"
00040 #elif defined(OS_FREEBSD)
00041 #include <sys/types.h>
00042 #include <sys/socket.h>
00043 #include <ifaddrs.h>
00044 #include <net/if_dl.h>
00045 #elif defined(OS_LINUX)
00046 #include <net/if_arp.h>
00047 #endif
00048 
00049 #include "ace/SOCK_Dgram.h"
00050 #include "pana_io.h"
00051 
00052 class PANA_EXPORT PANA_UdpTransport : public PANA_IO
00053 {
00054     public:
00055         PANA_UdpTransport() {
00056 #if defined(WIN32)
00057             LoadAddresses();
00058 #endif
00059         }
00060         virtual ~PANA_UdpTransport() {
00061 #if defined(WIN32)
00062             UnloadAddresses();
00063 #endif
00064         }
00065         virtual ACE_INT32 open(std::string &iface,
00066                                ACE_INET_Addr &listenAddr) {
00067             m_Ifname = iface;
00068             return m_Dgram.open(listenAddr);
00069         }
00070         virtual ACE_INT32 recv(void *buf,
00071                                size_t n,
00072                                ACE_UINT32 &srcPort,
00073                                PANA_DeviceIdContainer &srcDevices) {
00074            ACE_INET_Addr srcAddr;
00075            ACE_Time_Value tm(1, 0);
00076            ACE_INT32 pkt_len = m_Dgram.recv((char*)buf, n,
00077                                             srcAddr, 0, &tm);
00078 
00079            if (pkt_len > 0) {
00080 
00081                srcPort = srcAddr.get_port_number();
00082 
00083                PANA_DeviceId *ip;
00084                ACE_NEW_RETURN(ip, PANA_DeviceId(PANA_DeviceId::IPV4_ADDRESS), (-1));
00085 
00086                ACE_UINT32 ipAddr = srcAddr.get_ip_address();
00087                const_cast<std::string&>(ip->id()).assign((char*)&ipAddr, 
00088                                                          sizeof(ACE_UINT32));
00089                srcDevices.push_back(ip);
00090            }
00091            return (pkt_len);
00092         }
00093         virtual ACE_INT32 send(void *buf,
00094                                size_t n,
00095                                ACE_UINT32 destPort,
00096                                PANA_DeviceIdContainer &destDevices) {
00097 
00098             PANA_DeviceId *id = destDevices.search(PANA_DeviceId::IPV4_ADDRESS);
00099             if (id) {
00100                 ACE_INET_Addr destAddr;
00101                 ACE_UINT32 *ipAddr = (ACE_UINT32*)id->id().c_str();
00102                 destAddr.set(destPort, *ipAddr);
00103                 return m_Dgram.send(buf, n, destAddr);
00104             }
00105             return (-1);
00106         }
00107         virtual ACE_INT32 get_local_addr(PANA_DeviceIdContainer &localDevices) {
00108 #if defined(OS_LINUX)
00109             #define inaddrr(x)     (*(struct in_addr *) &ifr->x[sizeof sa.sin_port])
00110             #define IFRSIZE(sz)    ((int)((sz) * sizeof (struct ifreq)))
00111 
00112             int                ssize = 1, rc = (-1);
00113             struct ifreq       *ifr;
00114             struct ifreq       ifr_hw;
00115             struct ifconf      ifc;
00116             struct sockaddr_in sa;
00117 
00118             ifc.ifc_len = IFRSIZE(ssize);
00119             ifc.ifc_req = NULL;
00120 
00121             do {
00122 
00123                ++ssize;
00124 
00125                /* realloc buffer size until no overflow occurs  */
00126                ifc.ifc_req = (struct ifreq*)realloc(ifc.ifc_req, IFRSIZE(ssize));
00127                if (ifc.ifc_req == NULL) {
00128                   ACE_ERROR_RETURN((LM_ERROR, "(%P|%t) Allocation failure\n"), (-1));
00129                }
00130 
00131                ifc.ifc_len = IFRSIZE(ssize);
00132 
00133                /* attempt to retrieve IF conf */
00134                if (m_Dgram.control(SIOCGIFCONF, &ifc)) {
00135                   ACE_ERROR_RETURN((LM_ERROR, "(%P|%t) IOCTL error\n"), (-1));
00136                }
00137                
00138            } while  (IFRSIZE(ssize) <= ifc.ifc_len);
00139 
00140            ifr = ifc.ifc_req;
00141            for (;(char *) ifr < (char *) ifc.ifc_req + ifc.ifc_len; ++ifr) {
00142 
00143                if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data) {
00144                   continue;  /* duplicate, skip it */
00145                }
00146 
00147                if (m_Dgram.control(SIOCGIFFLAGS, ifr)) {
00148                   continue;  /* failed to get flags, skip it */
00149                }
00150 
00151                if (ACE_OS::strcmp(ifr->ifr_name, m_Ifname.data()) == 0) {
00152 
00153                    PANA_DeviceId *ip, *hw;
00154                    
00155                    char *u = &ifr->ifr_addr.sa_data[sizeof(sa.sin_port)];
00156                    ACE_UINT32 ipAddr = ACE_NTOHL(*(ACE_UINT32*)u);
00157 
00158                    ACE_NEW_RETURN(ip, PANA_DeviceId(PANA_DeviceId::IPV4_ADDRESS), (-1));
00159                    const_cast<std::string&>(ip->id()).assign((char*)&ipAddr, sizeof(ipAddr));
00160                    localDevices.push_back(ip);
00161 
00162                    ACE_OS::strcpy(ifr_hw.ifr_name, ifr->ifr_name);
00163                    if (m_Dgram.control(SIOCGIFHWADDR, &ifr_hw)) {
00164                       continue;  /* failed to get flags, skip it */
00165                    }
00166 
00167                    ACE_NEW_RETURN(hw, PANA_DeviceId(PANA_DeviceId::LL_ADDRESS), (-1));
00168                    switch (ifr_hw.ifr_hwaddr.sa_family) {
00169                        case ARPHRD_ETHER:
00170                            u = ifr_hw.ifr_hwaddr.sa_data;
00171                            const_cast<std::string&>(hw->id()).assign(u, 6);
00172                            localDevices.push_back(hw);
00173                            break;
00174                        default:
00175                            // TBD: Add others here
00176                            delete hw;
00177                            break;
00178                    }
00179                    rc = 0;
00180                    break;
00181                }
00182            }
00183 
00184            if (ifc.ifc_req) {
00185                free(ifc.ifc_req);
00186            }
00187 
00188            return (rc);
00189 #elif defined(OS_FREEBSD)
00190            int rc = (-1);
00191            struct ifaddrs *ifap, *ifn;
00192            if (getifaddrs(&ifap) == 0) {
00193                for (ifn = ifap; ifn != NULL; ifn = ifn->ifa_next) {
00194                    if (ACE_OS::strcmp(ifn->ifa_name, m_Ifname.data())) {
00195                        continue;
00196                    }
00197                    if ((ifn->ifa_addr == 0)) {
00198                        continue;
00199                    }
00200                    if (ifn->ifa_addr->sa_family == AF_INET) {
00201                        char *addr = (char*)ifn->ifa_addr + 
00202                                     offsetof(struct sockaddr_in, sin_addr);
00203                        ACE_UINT32 ipAddr = ACE_NTOHL(*(ACE_UINT32*)addr);
00204 
00205                        PANA_DeviceId *ip;
00206                        ACE_NEW_RETURN(ip, PANA_DeviceId(PANA_DeviceId::IPV4_ADDRESS), 
00207                                       (-1));
00208    
00209                        const_cast<std::string&>(ip->id()).assign
00210                                      ((char*)&ipAddr, sizeof(ipAddr));
00211                        localDevices.push_back(ip);
00212                        rc = 0;
00213                    }
00214                    else if (ifn->ifa_addr->sa_family == AF_LINK) {
00215                        struct sockaddr_dl *dl = (struct sockaddr_dl*)ifn->ifa_addr; 
00216                        PANA_DeviceId *hw;
00217                        ACE_NEW_RETURN(hw, PANA_DeviceId(PANA_DeviceId::LL_ADDRESS), (-1));
00218                        const_cast<std::string&>(hw->id()).assign(LLADDR(dl), dl->sdl_alen);
00219                        localDevices.push_back(hw);
00220                        rc = 0;
00221                    } 
00222                }
00223                freeifaddrs(ifap);
00224            }
00225            return (rc);
00226 #elif defined(WIN32)
00227            PIP_ADAPTER_INFO pAdapter = m_pAdapterInfo;
00228            while (pAdapter) {
00229                if (! ACE_OS::strncmp(m_Ifname.data(), 
00230                                      pAdapter->Description,
00231                                      m_Ifname.length())) {
00232                    CHAR szAddr[32];
00233                    if (pAdapter->CurrentIpAddress) {
00234                        ACE_OS::sprintf(szAddr, "%s:0", pAdapter->CurrentIpAddress->IpAddress.String);
00235                    }
00236                    else {
00237                        ACE_OS::sprintf(szAddr, "%s:0", pAdapter->IpAddressList.IpAddress.String);
00238                    }
00239                    ACE_INET_Addr aceIpAddr(szAddr);
00240                    ACE_UINT32 dwIpAddr = aceIpAddr.get_ip_address();
00241 
00242                    PANA_DeviceId *devId;
00243                    ACE_NEW_RETURN(devId, PANA_DeviceId(PANA_DeviceId::IPV4_ADDRESS), 
00244                                   (-1));
00245   
00246                    const_cast<std::string&>(devId->id()).assign((char*)&dwIpAddr, sizeof(dwIpAddr));
00247                    localDevices.push_back(devId);
00248 
00249                    PANA_DeviceId *hw;
00250                    ACE_NEW_RETURN(hw, PANA_DeviceId(PANA_DeviceId::LL_ADDRESS), (-1));
00251                    const_cast<std::string&>(hw->id()).assign((char*)pAdapter->Address, pAdapter->AddressLength);
00252                    localDevices.push_back(hw);
00253                    break;
00254                }
00255                pAdapter = pAdapter->Next;
00256            }
00257            return (pAdapter) ? (0) : (-1);
00258 #endif
00259         }
00260         virtual void close() {
00261            m_Dgram.close();
00262         }
00263 
00264     protected:
00265 #if defined(WIN32)
00266         void LoadAddresses() {
00267            m_pAdapterInfo = (IP_ADAPTER_INFO *)ACE_OS::malloc(sizeof(IP_ADAPTER_INFO));
00268            ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
00269            // Make an initial call to GetAdaptersInfo to get
00270            // the necessary size into the ulOutBufLen variable
00271            if (GetAdaptersInfo(m_pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
00272                ACE_OS::free(m_pAdapterInfo);
00273                m_pAdapterInfo = (IP_ADAPTER_INFO*)ACE_OS::malloc(ulOutBufLen);
00274            }
00275            GetAdaptersInfo(m_pAdapterInfo, &ulOutBufLen);
00276         }
00277         void UnloadAddresses() {
00278             ACE_OS::free(m_pAdapterInfo);
00279         }
00280 #endif
00281 
00282     private:
00283         std::string m_Ifname;   /*< store the interface name */
00284         ACE_SOCK_Dgram m_Dgram; /*< Localized socket */
00285 #if defined(WIN32)
00286         PIP_ADAPTER_INFO m_pAdapterInfo;
00287 #endif
00288 };
00289 
00290 #endif /* __PANA_UDP_TRANSPORT_H__ */
00291 

Generated on Fri Jun 25 19:18:30 2004 for PANA by doxygen 1.3.5