// NewConversation constructs a server-side authentication conversation.
// Conversations cannot be reused, so this must be called for each new
// authentication attempt.
5788
func (s *Server) NewConversation() *ServerConversation {
	s.RLock()
	defer s.RUnlock()
	return &ServerConversation{
		nonceGen:     s.nonceGen,
		hashGen:      s.hashGen,
		credentialCB: s.credentialCB,
	}
}
687051
func (c *ChatRPC) ChatJoinedConversation(
	_ context.Context, _ chat1.ChatJoinedConversationArg) error {
	return nil
}
457483
func (api *Client) UnArchiveConversation(channelID string) error {
	return api.UnArchiveConversationContext(context.Background(), channelID)
}
792023
func (api *Client) CreateConversation(channelName string, isPrivate bool) (*Channel, error) {
	return api.CreateConversationContext(context.Background(), channelName, isPrivate)
}
28664
func NewAuthenticatedClient() Client {
	authenticator := newMockAuthenticator(func(request *http.Request) error {
		request.Header.Set("Authorization", "fake-authorization")
		return nil
	})

	return NewClient(authenticator)
}
626560
func NewContact(chatID int64, phoneNumber, firstName string) ContactConfig {
	return ContactConfig{
		BaseChat: BaseChat{
			ChatID: chatID,
		},
		PhoneNumber: phoneNumber,
		FirstName:   firstName,
	}
}
1138116
func NewMessageToChannel(username string, text string) MessageConfig {
	return MessageConfig{
		BaseChat: BaseChat{
			ChannelUsername: username,
		},
		Text: text,
	}
}
544144
func (api *Client) OpenConversationContext(ctx context.Context, params *OpenConversationParameters) (*Channel, bool, bool, error) {
	values := url.Values{
		"token":     {api.token},
		"return_im": {strconv.FormatBool(params.ReturnIM)},
	}
	if params.ChannelID != "" {
		values.Add("channel", params.ChannelID)
	}
	if params.Users != nil {
		values.Add("users", strings.Join(params.Users, ","))
	}
	response := struct {
		Channel     *Channel `json:"channel"`
		NoOp        bool     `json:"no_op"`
		AlreadyOpen bool     `json:"already_open"`
		SlackResponse
	}{}
	err := api.postMethod(ctx, "conversations.open", values, &response)
	if err != nil {
		return nil, false, false, err
	}

	return response.Channel, response.NoOp, response.AlreadyOpen, response.Err()
}
227434
func NewConversationWithVersion(v int) *Conversation {
	var vv otrVersion

	switch v {
	case 2:
		vv = otrV2{}
	case 3:
		vv = otrV3{}
	}
	return &Conversation{version: vv}
}
737280
func (c *ConfigLocal) Chat() Chat {
	c.lock.RLock()
	defer c.lock.RUnlock()
	return c.chat
}
175965
func NewInitMessage(clientName string, user string, password string) InitMessage {
	var authToken map[string]interface{}
	if user == "" {
		authToken = map[string]interface{}{
			"scheme": "none",
		}
	} else {
		authToken = map[string]interface{}{
			"scheme":      "basic",
			"principal":   user,
			"credentials": password,
		}
	}

	return InitMessage{
		clientName: clientName,
		authToken:  authToken,
	}
}
216575
func (api *Client) CloseConversation(channelID string) (noOp bool, alreadyClosed bool, err error) {
	return api.CloseConversationContext(context.Background(), channelID)
}
1072432
func (c *chatLocal) GetConversationID(
	ctx context.Context, tlfName tlf.CanonicalName, tlfType tlf.Type,
	channelName string, chatType chat1.TopicType) (
	chat1.ConversationID, error) {
	if chatType != chat1.TopicType_KBFSFILEEDIT {
		panic(fmt.Sprintf("Bad topic type: %d", chatType))
	}

	c.data.lock.Lock()
	defer c.data.lock.Unlock()
	byID, ok := c.data.convs[tlfType][tlfName]
	if !ok {
		if _, ok := c.data.convs[tlfType]; !ok {
			c.data.convs[tlfType] = make(convLocalByNameMap)
		}
		if _, ok := c.data.convs[tlfType][tlfName]; !ok {
			byID = make(convLocalByIDMap)
			c.data.convs[tlfType][tlfName] = byID
		}
	}
	for _, conv := range byID {
		if conv.chanName == channelName {
			return conv.convID, nil
		}
	}

	// Make a new conversation.
	var idBytes [8]byte
	err := kbfscrypto.RandRead(idBytes[:])
	if err != nil {
		return nil, err
	}
	id := chat1.ConversationID(idBytes[:])
	c.log.CDebugf(ctx, "Making new conversation for %s, %s: %s",
		tlfName, channelName, id)
	conv := &convLocal{
		convID:   id,
		chanName: channelName,
	}
	c.data.convs[tlfType][tlfName][id.String()] = conv
	c.data.convsByID[id.String()] = conv

	h, err := GetHandleFromFolderNameAndType(
		ctx, c.config.KBPKI(), c.config.MDOps(), c.config,
		string(tlfName), tlfType)
	if err != nil {
		return nil, err
	}
	for config, cb := range c.data.newChannelCBs {
		// Only send notifications to those that can read the TLF.
		session, err := config.KBPKI().GetCurrentSession(ctx)
		if err != nil {
			return nil, err
		}
		isReader, err := isReaderFromHandle(
			ctx, h, config.KBPKI(), config, session.UID)
		if err != nil {
			return nil, err
		}
		if !isReader {
			continue
		}

		if cb == nil && config.KBFSOps() != nil {
			cb = config.KBFSOps().NewNotificationChannel
		}

		cb(ctx, h, id, channelName)
	}

	return id, nil
}
389538
func (api *Client) RenameConversationContext(ctx context.Context, channelID, channelName string) (*Channel, error) {
	values := url.Values{
		"token":   {api.token},
		"channel": {channelID},
		"name":    {channelName},
	}
	response := struct {
		SlackResponse
		Channel *Channel `json:"channel"`
	}{}
	err := api.postMethod(ctx, "conversations.rename", values, &response)
	if err != nil {
		return nil, err
	}

	return response.Channel, response.Err()
}
166319
func NewContext(ctx context.Context, msg string) context.Context {
	return context.WithValue(ctx, logContextKey, msg)
}
1291548
func (config Config) New() (authenticator.Request, *spec.SecurityDefinitions, error) {
	var authenticators []authenticator.Request
	var tokenAuthenticators []authenticator.Token
	securityDefinitions := spec.SecurityDefinitions{}

	// front-proxy, BasicAuth methods, local first, then remote
	// Add the front proxy authenticator if requested
	if config.RequestHeaderConfig != nil {
		requestHeaderAuthenticator, err := headerrequest.NewSecure(
			config.RequestHeaderConfig.ClientCA,
			config.RequestHeaderConfig.AllowedClientNames,
			config.RequestHeaderConfig.UsernameHeaders,
			config.RequestHeaderConfig.GroupHeaders,
			config.RequestHeaderConfig.ExtraHeaderPrefixes,
		)
		if err != nil {
			return nil, nil, err
		}
		authenticators = append(authenticators, authenticator.WrapAudienceAgnosticRequest(config.APIAudiences, requestHeaderAuthenticator))
	}

	// basic auth
	if len(config.BasicAuthFile) > 0 {
		basicAuth, err := newAuthenticatorFromBasicAuthFile(config.BasicAuthFile)
		if err != nil {
			return nil, nil, err
		}
		authenticators = append(authenticators, authenticator.WrapAudienceAgnosticRequest(config.APIAudiences, basicAuth))

		securityDefinitions["HTTPBasic"] = &spec.SecurityScheme{
			SecuritySchemeProps: spec.SecuritySchemeProps{
				Type:        "basic",
				Description: "HTTP Basic authentication",
			},
		}
	}

	// X509 methods
	if len(config.ClientCAFile) > 0 {
		certAuth, err := newAuthenticatorFromClientCAFile(config.ClientCAFile)
		if err != nil {
			return nil, nil, err
		}
		authenticators = append(authenticators, certAuth)
	}

	// Bearer token methods, local first, then remote
	if len(config.TokenAuthFile) > 0 {
		tokenAuth, err := newAuthenticatorFromTokenFile(config.TokenAuthFile)
		if err != nil {
			return nil, nil, err
		}
		tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, tokenAuth))
	}
	if len(config.ServiceAccountKeyFiles) > 0 {
		serviceAccountAuth, err := newLegacyServiceAccountAuthenticator(config.ServiceAccountKeyFiles, config.ServiceAccountLookup, config.APIAudiences, config.ServiceAccountTokenGetter)
		if err != nil {
			return nil, nil, err
		}
		tokenAuthenticators = append(tokenAuthenticators, serviceAccountAuth)
	}
	if utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) && config.ServiceAccountIssuer != "" {
		serviceAccountAuth, err := newServiceAccountAuthenticator(config.ServiceAccountIssuer, config.ServiceAccountKeyFiles, config.APIAudiences, config.ServiceAccountTokenGetter)
		if err != nil {
			return nil, nil, err
		}
		tokenAuthenticators = append(tokenAuthenticators, serviceAccountAuth)
	}
	if config.BootstrapToken {
		if config.BootstrapTokenAuthenticator != nil {
			// TODO: This can sometimes be nil because of
			tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, config.BootstrapTokenAuthenticator))
		}
	}
	// NOTE(ericchiang): Keep the OpenID Connect after Service Accounts.
	//
	// Because both plugins verify JWTs whichever comes first in the union experiences
	// cache misses for all requests using the other. While the service account plugin
	// simply returns an error, the OpenID Connect plugin may query the provider to
	// update the keys, causing performance hits.
	if len(config.OIDCIssuerURL) > 0 && len(config.OIDCClientID) > 0 {
		oidcAuth, err := newAuthenticatorFromOIDCIssuerURL(oidc.Options{
			IssuerURL:            config.OIDCIssuerURL,
			ClientID:             config.OIDCClientID,
			APIAudiences:         config.APIAudiences,
			CAFile:               config.OIDCCAFile,
			UsernameClaim:        config.OIDCUsernameClaim,
			UsernamePrefix:       config.OIDCUsernamePrefix,
			GroupsClaim:          config.OIDCGroupsClaim,
			GroupsPrefix:         config.OIDCGroupsPrefix,
			SupportedSigningAlgs: config.OIDCSigningAlgs,
			RequiredClaims:       config.OIDCRequiredClaims,
		})
		if err != nil {
			return nil, nil, err
		}
		tokenAuthenticators = append(tokenAuthenticators, oidcAuth)
	}
	if len(config.WebhookTokenAuthnConfigFile) > 0 {
		webhookTokenAuth, err := newWebhookTokenAuthenticator(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnCacheTTL, config.APIAudiences)
		if err != nil {
			return nil, nil, err
		}
		tokenAuthenticators = append(tokenAuthenticators, webhookTokenAuth)
	}

	if len(tokenAuthenticators) > 0 {
		// Union the token authenticators
		tokenAuth := tokenunion.New(tokenAuthenticators...)
		// Optionally cache authentication results
		if config.TokenSuccessCacheTTL > 0 || config.TokenFailureCacheTTL > 0 {
			tokenAuth = tokencache.New(tokenAuth, true, config.TokenSuccessCacheTTL, config.TokenFailureCacheTTL)
		}
		authenticators = append(authenticators, bearertoken.New(tokenAuth), websocket.NewProtocolAuthenticator(tokenAuth))
		securityDefinitions["BearerToken"] = &spec.SecurityScheme{
			SecuritySchemeProps: spec.SecuritySchemeProps{
				Type:        "apiKey",
				Name:        "authorization",
				In:          "header",
				Description: "Bearer Token authentication",
			},
		}
	}

	if len(authenticators) == 0 {
		if config.Anonymous {
			return anonymous.NewAuthenticator(), &securityDefinitions, nil
		}
		return nil, &securityDefinitions, nil
	}

	authenticator := union.New(authenticators...)

	authenticator = group.NewAuthenticatedGroupAdder(authenticator)

	if config.Anonymous {
		// If the authenticator chain returns an error, return an error (don't consider a bad bearer token
		// or invalid username/password combination anonymous).
		authenticator = union.NewFailOnError(authenticator, anonymous.NewAuthenticator())
	}

	return authenticator, &securityDefinitions, nil
}
1130339
func NewClient(url string, protocols []string) (*Client, error) {

	dialer := &websocket.Dialer{
		Proxy:             http.ProxyFromEnvironment,
		Subprotocols:      protocols,
		EnableCompression: true,
	}

	con, _, err := dialer.Dial(url, nil)
	if err != nil {
		return nil, err
	}

	return &Client{con}, nil

}