func (p *protocolV2) IDENTIFY(client *nsqd.ClientV2, params [][]byte) ([]byte, error) { var err error state := atomic.LoadInt32(&client.State) if state != stateInit { nsqd.NsqLogger().LogWarningf("[%s] command in wrong state: %v", client, state) return nil, protocol.NewFatalClientErr(nil, E_INVALID, "cannot IDENTIFY in current state") } bodyLen, err := readLen(client.Reader, client.LenSlice) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_BAD_BODY", "IDENTIFY failed to read body size") } if int64(bodyLen) > p.ctx.getOpts().MaxBodySize { return nil, protocol.NewFatalClientErr(nil, "E_BAD_BODY", fmt.Sprintf("IDENTIFY body too big %d > %d", bodyLen, p.ctx.getOpts().MaxBodySize)) } if bodyLen <= 0 { return nil, protocol.NewFatalClientErr(nil, "E_BAD_BODY", fmt.Sprintf("IDENTIFY invalid body size %d", bodyLen)) } body := make([]byte, bodyLen) _, err = io.ReadFull(client.Reader, body) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_BAD_BODY", "IDENTIFY failed to read body") } // body is a json structure with producer information var identifyData nsqd.IdentifyDataV2 err = json.Unmarshal(body, &identifyData) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_BAD_BODY", "IDENTIFY failed to decode JSON body") } nsqd.NsqLogger().LogDebugf("PROTOCOL(V2): [%s] %+v", client, identifyData) err = client.Identify(identifyData) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_BAD_BODY", "IDENTIFY "+err.Error()) } // bail out early if we're not negotiating features if !identifyData.FeatureNegotiation { return okBytes, nil } tlsv1 := p.ctx.GetTlsConfig() != nil && identifyData.TLSv1 deflate := p.ctx.getOpts().DeflateEnabled && identifyData.Deflate deflateLevel := 0 if deflate { if identifyData.DeflateLevel <= 0 { deflateLevel = 6 } deflateLevel = int(math.Min(float64(deflateLevel), float64(p.ctx.getOpts().MaxDeflateLevel))) } snappy := p.ctx.getOpts().SnappyEnabled && identifyData.Snappy if deflate && snappy { return nil, protocol.NewFatalClientErr(nil, "E_IDENTIFY_FAILED", "cannot enable both deflate and snappy compression") } resp, err := json.Marshal(struct { MaxRdyCount int64 `json:"max_rdy_count"` Version string `json:"version"` MaxMsgTimeout int64 `json:"max_msg_timeout"` MsgTimeout int64 `json:"msg_timeout"` TLSv1 bool `json:"tls_v1"` Deflate bool `json:"deflate"` DeflateLevel int `json:"deflate_level"` MaxDeflateLevel int `json:"max_deflate_level"` Snappy bool `json:"snappy"` SampleRate int32 `json:"sample_rate"` AuthRequired bool `json:"auth_required"` OutputBufferSize int `json:"output_buffer_size"` OutputBufferTimeout int64 `json:"output_buffer_timeout"` }{ MaxRdyCount: p.ctx.getOpts().MaxRdyCount, Version: version.Binary, MaxMsgTimeout: int64(p.ctx.getOpts().MaxMsgTimeout / time.Millisecond), MsgTimeout: int64(client.MsgTimeout / time.Millisecond), TLSv1: tlsv1, Deflate: deflate, DeflateLevel: deflateLevel, MaxDeflateLevel: p.ctx.getOpts().MaxDeflateLevel, Snappy: snappy, SampleRate: client.SampleRate, AuthRequired: p.ctx.isAuthEnabled(), OutputBufferSize: client.OutputBufferSize, OutputBufferTimeout: int64(client.OutputBufferTimeout / time.Millisecond), }) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_IDENTIFY_FAILED", "IDENTIFY failed "+err.Error()) } err = Send(client, frameTypeResponse, resp) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_IDENTIFY_FAILED", "IDENTIFY failed "+err.Error()) } if tlsv1 { nsqd.NsqLogger().Logf("PROTOCOL(V2): [%s] upgrading connection to TLS", client) err = client.UpgradeTLS() if err != nil { return nil, protocol.NewFatalClientErr(err, "E_IDENTIFY_FAILED", "IDENTIFY failed "+err.Error()) } err = Send(client, frameTypeResponse, okBytes) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_IDENTIFY_FAILED", "IDENTIFY failed "+err.Error()) } } if snappy { nsqd.NsqLogger().Logf("PROTOCOL(V2): [%s] upgrading connection to snappy", client) err = client.UpgradeSnappy() if err != nil { return nil, protocol.NewFatalClientErr(err, "E_IDENTIFY_FAILED", "IDENTIFY failed "+err.Error()) } err = Send(client, frameTypeResponse, okBytes) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_IDENTIFY_FAILED", "IDENTIFY failed "+err.Error()) } } if deflate { nsqd.NsqLogger().Logf("PROTOCOL(V2): [%s] upgrading connection to deflate", client) err = client.UpgradeDeflate(deflateLevel) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_IDENTIFY_FAILED", "IDENTIFY failed "+err.Error()) } err = Send(client, frameTypeResponse, okBytes) if err != nil { return nil, protocol.NewFatalClientErr(err, "E_IDENTIFY_FAILED", "IDENTIFY failed "+err.Error()) } } return nil, nil }