OpenLcbCLib 1.0 Alpha
OpenSource C Library to create OpenLcb/Lcc Nodes
Loading...
Searching...
No Matches
openlcb_login_statemachine.c File Reference

Implementation of the login state machine dispatcher. More...

Functions

void OpenLcbLoginStateMachine_initialize (const interface_openlcb_login_state_machine_t *interface_openlcb_login_state_machine)
 Stores the callback interface and wires up the outgoing message buffer.
 
void OpenLcbLoginStateMachine_process (openlcb_login_statemachine_info_t *openlcb_statemachine_info)
 Dispatches to the handler matching node->run_state.
 
bool OpenLcbLoginStatemachine_handle_outgoing_openlcb_message (void)
 Tries to send the pending outgoing message.
 
bool OpenLcbLoginStatemachine_handle_try_reenumerate (void)
 Re-enters the current handler if the enumerate flag is set.
 
bool OpenLcbLoginStatemachine_handle_try_enumerate_first_node (void)
 Gets the first node and processes it if login is not complete.
 
bool OpenLcbLoginStatemachine_handle_try_enumerate_next_node (void)
 Advances to the next node and processes it if login is not complete.
 
void OpenLcbLoginMainStatemachine_run (void)
 Runs one non-blocking step of login processing. Call from main loop.
 
openlcb_login_statemachine_info_tOpenLcbLoginStatemachine_get_statemachine_info (void)
 Returns pointer to internal state machine info. For unit testing only.
 

Detailed Description

Implementation of the login state machine dispatcher.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This module implements the main dispatcher for the OpenLCB login state machine. It manages the complete node initialization sequence by coordinating:

  • Node enumeration across all virtual nodes in the system
  • State-based dispatching to appropriate message handlers
  • Message transmission and retry logic
  • Re-enumeration control for multi-message sequences

Architecture Overview: The state machine uses a polling architecture where OpenLcbLoginMainStatemachine_run() is called repeatedly from the main application loop. Each call performs one atomic operation and returns immediately, maintaining a non-blocking design.

Processing Flow (per call to run function):

  1. Check for pending outgoing message and attempt transmission
  2. If enumerate flag set, re-enter current handler for next message
  3. If no current node, get first node from enumeration list
  4. If current node exists, get next node from enumeration list
  5. Process node if run_state indicates initialization in progress

State Dispatch Logic: The process function examines the node's run_state and calls the appropriate handler from the interface:

  • RUNSTATE_LOAD_INITIALIZATION_COMPLETE -> load_initialization_complete()
  • RUNSTATE_LOAD_PRODUCER_EVENTS -> load_producer_events()
  • RUNSTATE_LOAD_CONSUMER_EVENTS -> load_consumer_events()
  • RUNSTATE_LOGIN_COMPLETE -> on_login_complete() if set, then RUNSTATE_RUN
  • RUNSTATE_RUN or higher -> skip (already initialized)

Multi-Message Sequences: For nodes with multiple producer or consumer events, handlers set the enumerate flag to trigger re-entry without advancing to the next node. This allows sending multiple messages in sequence while maintaining the non-blocking design.

Internal State: The module maintains static state including:

  • Interface function pointers (set during initialization)
  • State machine info structure (current node, outgoing message buffer, flags)
  • Outgoing message buffer (pre-allocated, reused for all messages)
Author
Jim Kueneman
Date
4 Mar 2026
See also
openlcb_login_statemachine_handler.c - Message construction handlers
OpenLCB Message Network Standard S-9.7.3.1 - Initialization Complete
OpenLCB Event Transport Standard S-9.7.4 - Event Transport Protocol

Function Documentation

◆ OpenLcbLoginStateMachine_initialize()

void OpenLcbLoginStateMachine_initialize ( const interface_openlcb_login_state_machine_t * interface_openlcb_login_state_machine)

Stores the callback interface and wires up the outgoing message buffer.

Stores the callback interface. Call once at startup after OpenLcbLoginMessageHandler_initialize().

