Пример #1
0
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)
	}
}
Пример #2
0
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
}
Пример #3
0
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)
}