func (s *Server) createClient(conn net.Conn) *client { c := &client{srv: s, nc: conn, opts: defaultOpts, mpay: s.info.MaxPayload} // Grab JSON info string s.mu.Lock() info := s.infoJSON authRequired := s.info.AuthRequired tlsRequired := s.info.TLSRequired s.mu.Unlock() // Grab lock c.mu.Lock() // Initialize c.initClient(tlsRequired) c.Debugf("Client connection created") // Check for Auth if authRequired { ttl := secondsToDuration(s.opts.AuthTimeout) c.setAuthTimer(ttl) } // Send our information. s.sendInfo(c, info) // Unlock to register c.mu.Unlock() // Register with the server. s.mu.Lock() s.clients[c.cid] = c s.mu.Unlock() // Check for TLS if tlsRequired { // Re-Grab lock c.mu.Lock() c.Debugf("Starting TLS client connection handshake") c.nc = tls.Server(c.nc, s.opts.TLSConfig) conn := c.nc.(*tls.Conn) // Setup the timeout ttl := secondsToDuration(s.opts.TLSTimeout) time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) conn.SetReadDeadline(time.Now().Add(ttl)) // Force handshake c.mu.Unlock() if err := conn.Handshake(); err != nil { c.Debugf("TLS handshake error: %v", err) c.sendErr("Secure Connection - TLS Required") c.closeConnection() return nil } // Reset the read deadline conn.SetReadDeadline(time.Time{}) // Re-Grab lock c.mu.Lock() // Rewrap bw c.bw = bufio.NewWriterSize(c.nc, s.opts.BufSize) // Do final client initialization // Set the Ping timer c.setPingTimer() // Spin up the read loop. go c.readLoop() c.Debugf("TLS handshake complete") cs := conn.ConnectionState() c.Debugf("TLS version %s, cipher suite %s", tlsVersion(cs.Version), tlsCipher(cs.CipherSuite)) c.mu.Unlock() } return c }
func (s *Server) createClient(conn net.Conn) *client { c := &client{srv: s, nc: conn, opts: defaultOpts, mpay: s.info.MaxPayload, start: time.Now()} // Grab JSON info string s.mu.Lock() info := s.infoJSON authRequired := s.info.AuthRequired tlsRequired := s.info.TLSRequired s.totalClients++ s.mu.Unlock() // Grab lock c.mu.Lock() // Initialize c.initClient() c.Debugf("Client connection created") // Check for Auth if authRequired { c.setAuthTimer(secondsToDuration(s.opts.AuthTimeout)) } // Send our information. c.sendInfo(info) // Unlock to register c.mu.Unlock() // Register with the server. s.mu.Lock() // If server is not running, Shutdown() may have already gathered the // list of connections to close. It won't contain this one, so we need // to bail out now otherwise the readLoop started down there would not // be interrupted. if !s.running { s.mu.Unlock() return c } s.clients[c.cid] = c s.mu.Unlock() // Re-Grab lock c.mu.Lock() // Check for TLS if tlsRequired { c.Debugf("Starting TLS client connection handshake") c.nc = tls.Server(c.nc, s.opts.TLSConfig) conn := c.nc.(*tls.Conn) // Setup the timeout ttl := secondsToDuration(s.opts.TLSTimeout) time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) conn.SetReadDeadline(time.Now().Add(ttl)) // Force handshake c.mu.Unlock() if err := conn.Handshake(); err != nil { c.Debugf("TLS handshake error: %v", err) c.sendErr("Secure Connection - TLS Required") c.closeConnection() return nil } // Reset the read deadline conn.SetReadDeadline(time.Time{}) // Re-Grab lock c.mu.Lock() } // The connection may have been closed if c.nc == nil { c.mu.Unlock() return c } if tlsRequired { // Rewrap bw c.bw = bufio.NewWriterSize(c.nc, startBufSize) } // Do final client initialization // Set the Ping timer c.setPingTimer() // Spin up the read loop. s.startGoRoutine(func() { c.readLoop() }) if tlsRequired { c.Debugf("TLS handshake complete") cs := c.nc.(*tls.Conn).ConnectionState() c.Debugf("TLS version %s, cipher suite %s", tlsVersion(cs.Version), tlsCipher(cs.CipherSuite)) } c.mu.Unlock() return c }
func (s *Server) createRoute(conn net.Conn, rURL *url.URL) *client { didSolicit := rURL != nil r := &route{didSolicit: didSolicit} for _, route := range s.opts.Routes { if rURL != nil && (strings.ToLower(rURL.Host) == strings.ToLower(route.Host)) { r.routeType = Explicit } } c := &client{srv: s, nc: conn, opts: clientOpts{}, typ: ROUTER, route: r} // Grab server variables s.mu.Lock() infoJSON := s.routeInfoJSON authRequired := s.routeInfo.AuthRequired tlsRequired := s.routeInfo.TLSRequired s.mu.Unlock() // Grab lock c.mu.Lock() // Initialize c.initClient() c.Debugf("Route connection created") if didSolicit { // Do this before the TLS code, otherwise, in case of failure // and if route is explicit, it would try to reconnect to 'nil'... r.url = rURL } // Check for TLS if tlsRequired { // Copy off the config to add in ServerName if we tlsConfig := util.CloneTLSConfig(s.opts.Cluster.TLSConfig) // If we solicited, we will act like the client, otherwise the server. if didSolicit { c.Debugf("Starting TLS route client handshake") // Specify the ServerName we are expecting. host, _, _ := net.SplitHostPort(rURL.Host) tlsConfig.ServerName = host c.nc = tls.Client(c.nc, tlsConfig) } else { c.Debugf("Starting TLS route server handshake") c.nc = tls.Server(c.nc, tlsConfig) } conn := c.nc.(*tls.Conn) // Setup the timeout ttl := secondsToDuration(s.opts.Cluster.TLSTimeout) time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) conn.SetReadDeadline(time.Now().Add(ttl)) c.mu.Unlock() if err := conn.Handshake(); err != nil { c.Debugf("TLS route handshake error: %v", err) c.sendErr("Secure Connection - TLS Required") c.closeConnection() return nil } // Reset the read deadline conn.SetReadDeadline(time.Time{}) // Re-Grab lock c.mu.Lock() // Verify that the connection did not go away while we released the lock. if c.nc == nil { c.mu.Unlock() return nil } // Rewrap bw c.bw = bufio.NewWriterSize(c.nc, startBufSize) } // Do final client initialization // Set the Ping timer c.setPingTimer() // For routes, the "client" is added to s.routes only when processing // the INFO protocol, that is much later. // In the meantime, if the server shutsdown, there would be no reference // to the client (connection) to be closed, leaving this readLoop // uinterrupted, causing the Shutdown() to wait indefinitively. // We need to store the client in a special map, under a special lock. s.grMu.Lock() s.grTmpClients[c.cid] = c s.grMu.Unlock() // Spin up the read loop. s.startGoRoutine(func() { c.readLoop() }) if tlsRequired { c.Debugf("TLS handshake complete") cs := c.nc.(*tls.Conn).ConnectionState() c.Debugf("TLS version %s, cipher suite %s", tlsVersion(cs.Version), tlsCipher(cs.CipherSuite)) } // Queue Connect proto if we solicited the connection. if didSolicit { c.Debugf("Route connect msg sent") c.sendConnect(tlsRequired) } // Send our info to the other side. c.sendInfo(infoJSON) // Check for Auth required state for incoming connections. if authRequired && !didSolicit { ttl := secondsToDuration(s.opts.Cluster.AuthTimeout) c.setAuthTimer(ttl) } c.mu.Unlock() return c }
func (s *Server) createRoute(conn net.Conn, rURL *url.URL) *client { didSolicit := rURL != nil r := &route{didSolicit: didSolicit} for _, route := range s.opts.Routes { if rURL == route { r.routeType = Explicit } } c := &client{srv: s, nc: conn, opts: clientOpts{}, typ: ROUTER, route: r} // Grab server variables and clone known routes. s.mu.Lock() // copy info := s.routeInfo for _, r := range s.routes { r.mu.Lock() if r.route.url != nil { ri := RemoteInfo{ RemoteID: r.route.remoteID, URL: fmt.Sprintf("%s", r.route.url), AuthRequired: r.route.authRequired, TLSRequired: r.route.tlsRequired, } info.Routes = append(info.Routes, ri) } r.mu.Unlock() } s.mu.Unlock() authRequired := info.AuthRequired tlsRequired := info.TLSRequired // Grab lock c.mu.Lock() // Initialize c.initClient(tlsRequired) c.Debugf("Route connection created") // Check for TLS if tlsRequired { // Copy off the config to add in ServerName if we tlsConfig := *s.opts.ClusterTLSConfig // If we solicited, we will act like the client, otherwise the server. if didSolicit { c.Debugf("Starting TLS route client handshake") // Specify the ServerName we are expecting. host, _, _ := net.SplitHostPort(rURL.Host) tlsConfig.ServerName = host c.nc = tls.Client(c.nc, &tlsConfig) } else { c.Debugf("Starting TLS route server handshake") c.nc = tls.Server(c.nc, &tlsConfig) } conn := c.nc.(*tls.Conn) // Setup the timeout ttl := secondsToDuration(s.opts.ClusterTLSTimeout) time.AfterFunc(ttl, func() { tlsTimeout(c, conn) }) conn.SetReadDeadline(time.Now().Add(ttl)) c.mu.Unlock() if err := conn.Handshake(); err != nil { c.Debugf("TLS route handshake error: %v", err) c.sendErr("Secure Connection - TLS Required") c.closeConnection() return nil } // Reset the read deadline conn.SetReadDeadline(time.Time{}) // Re-Grab lock c.mu.Lock() // Rewrap bw c.bw = bufio.NewWriterSize(c.nc, s.opts.BufSize) // Do final client initialization // Set the Ping timer c.setPingTimer() // Spin up the read loop. go c.readLoop() c.Debugf("TLS handshake complete") cs := conn.ConnectionState() c.Debugf("TLS version %s, cipher suite %s", tlsVersion(cs.Version), tlsCipher(cs.CipherSuite)) } // Queue Connect proto if we solicited the connection. if didSolicit { r.url = rURL c.Debugf("Route connect msg sent") c.sendConnect(tlsRequired) } // Add other routes in that are known to the info payload b, _ := json.Marshal(info) infoJSON := []byte(fmt.Sprintf(InfoProto, b)) // Send our info to the other side. s.sendInfo(c, infoJSON) // Check for Auth required state for incoming connections. if authRequired && !didSolicit { ttl := secondsToDuration(s.opts.ClusterAuthTimeout) c.setAuthTimer(ttl) } // Unlock to register. c.mu.Unlock() // Register with the server. s.mu.Lock() s.routes[c.cid] = c s.mu.Unlock() // Now that the route is registered, we need to make sure that // the send of the local subs was not done too early (from // processRouteInfo). If it was, then send again. c.mu.Lock() sendLocalSubs := c.sendLocalSubs c.mu.Unlock() if sendLocalSubs { s.sendLocalSubsToRoute(c) } return c }
func (s *Server) createRoute(conn net.Conn, rURL *url.URL) *client { didSolicit := rURL != nil r := &route{didSolicit: didSolicit} c := &client{srv: s, nc: conn, opts: clientOpts{}, typ: ROUTER, route: r} // Grab server variables. s.mu.Lock() info := s.routeInfoJSON authRequired := s.routeInfo.AuthRequired tlsRequired := s.routeInfo.TLSRequired s.mu.Unlock() // Grab lock c.mu.Lock() // Initialize c.initClient() c.Debugf("Route connection created") // Check for TLS if tlsRequired { // Copy off the config to add in ServerName if we tlsConfig := *s.opts.ClusterTLSConfig // If we solicited, we will act like the client, otherwise the server. if didSolicit { c.Debugf("Starting TLS route client handshake") // Specify the ServerName we are expecting. host, _, _ := net.SplitHostPort(rURL.Host) tlsConfig.ServerName = host c.nc = tls.Client(c.nc, &tlsConfig) } else { c.Debugf("Starting TLS route server handshake") c.nc = tls.Server(c.nc, &tlsConfig) } conn := c.nc.(*tls.Conn) err := conn.Handshake() if err != nil { c.Debugf("TLS route handshake error: %v", err) c.closeConnection() return nil } // Rewrap bw c.bw = bufio.NewWriterSize(c.nc, s.opts.BufSize) } // Queue Connect proto if we solicited the connection. if didSolicit { r.url = rURL c.Debugf("Route connect msg sent") c.sendConnect(tlsRequired) } // Send our info to the other side. s.sendInfo(c, info) // Check for Auth required state for incoming connections. if authRequired && !didSolicit { ttl := secondsToDuration(s.opts.ClusterAuthTimeout) c.setAuthTimer(ttl) } // Unlock to register. c.mu.Unlock() // Register with the server. s.mu.Lock() s.routes[c.cid] = c s.mu.Unlock() return c }