1 /* SilcAsyncOperation tests */
2
3 #include "silc.h"
4 #include "silcfsm.h"
5 #include "silcasync.h"
6
7 typedef void (*Callback)(void *context);
8
9 SilcSchedule schedule;
10
11 typedef struct {
12 SilcFSM fsm;
13 SilcFSMEventStruct sema;
14 SilcAsyncOperation op;
15 Callback cb;
16 void *cb_context;
17 SilcBool aborted;
18 } *Foo;
19
20 SILC_FSM_STATE(test_st_start);
21 SILC_FSM_STATE(test_st_second);
22 SILC_FSM_STATE(test_st_finish);
23
SILC_TASK_CALLBACK(async_call_timeout)24 SILC_TASK_CALLBACK(async_call_timeout)
25 {
26 Foo f = context;
27 SILC_LOG_DEBUG(("******Async call cb, continuing FSM"));
28 silc_async_free(f->op);
29 f->cb(f->cb_context);
30 }
31
async_abort(SilcAsyncOperation op,void * context)32 static void async_abort(SilcAsyncOperation op, void *context)
33 {
34 Foo f = context;
35 SILC_LOG_DEBUG(("Async operation aborted"));
36 silc_schedule_task_del_by_context(schedule, f);
37 silc_schedule_task_del_by_callback(schedule, async_call_timeout);
38 f->aborted = TRUE;
39 }
40
async_call(Callback cb,void * context)41 static SilcAsyncOperation async_call(Callback cb, void *context)
42 {
43 Foo f = context;
44
45 SILC_LOG_DEBUG(("Async call"));
46
47 f->cb = cb;
48 f->cb_context = context;
49 f->op = silc_async_alloc(async_abort, NULL, f);
50
51 silc_schedule_task_add(schedule, 0, async_call_timeout, f, 2, 1,
52 SILC_TASK_TIMEOUT);
53
54 return f->op;
55 }
56
async_call_cb(void * context)57 static void async_call_cb(void *context)
58 {
59 Foo f = context;
60 SILC_LOG_DEBUG(("*******Callback, signal and continue to next state"));
61 f->op = NULL;
62 SILC_FSM_EVENT_SIGNAL(&f->sema);
63 SILC_FSM_CALL_CONTINUE(f->fsm);
64 }
65
SILC_FSM_STATE(test_st_start)66 SILC_FSM_STATE(test_st_start)
67 {
68 Foo f = fsm_context;
69
70 SILC_LOG_DEBUG(("test_st_start"));
71
72 silc_fsm_event_init(&f->sema, fsm);
73
74 /** Wait async callback */
75 SILC_LOG_DEBUG(("Call async call"));
76 silc_fsm_next_later(fsm, test_st_second, 1, 0);
77 SILC_FSM_CALL((f->op = async_call(async_call_cb, f)));
78 }
79
SILC_FSM_STATE(test_st_second)80 SILC_FSM_STATE(test_st_second)
81 {
82 Foo f = fsm_context;
83 SilcBool timedout;
84
85 SILC_LOG_DEBUG(("test_st_second"));
86
87 SILC_FSM_EVENT_TIMEDWAIT(&f->sema, 0, 1, &timedout);
88
89 if (timedout == TRUE) {
90 SILC_LOG_DEBUG(("Sema timedout, aborting async operation"));
91 if (f->op)
92 silc_async_abort(f->op, NULL, NULL);
93 }
94
95 /** Finish */
96 silc_fsm_next_later(fsm, test_st_finish, 2, 0);
97 return SILC_FSM_WAIT;
98 }
99
SILC_FSM_STATE(test_st_finish)100 SILC_FSM_STATE(test_st_finish)
101 {
102 SILC_LOG_DEBUG(("test_st_finish"));
103
104 SILC_LOG_DEBUG(("Finish machine"));
105 return SILC_FSM_FINISH;
106 }
107
destructor(SilcFSM fsm,void * fsm_context,void * destructor_context)108 static void destructor(SilcFSM fsm, void *fsm_context,
109 void *destructor_context)
110 {
111 SILC_LOG_DEBUG(("FSM destructor, stopping scheduler"));
112 silc_fsm_free(fsm);
113 silc_schedule_stop(schedule);
114 }
115
main(int argc,char ** argv)116 int main(int argc, char **argv)
117 {
118 SilcBool success = FALSE;
119 SilcFSM fsm;
120 Foo f;
121
122 if (argc > 1 && !strcmp(argv[1], "-d")) {
123 silc_log_debug(TRUE);
124 silc_log_debug_hexdump(TRUE);
125 silc_log_set_debug_string("*async*");
126 }
127
128 SILC_LOG_DEBUG(("Allocating scheduler"));
129 schedule = silc_schedule_init(0, NULL);
130
131 f = silc_calloc(1, sizeof(*f));
132 if (!f)
133 goto err;
134
135 SILC_LOG_DEBUG(("Allocating FSM context"));
136 fsm = silc_fsm_alloc(f, destructor, NULL, schedule);
137 if (!fsm)
138 goto err;
139 silc_fsm_start(fsm, test_st_start);
140 f->fsm = fsm;
141
142 SILC_LOG_DEBUG(("Running scheduler"));
143 silc_schedule(schedule);
144
145 if (!f->aborted)
146 goto err;
147
148 silc_schedule_uninit(schedule);
149 silc_free(f);
150
151 success = TRUE;
152
153 err:
154 SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
155 fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
156
157 return success;
158 }
159