func (r *reader) readEvents(in io.Reader, events []interface{}) ([]interface{}, error) { for len(events) < cap(events) { var hdr [2]byte if err := readFull(in, hdr[:]); err != nil { return nil, err } if hdr[0] != protocol.CodeVersion { log.Println("Event protocol version error") return nil, ErrProtocolError } switch hdr[1] { case protocol.CodeDataFrame: event, err := r.readEvent(in) if err != nil { log.Printf("failed to read json event with: %v\n", err) return nil, err } events = append(events, event) case protocol.CodeCompressed: readEvents, err := r.readCompressed(in, events) if err != nil { return nil, err } events = readEvents default: log.Printf("Unknown frame type: %v", hdr[1]) return nil, ErrProtocolError } } return events, nil }
func (h *defaultHandler) handle() error { log.Printf("Start client handler") defer log.Printf("client handler stopped") defer h.Stop() for { // 1. read data into batch b, err := h.reader.ReadBatch() if err != nil { return err } // read next batch if empty batch has been received if b == nil { continue } // 2. push batch to ACK queue select { case <-h.signal: return nil case h.ch <- b: } // 3. push batch to server receive queue: if err := h.cb.OnEvents(b); err != nil { return nil } } }
func (r *reader) ReadBatch() (*lj.Batch, error) { // 1. read window size var win [6]byte _ = r.conn.SetReadDeadline(time.Time{}) // wait for next batch without timeout if err := readFull(r.in, win[:]); err != nil { return nil, err } if win[0] != protocol.CodeVersion && win[1] != protocol.CodeWindowSize { log.Printf("Expected window from. Received %v", win[0:1]) return nil, ErrProtocolError } count := int(binary.BigEndian.Uint32(win[2:])) if count == 0 { return nil, nil } if err := r.conn.SetReadDeadline(time.Now().Add(r.timeout)); err != nil { return nil, err } events, err := r.readEvents(r.in, make([]interface{}, 0, count)) if events == nil || err != nil { log.Printf("readEvents failed with: %v", err) return nil, err } return lj.NewBatch(events), nil }
func (s *Server) startConnHandler(client net.Conn) { var wgStart sync.WaitGroup h, err := s.opts.Handler(newChanCallback(s.sig.Sig(), s.ch), client) if err != nil { log.Printf("Failed to initialize client handler: %v", h) return } s.sig.Add(1) wgStart.Add(1) stopped := make(chan struct{}, 1) go func() { defer s.sig.Done() defer close(stopped) // signal handler loop stopped wgStart.Done() h.Run() }() wgStart.Wait() go func() { select { case <-s.sig.Sig(): // server shutdown h.Stop() case <-stopped: // handler loop stopped } }() }
func (r *reader) readCompressed(in io.Reader, events []interface{}) ([]interface{}, error) { var hdr [4]byte if err := readFull(in, hdr[:]); err != nil { return nil, err } payloadSz := binary.BigEndian.Uint32(hdr[:]) limit := io.LimitReader(in, int64(payloadSz)) reader, err := zlib.NewReader(limit) if err != nil { log.Printf("Failed to initialized zlib reader %v\n", err) return nil, err } events, err = r.readEvents(reader, events) if err != nil { _ = reader.Close() return nil, err } if err := reader.Close(); err != nil { return nil, err } // consume final bytes from limit reader for { var tmp [16]byte if _, err := limit.Read(tmp[:]); err != nil { if err != io.EOF { return nil, err } break } } return events, nil }
func (s *Server) run() { defer s.sig.Done() for { client, err := s.listener.Accept() if err != nil { break } log.Printf("New connection from %v", client.RemoteAddr()) s.startConnHandler(client) } }
func newServer(l net.Listener, opts ...Option) (Server, error) { cfg, err := applyOptions(opts) if err != nil { return nil, err } var servers []func(net.Listener) (Server, byte, error) log.Printf("Server config: %#v", cfg) if cfg.v1 { servers = append(servers, func(l net.Listener) (Server, byte, error) { s, err := v1.NewWithListener(l, v1.Timeout(cfg.timeout), v1.Channel(cfg.ch), v1.TLS(cfg.tls)) return s, '1', err }) } if cfg.v2 { servers = append(servers, func(l net.Listener) (Server, byte, error) { s, err := v2.NewWithListener(l, v2.Keepalive(cfg.keepalive), v2.Timeout(cfg.timeout), v2.Channel(cfg.ch), v2.TLS(cfg.tls), v2.JSONDecoder(cfg.decoder)) return s, '2', err }) } if len(servers) == 0 { return nil, ErrNoVersionEnabled } if len(servers) == 1 { s, _, err := servers[0](l) return s, err } ownCH := false if cfg.ch == nil { ownCH = true cfg.ch = make(chan *lj.Batch, 128) } mux := make([]muxServer, len(servers)) for i, mk := range servers { muxL := newMuxListener(l) log.Printf("mk: %v", i) s, b, err := mk(muxL) if err != nil { return nil, err } mux[i] = muxServer{ mux: b, l: muxL, server: s, } } s := &server{ ch: cfg.ch, ownCH: ownCH, netListener: l, mux: mux, done: make(chan struct{}), } s.wg.Add(1) go s.run() return s, nil }