github.com/sujit-baniya/log@v1.0.73/gelf/tcpreader.go (about) 1 package gelf 2 3 import ( 4 "bufio" 5 "encoding/json" 6 "fmt" 7 "net" 8 "time" 9 ) 10 11 type TCPReader struct { 12 listener *net.TCPListener 13 conn net.Conn 14 messages chan []byte 15 } 16 17 type connChannels struct { 18 drop chan string 19 confirm chan string 20 } 21 22 func newTCPReader(addr string) (*TCPReader, chan string, chan string, error) { 23 var err error 24 tcpAddr, err := net.ResolveTCPAddr("tcp", addr) 25 if err != nil { 26 return nil, nil, nil, fmt.Errorf("ResolveTCPAddr('%s'): %s", addr, err) 27 } 28 29 listener, err := net.ListenTCP("tcp", tcpAddr) 30 if err != nil { 31 return nil, nil, nil, fmt.Errorf("ListenTCP: %s", err) 32 } 33 34 r := &TCPReader{ 35 listener: listener, 36 messages: make(chan []byte, 100), // Make a buffered channel with at most 100 messages 37 } 38 39 closeSignal := make(chan string, 1) 40 doneSignal := make(chan string, 1) 41 42 go r.listenUntilCloseSignal(closeSignal, doneSignal) 43 44 return r, closeSignal, doneSignal, nil 45 } 46 47 func (r *TCPReader) accepter(connections chan net.Conn) { 48 for { 49 conn, err := r.listener.Accept() 50 if err != nil { 51 break 52 } 53 connections <- conn 54 } 55 } 56 57 func (r *TCPReader) listenUntilCloseSignal(closeSignal chan string, doneSignal chan string) { 58 defer func() { doneSignal <- "done" }() 59 defer r.listener.Close() 60 var conns []connChannels 61 connectionsChannel := make(chan net.Conn, 1) 62 go r.accepter(connectionsChannel) 63 for { 64 select { 65 case conn := <-connectionsChannel: 66 dropSignal := make(chan string, 1) 67 dropConfirm := make(chan string, 1) 68 channels := connChannels{drop: dropSignal, confirm: dropConfirm} 69 go handleConnection(conn, r.messages, dropSignal, dropConfirm) 70 conns = append(conns, channels) 71 default: 72 } 73 74 select { 75 case sig := <-closeSignal: 76 if sig == "stop" || sig == "drop" { 77 if len(conns) >= 1 { 78 for _, s := range conns { 79 if s.drop != nil { 80 s.drop <- "drop" 81 <-s.confirm 82 conns = append(conns[:0], conns[1:]...) 83 } 84 } 85 if sig == "stop" { 86 return 87 } 88 } else if sig == "stop" { 89 closeSignal <- "stop" 90 } 91 if sig == "drop" { 92 doneSignal <- "done" 93 } 94 } 95 default: 96 } 97 } 98 } 99 100 func (r *TCPReader) addr() string { 101 return r.listener.Addr().String() 102 } 103 104 func handleConnection(conn net.Conn, messages chan<- []byte, dropSignal chan string, dropConfirm chan string) { 105 defer func() { dropConfirm <- "done" }() 106 defer conn.Close() 107 reader := bufio.NewReader(conn) 108 109 var b []byte 110 var err error 111 drop := false 112 canDrop := false 113 114 for { 115 conn.SetDeadline(time.Now().Add(2 * time.Second)) 116 if b, err = reader.ReadBytes(0); err != nil { 117 if drop { 118 return 119 } 120 } else if len(b) > 0 { 121 messages <- b 122 canDrop = true 123 if drop { 124 return 125 } 126 } else if drop { 127 return 128 } 129 select { 130 case sig := <-dropSignal: 131 if sig == "drop" { 132 drop = true 133 time.Sleep(1 * time.Second) 134 if canDrop { 135 return 136 } 137 } 138 default: 139 } 140 } 141 } 142 143 func (r *TCPReader) readMessage() (*Message, error) { 144 b := <-r.messages 145 146 var msg Message 147 if err := json.Unmarshal(b[:len(b)-1], &msg); err != nil { 148 return nil, fmt.Errorf("json.Unmarshal: %s", err) 149 } 150 151 return &msg, nil 152 } 153 154 func (r *TCPReader) Close() { 155 r.listener.Close() 156 }