func (contextData ContextNewData) Update(context *helpers.ConnectionContext) { context.Clear() context.SetCid(contextData.cid) context.SetupTmpData(contextData.data) if contextData.auth { context.DoAuth() } if contextData.group != 0 { context.SetClientGroup(contextData.group) } }
func sendAuthResult( cmd *ClientCmd, context *helpers.ConnectionContext, option HandlerParamsReader) (*ServerCmd, error) { // Check client hash serverKey := context.GetTmpData() var err error var result *ServerCmd if len(serverKey) == option.GetDefaultKeySize() { requestData := (*cmd).Data if len(requestData) > 0 { if clientParts := strings.Split(requestData, ":"); len(clientParts) == 2 { // clientParts[0] - hash from client clientParts[1] - client "salt" line := fmt.Sprintf( "%s%s%s", // main key option.GetSecretKey(), // client key clientParts[1], // server key serverKey) if hashMethod(line, option) == clientParts[0] { rand := helpers.NewSystemRandom() keySize, node := option.GetCidConstructorData() contextData := ContextNewData{auth: true} // offer new cid answer := ServerCmd{ contextUpdater: &contextData, baseCmd: baseCmd{Cid: rand.CreateCid(keySize, node), Target: CmdClientData}} result = &answer } else { err = errors.New("Auth failed!") } } else { err = errors.New("Client data format error.") } } else { err = errors.New("Client data not found.") } } else { // incorrect err = errors.New("Connection without auth request?") } return result, err }
func connectionHandler( server *RlServer, toCoreBuffer *chan protocol.CoreMsg, connection net.Conn, label string, dispatcher *AnswerDispatcher, stat *RlStatistic) { // server and service connections defer connection.Close() options := server.GetOption() connectionContext := helpers.ConnectionContext{} buffer := bufio.NewReader(connection) wait := true answerWriterActive := false var answer *string answerBuffer := make(chan protocol.ServerCmd, options.BufferSize) localConnectionInfo := newConnectionInfo(label) for wait { line, _, err := buffer.ReadLine() answer = nil if err != nil { if err == io.EOF { // client break connection localConnectionInfo.SetActive(false) if cid, exists := connectionContext.GetCid(); exists { dispatcher.RemoveChannel(cid, true) } } wait = false } else { stat.Append(StatIncomeDataSize, len(line)) cmd, err := protocol.NewClientCmd(&line) if err != nil { wait = false rllogger.Outputf( rllogger.LogWarn, "Incorrect command from %s error: %s", label, err) answer = protocol.FastErrorAnswer(err, protocol.ErrCodeFormatProblem) } else { if cmd.RequiredClose() { wait = false rllogger.Outputf(rllogger.LogInfo, "close command from %s", label) } else { // check auth if cmd.RequiredAuth() && !connectionContext.IsAuth() { answer = protocol.FastErrorAnswer( "Access denied!", protocol.ErrCodeAccessDenied) } else { // try get fast handler if exists, handler := cmd.GetFastHandler(); exists { if newAnswer, err := handler(cmd, &connectionContext, options); err != nil { rllogger.Outputf( rllogger.LogWarn, "Client: %s target: %d Handler error: %s", label, cmd.Target, err) answer = protocol.FastErrorAnswer(err, protocol.ErrCodeProtocolProblem) } else { if dataPtr, dumpErr := newAnswer.Dump(); dumpErr != nil { answer = protocol.FastErrorAnswer(err, protocol.ErrCodeImplementationProblem) } else { answer = dataPtr if exists, contextUpdater := newAnswer.GetContextUpdater(); exists { contextUpdater.Update(&connectionContext) rllogger.Outputf( rllogger.LogDebug, "-> %s context updated: %s", label, connectionContext) } } } } else { clientGroup := connectionContext.GetClientGroup() msg, convertError := protocol.NewCoreMsg(clientGroup, cmd) if convertError != nil { rllogger.Outputf( rllogger.LogWarn, "Msg create error: %s from %s", convertError, label) answer = protocol.FastErrorAnswer( convertError, protocol.ErrCodeProtocolProblem) } else { *toCoreBuffer <- *msg if !answerWriterActive { answerWriterActive = true // this channel to dispatcher dispatcher.AddChannel((*msg).Cid, &answerBuffer) // run async answer writer go conntectionWriteAnswer( connection, &answerBuffer, localConnectionInfo, stat) } } } } } } // write sync handler answer if answer != nil { writen, err := connection.Write([]byte(*answer)) if err != nil { rllogger.Outputf( rllogger.LogError, "Can't send answer to %s error: %s", label, err) } else { stat.Append(StatOutcomeDataSize, writen) } } } } //not need "close(answerBuffer)" dispatcher do it stat.Append(StatConnectionCount, -1) server.ChangeConnectionCount(-1) }