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 ProcUpdateStatus(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 { // check params.data is number type if newStatus, err := strconv.ParseUint(cmd.Params.Data, 10, 16); err == nil { changes := connectionsupport.StateChanges{ ChangeType: connectionsupport.StateChangesTypeStatus, Status: uint16(newStatus)} resultChanges = &changes answer = inIns.MakeOkAnswer( fmt.Sprintf("{\"ok\": true, \"status\": %d}", newStatus)) insType = coreprocessing.TypeInstructionOk } else { errCode = transport.ErrorCodeMethodParamsFormatWrong errStr = "Status has unexpected type." } } else { errCode = transport.ErrorCodeCommandFormatWrong errStr = "Command is empty." } if errCode > 0 { insType = coreprocessing.TypeInstructionProblem answer = inIns.MakeErrAnswer(errCode, errStr) } result = coreprocessing.NewCoreInstruction(insType) result.SetAnswer(answer) result.StateChanges = resultChanges return result }
func ProcResultReturned(handler *coreprocessing.Handler, inIns *coreprocessing.CoreInstruction) *coreprocessing.CoreInstruction { var answer *transport.Answer var resultChanges *connectionsupport.StateChanges var errStr string insType := coreprocessing.TypeInstructionSkip errCode := 0 if cmd, exists := inIns.GetCommand(); exists { // return status resultChanges = &(connectionsupport.StateChanges{ ChangeType: connectionsupport.StateChangesTypeStatus, Status: connectionsupport.ClientStatusActive}) if len((*cmd).Params.Task) < 1 { errCode = transport.ErrorCodeMethodParamsFormatWrong errStr = "Task Id does not exist." } } else { errCode = transport.ErrorCodeCommandFormatWrong errStr = "Command is empty." } if errCode > 0 { insType = coreprocessing.TypeInstructionProblem answer = inIns.MakeErrAnswer(errCode, errStr) } else { answer = inIns.MakeOkAnswer( fmt.Sprintf("{\"ok\": true, \"status\": %d}", resultChanges.Status)) insType = coreprocessing.TypeInstructionOk } result := coreprocessing.NewCoreInstruction(insType) result.SetAnswer(answer) result.StateChanges = resultChanges return result }
// ProcRegistration=> // func TestRegistrationEmptyParams(t *testing.T) { option := options.SysOption{ Statistic: false} stat := statistic.NewStatistic(option) handler := coreprocessing.NewHandler(1, option, stat) inIns := coreprocessing.NewCoreInstruction(coreprocessing.TypeInstructionReg) cmd := transport.NewCommand(0, "27d90e5e-0000000000000011-1", "registration", "") // expected methods as list of string (*cmd).Params.Json = "{\"methods\": \"none\", \"group\": 1}" inIns.SetCommand(cmd) outIns := coremethods.ProcRegistration(handler, inIns) if answer, exists := outIns.GetAnswer(); exists { err := (*answer).Error.Code if err > 0 { t.Logf("Answer has error, %s.", (*answer).Error) if err != transport.ErrorCodeMethodParamsFormatWrong { t.Error("Unexpected error code: %d.", err) } } else { t.Error("This answer must have error.") } } else { t.Errorf("Empty answer to %s.", *cmd) } }
func TestUpdateStatusChanged(t *testing.T) { option := options.SysOption{ Statistic: false} var newStatus uint16 = 1 stat := statistic.NewStatistic(option) handler := coreprocessing.NewHandler(1, option, stat) inIns := coreprocessing.NewCoreInstruction(coreprocessing.TypeInstructionReg) cmd := transport.NewCommand(0, "27d90e5e-0000000000000011-1", "statusupdate", fmt.Sprint(newStatus)) inIns.SetCommand(cmd) outIns := coremethods.ProcUpdateStatus(handler, inIns) if answer, exists := outIns.GetAnswer(); exists { if (*answer).Error.Code > 0 { t.Errorf( "Answer has error with code: %d msg: %s.", (*answer).Error.Code, (*answer).Error.Message) } else { if outIns.StateChanges != nil { if outIns.StateChanges.Status != newStatus { t.Errorf("State change delegator has wrong status: %d.", outIns.StateChanges.Status) } } else { t.Error("Empty state change delegator.") } } } else { t.Errorf("Empty answer to %s.", *cmd) } }
func TestRegistrationUnknownGroup(t *testing.T) { option := options.SysOption{ Statistic: false} stat := statistic.NewStatistic(option) handler := coreprocessing.NewHandler(1, option, stat) cheker := forTestConnectionStateCheck{Auth: true} handler.StateCheker = &cheker inIns := coreprocessing.NewCoreInstruction(coreprocessing.TypeInstructionReg) cmd := transport.NewCommand(0, "27d90e5e-0000000000000011-1", "registration", "") (*cmd).Params.Json = "{\"methods\": [\"none\"], \"group\": 4}" inIns.SetCommand(cmd) outIns := coremethods.ProcRegistration(handler, inIns) if answer, exists := outIns.GetAnswer(); exists { err := (*answer).Error.Code if err > 0 { t.Logf("Answer has error, %s.", (*answer).Error) if err != transport.ErrorCodeUnexpectedValue { t.Error("Unexpected error code: %d.", err) } } else { t.Error("This answer must have error.") } } else { t.Errorf("Empty answer to %s.", *cmd) } }
// 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 }
// return date size in result func ProcPing(handler *coreprocessing.Handler, inIns *coreprocessing.CoreInstruction) *coreprocessing.CoreInstruction { var insType int var result string if cmd, exists := inIns.GetCommand(); exists { insType = coreprocessing.TypeInstructionPong result = fmt.Sprintf( "{\"data\": %d, \"exists\": true}", len(cmd.Params.Data)+len(cmd.Params.Json)) } else { insType = coreprocessing.TypeInstructionSkip } outIns := coreprocessing.NewCoreInstruction(insType) if insType == coreprocessing.TypeInstructionPong { outIns.SetAnswer(inIns.MakeOkAnswer(result)) } return outIns }
// ProcUpdateStatus => // func TestUpdateStatusEmptyParams(t *testing.T) { option := options.SysOption{ Statistic: false} stat := statistic.NewStatistic(option) handler := coreprocessing.NewHandler(1, option, stat) inIns := coreprocessing.NewCoreInstruction(coreprocessing.TypeInstructionReg) cmd := transport.NewCommand(0, "27d90e5e-0000000000000011-1", "statusupdate", "") inIns.SetCommand(cmd) outIns := coremethods.ProcUpdateStatus(handler, inIns) if answer, exists := outIns.GetAnswer(); exists { if (*answer).Error.Code != transport.ErrorCodeMethodParamsFormatWrong { t.Errorf("Answer hasn't error with code: %d.", transport.ErrorCodeMethodParamsFormatWrong) } } else { t.Errorf("Empty answer to %s.", *cmd) } }
func TestRegistratioAddGroupClient(t *testing.T) { option := options.SysOption{ Statistic: false} stat := statistic.NewStatistic(option) cid := "27d90e5e-0000000000000012-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( "{\"group\": %d}", connectionsupport.GroupConnectionClient) 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.GroupConnectionClient { if answer, exists := outIns.GetAnswer(); exists { if (*answer).Result != "{\"ok\": true}" { t.Errorf("Incorrect answer data: %s", (*answer).Result) } } else { t.Error("Answer data is empty.") } } 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) } }
// check token by client public key func ProcAuth(handler *coreprocessing.Handler, inIns *coreprocessing.CoreInstruction) *coreprocessing.CoreInstruction { // client sends in params: // - json: {"key": "<key name>"} // - data: "<base64 token string, use JWT protocol (random data inside)>" // getting (search on option.KeyDir) client public key by name (in command params) handler.Stat.AddOneMsg("auth_request") changes := connectionsupport.StateChanges{ ChangeType: connectionsupport.StateChangesTypeAuth} var result *coreprocessing.CoreInstruction var resultErr error var errCode int if cmd, exists := inIns.GetCommand(); exists { if authData, err := newAuthData(cmd.Params); err == nil { if err := authData.Check(handler.Option); err != nil { errCode = transport.ErrorCodeMethodAuthFailed resultErr = err } } else { resultErr = err errCode = transport.ErrorCodeMethodParamsFormatWrong } } else { errCode = transport.ErrorCodeCommandFormatWrong resultErr = errors.New("Not found command in instruction.") } var answer *transport.Answer var insType int if errCode > 0 { changes.Auth = false answer = inIns.MakeErrAnswer(errCode, fmt.Sprint(resultErr)) insType = coreprocessing.TypeInstructionProblem rllogger.Outputf(rllogger.LogWarn, "Failed auth from %s with error: %s", inIns.Cid, resultErr) } else { changes.Auth = true handler.Stat.AddOneMsg("auth_successfull") answer = inIns.MakeOkAnswer("{\"auth\":true}") insType = coreprocessing.TypeInstructionOk rllogger.Outputf(rllogger.LogDebug, "Successfull auth from %s", inIns.Cid) } result = coreprocessing.NewCoreInstruction(insType) result.SetAnswer(answer) result.StateChanges = &changes return result }
func ProcCallServerMethod( handler *coreprocessing.Handler, inIns *coreprocessing.CoreInstruction, outIns *coreprocessing.CoreInstruction) []*coreprocessing.CoreInstruction { // var result []*coreprocessing.CoreInstruction if answer, exists := outIns.GetAnswer(); exists { if (*answer).Error.Code == 0 { if srcCmd, hasCmd := inIns.GetCommand(); hasCmd { rpcData := RpcAnswerData{} // little overhead - parse JSON if loadErr := json.Unmarshal([]byte((*answer).Result), &rpcData); loadErr == nil { srcParams := (*srcCmd).Params srcParams.Task = rpcData.Task // replace cid srcParams.Cid = rpcData.Cid newCmd := transport.NewCommandWithParams(0, (*srcCmd).Method, srcParams) resultIns := coreprocessing.NewCoreInstruction(coreprocessing.TypeInstructionExecute) resultIns.SetCommand(newCmd) result = []*coreprocessing.CoreInstruction{resultIns} } else { rllogger.Outputf( rllogger.LogError, "Answer from ProcRouteRpc has incorrect data format, from: %s", inIns.Cid) } } else { rllogger.Outputf(rllogger.LogError, "Answer lost in ProcRouteRpc! from: %s", inIns.Cid) } } } else { rllogger.Outputf(rllogger.LogError, "Answer lost in ProcRouteRpc! from: %s", inIns.Cid) } return result }
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) } }