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) 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 }