// readMsgFromSocket will pull basestation (and extended basestation) // formatted messages from the socket, and send them down the channel. // It will retry the connection on failure. func readMsgFromSocket(wg *sync.WaitGroup, hostport string, msgChan chan<- *adsb.Msg) { nTimeMismatches := 0 lastBackoff := time.Second wg.Add(1) outerLoop: for { if weAreDone() { break } // outer conn, err := net.Dial("tcp", hostport) if err != nil { Log.Printf("connect '%s': err %s; trying again in %s ...", hostport, err, lastBackoff*2) time.Sleep(lastBackoff) if lastBackoff < time.Minute*5 { lastBackoff *= 2 } continue } lastBackoff = time.Second Log.Printf("connected to '%s'", hostport) // a net.Conn implements io.Reader scanner := bufio.NewScanner(conn) for scanner.Scan() { // This can block indefinitely ... if weAreDone() { break outerLoop } if err := scanner.Err(); err != nil { Log.Printf("killing connection, scanner err: %v\n", err) conn.Close() break // inner } msg := adsb.Msg{} text := scanner.Text() if err := msg.FromSBS1(text); err != nil { Log.Printf("killing connection, SBS input:%q, parse fail: %v", text, err) break // inner } // If there is significant clock skew, we should bail. But, it seems // that sometimes we pick up stale data from dump1090; so wait to see // if it passes. offset := time.Since(msg.GeneratedTimestampUTC) if offset > time.Minute*30 || offset < time.Minute*-30 { nTimeMismatches++ if nTimeMismatches < 100 { continue // do not process this message } else { Log.Fatalf("100 bad msgs; set -timeloc ?\nNow = %s\nmsg = %s\n", time.Now(), msg.GeneratedTimestampUTC) } } // If the message is flagged as one we should mask, honor that if msg.IsMasked() { continue } msgChan <- &msg } } wg.Done() Log.Printf(" ---- readMsgFromSocket, clean shutdown\n") }