Beispiel #1
0
func ProcRecordResult(
	handler *coreprocessing.Handler,
	inIns *coreprocessing.CoreInstruction,
	outIns *coreprocessing.CoreInstruction) []*coreprocessing.CoreInstruction {
	//
	var result []*coreprocessing.CoreInstruction
	if answer, _ := outIns.GetAnswer(); (*answer).Error.Code == 0 {
		if srcCmd, hasCmd := inIns.GetCommand(); hasCmd {
			rpcManager := coreprocessing.NewRpcServerManager()
			taskId := (*srcCmd).Params.Task
			if targetCidPtr := rpcManager.ResultDirectionDict.Get(taskId); targetCidPtr != nil {
				// check client group
				if handler.StateCheker.ClientInGroup(*targetCidPtr, connectionsupport.GroupConnectionWsClient) {
					cmd := transport.NewCommandWithParams(
						0, "result", transport.MethodParams{
							Cid:  *targetCidPtr,
							Task: taskId,
							Json: (*srcCmd).Params.Json})
					clientIns := coreprocessing.NewCoreInstruction(coreprocessing.TypeInstructionSetResult)
					clientIns.SetCommand(cmd)
					result = make([]*coreprocessing.CoreInstruction, 1)
					result[0] = clientIns
				} else {
					rpcManager.ResultBufferDict.Set(taskId, (*srcCmd).Params.Json)
				}
			} else {
				rllogger.Outputf(rllogger.LogError, "Processing pass for: %s", srcCmd)
			}
		}
	}
	return result
}
func (server *ConnectionServer) connectionReadProcessing(
	connection net.Conn,
	workerManager *coresupport.CoreWorkerManager,
	label string) {
	//
	defer connection.Close()
	buffer := bufio.NewReader(connection)
	wait := true
	hasAnswerChannel := false
	connectionData := server.connectionDataManager.NewConnection()
	// TODO: rllogger.LogDebug
	rllogger.Outputf(rllogger.LogInfo, "new connection %s", connectionData.Cid)
	sizeBuffer := (*server).option.BufferSize

	for wait {
		//
		lineData, _, err := buffer.ReadLine()
		if err == nil {
			server.stat.SendMsg("income_data_size", len(lineData))
			if cmd, err := transport.ParseCommand(&lineData); err == nil {
				workerManager.Processing(cmd, server.connectionDataManager, connectionData)
				if !hasAnswerChannel {
					// create
					backChannel := make(chan coreprocessing.CoreInstruction, sizeBuffer)
					// dont like closure, only realy need
					go connectionWriteProcessing(
						connection, &backChannel, (*server).connectionDataManager, server.stat, label)
					workerManager.AppendBackChannel(connectionData, &backChannel)
					hasAnswerChannel = true
				}
			} else {
				server.stat.SendMsg("bad_command_count", 1)
				rllogger.Outputf(rllogger.LogWarn, "connection %s bad command: %s", connectionData.Cid, err)
			}
		} else {
			// has error
			if err == io.EOF {
				// client break connection
				workerManager.BrokenConnection(connectionData)
				rllogger.Outputf(rllogger.LogDebug, "broken connection %s", connectionData.Cid)
			}
			wait = false
		}
	}
	server.stat.DelOneMsg("connection_count")
	// remove from methods
	if server.connectionDataManager.ClientInGroup(connectionData.Cid, connectionsupport.GroupConnectionServer) {
		cidMethods := coreprocessing.NewRpcServerManager()
		cidMethods.Remove(connectionData.Cid)
		server.stat.DelOneMsg("count_connection_server")
	} else {
		server.stat.DelOneMsg("count_connection_client")
	}
	workerManager.RemoveBackChannel(connectionData)
	server.connectionDataManager.RemoveConnection(connectionData.Cid)
	// TODO: rllogger.LogDebug
	rllogger.Outputf(rllogger.LogInfo, "out connection %s", connectionData.Cid)
}
Beispiel #3
0
// main method for client routing to server methods
func ProcRouteRpc(handler *coreprocessing.Handler, inIns *coreprocessing.CoreInstruction) *coreprocessing.CoreInstruction {
	var answer *transport.Answer
	var errStr string
	var answerData string
	insType := coreprocessing.TypeInstructionSkip
	errCode := 0
	// check methods
	if cmd, exists := inIns.GetCommand(); exists {
		rpcManager := coreprocessing.NewRpcServerManager()
		variants := rpcManager.GetCidVariants((*cmd).Method)
		if len(variants) > 0 {
			var freeCid string
			for _, serverCid := range variants {
				if !handler.StateCheker.ClientBusy(serverCid) {
					freeCid = serverCid
					break
				}
			}
			if len(freeCid) > 0 {
				data := RpcAnswerData{
					Cid:  freeCid,
					Task: handler.TaskIdGenerator.CreateTaskId()}
				// TODO: to debug
				rllogger.Outputf(rllogger.LogInfo, "rpc call: '%s()' -> %s", (*cmd).Method, data)
				if strData, err := json.Marshal(data); err == nil {
					answerData = string(strData)
					rpcManager.ResultDirectionDict.Set(data.Task, (*inIns).Cid)
				} else {
					errCode = transport.ErrorCodeInternalProblem
					errStr = fmt.Sprintf("Error dump %T: '%s'", data, err)
				}
			} else {
				errCode = transport.ErrorCodeAllServerBusy
				errStr = fmt.Sprintf("All server busy for method '%s'.", (*cmd).Method)
			}
		} else {
			errCode = transport.ErrorCodeRemouteMethodNotExists
			errStr = fmt.Sprintf("Method '%s' unregistred or workers lost.", (*cmd).Method)
		}
	} else {
		errCode = transport.ErrorCodeCommandFormatWrong
		errStr = "Command is empty."
	}
	if errCode > 0 {
		insType = coreprocessing.TypeInstructionProblem
		answer = inIns.MakeErrAnswer(errCode, errStr)
	} else {
		insType = coreprocessing.TypeInstructionOk
		answer = inIns.MakeOkAnswer(answerData)
	}
	result := coreprocessing.NewCoreInstruction(insType)
	result.SetAnswer(answer)
	return result
}
Beispiel #4
0
func ProcRegistration(handler *coreprocessing.Handler, inIns *coreprocessing.CoreInstruction) *coreprocessing.CoreInstruction {
	insType := coreprocessing.TypeInstructionSkip
	var answer *transport.Answer
	var result *coreprocessing.CoreInstruction
	var resultChanges *connectionsupport.StateChanges
	var errStr string
	errCode := 0
	if cmd, exists := inIns.GetCommand(); exists {
		info := ClientInfo{}
		if loadErr := json.Unmarshal([]byte((*cmd).Params.Json), &info); loadErr == nil {
			if (*handler).StateCheker.IsAuth(inIns.Cid) {
				// TODO: need implimentation for replace current cid to old
				switch info.Group {
				case connectionsupport.GroupConnectionClient:
					{
						changes := connectionsupport.StateChanges{
							ChangeType:            connectionsupport.StateChangesTypeGroup,
							ConnectionClientGroup: connectionsupport.GroupConnectionClient}
						resultChanges = &changes
						answer = inIns.MakeOkAnswer(
							fmt.Sprintf("{\"ok\": true, \"cid\": \"%s\"}", inIns.Cid))
					}
				case connectionsupport.GroupConnectionServer:
					{
						dict := coreprocessing.NewMethodInstructionDict()
						methodsCount := dict.RegisterClientMethods(info.Methods...)
						rpcManager := coreprocessing.NewRpcServerManager()
						rpcManager.Append(inIns.Cid, &(info.Methods))
						answer = inIns.MakeOkAnswer(
							fmt.Sprintf(
								"{\"methods_count\": %d, \"ok\": true, \"cid\": \"%s\"}",
								methodsCount, inIns.Cid))

						changes := connectionsupport.StateChanges{
							ChangeType:            connectionsupport.StateChangesTypeGroup,
							ConnectionClientGroup: connectionsupport.GroupConnectionServer}
						resultChanges = &changes
					}
				case connectionsupport.GroupConnectionWsClient:
					{
						// denied
						errCode = transport.ErrorCodeAccessDenied
						errStr = "Web-socket client don't accepted on simple TCP socket."
					}
				default:
					{
						errCode = transport.ErrorCodeUnexpectedValue
						errStr = "Unknown group, see the protocol specification."
					}
				}
			} else {
				errCode = transport.ErrorCodeAccessDenied
				errStr = "Access denied."
			}
		} else {
			errCode = transport.ErrorCodeMethodParamsFormatWrong
			errStr = fmt.Sprint(loadErr)
		}
	} else {
		errCode = transport.ErrorCodeCommandFormatWrong
		errStr = "Command is empty."
	}
	if errCode > 0 {
		insType = coreprocessing.TypeInstructionProblem
		answer = inIns.MakeErrAnswer(errCode, errStr)
	} else {
		insType = coreprocessing.TypeInstructionOk
	}
	result = coreprocessing.NewCoreInstruction(insType)
	result.SetAnswer(answer)
	result.StateChanges = resultChanges
	return result
}
func TestRegistratioAddGroupServer(t *testing.T) {
	option := options.SysOption{
		Statistic: false}
	stat := statistic.NewStatistic(option)
	methodName := "test_test"
	cid := "27d90e5e-0000000000000011-1"
	handler := coreprocessing.NewHandler(1, option, stat)
	cheker := forTestConnectionStateCheck{Auth: true}
	handler.StateCheker = &cheker
	inIns := coreprocessing.NewCoreInstruction(coreprocessing.TypeInstructionReg)
	cmd := transport.NewCommand(0, cid, "registration", "")
	(*cmd).Params.Json = fmt.Sprintf(
		"{\"methods\": [\"%s\"], \"group\": %d}", methodName, connectionsupport.GroupConnectionServer)
	inIns.SetCommand(cmd)
	outIns := coremethods.ProcRegistration(handler, inIns)
	if answer, exists := outIns.GetAnswer(); exists {
		err := (*answer).Error.Code
		if err > 0 {
			t.Error("Answer with problem, %s", (*answer).Error)
		} else {
			stCh := (*outIns).StateChanges
			if stCh != nil {
				if (*stCh).ChangeType == connectionsupport.StateChangesTypeGroup {
					if (*stCh).ConnectionClientGroup == connectionsupport.GroupConnectionServer {
						cidMethods := coreprocessing.NewRpcServerManager()
						cidList := cidMethods.GetCidVariants(methodName)
						if len(cidList) > 0 {
							exists := false
							for _, variant := range cidList {
								t.Logf("%s == %s ?", cid, variant)
								if variant == cid {
									exists = true
								}
							}
							if exists {
								// check answer
								if answer, exists := outIns.GetAnswer(); exists {
									if (*answer).Result != "{\"methods_count\": 1, \"ok\": true}" {
										t.Errorf("Incorrect answer data: %s", (*answer).Result)
									}
								} else {
									t.Error("Answer data is empty.")
								}
							} else {
								t.Errorf("Not found cid '%s' for method '%s'.", cid, methodName)
							}
						} else {
							t.Errorf("New cid '%s' lost for method '%s'.", cid, methodName)
						}
					} else {
						t.Errorf("Incorrect connection group %s in changes.", (*stCh).ConnectionClientGroup)
					}
				} else {
					t.Errorf("Type of changes is not a {}", connectionsupport.StateChangesTypeGroup)
				}

			} else {
				t.Error("Changes empty.")
			}
		}
	} else {
		t.Errorf("Empty answer to %s.", *cmd)
	}
}