Coverage Report

Created: 2026-07-14 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open5gs/lib/core/ogs-fsm.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
3
 *
4
 * This file is part of Open5GS.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
#include "ogs-core.h"
21
22
typedef struct fsm_event_s {
23
    int id;
24
} fsm_event_t;
25
26
static fsm_event_t entry_event = {
27
    OGS_FSM_ENTRY_SIG,
28
};
29
static fsm_event_t exit_event = {
30
    OGS_FSM_EXIT_SIG,
31
};
32
33
const char *OGS_FSM_NAME_INIT_SIG = "INIT";
34
const char *OGS_FSM_NAME_ENTRY_SIG = "ENTRY";
35
const char *OGS_FSM_NAME_EXIT_SIG = "EXIT";
36
37
static void fsm_entry(ogs_fsm_t *sm, ogs_fsm_handler_t state, fsm_event_t *e)
38
0
{
39
0
    ogs_assert(sm);
40
0
    ogs_assert(state);
41
42
0
    if (e) {
43
0
        e->id = OGS_FSM_ENTRY_SIG;
44
0
        (*state)(sm, e);
45
0
    } else {
46
0
        (*state)(sm, &entry_event);
47
0
    }
48
0
}
49
50
static void fsm_exit(ogs_fsm_t *sm, ogs_fsm_handler_t state, fsm_event_t *e)
51
0
{
52
0
    ogs_assert(sm);
53
0
    ogs_assert(state);
54
55
0
    if (e) {
56
0
        e->id = OGS_FSM_EXIT_SIG;
57
0
        (*state)(sm, e);
58
0
    } else {
59
0
        (*state)(sm, &exit_event);
60
0
    }
61
0
}
62
63
static void fsm_change(
64
        ogs_fsm_t *sm,
65
        ogs_fsm_handler_t oldstate,
66
        ogs_fsm_handler_t newstate,
67
        fsm_event_t *e)
68
0
{
69
0
    ogs_assert(sm);
70
0
    ogs_assert(oldstate);
71
0
    ogs_assert(newstate);
72
73
0
    fsm_exit(sm, oldstate, e);
74
0
    fsm_entry(sm, newstate, e);
75
0
}
76
77
void ogs_fsm_init(void *fsm, void *init, void *fini, void *event)
78
0
{
79
0
    ogs_fsm_t *sm = fsm;
80
0
    fsm_event_t *e = event;
81
82
0
    ogs_assert(sm);
83
84
0
    sm->init = sm->state = init;
85
0
    sm->fini = fini;
86
87
0
    if (sm->init) {
88
0
        (*sm->init)(sm, e);
89
90
0
        if (sm->init != sm->state) {
91
0
            ogs_assert(sm->state);
92
0
            fsm_entry(sm, sm->state, e);
93
0
        }
94
0
    }
95
0
}
96
97
void ogs_fsm_tran(void *fsm, void *state, void *event)
98
0
{
99
0
    ogs_fsm_t *sm = fsm;
100
0
    fsm_event_t *e = event;
101
0
    ogs_fsm_handler_t tmp = NULL;
102
103
0
    ogs_assert(sm);
104
105
0
    tmp = sm->state;
106
0
    ogs_assert(tmp);
107
108
0
    sm->state = state;
109
0
    ogs_assert(sm->state);
110
111
0
    if (sm->state != tmp)
112
0
        fsm_change(fsm, tmp, sm->state, e);
113
0
}
114
115
void ogs_fsm_dispatch(void *fsm, void *event)
116
0
{
117
0
    ogs_fsm_t *sm = fsm;
118
0
    fsm_event_t *e = event;
119
0
    ogs_fsm_handler_t tmp = NULL;
120
121
0
    ogs_assert(sm);
122
123
0
    tmp = sm->state;
124
0
    ogs_assert(tmp);
125
126
0
    if (e)
127
0
        (*tmp)(sm, e);
128
129
0
    if (sm->state != tmp)
130
0
        fsm_change(fsm, tmp, sm->state, e);
131
0
}
132
133
void ogs_fsm_fini(void *fsm, void *event)
134
0
{
135
0
    ogs_fsm_t *sm = fsm;
136
0
    fsm_event_t *e = event;
137
138
0
    ogs_assert(sm);
139
140
0
    if (sm->fini != sm->state) {
141
0
        ogs_assert(sm->state);
142
0
        fsm_exit(sm, sm->state, e);
143
144
0
        if (sm->fini)
145
0
            (*sm->fini)(sm, e);
146
0
    }
147
148
0
    sm->init = sm->state = sm->fini = NULL;
149
0
}