func (rcv *TCP) handleConnection(conn net.Conn) { atomic.AddInt32(&rcv.active, 1) defer atomic.AddInt32(&rcv.active, -1) defer conn.Close() reader := bufio.NewReader(conn) for { conn.SetReadDeadline(time.Now().Add(2 * time.Minute)) line, err := reader.ReadBytes('\n') if err != nil { if err == io.EOF { if len(line) > 0 { logrus.Warningf("[tcp] Unfinished line: %#v", line) } } else { atomic.AddUint32(&rcv.errors, 1) logrus.Error(err) } break } if len(line) > 0 { // skip empty lines if msg, err := points.ParseText(string(line)); err != nil { atomic.AddUint32(&rcv.errors, 1) logrus.Info(err) } else { atomic.AddUint32(&rcv.metricsReceived, 1) rcv.out <- msg } } } }
// Listen bind port. Receive messages and send to out channel func (rcv *UDP) Listen(addr *net.UDPAddr) error { var err error rcv.conn, err = net.ListenUDP("udp", addr) if err != nil { return err } go func() { ticker := time.NewTicker(rcv.metricInterval) defer ticker.Stop() for { select { case <-ticker.C: metricsReceived := atomic.LoadUint32(&rcv.metricsReceived) atomic.AddUint32(&rcv.metricsReceived, -metricsReceived) rcv.Stat("udp.metricsReceived", float64(metricsReceived)) incompleteReceived := atomic.LoadUint32(&rcv.incompleteReceived) atomic.AddUint32(&rcv.incompleteReceived, -incompleteReceived) rcv.Stat("udp.incompleteReceived", float64(incompleteReceived)) errors := atomic.LoadUint32(&rcv.errors) atomic.AddUint32(&rcv.errors, -errors) rcv.Stat("udp.errors", float64(errors)) logrus.WithFields(logrus.Fields{ "metricsReceived": int(metricsReceived), "incompleteReceived": int(incompleteReceived), "errors": int(errors), }).Info("[udp] doCheckpoint()") case <-rcv.exit: rcv.conn.Close() return } } }() go func() { defer rcv.conn.Close() var buf [2048]byte var data *bytes.Buffer lines := newIncompleteStorage() for { rlen, peer, err := rcv.conn.ReadFromUDP(buf[:]) if err != nil { if strings.Contains(err.Error(), "use of closed network connection") { break } atomic.AddUint32(&rcv.errors, 1) logrus.Error(err) continue } prev := lines.pop(peer.String()) if prev != nil { data = bytes.NewBuffer(prev) data.Write(buf[:rlen]) } else { data = bytes.NewBuffer(buf[:rlen]) } for { line, err := data.ReadBytes('\n') if err != nil { if err == io.EOF { if len(line) > 0 { // incomplete line received if rcv.logIncomplete { logIncomplete(peer, buf[:rlen], line) } lines.store(peer.String(), line) atomic.AddUint32(&rcv.incompleteReceived, 1) } } else { atomic.AddUint32(&rcv.errors, 1) logrus.Error(err) } break } if len(line) > 0 { // skip empty lines if msg, err := points.ParseText(string(line)); err != nil { atomic.AddUint32(&rcv.errors, 1) logrus.Info(err) } else { atomic.AddUint32(&rcv.metricsReceived, 1) rcv.out <- msg } } } } close(rcv.finished) }() return nil }
func (rcv *UDP) receiveWorker(exit chan bool) { defer rcv.conn.Close() var buf [65535]byte var data *bytes.Buffer lines := newIncompleteStorage() for { rlen, peer, err := rcv.conn.ReadFromUDP(buf[:]) if err != nil { if strings.Contains(err.Error(), "use of closed network connection") { break } atomic.AddUint32(&rcv.errors, 1) logrus.Error(err) continue } prev := lines.pop(peer.String()) if prev != nil { data = bytes.NewBuffer(prev) data.Write(buf[:rlen]) } else { data = bytes.NewBuffer(buf[:rlen]) } for { line, err := data.ReadBytes('\n') if err != nil { if err == io.EOF { if len(line) > 0 { // incomplete line received if rcv.logIncomplete { logIncomplete(peer, buf[:rlen], line) } lines.store(peer.String(), line) atomic.AddUint32(&rcv.incompleteReceived, 1) } } else { atomic.AddUint32(&rcv.errors, 1) logrus.Error(err) } break } if len(line) > 0 { // skip empty lines if msg, err := points.ParseText(string(line)); err != nil { atomic.AddUint32(&rcv.errors, 1) logrus.Info(err) } else { atomic.AddUint32(&rcv.metricsReceived, 1) rcv.out <- msg } } } } }