IBR-DTNSuite
0.8
|
00001 /* 00002 * udpsocket.cpp 00003 * 00004 * Created on: 02.03.2010 00005 * Author: morgenro 00006 */ 00007 00008 #include "ibrcommon/config.h" 00009 #include "ibrcommon/net/udpsocket.h" 00010 #include "ibrcommon/Logger.h" 00011 #include <sys/socket.h> 00012 #include <errno.h> 00013 #include <sys/types.h> 00014 #include <netinet/in.h> 00015 #include <arpa/inet.h> 00016 #include <string.h> 00017 00018 #ifndef HAVE_BZERO 00019 #define bzero(s,n) (memset((s), '\0', (n)), (void) 0) 00020 #endif 00021 00022 namespace ibrcommon 00023 { 00024 udpsocket::udpsocket() throw (SocketException) 00025 { 00026 } 00027 00028 udpsocket::~udpsocket() 00029 { 00030 _socket.close(); 00031 } 00032 00033 void udpsocket::shutdown() 00034 { 00035 _socket.close(); 00036 } 00037 00038 int udpsocket::receive(char* data, size_t maxbuffer) 00039 { 00040 struct sockaddr_in clientAddress; 00041 socklen_t clientAddressLength = sizeof(clientAddress); 00042 00043 std::list<int> fds; 00044 _socket.select(fds, NULL); 00045 int fd = fds.front(); 00046 00047 // data waiting 00048 return recvfrom(fd, data, maxbuffer, MSG_WAITALL, (struct sockaddr *) &clientAddress, &clientAddressLength); 00049 } 00050 00051 int udpsocket::receive(char* data, size_t maxbuffer, std::string &address, unsigned int &port) 00052 { 00053 struct sockaddr_storage addr; 00054 socklen_t fromlen = sizeof(addr); 00055 char ipstr[INET6_ADDRSTRLEN]; 00056 00057 std::list<int> fds; 00058 _socket.select(fds, NULL); 00059 int fd = fds.front(); 00060 00061 // data waiting 00062 int ret = recvfrom(fd, data, maxbuffer, MSG_WAITALL, (struct sockaddr *) &addr, &fromlen); 00063 00064 if ( addr.ss_family == AF_INET ) 00065 { 00066 // IPv4 00067 inet_ntop(addr.ss_family, &((struct sockaddr_in *)&addr)->sin_addr, ipstr, sizeof ipstr); 00068 address = std::string(ipstr); 00069 port = ntohs(((struct sockaddr_in *)&addr)->sin_port); 00070 } 00071 else if ( addr.ss_family == AF_INET6 ) 00072 { 00073 // IPv6 00074 inet_ntop(addr.ss_family, &((struct sockaddr_in6 *)&addr)->sin6_addr, ipstr, sizeof ipstr); 00075 address = std::string(ipstr); 00076 port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port); 00077 } 00078 else 00079 { 00080 address = "unknown"; 00081 port = 0; 00082 } 00083 00084 return ret; 00085 } 00086 00087 int udpsocket::send(const ibrcommon::vaddress &addr, const unsigned int port, const char *data, const size_t length) 00088 { 00089 int stat = -1; 00090 00091 // iterate over all sockets 00092 std::list<int> fds = _socket.get(); 00093 00094 for (std::list<int>::const_iterator iter = fds.begin(); iter != fds.end(); iter++) 00095 { 00096 try { 00097 ssize_t ret = 0; 00098 int flags = 0; 00099 00100 struct addrinfo hints, *ainfo; 00101 memset(&hints, 0, sizeof hints); 00102 00103 hints.ai_socktype = SOCK_DGRAM; 00104 ainfo = addr.addrinfo(&hints, port); 00105 00106 ret = ::sendto(*iter, data, length, flags, ainfo->ai_addr, ainfo->ai_addrlen); 00107 00108 freeaddrinfo(ainfo); 00109 00110 // if the send was successful, set the correct return value 00111 if (ret != -1) 00112 { 00113 stat = ret; 00114 00115 if ((!addr.isBroadcast()) && (!addr.isMulticast())) 00116 { 00117 // stop here 00118 break; 00119 } 00120 } 00121 } catch (const ibrcommon::vsocket_exception&) { 00122 IBRCOMMON_LOGGER_DEBUG(5) << "can not send message to " << addr.toString() << IBRCOMMON_LOGGER_ENDL; 00123 } 00124 } 00125 00126 return stat; 00127 } 00128 }