00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #include <oasys/io/NetUtils.h>
00022
00023 #include "DTNTunnel.h"
00024 #include "UDPTunnel.h"
00025
00026 namespace dtntunnel {
00027
00028
00029 UDPTunnel::UDPTunnel()
00030 : IPTunnel("UDPTunnel", "/dtntunnel/udp"),
00031 sock_("/dtntunnel/udp/sock")
00032 {
00033 sock_.init_socket();
00034 }
00035
00036
00037 void
00038 UDPTunnel::add_listener(in_addr_t listen_addr, u_int16_t listen_port,
00039 in_addr_t remote_addr, u_int16_t remote_port)
00040 {
00041
00042 new Listener(listen_addr, listen_port, remote_addr, remote_port);
00043 }
00044
00045
00046 void
00047 UDPTunnel::handle_bundle(dtn::APIBundle* bundle)
00048 {
00049 DTNTunnel::BundleHeader hdr;
00050 memcpy(&hdr, bundle->payload_.buf(), sizeof(hdr));
00051 hdr.remote_port_ = htons(hdr.remote_port_);
00052
00053 char* bp = bundle->payload_.buf() + sizeof(hdr);
00054 int len = bundle->payload_.len() - sizeof(hdr);
00055
00056 int cc = sock_.sendto(bp, len,
00057 0, hdr.remote_addr_, hdr.remote_port_);
00058 if (cc != len) {
00059 log_err("error sending packet to %s:%d: %s",
00060 intoa(hdr.remote_addr_), hdr.remote_port_, strerror(errno));
00061 } else {
00062 log_debug("sent %zu byte packet to %s:%d",
00063 bundle->payload_.len() - sizeof(hdr),
00064 intoa(hdr.remote_addr_), hdr.remote_port_);
00065 }
00066
00067 delete bundle;
00068 }
00069
00070
00071 UDPTunnel::Listener::Listener(in_addr_t listen_addr, u_int16_t listen_port,
00072 in_addr_t remote_addr, u_int16_t remote_port)
00073 : Thread("UDPTunnel::Listener", DELETE_ON_EXIT),
00074 Logger("UDPTunnel::Listener", "/dtntunnel/udp/listener"),
00075 sock_("/dtntunnel/udp/listener/sock"),
00076 listen_addr_(listen_addr),
00077 listen_port_(listen_port),
00078 remote_addr_(remote_addr),
00079 remote_port_(remote_port)
00080 {
00081 start();
00082 }
00083
00084
00085 void
00086 UDPTunnel::Listener::run()
00087 {
00088 DTNTunnel* tunnel = DTNTunnel::instance();
00089 int ret = sock_.bind(listen_addr_, listen_port_);
00090 if (ret != 0) {
00091 log_err("can't bind to %s:%u", intoa(listen_addr_), listen_port_);
00092 return;
00093 }
00094
00095 DTNTunnel::BundleHeader hdr;
00096 hdr.protocol_ = IPPROTO_UDP;
00097 hdr.seqno_ = 0;
00098 hdr.client_addr_ = listen_addr_;
00099 hdr.client_port_ = htons(listen_port_);
00100 hdr.remote_addr_ = remote_addr_;
00101 hdr.remote_port_ = htons(remote_port_);
00102
00103 while (1) {
00104 int len = sock_.recv(recv_buf_, sizeof(recv_buf_), 0);
00105 if (len <= 0) {
00106 log_err("error reading from socket: %s", strerror(errno));
00107 return;
00108 }
00109
00110 log_debug("got %d byte packet", len);
00111
00112 dtn::APIBundle* b = new dtn::APIBundle();
00113 char* bp = b->payload_.buf(sizeof(hdr) + len);
00114 memcpy(bp, &hdr, sizeof(hdr));
00115 memcpy(bp + sizeof(hdr), recv_buf_, len);
00116 b->payload_.set_len(sizeof(hdr) + len);
00117
00118 if (tunnel->send_bundle(b, tunnel->dest_eid()) != DTN_SUCCESS)
00119 exit(1);
00120 }
00121 }
00122
00123 }