func (srv *Service) negotiateNewMuxConn(conn net.Conn) { // Deadline of 10s on mux negotiation. if err := conn.SetDeadline(time.Now().Add(10 * time.Second)); err != nil { srv.log.Printf("Could not set deadline on incoming mux connection - ignoring: %v", err) } srv.log.Printf("Got mux client %v, negotiating version", conn.RemoteAddr()) // Protocol version. if err := muxcommon.ReadCheckVersion(conn); err != nil { conn.Close() srv.log.Printf("Error checking mux client version: %v", err) return } if err := muxcommon.SendVersion(conn); err != nil { conn.Close() srv.log.Printf("Error sending version: %v", err) return } // TODO: Authenticate connection before handing to muxMatcher. srv.log.Print("Setting up compression") // Set up compression on the data flowing from mux client to mux server. compConnRead, err := zlib.NewReader(conn) if err != nil { conn.Close() srv.log.Printf("Failed to initiate reading of compressed data on incoming mux connection: %v", err) return } // Negotiation complete. conn.SetDeadline(time.Time{}) srv.log.Printf("New mux client connected from %v", conn.RemoteAddr()) srv.newMuxConn <- frames.NewClient(&netutil.ConnWrapper{ Reader: compConnRead, Writer: conn, UnderlyingConn: conn, ReadCloser: compConnRead, }) }
func (srv *Service) SetConfig(cfg *services.MuxClientConfig) error { srv.lock.Lock() defer srv.lock.Unlock() if cfg.MuxAddr != srv.cfg.MuxAddr { var l net.Listener var err error if cfg.MuxAddr != "" { var conn net.Conn if conn, err = net.Dial("tcp", cfg.MuxAddr); err != nil { return err } srv.log.Printf("Connected to mux server %v, negotiating version", conn.RemoteAddr()) // Protocol version. muxcommon.SendVersion(conn) if err = muxcommon.ReadCheckVersion(conn); err != nil { conn.Close() return err } // TODO: Authenticate connection. srv.log.Printf("Setting up compression") // Set up compression on the data flowing from the mux client to the mux // server. Apply a FlushingWriter as well to flush data periodically. w, err := zlib.NewWriterLevel(conn, zlib.BestSpeed) if err != nil { conn.Close() return err } // Flush the writer to send headers so that the server knows that the // compressed connection is good. w.Flush() // TODO: Should the interval be configurable? compConnWrite := muxcommon.NewFlushingWriter(w, 50*time.Millisecond) wrappedConn := &netutil.ConnWrapper{ Reader: conn, Writer: compConnWrite, UnderlyingConn: conn, WriteCloser: compConnWrite, } log.Printf("Waiting for incoming muxed connections") if l, err = frames.Listen(wrappedConn); err != nil { conn.Close() return err } } if srv.listener != nil { srv.listener.Close() } srv.listener = l if srv.listener != nil { go srv.handleListener(srv.manager, srv.listener, cfg.ArtemisServerAddr) } } srv.cfg = *cfg return nil }