* @brief This function is called (indirectly) when we receive a "call" SML * message from the kernel. *************************************************************/
| 394 | * message from the kernel. |
| 395 | *************************************************************/ |
| 396 | ElementXML* Kernel::ProcessIncomingSML(Connection* pConnection, ElementXML* pIncomingMsg) |
| 397 | { |
| 398 | // Create a reply |
| 399 | ElementXML* pResponse = pConnection->CreateSMLResponse(pIncomingMsg) ; |
| 400 | |
| 401 | // Make sure the connection hasn't been closed along the way |
| 402 | if (pConnection->IsClosed()) |
| 403 | { |
| 404 | return pResponse ; |
| 405 | } |
| 406 | |
| 407 | // Special case. We want to intercept XML trace messages and pass them directly to the handler |
| 408 | // without analyzing them. This is just to boost performance for these messages as speed is critical here |
| 409 | // as they're used for trace output. |
| 410 | Agent* pAgent = IsXMLTraceEvent(pIncomingMsg) ; |
| 411 | if (pAgent) |
| 412 | { |
| 413 | pAgent->ReceivedXMLTraceEvent(smlEVENT_XML_TRACE_OUTPUT, pIncomingMsg, pResponse) ; |
| 414 | return pResponse ; |
| 415 | } |
| 416 | |
| 417 | // Analyze the message and find important tags |
| 418 | AnalyzeXML msg ; |
| 419 | msg.Analyze(pIncomingMsg) ; |
| 420 | |
| 421 | // Get the "name" attribute from the <command> tag |
| 422 | char const* pCommandName = msg.GetCommandName() ; |
| 423 | |
| 424 | // Look up the agent name parameter (most commands have this) |
| 425 | char const* pAgentName = msg.GetArgString(sml_Names::kParamAgent) ; |
| 426 | |
| 427 | // Find the client agent structure that matches this agent |
| 428 | if (pAgentName && pCommandName) |
| 429 | { |
| 430 | Agent* pAgent = GetAgent(pAgentName) ; |
| 431 | |
| 432 | // If this is a command for a known agent and it's an "output" command |
| 433 | // then we're interested in it. |
| 434 | if (pAgent && strcmp(sml_Names::kCommand_Output, pCommandName) == 0) |
| 435 | { |
| 436 | // Pass the incoming message over to the agent |
| 437 | pAgent->ReceivedOutput(&msg, pResponse) ; |
| 438 | } |
| 439 | |
| 440 | // If this is a command for a known agent and it's an "output_init" command |
| 441 | // then we're interested in it. Note that this is a special case and |
| 442 | // is not the spot for general init-soar event handling. |
| 443 | if (pAgent && strcmp(sml_Names::kCommand_OutputInit, pCommandName) == 0) |
| 444 | { |
| 445 | // Remove the output link |
| 446 | pAgent->GetWM()->InvalidateOutputLink(); |
| 447 | } |
| 448 | |
| 449 | if (pAgent && strcmp(sml_Names::kCommand_Event, pCommandName) == 0) |
| 450 | { |
| 451 | // This is an event specific to an agent, so handle it there. |
| 452 | pAgent->ReceivedEvent(&msg, pResponse) ; |
| 453 | } |
no test coverage detected