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