func test1(conn net.PacketConn, addr net.Addr, softwareName string) (*packet, net.Addr, bool, *Host, error) { packet, err := sendBindingReq(conn, addr, softwareName) if err != nil { return nil, nil, false, nil, err } if packet == nil { return nil, nil, false, nil, nil } // RFC 3489 doesn't require the server return XOR mapped address. hostMappedAddr := packet.xorMappedAddr() if hostMappedAddr == nil { hostMappedAddr = packet.mappedAddr() if hostMappedAddr == nil { return nil, nil, false, nil, errors.New("No mapped address.") } } identical := isLocalAddress(conn.LocalAddr().String(), hostMappedAddr.TransportAddr()) hostChangedAddr := packet.changedAddr() if hostChangedAddr == nil { return packet, nil, identical, hostMappedAddr, nil } changedAddrStr := hostChangedAddr.TransportAddr() changedAddr, err := net.ResolveUDPAddr("udp", changedAddrStr) if err != nil { return nil, nil, false, nil, errors.New("Failed to resolve changed address.") } return packet, changedAddr, identical, hostMappedAddr, nil }
func newConnection(c net.PacketConn, addr net.Addr, tq *timerQueue, tag []byte, closed func()) *connection { conn := &connection{ Cond: sync.Cond{L: new(sync.Mutex)}, addr: addr, localAddr: c.LocalAddr(), closeWait: make(chan struct{}), } var tag3 [3]byte copy(tag3[:], tag) go conn.proc(c, tq, tag3, closed) return conn }
// Serve accepts incoming TFTP read requests on the listener l, // creating a new service goroutine for each. The service goroutines // use handler to get a byte stream and send it to the client. func Serve(l net.PacketConn, handler Handler) { Log("Listening on %s", l.LocalAddr()) buf := make([]byte, 512) for { n, addr, err := l.ReadFrom(buf) if err != nil { Log("Reading from socket: %s", err) continue } req, err := parseRRQ(addr, buf[:n]) if err != nil { Debug("parseRRQ: %s", err) l.WriteTo(mkError(err), addr) continue } go transfer(addr, req, handler) } }
func (self *UdpServer) start() error { var conn net.PacketConn var e error if nil == self.listenAddr { conn, e = net.ListenPacket("udp", self.origin) } else { conn, e = net.ListenPacket("udp", self.listenAddr.String()) } if nil != e { return e } self.conn = conn self.listenAddr = conn.LocalAddr() self.waitGroup.Add(1) go self.serve() return nil }
func (svr *snmpTestServer) Start() { var in net.PacketConn var e error if nil == svr.listenAddr { in, e = net.ListenPacket("udp", svr.origin) svr.t.Log("[test_server]", "listen at", in.LocalAddr()) } else { in, e = net.ListenPacket("udp", svr.listenAddr.String()) svr.t.Log("[test_server]", "listen at", svr.listenAddr.String()) } if nil != e { panic(e.Error()) } svr.isFirstListen = false svr.waitGroup.Add(1) svr.conn = in svr.listenAddr = in.LocalAddr() go serveTestUdp2(svr) }
// Listen announces on existing packet-based connection func ListenConn(conn net.PacketConn) (net.Listener, error) { l := &listener{ Cond: sync.Cond{ L: new(sync.Mutex), }, addr: conn.LocalAddr(), } rld := &receiveLoopData{ Cond: sync.Cond{ L: new(sync.Mutex), }, buffers: [][]byte{ make([]byte, 65536), make([]byte, 65536), make([]byte, 65536), }, } pld := &processLoopData{ Cond: sync.Cond{ L: new(sync.Mutex), }, } l.stopListening = func() { pld.L.Lock() pld.rejectNewConnections = true pld.L.Unlock() pld.Signal() } go receiveLoop(conn, l, rld, pld) go processLoop(conn, l, rld, pld) return l, nil }
logMessages []*events.LogMessage udpConn net.PacketConn ) var _ = Describe("LogIntegration", func() { Context("with standard initialization", func() { origin := []string{"test-origin"} BeforeEach(func() { var err error logMessages = nil udpConn, err = net.ListenPacket("udp4", ":0") Expect(err).ToNot(HaveOccurred()) go listenForLogs() udpAddr := udpConn.LocalAddr().(*net.UDPAddr) dropsonde.Initialize(fmt.Sprintf("localhost:%d", udpAddr.Port), origin...) sender := metric_sender.NewMetricSender(dropsonde.AutowiredEmitter()) batcher := metricbatcher.New(sender, 100*time.Millisecond) metrics.Initialize(sender, batcher) }) AfterEach(func() { udpConn.Close() }) It("sends dropped error message for messages which are just under 64k and don't fit in UDP packet", func() { logSender := log_sender.NewLogSender(dropsonde.AutowiredEmitter(), time.Second, loggertesthelper.Logger()) const length = 64*1024 - 1 reader := strings.NewReader(strings.Repeat("s", length) + "\n")
}) }) Describe("Emit()", func() { var udpEmitter emitter.ByteEmitter Context("when the agent is listening", func() { var agentListener net.PacketConn BeforeEach(func() { var err error agentListener, err = net.ListenPacket("udp4", "") Expect(err).ToNot(HaveOccurred()) udpEmitter, err = emitter.NewUdpEmitter(agentListener.LocalAddr().String()) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { agentListener.Close() }) It("should send the data", func(done Done) { err := udpEmitter.Emit(testData) Expect(err).ToNot(HaveOccurred()) buffer := make([]byte, 4096) readCount, _, err := agentListener.ReadFrom(buffer) Expect(err).ToNot(HaveOccurred()) Expect(buffer[:readCount]).To(Equal(testData))
for { buffer := make([]byte, 1024) n, _, err := testMetricsListener.ReadFrom(buffer) if err != nil { close(testMetricsChan) return } var envelope events.Envelope err = proto.Unmarshal(buffer[:n], &envelope) Expect(err).NotTo(HaveOccurred()) testMetricsChan <- &envelope } }() port, err := strconv.Atoi(strings.TrimPrefix(testMetricsListener.LocalAddr().String(), "127.0.0.1:")) Expect(err).NotTo(HaveOccurred()) client = bbs.NewClient(bbsURL.String()) bbsArgs = testrunner.Args{ Address: bbsAddress, AdvertiseURL: bbsURL.String(), AuctioneerAddress: auctioneerServer.URL(), ConsulCluster: consulRunner.ConsulCluster(), DropsondePort: port, EtcdCluster: etcdUrl, // etcd is still being used to test version migration in migration_version_test.go DatabaseDriver: sqlRunner.DriverName(), DatabaseConnectionString: sqlRunner.ConnectionString(), MetricsReportInterval: 10 * time.Millisecond, HealthAddress: bbsHealthAddress,
// receives packets from the receive loop and dispatches them // to their corresponding connections func processLoop(c net.PacketConn, l *listener, rld *receiveLoopData, pld *processLoopData) { var ( quit bool wg = new(sync.WaitGroup) tq = newTimerQueue() connections = struct { sync.RWMutex M map[uint32]*connection }{ M: make(map[uint32]*connection), } ) // keep a refcount to `c` for ourselves wg.Add(1) defer wg.Done() // wait for all pending connections, then close the socket go func() { wg.Wait() c.Close() tq.Close() }() // generate a new key for cookies cookieKey := make([]byte, sha1.Size) if _, err := crand.Read(cookieKey); err != nil { l.L.Lock() l.err = fmt.Errorf("Failed to generate cookie secret: %v", err) l.L.Unlock() l.Broadcast() return } sig := hmac.New(sha1.New, cookieKey) // generate addler32(localaddr) var localAddrSum [4]byte binary.LittleEndian.PutUint32(localAddrSum[:], adler32.Checksum([]byte(c.LocalAddr().String()))) shouldWait := func() bool { waitOnConnections := pld.rejectNewConnections && pld.remainingConnections == 0 return pld.err == nil && len(pld.Q) == 0 && !waitOnConnections } var packets []processLoopPacket for !quit { // wait for a packet to become available pld.L.Lock() for shouldWait() { pld.Wait() } rejectNewConnections := pld.rejectNewConnections pldErr := pld.err quit = pldErr != nil packets, pld.Q = pld.Q, packets[:0] remainingConnections := pld.remainingConnections pld.L.Unlock() if rejectNewConnections && remainingConnections == 0 { quit = true } // process packets for ii := range packets { buffer, addr := packets[ii].D, packets[ii].A switch PacketType(buffer[0]) { case PacketInit: // are we accepting new connections? if rejectNewConnections { continue } // verify length const MinInitPacketLength = 9 if len(buffer) < MinInitPacketLength { continue } // verify protocol magic if !bytes.Equal(buffer[1:5], protocolMagic) { continue } // verify version if buffer[5] != version1 { sendAbort(c, addr, buffer[6:9]) continue } var outgoing [32]byte now := time.Now() outgoing[0] = byte(PacketCookie) if _, err := crand.Read(outgoing[1:4]); err != nil { return } copy(outgoing[4:7], buffer[6:9]) outgoing[7] = version1 binary.LittleEndian.PutUint32(outgoing[8:12], uint32(now.Add(5*time.Second).Unix()+1)) sig.Reset() sig.Write(outgoing[1:12]) sig.Write(localAddrSum[:]) sig.Sum(outgoing[1:12]) c.WriteTo(outgoing[:], addr) case PacketCookieEcho: // are we accepting new connections if rejectNewConnections { continue } // verify length const CookieEchoPacketLength = 32 if len(buffer) != CookieEchoPacketLength { continue } // verify signature sig.Reset() sig.Write(buffer[1:12]) sig.Write(localAddrSum[:]) if !hmac.Equal(sig.Sum(nil), buffer[12:]) { continue } // verify version if buffer[7] != version1 { sendAbort(c, addr, buffer[1:4]) continue } // vetify timeout now := time.Now() if time.Unix(int64(binary.LittleEndian.Uint32(buffer[8:12])), 0).Before(now) { sendAbort(c, addr, buffer[1:4]) continue } // decode connection tag to uin32 tagId := binary.LittleEndian.Uint32(buffer[3:7]) >> 8 connections.RLock() _, ok := connections.M[tagId] connections.RUnlock() // create new connection if !ok { // create connection wg.Add(1) connections.Lock() conn := newConnection(c, addr, tq, buffer[1:4], func() { connections.Lock() delete(connections.M, tagId) connections.Unlock() wg.Done() pld.L.Lock() pld.remainingConnections-- remain := pld.remainingConnections pld.L.Unlock() if remain == 0 { pld.Signal() } }) connections.M[tagId] = conn connections.Unlock() pld.L.Lock() pld.remainingConnections++ pld.L.Unlock() l.L.Lock() l.pending = append(l.pending, conn) l.L.Unlock() l.Signal() } // send COOKIE-ACK var outgoing [4]byte outgoing[0] = byte(PacketCookieAck) copy(outgoing[1:4], buffer[1:4]) c.WriteTo(outgoing[:], addr) default: // parse connection tag tagId := binary.LittleEndian.Uint32(buffer[0:4]) >> 8 connections.RLock() conn, ok := connections.M[tagId] connections.RUnlock() // discard packets addressed to unknown connections if !ok { sendAbort(c, addr, buffer[1:4]) continue } // copy the packet data so we can reuse the buffer p := NewPacket(len(buffer)) copy(p.D, buffer) // queue the packet onto the connection conn.L.Lock() conn.Incoming = append(conn.Incoming, p) conn.L.Unlock() conn.Signal() } } // return the packet to the receive loop rld.L.Lock() for ii := range packets { rld.buffers = append(rld.buffers, packets[ii].D) } rld.L.Unlock() rld.Signal() // if we were signaled to quit, terminate existing connections if pldErr != nil { connections.Lock() m := connections.M connections.M = make(map[uint32]*connection) connections.Unlock() for _, c := range m { c.closeWithError(pldErr) } } } }