24 #include <ibrcommon/Logger.h>
25 #include <ibrcommon/net/socket.h>
30 #define EADDRINUSE WSAEADDRINUSE
37 const ibrcommon::vaddress UDPDatagramService::BROADCAST_ADDR(
"ff02::1", UDPDatagramService::BROADCAST_PORT, AF_INET6);
40 : _msock(NULL), _iface(iface), _bind_port(port)
67 _msock =
new ibrcommon::multicastsocket(BROADCAST_PORT);
70 _msock->join(BROADCAST_ADDR, _iface);
71 }
catch (
const ibrcommon::socket_raw_error &e) {
72 if (e.error() != EADDRINUSE) {
73 IBRCOMMON_LOGGER_TAG(
"UDPDatagramService", error) <<
"join failed on " << _iface.toString() <<
"; " << e.what() << IBRCOMMON_LOGGER_ENDL;
75 }
catch (
const ibrcommon::socket_exception &e) {
76 IBRCOMMON_LOGGER_DEBUG_TAG(
"UDPDatagramService", 10) <<
"can not join " << BROADCAST_ADDR.toString() <<
" on " << _iface.toString() <<
"; " << e.what() << IBRCOMMON_LOGGER_ENDL;
84 _vsocket.add(
new ibrcommon::udpsocket(_bind_port));
87 std::list<ibrcommon::vaddress> addrs = _iface.getAddresses();
90 std::stringstream ss; ss << _bind_port;
92 for (std::list<ibrcommon::vaddress>::iterator iter = addrs.begin(); iter != addrs.end(); ++iter) {
93 ibrcommon::vaddress &addr = (*iter);
96 switch (addr.family()) {
99 addr.setService(ss.str());
100 _vsocket.add(
new ibrcommon::udpsocket(addr), _iface);
107 }
catch (
const ibrcommon::Exception&) {
108 throw DatagramException(
"bind failed");
133 ibrcommon::vaddress destination;
134 UDPDatagramService::decode(identifier, destination);
137 send(type, flags, seqno, destination, buf, length);
148 send(type, flags, seqno, BROADCAST_ADDR, buf, length);
154 std::vector<char> tmp(length + 2);
160 tmp[1] =
static_cast<char>((0xf0 & (flags << 4)) | (0x0f & seqno));
163 ::memcpy(&tmp[2], buf, length);
165 IBRCOMMON_LOGGER_DEBUG_TAG(
"UDPDatagramService", 20) <<
"send() type: " << std::hex << (int)type <<
"; flags: " << std::hex << (
int)flags << "; seqno: " << std::dec << seqno << "; address: " << destination.toString() << IBRCOMMON_LOGGER_ENDL;
168 ibrcommon::socketset sockset = _vsocket.getAll();
169 for (ibrcommon::socketset::iterator iter = sockset.begin(); iter != sockset.end(); ++iter) {
170 if ((*iter) == _msock)
continue;
172 ibrcommon::udpsocket &sock =
dynamic_cast<ibrcommon::udpsocket&
>(**iter);
173 sock.sendto(&tmp[0], length + 2, 0, destination);
175 }
catch (
const ibrcommon::Exception&) {
176 }
catch (
const std::bad_cast&) { }
180 throw DatagramException(
"send failed");
181 }
catch (
const ibrcommon::Exception&) {
182 throw DatagramException(
"send failed");
197 ibrcommon::socketset readfds;
198 _vsocket.select(&readfds, NULL, NULL, NULL);
200 for (ibrcommon::socketset::iterator iter = readfds.begin(); iter != readfds.end(); ++iter) {
202 ibrcommon::udpsocket &sock =
dynamic_cast<ibrcommon::udpsocket&
>(**iter);
204 std::vector<char> tmp(length + 2);
205 ibrcommon::vaddress peeraddr;
206 size_t ret = sock.recvfrom(&tmp[0], length + 2, 0, peeraddr);
212 flags = 0x0f & (tmp[1] >> 4);
213 seqno = 0x0f & tmp[1];
216 address = UDPDatagramService::encode(peeraddr);
219 ::memcpy(buf, &tmp[2], ret - 2);
221 IBRCOMMON_LOGGER_DEBUG_TAG(
"UDPDatagramService", 20) <<
"recvfrom() type: " << std::hex << (int)type <<
"; flags: " << std::hex << (
int)flags <<
"; seqno: " << seqno <<
"; address: " << peeraddr.toString() << IBRCOMMON_LOGGER_ENDL;
224 }
catch (
const std::bad_cast&) {
228 }
catch (
const ibrcommon::Exception&) {
243 std::list<ibrcommon::vaddress> addrs = _iface.getAddresses();
245 for (std::list<ibrcommon::vaddress>::iterator iter = addrs.begin(); iter != addrs.end(); ++iter) {
246 ibrcommon::vaddress &addr = (*iter);
250 switch (addr.family()) {
253 return UDPDatagramService::encode(addr, _bind_port);
258 }
catch (
const ibrcommon::vaddress::address_exception &ex) {
259 IBRCOMMON_LOGGER_DEBUG_TAG(
"UDPDatagramService", 25) << ex.what() << IBRCOMMON_LOGGER_ENDL;
290 const std::string UDPDatagramService::encode(
const ibrcommon::vaddress &address,
const int port)
292 std::stringstream ss;
293 ss <<
"ip=" << address.address() <<
";port=";
295 if (port == 0) ss << address.service();
302 void UDPDatagramService::decode(
const std::string &identifier, ibrcommon::vaddress &address)
309 std::vector<string>::const_iterator param_iter = parameters.begin();
311 while (param_iter != parameters.end())
315 if (p[0].compare(
"ip") == 0)
320 if (p[0].compare(
"port") == 0)
328 address = ibrcommon::vaddress(addr, port);
UDPDatagramService(const ibrcommon::vinterface &iface, int port, size_t mtu=1280)
virtual const ibrcommon::vinterface & getInterface() const
virtual ~UDPDatagramService()
virtual size_t recvfrom(char *buf, size_t length, char &type, char &flags, unsigned int &seqno, std::string &address)
unsigned int max_seq_numbers
virtual const std::string getServiceDescription() const
virtual void send(const char &type, const char &flags, const unsigned int &seqno, const std::string &address, const char *buf, size_t length)
virtual dtn::core::Node::Protocol getProtocol() const
virtual const DatagramService::Parameter & getParameter() const
static std::vector< std::string > tokenize(const std::string &token, const std::string &data, const std::string::size_type max=std::string::npos)