Algorithm:

  1. Store interface pointer
  2. Link outgoing message buffer pointers in state machine info
  3. Set payload type to BASIC, clear message and payload
  4. Mark buffer as allocated, set current node to NULL
* @param interface_openlcb_login_state_machine Pointer to interface structure
* 

◆ OpenLcbLoginStateMachine_process()

void OpenLcbLoginStateMachine_process ( openlcb_login_statemachine_info_t * openlcb_statemachine_info)

Dispatches to the handler matching node->run_state.

Dispatches to the handler matching node->run_state. Exposed for unit testing.

Algorithm:

  1. Switch on run_state
  2. RUNSTATE_LOAD_INITIALIZATION_COMPLETE → load_initialization_complete()
  3. RUNSTATE_LOAD_PRODUCER_EVENTS → load_producer_events()
  4. RUNSTATE_LOAD_CONSUMER_EVENTS → load_consumer_events()
  5. RUNSTATE_LOGIN_COMPLETE → on_login_complete() if set, then RUNSTATE_RUN
  6. All other states → return without action
* @param openlcb_statemachine_info Pointer to state machine info with node and message buffer
* 

◆ OpenLcbLoginStatemachine_handle_outgoing_openlcb_message()

bool OpenLcbLoginStatemachine_handle_outgoing_openlcb_message ( void )

Tries to send the pending outgoing message.

Tries to send the pending message; returns true if one was pending. Exposed for unit testing.

Algorithm:

  1. If valid flag not set, return false
  2. Call send_openlcb_msg(); clear valid on success
  3. Return true (caller should keep retrying until sent)
Returns
true if a message was pending, false if idle

◆ OpenLcbLoginStatemachine_handle_try_reenumerate()

bool OpenLcbLoginStatemachine_handle_try_reenumerate ( void )

Re-enters the current handler if the enumerate flag is set.

Re-enters the state processor if the enumerate flag is set. Exposed for unit testing.

Algorithm:

  1. If enumerate flag not set, return false
  2. Call process_login_statemachine() to generate next message
  3. Return true (keep going until handler clears the flag)
Returns
true if re-enumeration occurred, false if complete

◆ OpenLcbLoginStatemachine_handle_try_enumerate_first_node()

bool OpenLcbLoginStatemachine_handle_try_enumerate_first_node ( void )

Gets the first node and processes it if login is not complete.

Starts enumeration from the first node if none is active. Exposed for unit testing.

Algorithm:

  1. If current node already set, return false
  2. Get first node; return true if NULL (no nodes)
  3. If run_state < RUNSTATE_RUN, call process_login_statemachine()
  4. Return true
Returns
true if first node attempt was made, false if current node already exists

◆ OpenLcbLoginStatemachine_handle_try_enumerate_next_node()

bool OpenLcbLoginStatemachine_handle_try_enumerate_next_node ( void )

Advances to the next node and processes it if login is not complete.

Advances to the next node needing login. Exposed for unit testing.

Algorithm:

  1. If no current node, return false
  2. Get next node; return true if NULL (end of list)
  3. If run_state < RUNSTATE_RUN, call process_login_statemachine()
  4. Return true
Returns
true if next node attempt was made, false if no current node exists

◆ OpenLcbLoginMainStatemachine_run()

void OpenLcbLoginMainStatemachine_run ( void )

Runs one non-blocking step of login processing. Call from main loop.

Algorithm:

  1. Try to send pending outgoing message (highest priority)
  2. Re-enumerate if multi-message sequence in progress
  3. Get first node if none active
  4. Advance to next node Each step returns immediately after one operation.

◆ OpenLcbLoginStatemachine_get_statemachine_info()

openlcb_login_statemachine_info_t * OpenLcbLoginStatemachine_get_statemachine_info ( void )

Returns pointer to internal state machine info. For unit testing only.

Returns pointer to internal static state machine info. For unit testing only — do not modify.


Copyright (c) 2026 Jim Kueneman all rights reserved. See the License