/src/libwebsockets/lib/core-net/state.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * libwebsockets - small server side websockets and web server implementation |
3 | | * |
4 | | * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com> |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | | * of this software and associated documentation files (the "Software"), to |
8 | | * deal in the Software without restriction, including without limitation the |
9 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
10 | | * sell copies of the Software, and to permit persons to whom the Software is |
11 | | * furnished to do so, subject to the following conditions: |
12 | | * |
13 | | * The above copyright notice and this permission notice shall be included in |
14 | | * all copies or substantial portions of the Software. |
15 | | * |
16 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
22 | | * IN THE SOFTWARE. |
23 | | */ |
24 | | |
25 | | #include "private-lib-core.h" |
26 | | |
27 | | void |
28 | | lws_state_reg_notifier(lws_state_manager_t *mgr, |
29 | | lws_state_notify_link_t *notify_link) |
30 | 0 | { |
31 | 0 | lws_dll2_add_head(¬ify_link->list, &mgr->notify_list); |
32 | 0 | } |
33 | | |
34 | | void |
35 | | lws_state_reg_deregister(lws_state_notify_link_t *nl) |
36 | 0 | { |
37 | 0 | lws_dll2_remove(&nl->list); |
38 | 0 | } |
39 | | |
40 | | void |
41 | | lws_state_reg_notifier_list(lws_state_manager_t *mgr, |
42 | | lws_state_notify_link_t * const *notify_link_array) |
43 | 0 | { |
44 | 0 | if (notify_link_array) |
45 | 0 | while (*notify_link_array) |
46 | 0 | lws_state_reg_notifier(mgr, *notify_link_array++); |
47 | 0 | } |
48 | | |
49 | | #if (_LWS_ENABLED_LOGS & (LLL_INFO | LLL_DEBUG)) |
50 | | static const char * |
51 | | _systnm(lws_state_manager_t *mgr, int state, char *temp8) |
52 | 0 | { |
53 | 0 | if (!mgr->state_names) { |
54 | 0 | lws_snprintf(temp8, 8, "%d", state); |
55 | 0 | return temp8; |
56 | 0 | } |
57 | | |
58 | 0 | return mgr->state_names[state]; |
59 | 0 | } |
60 | | #endif |
61 | | |
62 | | static int |
63 | | _report(lws_state_manager_t *mgr, int a, int b) |
64 | 0 | { |
65 | 0 | #if (_LWS_ENABLED_LOGS & LLL_INFO) |
66 | 0 | char temp8[8]; |
67 | 0 | #endif |
68 | |
|
69 | 0 | lws_start_foreach_dll(struct lws_dll2 *, d, mgr->notify_list.head) { |
70 | 0 | lws_state_notify_link_t *l = |
71 | 0 | lws_container_of(d, lws_state_notify_link_t, list); |
72 | |
|
73 | 0 | if (l->notify_cb(mgr, l, a, b)) { |
74 | | /* a dependency took responsibility for retry */ |
75 | |
|
76 | 0 | #if (_LWS_ENABLED_LOGS & LLL_INFO) |
77 | 0 | lwsl_cx_info(mgr->context, "%s: %s: rejected '%s' -> '%s'", |
78 | 0 | mgr->name, l->name, |
79 | 0 | _systnm(mgr, a, temp8), |
80 | 0 | _systnm(mgr, b, temp8)); |
81 | 0 | #endif |
82 | |
|
83 | 0 | return 1; |
84 | 0 | } |
85 | |
|
86 | 0 | } lws_end_foreach_dll(d); |
87 | |
|
88 | 0 | return 0; |
89 | 0 | } |
90 | | |
91 | | static int |
92 | | _lws_state_transition(lws_state_manager_t *mgr, int target) |
93 | 0 | { |
94 | 0 | #if (_LWS_ENABLED_LOGS & LLL_DEBUG) |
95 | 0 | char temp8[8]; |
96 | 0 | #endif |
97 | |
|
98 | 0 | if (_report(mgr, mgr->state, target)) |
99 | 0 | return 1; |
100 | | |
101 | 0 | #if (_LWS_ENABLED_LOGS & LLL_DEBUG) |
102 | 0 | if (mgr->context) |
103 | 0 | lwsl_cx_debug(mgr->context, "%s: changed %d '%s' -> %d '%s'", mgr->name, |
104 | 0 | mgr->state, _systnm(mgr, mgr->state, temp8), target, |
105 | 0 | _systnm(mgr, target, temp8)); |
106 | 0 | #endif |
107 | |
|
108 | 0 | mgr->state = target; |
109 | | |
110 | | /* Indicate success by calling the notifers again with both args same */ |
111 | 0 | _report(mgr, target, target); |
112 | |
|
113 | 0 | #if defined(LWS_WITH_SYS_SMD) |
114 | 0 | if (mgr->smd_class && mgr->context) |
115 | 0 | (void)lws_smd_msg_printf(mgr->context, |
116 | 0 | mgr->smd_class, "{\"state\":\"%s\"}", |
117 | 0 | mgr->state_names[target]); |
118 | 0 | #endif |
119 | |
|
120 | 0 | return 0; |
121 | 0 | } |
122 | | |
123 | | int |
124 | | lws_state_transition_steps(lws_state_manager_t *mgr, int target) |
125 | 0 | { |
126 | 0 | int n = 0; |
127 | 0 | #if (_LWS_ENABLED_LOGS & LLL_INFO) |
128 | 0 | int i = mgr->state; |
129 | 0 | char temp8[8]; |
130 | 0 | #endif |
131 | |
|
132 | 0 | if (mgr->state > target) |
133 | 0 | return 0; |
134 | | |
135 | 0 | while (!n && mgr->state != target) |
136 | 0 | n = _lws_state_transition(mgr, mgr->state + 1); |
137 | |
|
138 | 0 | #if (_LWS_ENABLED_LOGS & LLL_INFO) |
139 | 0 | lwsl_cx_info(mgr->context, "%s -> %s", _systnm(mgr, i, temp8), |
140 | 0 | _systnm(mgr, mgr->state, temp8)); |
141 | 0 | #endif |
142 | |
|
143 | 0 | return 0; |
144 | 0 | } |
145 | | |
146 | | int |
147 | | lws_state_transition(lws_state_manager_t *mgr, int target) |
148 | 0 | { |
149 | 0 | if (mgr->state != target) |
150 | 0 | _lws_state_transition(mgr, target); |
151 | |
|
152 | 0 | return 0; |
153 | 0 | } |