func DialTunnel(addr string) (tc net.Conn, err error) { var conn *net.UDPConn var t *Tunnel udpaddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { return } conn, err = net.DialUDP("udp", nil, udpaddr) if err != nil { return } localaddr := conn.LocalAddr() localstr := localaddr.String() name := fmt.Sprintf("%s_cli", strings.Split(localstr, ":")[1]) t = NewTunnel(udpaddr, name, make(chan *SendBlock, TBUFSIZE)) c := &Client{t, conn, name, make(chan uint8)} t.onclose = func() { sutils.Info("close tunnel", localaddr) conn.Close() close(c.c_close) close(t.c_send) } go c.sender() go c.recver() t.c_event <- EV_CONNECT <-t.c_connect sutils.Info("create tunnel", localaddr) return &TunnelConn{t, localaddr}, nil }
func (udp *Udp) listen(conn *net.UDPConn) { log.Info("Begin listening for UDP on address %s", conn.LocalAddr()) buffer := make([]byte, c_BUFSIZE) for { num, _, err := conn.ReadFromUDP(buffer) if err != nil { if udp.stop { log.Info("Stopped listening for UDP on %s", conn.LocalAddr) break } else { log.Severe("Failed to read from UDP buffer: " + err.Error()) continue } } pkt := append([]byte(nil), buffer[:num]...) go func() { msg, err := parser.ParseMessage(pkt) if err != nil { log.Warn("Failed to parse SIP message: %s", err.Error()) } else { udp.output <- msg } }() } }
func GatherCandidates(sock *net.UDPConn) ([]candidate, error) { laddr := sock.LocalAddr().(*net.UDPAddr) ret := []candidate{} switch { case laddr.IP.IsLoopback(): return nil, errors.New("Connecting over loopback not supported") case laddr.IP.IsUnspecified(): addrs, err := net.InterfaceAddrs() if err != nil { return nil, err } for _, addr := range addrs { ip, ok := addr.(*net.IPNet) if ok && ip.IP.IsGlobalUnicast() { ret = append(ret, candidate{&net.UDPAddr{ip.IP, laddr.Port, ""}, 0}) } } default: ret = append(ret, candidate{laddr, 0}) } // Get the reflexive address reflexive, err := getReflexive(sock) if err == nil { ret = append(ret, candidate{reflexive, 0}) } setPriorities(ret) return ret, nil }
func (listener *Listener) newUDPSession(remote *net.UDPAddr) (*UDPSession, bool) { remoteAddrStr := remote.String() listener.Lock() if sess, ok := listener.remoteAddrs[remoteAddrStr]; ok == true { listener.Unlock() return sess, true } listener.Unlock() var err error var local *net.UDPConn if local, err = net.ListenUDP("udp", &net.UDPAddr{}); err != nil { //log.Println(err) return nil, false } localAddr := local.LocalAddr().(*net.UDPAddr) sess := newUDPSession(listener, remote, local, localAddr) listener.Lock() listener.remoteAddrs[remoteAddrStr] = sess listener.Unlock() return sess, false }
// Creates a 2 byte ClientID from the local machine's IP. func GetClientId() (id []byte, err error) { var conn *net.UDPConn var addr *net.UDPAddr // Connect to a random machine somewhere in this subnet. It's irrelevant // where to, as long as it's not the loopback address. if addr, err = net.ResolveUDPAddr("udp", "192.168.1.1:0"); err != nil { return } if conn, err = net.DialUDP("udp", nil, addr); err != nil { return } defer conn.Close() // strip port number off. str := conn.LocalAddr().String() if idx := strings.LastIndex(str, ":"); idx != -1 { str = str[0:idx] } var ip net.IP if ip = net.ParseIP(str).To16(); ip == nil { return } // TODO(jimt): I am unsure how 2 full IPv6 addresses in the same subnet relate // to eachother. Specifically if the 2 last bytes in the 16-byte address are // really the relevant bits that set them apart from eachother. // For IPv4 this is simple: 192.168.2.101 vs 192.168.2.102 -> we need the // '2.101' and '2.102' bits. Bytes are stored in Big Endian order. id = []byte{ip[14], ip[15]} return }
/* Used to listen for incoming UDP packets on an given connection. Runs an infinite loop reading from the connection to a buffer. When a message is complete, it sends it to to the caller via the receive channel. */ func udpConnectionReader(connection *net.UDPConn, messageSize int, receiveChannel chan<- UDPMessage) { defer func() { if r := recover(); r != nil { log.Println("UDPConnectionReader:\t ERROR in udpConnectionReader:\t %s \n Closig connection.", r) connection.Close() } }() for { if debug { log.Printf("UDPConnectionReader:\t Waiting on data from UDPConnection %s\n", connection.LocalAddr().String()) } buffer := make([]byte, messageSize) // TODO: Do without allocation memory each time! n, returnAddress, err := connection.ReadFromUDP(buffer) if err != nil || n < 0 || n > messageSize { log.Println("UDPConnectionReader:\t Error in ReadFromUDP:", err) } else { if debug { log.Println("UDPConnectionReader:\t Received package from:", returnAddress.String()) log.Println("UDP-Listen:\t", string(buffer[:])) } receiveChannel <- UDPMessage{RAddress: returnAddress.String(), Data: buffer[:n], Length: n} } } }
func listenServer(conn *net.UDPConn, receiveChannel chan UDPMessage, networkLogger log.Logger) { networkLogger.Printf("Listening on %s", conn.LocalAddr().String()) for { buf := make([]byte, 1024) len, raddr, _ := conn.ReadFromUDP(buf) receiveChannel <- UDPMessage{Address: IP(raddr.IP.String()), Data: buf[:len], Length: len} } }
func getUDPAddr(conn *net.UDPConn) *net.UDPAddr { addr := conn.LocalAddr() udpAddr, ok := addr.(*net.UDPAddr) if !ok { log.Fatal() } return udpAddr }
// Listen launches the various server goroutines and starts the various listeners. // If the listener params are nil, these are constructed from the parameters in the conf. Otherwise they are // used as-is. This makes it possible for the tests to construct listeners on an available port and pass them // in. func (s *Server) Listen(clientConn *net.UDPConn, forwardListener, debugListener net.Listener) error { go s.handleMetaStats() go s.flush() go s.aggregate() if s.conf.OSStats != nil { go s.checkOSStats() } if s.conf.Scripts != nil { go s.runScripts() } if s.conf.forwardingEnabled { s.forwardingIncoming = make(chan *Stat, incomingQueueSize) go s.flushForwarding() go s.aggregateForwarding() } errorCh := make(chan error) if s.conf.forwarderEnabled { if forwardListener == nil { l, err := net.Listen("tcp", s.conf.ForwarderListenAddr) if err != nil { return err } forwardListener = tcpKeepAliveListener{l.(*net.TCPListener)} } s.l.Println("Listening for forwarded gost messages on", forwardListener.Addr()) go s.aggregateForwarded() go func() { errorCh <- s.forwardServer(forwardListener) }() } if err := s.debugServer.Start(s.conf.DebugPort, debugListener); err != nil { return err } if clientConn == nil { udpAddr := fmt.Sprintf("localhost:%d", s.conf.Port) udp, err := net.ResolveUDPAddr("udp", udpAddr) if err != nil { return err } clientConn, err = net.ListenUDP("udp", udp) if err != nil { return err } } s.l.Println("Listening for UDP client requests on", clientConn.LocalAddr()) go func() { errorCh <- s.clientServer(clientConn) }() // Indicate that we've started s.metaInc("server_start") return <-errorCh }
func handleudp(conn *net.UDPConn, remaddr net.Addr, message []byte) { fmt.Printf("UDP packet from %s (to %s)... ", remaddr, conn.LocalAddr()) n, error := conn.WriteTo(message, remaddr) checkError("Cannot write", error) if n != len(message) { panic("Cannot write") } fmt.Printf("Echoed %d bytes\n", n) }
func GatherCandidates(sock *net.UDPConn, outIpList string) ([]candidate, error) { laddr := sock.LocalAddr().(*net.UDPAddr) ret := []candidate{} switch { case laddr.IP.IsLoopback(): return nil, errors.New("Connecting over loopback not supported") case laddr.IP.IsUnspecified(): addrs, err := net.InterfaceAddrs() if err != nil { return nil, err } for _, addr := range addrs { ip, ok := addr.(*net.IPNet) if ok && ip.IP.IsGlobalUnicast() { ret = append(ret, candidate{&net.UDPAddr{IP: ip.IP, Port: laddr.Port}}) } } default: ret = append(ret, candidate{laddr}) } addip := func(ipStr string, port int) { ip := net.ParseIP(ipStr) if port == 0 { port = laddr.Port } bHave := false for _, info := range ret { if info.Addr.IP.Equal(ip) && info.Addr.Port == port { bHave = true break } } if !bHave { ret = append(ret, candidate{&net.UDPAddr{IP: ip, Port: port}}) } } // Get the reflexive address if *stunserver != "" { ip, port, err := getReflexive(sock) if err == nil { addip(ip, port) } } arr := strings.Split(outIpList, ";") for _, ip := range arr { addip(ip, 0) } /* for _, info := range ret { log.Println("init ip:", info.Addr.String()) }*/ return ret, nil }
func findAddress() (addr string, err error) { var udpAddr *net.UDPAddr if udpAddr, err = net.ResolveUDPAddr("udp", "www.internic.net:80"); err != nil { return } var udpConn *net.UDPConn if udpConn, err = net.DialUDP("udp", nil, udpAddr); err != nil { return } addr = udpConn.LocalAddr().String() return }
func StartListener(conn *net.UDPConn, callback func(address *net.UDPAddr)) { log.Println("listener:Listening on:", conn.LocalAddr()) buf := make([]byte, 1024) for { //log.Println("listener:going to read") n, addr, err := conn.ReadFromUDP(buf) checkError(err) log.Println("listener:received:", n, "bytes from:", addr) callback(addr) } }
func listen(c chan string, conn *net.UDPConn, label string) { log.Printf("listening to %s", conn.LocalAddr().String()) buf := make([]byte, 9999) for { n, _, err := conn.ReadFromUDP(buf) if err != nil { log.Print(err) time.Sleep(3 * time.Second) continue } s := string(buf[:n]) log.Printf("%s got {%s}", label, s) c <- s } }
func TestIngestPacket_CRC(t *testing.T) { m := GetMemberlist(t) m.config.EnableCompression = false defer m.Shutdown() var udp *net.UDPConn for port := 60000; port < 61000; port++ { udpAddr := fmt.Sprintf("127.0.0.1:%d", port) udpLn, err := net.ListenPacket("udp", udpAddr) if err == nil { udp = udpLn.(*net.UDPConn) break } } if udp == nil { t.Fatalf("no udp listener") } // Get a message with a checksum payload := []byte{3, 3, 3, 3} m.rawSendMsgUDP(udp.LocalAddr(), &Node{PMax: 5}, payload) in := make([]byte, 1500) n, _, err := udp.ReadFrom(in) if err != nil { t.Fatalf("unexpected err %s", err) } in = in[0:n] if len(in) != 9 { t.Fatalf("bad: %v", in) } // Corrupt the checksum in[1] <<= 1 logs := &bytes.Buffer{} logger := log.New(logs, "", 0) m.logger = logger m.ingestPacket(in, udp.LocalAddr(), time.Now()) if !strings.Contains(logs.String(), "invalid checksum") { t.Fatalf("bad: %s", logs.String()) } }
func (p *Proxy) proxyUDPStream(ctx context.Context, src *net.UDPConn) { srcRemoteAddr := src.RemoteAddr().(*net.UDPAddr) srcLocalAddr := src.LocalAddr().(*net.UDPAddr) route := p.routes.GetTable().Lookup(protocols.UDP, srcRemoteAddr.IP, srcLocalAddr.IP, uint16(srcRemoteAddr.Port), uint16(srcLocalAddr.Port)) if route == nil { src.Close() return } go func() { dstAddr := net.UDPAddr{ IP: route.Outbound.DstIP, Port: int(route.Outbound.DstPort), } dst, err := net.DialUDP("udp", nil, &dstAddr) if err != nil { src.Close() return } dst.SetKeepAlivePeriod(10 * time.Second) src.SetKeepAlivePeriod(10 * time.Second) go func() { <-ctx.Done() src.Close() dst.Close() }() go func() { defer dst.CloseWrite() defer src.CloseRead() io.Copy(dst, src) }() go func() { defer src.CloseWrite() defer dst.CloseRead() io.Copy(src, dst) }() }() }
func (trans *udpTransportProvider) newConn(udp *net.UDPConn, remote_addr *udpAddr, protocol Protocol, err error) (*udpConn, error) { if err != nil { return nil, err } local, ok := udp.LocalAddr().(*net.UDPAddr) if !ok { return nil, fmt.Errorf("Could not convert LocalAddr to *net.UDPAddr: %v", udp.LocalAddr()) } return &udpConn{ trans: trans, udp: udp, protocol: protocol, local: udpAddr{trans, local}, remote: remote_addr, retries: DefaultRetries, }, nil }
func ReceiveDatagrams(hostAndPort string) *data.EventStream { var conn *net.UDPConn conn, err := createUDPListener(hostAndPort) if err != nil { panic("Could not create UDP listener") } fmt.Printf("Listener for UDP connections on %s\n", conn.LocalAddr().String()) eventStream := data.NewEventStream() go rcv(conn, eventStream) return eventStream }
func rd(out chan string, conn *net.UDPConn, quit chan struct{}) { log.Printf("rd: %s", conn.LocalAddr()) defer log.Printf("rd: done") const maxSize = 4096 for { select { case <-quit: return default: b := make([]byte, maxSize) conn.SetReadDeadline(time.Now().Add(cycle)) n, remoteAddr, err := conn.ReadFrom(b) if err != nil { continue } if n >= maxSize { log.Printf("%s: too big", remoteAddr) continue } out <- string(b[:n]) } } }
func Main(clusterName, self, buri, rwsk, rosk string, cl *doozer.Conn, udpConn *net.UDPConn, listener, webListener net.Listener, pulseInterval, fillDelay, kickTimeout int64, hi int64) { listenAddr := listener.Addr().String() canWrite := make(chan bool, 1) in := make(chan consensus.Packet, 50) out := make(chan consensus.Packet, 50) st := store.New() pr := &proposer{ seqns: make(chan int64, alpha), props: make(chan *consensus.Prop), st: st, } calSrv := func(start int64) { go gc.Pulse(self, st.Seqns, pr, pulseInterval) go gc.Clean(st, hi, time.Tick(1e9)) var m consensus.Manager m.Self = self m.DefRev = start m.Alpha = alpha m.In = in m.Out = out m.Ops = st.Ops m.PSeqn = pr.seqns m.Props = pr.props m.TFill = fillDelay m.Store = st m.Ticker = time.Tick(10e6) go m.Run() } hostname, err := os.Hostname() if err != nil { hostname = "unknown" } if cl == nil { // we are the only node in a new cluster set(st, "/ctl/name", clusterName, store.Missing) set(st, "/ctl/node/"+self+"/addr", listenAddr, store.Missing) set(st, "/ctl/node/"+self+"/hostname", hostname, store.Missing) set(st, "/ctl/node/"+self+"/version", Version, store.Missing) set(st, "/ctl/cal/0", self, store.Missing) if buri == "" { set(st, "/ctl/ns/"+clusterName+"/"+self, listenAddr, store.Missing) } calSrv(<-st.Seqns) // Skip ahead alpha steps so that the registrar can provide a // meaningful cluster. for i := 0; i < alpha; i++ { st.Ops <- store.Op{1 + <-st.Seqns, store.Nop} } canWrite <- true go setReady(pr, self) } else { setC(cl, "/ctl/node/"+self+"/addr", listenAddr, store.Clobber) setC(cl, "/ctl/node/"+self+"/hostname", hostname, store.Clobber) setC(cl, "/ctl/node/"+self+"/version", Version, store.Clobber) rev, err := cl.Rev() if err != nil { panic(err) } stop := make(chan bool, 1) go follow(st, cl, rev+1, stop) errs := make(chan error) go func() { e, ok := <-errs if ok { panic(e) } }() doozer.Walk(cl, rev, "/", cloner{st.Ops, cl}, errs) close(errs) st.Flush() ch, err := st.Wait(store.Any, rev+1) if err == nil { <-ch } go func() { n := activate(st, self, cl) calSrv(n) advanceUntil(cl, st.Seqns, n+alpha) stop <- true canWrite <- true go setReady(pr, self) if buri != "" { b, err := doozer.DialUri(buri, "") if err != nil { panic(err) } setC( b, "/ctl/ns/"+clusterName+"/"+self, listenAddr, store.Missing, ) } }() } shun := make(chan string, 3) // sufficient for a cluster of 7 go member.Clean(shun, st, pr) go server.ListenAndServe(listener, canWrite, st, pr, rwsk, rosk) if rwsk == "" && rosk == "" && webListener != nil { web.Store = st web.ClusterName = clusterName go web.Serve(webListener) } go func() { for p := range out { n, err := udpConn.WriteTo(p.Data, p.Addr) if err != nil { log.Println(err) continue } if n != len(p.Data) { log.Println("packet len too long:", len(p.Data)) continue } } }() selfAddr, ok := udpConn.LocalAddr().(*net.UDPAddr) if !ok { panic("no UDP addr") } lv := liveness{ timeout: kickTimeout, ival: kickTimeout / 2, self: selfAddr, shun: shun, } for { t := time.Now().UnixNano() buf := make([]byte, maxUDPLen) n, addr, err := udpConn.ReadFromUDP(buf) if err == syscall.EINVAL { return } if err != nil { log.Println(err) continue } buf = buf[:n] lv.mark(addr, t) lv.check(t) in <- consensus.Packet{addr, buf} } }
. "github.com/onsi/gomega" ) var _ = Describe("UDP Client", func() { var ( client *clientpool.UDPClient udpListener *net.UDPConn ) BeforeEach(func() { udpAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0") Expect(err).NotTo(HaveOccurred()) udpListener, err = net.ListenUDP("udp", udpAddr) Expect(err).NotTo(HaveOccurred()) client, err = clientpool.NewUDPClient(gosteno.NewLogger("TestLogger"), udpListener.LocalAddr().String()) Expect(err).NotTo(HaveOccurred()) }) AfterEach(func() { client.Close() udpListener.Close() }) Describe("NewUDPClient", func() { Context("when the address is invalid", func() { It("returns an error", func() { _, err := clientpool.NewUDPClient(gosteno.NewLogger("TestLogger"), "127.0.0.1:abc") Expect(err).To(HaveOccurred()) }) })
func GatherCandidates(sock *net.UDPConn, outIpList string, udpAddr string) ([]candidate, error) { laddr := sock.LocalAddr().(*net.UDPAddr) ret := []candidate{} switch { case laddr.IP.IsLoopback(): return nil, errors.New("Connecting over loopback not supported") case laddr.IP.IsUnspecified(): addrs, err := net.InterfaceAddrs() if err != nil { return nil, err } for _, addr := range addrs { ip, ok := addr.(*net.IPNet) if ok && ip.IP.IsGlobalUnicast() { ret = append(ret, candidate{&net.UDPAddr{IP: ip.IP, Port: laddr.Port}}) } } default: ret = append(ret, candidate{laddr}) } addip := func(ipStr string, port int) { ip := net.ParseIP(ipStr) if port == 0 { port = laddr.Port } bHave := false for _, info := range ret { if info.Addr.IP.Equal(ip) && info.Addr.Port == port { bHave = true break } } if !bHave { ret = append(ret, candidate{&net.UDPAddr{IP: ip, Port: port}}) } } if udpAddr != "" { addr, err := net.ResolveUDPAddr("udp", udpAddr) if err != nil { fmt.Println("Can't resolve udp address: ", err) return nil, err } p2pAddr := "" for i := 0; i < 5; i++ { sock.WriteToUDP([]byte("makehole"), addr) buf := make([]byte, 100) sock.SetReadDeadline(time.Now().Add(time.Duration(1) * time.Second)) n, _, err := sock.ReadFromUDP(buf) if err != nil { fmt.Println("Can't ReadFromUDP: ", err, addr.String()) continue } else { p2pAddr = string(buf[0:n]) fmt.Println("read: ", p2pAddr) break } } addLen := len(p2pAddr) if addLen > 0 { tmparr := strings.Split(p2pAddr, ":") var strip string var strport string strip, strport = tmparr[0], tmparr[1] ip := net.ParseIP(strip) port, _ := strconv.Atoi(strport) ret = append(ret, candidate{&net.UDPAddr{IP: ip, Port: port}}) } } arr := strings.Split(outIpList, ";") for _, ip := range arr { addip(ip, 0) } /* for _, info := range ret { log.Println("init ip:", info.Addr.String()) }*/ return ret, nil }
func TestRawSendUdp_CRC(t *testing.T) { m := GetMemberlist(t) m.config.EnableCompression = false defer m.Shutdown() var udp *net.UDPConn for port := 60000; port < 61000; port++ { udpAddr := fmt.Sprintf("127.0.0.1:%d", port) udpLn, err := net.ListenPacket("udp", udpAddr) if err == nil { udp = udpLn.(*net.UDPConn) break } } if udp == nil { t.Fatalf("no udp listener") } // Pass a nil node with no nodes registered, should result in no checksum payload := []byte{3, 3, 3, 3} m.rawSendMsgUDP(udp.LocalAddr(), nil, payload) in := make([]byte, 1500) n, _, err := udp.ReadFrom(in) if err != nil { t.Fatalf("unexpected err %s", err) } in = in[0:n] if len(in) != 4 { t.Fatalf("bad: %v", in) } // Pass a non-nil node with PMax >= 5, should result in a checksum m.rawSendMsgUDP(udp.LocalAddr(), &Node{PMax: 5}, payload) in = make([]byte, 1500) n, _, err = udp.ReadFrom(in) if err != nil { t.Fatalf("unexpected err %s", err) } in = in[0:n] if len(in) != 9 { t.Fatalf("bad: %v", in) } // Register a node with PMax >= 5 to be looked up, should result in a checksum m.nodeMap["127.0.0.1"] = &nodeState{ Node: Node{PMax: 5}, } m.rawSendMsgUDP(udp.LocalAddr(), nil, payload) in = make([]byte, 1500) n, _, err = udp.ReadFrom(in) if err != nil { t.Fatalf("unexpected err %s", err) } in = in[0:n] if len(in) != 9 { t.Fatalf("bad: %v", in) } }
func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) { errc := make(chan error, 2) var clientAddr *net.UDPAddr go func() { b := make([]byte, LargeBufferSize) for { n, laddr, err := relay.ReadFromUDP(b) if err != nil { errc <- err return } if clientAddr == nil { clientAddr = laddr } dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) if err != nil { errc <- err return } raddr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) if err != nil { continue // drop silently } if _, err := peer.WriteToUDP(dgram.Data, raddr); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[socks5-udp] %s >>> %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data)) } }() go func() { b := make([]byte, LargeBufferSize) for { n, raddr, err := peer.ReadFromUDP(b) if err != nil { errc <- err return } if clientAddr == nil { continue } buf := bytes.Buffer{} dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, ToSocksAddr(raddr)), b[:n]) dgram.Write(&buf) if _, err := relay.WriteToUDP(buf.Bytes(), clientAddr); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[socks5-udp] %s <<< %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data)) } }() select { case err = <-errc: //log.Println("w exit", err) } return }
func close(c *net.UDPConn) { log.Printf("closing: %s -> %s", c.LocalAddr().String(), c.RemoteAddr().String()) c.Close() }
func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err error) { errc := make(chan error, 2) var clientAddr *net.UDPAddr go func() { b := make([]byte, LargeBufferSize) for { n, addr, err := uc.ReadFromUDP(b) if err != nil { errc <- err return } var dgram *gosocks5.UDPDatagram if client { // pipe from relay to tunnel dgram, err = gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) if err != nil { errc <- err return } if clientAddr == nil { clientAddr = addr } dgram.Header.Rsv = uint16(len(dgram.Data)) if err := dgram.Write(cc); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) } else { // pipe from peer to tunnel dgram = gosocks5.NewUDPDatagram( gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n]) if err := dgram.Write(cc); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", cc.RemoteAddr(), dgram.Header.Addr, len(dgram.Data)) } } }() go func() { for { dgram, err := gosocks5.ReadUDPDatagram(cc) if err != nil { errc <- err return } if client { // pipe from tunnel to relay if clientAddr == nil { continue } dgram.Header.Rsv = 0 buf := bytes.Buffer{} dgram.Write(&buf) if _, err := uc.WriteToUDP(buf.Bytes(), clientAddr); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) } else { // pipe from tunnel to peer addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) if err != nil { continue // drop silently } if _, err := uc.WriteToUDP(dgram.Data, addr); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data)) } } }() select { case err = <-errc: } return }
// NetIO shares GitChanges on toNet with the network via a multicast group. It // will pass on GitChanges from the network via fromNet. It uniques the daemon // instance by changing the .Name member to be name@<host IP>/<original .Name) func NetIO(l log.Logger, repo Repo, addr *net.UDPAddr, fromNet, toNet chan GitChange) { var ( err error recvConn, sendConn *net.UDPConn // UDP connections to allow us to send and receive change updates ) l.Info("Joining %v multicast(%t) group", addr, addr.IP.IsMulticast()) if recvConn, sendConn, err = establishConnPair(addr); err != nil { l.Critical("Error joining listening: %s\n", addr, err) return } l.Info("Successfully joined %v multicast(%t) group", addr, addr.IP.IsMulticast()) defer recvConn.Close() defer sendConn.Close() hostIp := sendConn.LocalAddr().(*net.UDPAddr).IP.String() term := false defer func() { term = true }() rawFromNet := make(chan []byte, 128) go func() { for !term { b := make([]byte, 1024) if n, err := recvConn.Read(b); err != nil { l.Critical("Cannot read socket: %s", err) continue } else { rawFromNet <- b[:n] } } }() for { select { case req, ok := <-toNet: if !ok { return } req.User = repo.User() req.HostIp = hostIp l.Info("Sending %+v", req) buf := &bytes.Buffer{} enc := gob.NewEncoder(buf) if err := enc.Encode(req); err != nil { l.Critical("%s", err) continue } l.Fine("Sending %+v", buf.Bytes()) if _, err := sendConn.Write(buf.Bytes()); err != nil { l.Critical("%s", err) continue } case resp := <-rawFromNet: var change GitChange dec := gob.NewDecoder(bytes.NewReader(resp)) if err := dec.Decode(&change); err != nil { l.Critical("%s", err) continue } else { l.Debug("received %+v", change) } if rootCommit, err := repo.RootCommit(); err != nil { log.Critical("Error getting root commit") } else { if (repo.User() != change.User) && (rootCommit == change.RootCommit) { fromNet <- change } } } } }
// Sends the data in sendbuf to peer_addr (with possible resends) and waits for // an ACK with the correct block id, if sendbuf contains a DATA message. // Returns true if the sending was successful and the ACK was received. func sendAndWaitForAck(udp_conn *net.UDPConn, peer_addr *net.UDPAddr, sendbuf []byte, retransmissions, dups, strays *int) bool { // absolute deadline when this function will return false deadline := time.Now().Add(total_timeout) readbuf := make([]byte, 4096) *retransmissions-- // to counter the ++ being done at the start of the loop outer: for { // re/send *retransmissions++ n, err := udp_conn.Write(sendbuf) if err != nil { util.Log(0, "ERROR! TFTP error in Write(): %v", err) break } if n != len(sendbuf) { util.Log(0, "ERROR! TFTP: Incomplete write") break } //util.Log(2, "DEBUG! TFTP: Sent %v bytes to %v. Waiting for ACK...", len(sendbuf), peer_addr) for { // check absolute deadline if time.Now().After(deadline) { break outer } // set deadline for next read timo := time.Duration(rand.Int63n(int64(max_wait_retry-min_wait_retry))) + min_wait_retry endtime2 := time.Now().Add(timo) if endtime2.After(deadline) { endtime2 = deadline } udp_conn.SetReadDeadline(endtime2) n, from, err := udp_conn.ReadFromUDP(readbuf) if err != nil { e, ok := err.(*net.OpError) if !ok || !e.Timeout() { util.Log(0, "ERROR! TFTP ReadFromUDP() failed while waiting for ACK from %v (local address: %v): %v", udp_conn.RemoteAddr(), udp_conn.LocalAddr(), err) break outer // retries make no sense => bail out } else { //util.Log(2, "DEBUG! TFTP timeout => resend %#v", sendbuf) continue outer // resend } } if from.Port != peer_addr.Port { *strays++ emsg := fmt.Sprintf("WARNING! TFTP server got UDP packet from incorrect source: %v instead of %v", from.Port, peer_addr.Port) sendError(udp_conn, from, 5, emsg) // 5 => Unknown transfer ID continue // This error is not fatal since it doesn't affect our peer } if n == 4 && readbuf[0] == 0 && readbuf[1] == 4 && // 4 => ACK (sendbuf[1] != 3 || // we did not send DATA // or the ACK's block id is the same as the one we sent (readbuf[2] == sendbuf[2] && readbuf[3] == sendbuf[3])) { //util.Log(2, "DEBUG! TFTP: Received ACK from %v: %#v", peer_addr, readbuf[0:n]) return true } else { if readbuf[0] == 0 && readbuf[1] == 5 { // error util.Log(0, "ERROR! TFTP ERROR received while waiting for ACK from %v: %v", peer_addr, string(readbuf[4:n])) break outer // retries make no sense => bail out } else { // if we sent DATA but the ACK is not for the block we sent, // increase dup counter. If we wanted to be anal we would need to check // if the block id is one less for it to be an actual dup, but // since the dup counter is only for reporting, we don't care. if sendbuf[1] == 3 && (readbuf[2] != sendbuf[2] || readbuf[3] != sendbuf[3]) { *dups++ //util.Log(2, "DEBUG! TFTP duplicate ACK received: %#v => Ignored", string(readbuf[0:n])) // ONLY "continue", NOT "continue outer", i.e. DUPs DO NOT CAUSE A RESEND. // THIS PREVENTS http://en.wikipedia.org/wiki/Sorcerer's_Apprentice_Syndrome // When timeout happens, it will cause a resend. continue } else { emsg := fmt.Sprintf("ERROR! TFTP server waiting for ACK from %v but got: %#v", peer_addr, string(readbuf[0:n])) sendError(udp_conn, from, 0, emsg) // 0 => Unspecified error break outer // retries make no sense => bail out } } } } } util.Log(0, "ERROR! TFTP send not acknowledged by %v (retransmissions: %v, dups: %v, strays: %v)", peer_addr, *retransmissions, *dups, *strays) return false }