00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
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
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;
00145 }
00146
00147 if (m_Dgram.control(SIOCGIFFLAGS, ifr)) {
00148 continue;
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;
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
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
00270
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;
00284 ACE_SOCK_Dgram m_Dgram;
00285 #if defined(WIN32)
00286 PIP_ADAPTER_INFO m_pAdapterInfo;
00287 #endif
00288 };
00289
00290 #endif
00291