1 /*
2 * Copyright (C) 2014-2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <assert.h>
18 #include <lk/list.h>
19 #include <stddef.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <trusty/time.h>
24 #include <trusty_ipc.h>
25 #include <uapi/err.h>
26
27 #define TLOG_TAG "ipc-unittest-srv"
28
29 #include <app/ipc_unittest/common.h>
30 #include <ipc_unittest_uuid_consts.h>
31
32 typedef void (*event_handler_proc_t)(const uevent_t* ev);
33
34 typedef struct tipc_event_handler {
35 event_handler_proc_t proc;
36 void* priv;
37 } tipc_event_handler_t;
38
39 typedef struct tipc_srv {
40 const char* name;
41 unsigned int msg_num;
42 size_t msg_size;
43 unsigned int port_flags;
44 size_t port_state_size;
45 size_t chan_state_size;
46 event_handler_proc_t port_handler;
47 event_handler_proc_t chan_handler;
48 } tipc_srv_t;
49
50 typedef struct tipc_srv_state {
51 const struct tipc_srv* service;
52 handle_t port;
53 void* priv;
54 tipc_event_handler_t handler;
55 } tipc_srv_state_t;
56
57 /* closer services */
58 static void closer1_handle_port(const uevent_t* ev);
59
60 typedef struct closer1_state {
61 unsigned int conn_cnt;
62 } closer1_state_t;
63
64 static void closer2_handle_port(const uevent_t* ev);
65
66 typedef struct closer2_state {
67 unsigned int conn_cnt;
68 } closer2_state_t;
69
70 static void closer3_handle_port(const uevent_t* ev);
71
72 typedef struct closer3_state {
73 handle_t chans[4];
74 unsigned int chan_cnt;
75 } closer3_state_t;
76
77 /* connect service */
78 static void connect_handle_port(const uevent_t* ev);
79
80 /* datasync service */
81 static void datasink_handle_port(const uevent_t* ev);
82 static void datasink_handle_chan(const uevent_t* ev);
83
84 /* datasink service has no per channel state so we can
85 * just attach handler struct directly to channel handle
86 */
87 static struct tipc_event_handler _datasink_chan_handler = {
88 .proc = datasink_handle_chan,
89 .priv = NULL,
90 };
91
92 /* echo service */
93 static void echo_handle_port(const uevent_t* ev);
94 static void echo_handle_chan(const uevent_t* ev);
95
96 struct echo_msg {
97 uint8_t msg_buf[MAX_PORT_BUF_SIZE];
98 size_t msg_len;
99 handle_t handles[IPC_MAX_MSG_HANDLES];
100 size_t handle_cnt;
101 };
102
103 typedef struct echo_chan_state {
104 struct tipc_event_handler handler;
105 unsigned int msg_max_num;
106 struct echo_msg echo_msgs[];
107 } echo_chan_state_t;
108
109 /* uuid service */
110 static void uuid_handle_port(const uevent_t* ev);
111
112 /* Other globals */
113 static bool stopped = false;
114
115 /************************************************************************/
116
117 #define IPC_PORT_ALLOW_ALL \
118 (IPC_PORT_ALLOW_NS_CONNECT | IPC_PORT_ALLOW_TA_CONNECT)
119
120 #define SRV_NAME(name) SRV_PATH_BASE ".srv." name
121
122 static const struct tipc_srv _services[] = {
123 {
124 .name = SRV_NAME("closer1"),
125 .msg_num = 2,
126 .msg_size = 64,
127 .port_flags = IPC_PORT_ALLOW_ALL,
128 .port_handler = closer1_handle_port,
129 .port_state_size = sizeof(struct closer1_state),
130 .chan_handler = NULL,
131 },
132 {
133 .name = SRV_NAME("closer2"),
134 .msg_num = 2,
135 .msg_size = 64,
136 .port_flags = IPC_PORT_ALLOW_ALL,
137 .port_handler = closer2_handle_port,
138 .port_state_size = sizeof(struct closer2_state),
139 .chan_handler = NULL,
140 },
141 {
142 .name = SRV_NAME("closer3"),
143 .msg_num = 2,
144 .msg_size = 64,
145 .port_flags = IPC_PORT_ALLOW_ALL,
146 .port_handler = closer3_handle_port,
147 .port_state_size = sizeof(struct closer3_state),
148 .chan_handler = NULL,
149 },
150 {
151 .name = SRV_NAME("connect"),
152 .msg_num = 2,
153 .msg_size = 64,
154 .port_flags = IPC_PORT_ALLOW_TA_CONNECT,
155 .port_handler = connect_handle_port,
156 .chan_handler = NULL,
157 },
158 /* datasink services */
159 {
160 .name = SRV_NAME("datasink"),
161 .msg_num = 2,
162 .msg_size = 64,
163 .port_flags = IPC_PORT_ALLOW_ALL,
164 .port_handler = datasink_handle_port,
165 .chan_handler = NULL,
166 },
167 {
168 .name = SRV_NAME("ns_only"),
169 .msg_num = 8,
170 .msg_size = 64,
171 .port_flags = IPC_PORT_ALLOW_NS_CONNECT,
172 .port_handler = datasink_handle_port,
173 .chan_handler = NULL,
174 },
175 {
176 .name = SRV_NAME("ta_only"),
177 .msg_num = 8,
178 .msg_size = 64,
179 .port_flags = IPC_PORT_ALLOW_TA_CONNECT,
180 .port_handler = datasink_handle_port,
181 .chan_handler = NULL,
182 },
183 /* echo */
184 {
185 .name = SRV_NAME("echo"),
186 .msg_num = 8,
187 .msg_size = MAX_PORT_BUF_SIZE,
188 .port_flags = IPC_PORT_ALLOW_ALL,
189 .port_handler = echo_handle_port,
190 .chan_handler = echo_handle_chan,
191 },
192 /* uuid test */
193 {
194 .name = SRV_NAME("uuid"),
195 .msg_num = 2,
196 .msg_size = 64,
197 .port_flags = IPC_PORT_ALLOW_ALL,
198 .port_handler = uuid_handle_port,
199 .chan_handler = NULL,
200 },
201 };
202
203 static struct tipc_srv_state _srv_states[countof(_services)] = {
204 [0 ...(countof(_services) - 1)] =
205 {
206 .port = INVALID_IPC_HANDLE,
207 },
208 };
209
210 /************************************************************************/
211
get_srv_state(const uevent_t * ev)212 static struct tipc_srv_state* get_srv_state(const uevent_t* ev) {
213 return containerof(ev->cookie, struct tipc_srv_state, handler);
214 }
215
_destroy_service(struct tipc_srv_state * state)216 static void _destroy_service(struct tipc_srv_state* state) {
217 if (!state) {
218 TLOGI("non-null state expected\n");
219 return;
220 }
221
222 /* free state if any */
223 if (state->priv) {
224 free(state->priv);
225 state->priv = NULL;
226 }
227
228 /* close port */
229 if (state->port != INVALID_IPC_HANDLE) {
230 int rc = close(state->port);
231 if (rc != NO_ERROR) {
232 TLOGI("Failed (%d) to close port %d\n", rc, state->port);
233 }
234 state->port = INVALID_IPC_HANDLE;
235 }
236
237 /* reset handler */
238 state->service = NULL;
239 state->handler.proc = NULL;
240 state->handler.priv = NULL;
241 }
242
243 /*
244 * Create service
245 */
_create_service(const struct tipc_srv * srv,struct tipc_srv_state * state)246 static int _create_service(const struct tipc_srv* srv,
247 struct tipc_srv_state* state) {
248 if (!srv || !state) {
249 TLOGI("null services specified\n");
250 return ERR_INVALID_ARGS;
251 }
252
253 /* create port */
254 int rc = port_create(srv->name, srv->msg_num, srv->msg_size,
255 srv->port_flags);
256 if (rc < 0) {
257 TLOGI("Failed (%d) to create port\n", rc);
258 return rc;
259 }
260
261 /* setup port state */
262 state->port = (handle_t)rc;
263 state->handler.proc = srv->port_handler;
264 state->handler.priv = state;
265 state->service = srv;
266 state->priv = NULL;
267
268 if (srv->port_state_size) {
269 /* allocate port state */
270 state->priv = calloc(1, srv->port_state_size);
271 if (!state->priv) {
272 rc = ERR_NO_MEMORY;
273 goto err_calloc;
274 }
275 }
276
277 /* attach handler to port handle */
278 rc = set_cookie(state->port, &state->handler);
279 if (rc < 0) {
280 TLOGI("Failed (%d) to set cookie on port %d\n", rc, state->port);
281 goto err_set_cookie;
282 }
283
284 return NO_ERROR;
285
286 err_calloc:
287 err_set_cookie:
288 _destroy_service(state);
289 return rc;
290 }
291
292 /*
293 * Restart specified service
294 */
restart_service(struct tipc_srv_state * state)295 static int restart_service(struct tipc_srv_state* state) {
296 if (!state) {
297 TLOGI("non-null state expected\n");
298 return ERR_INVALID_ARGS;
299 }
300
301 const struct tipc_srv* srv = state->service;
302 _destroy_service(state);
303 return _create_service(srv, state);
304 }
305
306 /*
307 * Kill all servoces
308 */
kill_services(void)309 static void kill_services(void) {
310 TLOGD("Terminating unittest services\n");
311
312 /* close any opened ports */
313 for (unsigned int i = 0; i < countof(_services); i++) {
314 _destroy_service(&_srv_states[i]);
315 }
316 }
317
318 /*
319 * Initialize all services
320 */
init_services(void)321 static int init_services(void) {
322 TLOGD("Init unittest services!!!\n");
323
324 for (unsigned int i = 0; i < countof(_services); i++) {
325 int rc = _create_service(&_services[i], &_srv_states[i]);
326 if (rc < 0) {
327 TLOGI("Failed (%d) to create service %s\n", rc, _services[i].name);
328 return rc;
329 }
330 }
331
332 return 0;
333 }
334
335 /*
336 * Handle common port errors
337 */
handle_port_errors(const uevent_t * ev)338 static bool handle_port_errors(const uevent_t* ev) {
339 if ((ev->event & IPC_HANDLE_POLL_ERROR) ||
340 (ev->event & IPC_HANDLE_POLL_HUP) ||
341 (ev->event & IPC_HANDLE_POLL_MSG) ||
342 (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED)) {
343 /* should never happen with port handles */
344 TLOGI("error event (0x%x) for port (%d)\n", ev->event, ev->handle);
345
346 /* recreate service */
347 restart_service(get_srv_state(ev));
348 return true;
349 }
350
351 return false;
352 }
353
354 /****************************** connect test service *********************/
355
356 /*
357 * Local wrapper on top of async connect that provides
358 * synchronos connect with timeout.
359 */
sync_connect(const char * path,unsigned int timeout)360 int sync_connect(const char* path, unsigned int timeout) {
361 int rc;
362 uevent_t evt;
363 handle_t chan;
364
365 rc = connect(path, IPC_CONNECT_ASYNC | IPC_CONNECT_WAIT_FOR_PORT);
366 if (rc >= 0) {
367 chan = (handle_t)rc;
368 rc = wait(chan, &evt, timeout);
369 if (rc == 0) {
370 rc = ERR_BAD_STATE;
371 if (evt.handle == chan) {
372 if (evt.event & IPC_HANDLE_POLL_READY)
373 return chan;
374
375 if (evt.event & IPC_HANDLE_POLL_HUP)
376 rc = ERR_CHANNEL_CLOSED;
377 }
378 }
379 close(chan);
380 }
381 return rc;
382 }
383
connect_handle_port(const uevent_t * ev)384 static void connect_handle_port(const uevent_t* ev) {
385 uuid_t peer_uuid;
386
387 if (handle_port_errors(ev))
388 return;
389
390 if (ev->event & IPC_HANDLE_POLL_READY) {
391 char path[MAX_PORT_PATH_LEN];
392
393 /* accept incomming connection and close it */
394 int rc = accept(ev->handle, &peer_uuid);
395 if (rc < 0 && rc != ERR_CHANNEL_CLOSED) {
396 TLOGI("accept failed (%d)\n", rc);
397 return;
398 }
399 if (rc >= 0) {
400 close((handle_t)rc);
401 }
402
403 /* but then issue a series of connect requests */
404 for (unsigned int i = FIRST_FREE_HANDLE; i < MAX_USER_HANDLES; i++) {
405 sprintf(path, "%s.port.accept%d", SRV_PATH_BASE, i);
406 rc = sync_connect(path, 1000);
407 close((handle_t)rc);
408 }
409 }
410 }
411
412 /****************************** closer services **************************/
413
closer1_handle_port(const uevent_t * ev)414 static void closer1_handle_port(const uevent_t* ev) {
415 uuid_t peer_uuid;
416 struct closer1_state* st = get_srv_state(ev)->priv;
417
418 if (handle_port_errors(ev))
419 return;
420
421 if (ev->event & IPC_HANDLE_POLL_READY) {
422 /* new connection request, bump counter */
423 st->conn_cnt++;
424
425 /* accept it */
426 int rc = accept(ev->handle, &peer_uuid);
427 if (rc < 0) {
428 TLOGI("accept failed (%d)\n", rc);
429 return;
430 }
431 handle_t chan = (handle_t)rc;
432
433 if (st->conn_cnt & 1) {
434 /* sleep a bit */
435 trusty_nanosleep(0, 0, 100 * MSEC);
436 }
437 /* and close it */
438 rc = close(chan);
439 if (rc != NO_ERROR) {
440 TLOGI("Failed (%d) to close chan %d\n", rc, chan);
441 }
442 }
443 }
444
closer2_handle_port(const uevent_t * ev)445 static void closer2_handle_port(const uevent_t* ev) {
446 struct closer2_state* st = get_srv_state(ev)->priv;
447
448 if (handle_port_errors(ev))
449 return;
450
451 if (ev->event & IPC_HANDLE_POLL_READY) {
452 /* new connection request, bump counter */
453 st->conn_cnt++;
454 if (st->conn_cnt & 1) {
455 /* sleep a bit */
456 trusty_nanosleep(0, 0, 100 * MSEC);
457 }
458
459 /*
460 * then close the port without accepting any connections
461 * and restart it again
462 */
463 restart_service(get_srv_state(ev));
464 }
465 }
466
closer3_handle_port(const uevent_t * ev)467 static void closer3_handle_port(const uevent_t* ev) {
468 uuid_t peer_uuid;
469 struct closer3_state* st = get_srv_state(ev)->priv;
470
471 if (handle_port_errors(ev))
472 return;
473
474 if (ev->event & IPC_HANDLE_POLL_READY) {
475 /* accept connection */
476 int rc = accept(ev->handle, &peer_uuid);
477 if (rc < 0) {
478 TLOGI("accept failed (%d)\n", rc);
479 return;
480 }
481 /* add it to connection pool */
482 st->chans[st->chan_cnt++] = (handle_t)rc;
483
484 /* attach datasink service handler just in case */
485 set_cookie((handle_t)rc, &_datasink_chan_handler);
486
487 /* when max number of connection reached */
488 if (st->chan_cnt == countof(st->chans)) {
489 /* wait a bit */
490 trusty_nanosleep(0, 0, 100 * MSEC);
491
492 /* and close them all */
493 for (unsigned int i = 0; i < st->chan_cnt; i++)
494 close(st->chans[i]);
495 st->chan_cnt = 0;
496 }
497 return;
498 }
499 }
500
501 /****************************** datasync service **************************/
502
datasink_handle_msg(const uevent_t * ev)503 static int datasink_handle_msg(const uevent_t* ev) {
504 int rc;
505 ipc_msg_info_t inf;
506
507 /* for all messages */
508 for (;;) {
509 /* get message */
510 rc = get_msg(ev->handle, &inf);
511 if (rc == ERR_NO_MSG)
512 break; /* no new messages */
513
514 if (rc != NO_ERROR) {
515 TLOGI("failed (%d) to get_msg for chan (%d)\n", rc, ev->handle);
516 return rc;
517 }
518
519 /* and retire it without actually reading */
520 rc = put_msg(ev->handle, inf.id);
521 if (rc != NO_ERROR) {
522 TLOGI("failed (%d) to putt_msg for chan (%d)\n", rc, ev->handle);
523 return rc;
524 }
525 }
526
527 return NO_ERROR;
528 }
529
530 /*
531 * Datasink service channel handler
532 */
datasink_handle_chan(const uevent_t * ev)533 static void datasink_handle_chan(const uevent_t* ev) {
534 if ((ev->event & IPC_HANDLE_POLL_ERROR) ||
535 (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED)) {
536 /* close it as it is in an error state */
537 TLOGI("error event (0x%x) for chan (%d)\n", ev->event, ev->handle);
538 close(ev->handle);
539 return;
540 }
541
542 if (ev->event & IPC_HANDLE_POLL_MSG) {
543 if (datasink_handle_msg(ev) != 0) {
544 close(ev->handle);
545 return;
546 }
547 }
548
549 if (ev->event & IPC_HANDLE_POLL_HUP) {
550 /* closed by peer */
551 close(ev->handle);
552 return;
553 }
554 }
555
556 /*
557 * Datasink service port event handler
558 */
datasink_handle_port(const uevent_t * ev)559 static void datasink_handle_port(const uevent_t* ev) {
560 uuid_t peer_uuid;
561
562 if (handle_port_errors(ev))
563 return;
564
565 if (ev->event & IPC_HANDLE_POLL_READY) {
566 /* incomming connection: accept it */
567 int rc = accept(ev->handle, &peer_uuid);
568 if (rc < 0) {
569 TLOGI("failed (%d) to accept on port %d\n", rc, ev->handle);
570 return;
571 }
572
573 handle_t chan = (handle_t)rc;
574 rc = set_cookie(chan, &_datasink_chan_handler);
575 if (rc) {
576 TLOGI("failed (%d) to set_cookie on chan %d\n", rc, chan);
577 }
578 }
579 }
580
581 /****************************** echo service **************************/
582
send_msg_wait(handle_t chan,ipc_msg_t * msg)583 static int send_msg_wait(handle_t chan, ipc_msg_t* msg) {
584 int rc;
585 uevent_t ev;
586
587 while (true) {
588 rc = send_msg(chan, msg);
589
590 if (rc != ERR_NOT_ENOUGH_BUFFER) {
591 return rc;
592 }
593
594 while (true) {
595 rc = wait(chan, &ev, INFINITE_TIME);
596 if (rc < 0) {
597 return rc;
598 }
599
600 if (ev.event & IPC_HANDLE_POLL_HUP) {
601 /*
602 * It is possible that ev.event & IPC_HANDLE_POLL_MSG is also
603 * true which means the client sent a message and hung up on us.
604 * There isn't anything the echo server can do with those, so we
605 * simply log the occurrence.
606 */
607 if (ev.event & IPC_HANDLE_POLL_MSG) {
608 TLOGW("Client sent a message and hung up;"
609 " message discarded.\n");
610 }
611
612 return ERR_CHANNEL_CLOSED;
613 }
614
615 if (ev.event & IPC_HANDLE_POLL_SEND_UNBLOCKED) {
616 break;
617 }
618
619 /* if ev.event & IPC_HANDLE_POLL_MSG is true, continue looping */
620 }
621 }
622
623 __UNREACHABLE;
624 }
625
echo_handle_msg(const uevent_t * ev)626 static int echo_handle_msg(const uevent_t* ev) {
627 int rc;
628 ipc_msg_info_t msg_info;
629 ipc_msg_t msg;
630 msg.num_iov = 1;
631 size_t msg_cnt = 0;
632 echo_chan_state_t* st = containerof(ev->cookie, echo_chan_state_t, handler);
633
634 /* get all messages */
635 while (msg_cnt < st->msg_max_num) {
636 rc = get_msg(ev->handle, &msg_info);
637 if (rc == ERR_NO_MSG)
638 break; /* no new messages */
639
640 if (rc != NO_ERROR) {
641 TLOGI("failed (%d) to get_msg for chan (%d)\n", rc, ev->handle);
642 return rc;
643 }
644
645 /* save handle count */
646 st->echo_msgs[msg_cnt].handle_cnt = msg_info.num_handles;
647 /* prepare message structure for read */
648 struct iovec iov = {
649 .iov_base = (void*)st->echo_msgs[msg_cnt].msg_buf,
650 .iov_len = MAX_PORT_BUF_SIZE,
651 };
652 msg.iov = &iov;
653 msg.handles = st->echo_msgs[msg_cnt].handles;
654 msg.num_handles = msg_info.num_handles;
655
656 /* read msg content */
657 rc = read_msg(ev->handle, msg_info.id, 0, &msg);
658 if (rc < 0) {
659 TLOGI("failed (%d) to read_msg for chan (%d)\n", rc, ev->handle);
660 return rc;
661 }
662
663 /* update number of bytes received */
664 st->echo_msgs[msg_cnt].msg_len = (size_t)rc;
665
666 /* retire original message */
667 rc = put_msg(ev->handle, msg_info.id);
668 if (rc != NO_ERROR) {
669 TLOGI("failed (%d) to put_msg for chan (%d)\n", rc, ev->handle);
670 return rc;
671 }
672
673 msg_cnt++;
674 }
675
676 /* echo all messages received */
677 for (unsigned int i = 0; i < msg_cnt; i++) {
678 /* prepare message structure for send */
679 struct iovec iov = {
680 .iov_base = (void*)st->echo_msgs[i].msg_buf,
681 .iov_len = st->echo_msgs[i].msg_len,
682 };
683 msg.iov = &iov;
684 msg.handles = st->echo_msgs[i].handles;
685 msg.num_handles = st->echo_msgs[i].handle_cnt;
686
687 /* and send it back */
688 rc = send_msg_wait(ev->handle, &msg);
689
690 /* close all received handles */
691 for (unsigned int j = 0; j < msg.num_handles; j++) {
692 close(st->echo_msgs[i].handles[j]);
693 }
694
695 if (rc < 0) {
696 TLOGI("failed (%d) to send_msg for chan (%d)\n", rc, ev->handle);
697 return rc;
698 }
699 }
700 return NO_ERROR;
701 }
702
703 /*
704 * echo service channel handler
705 */
echo_handle_chan(const uevent_t * ev)706 static void echo_handle_chan(const uevent_t* ev) {
707 if (ev->event & IPC_HANDLE_POLL_ERROR) {
708 /* close it as it is in an error state */
709 TLOGI("error event (0x%x) for chan (%d)\n", ev->event, ev->handle);
710 goto close_it;
711 }
712
713 if (ev->event & (IPC_HANDLE_POLL_MSG | IPC_HANDLE_POLL_SEND_UNBLOCKED)) {
714 if (echo_handle_msg(ev) != 0) {
715 TLOGI("error event (0x%x) for chan (%d)\n", ev->event, ev->handle);
716 goto close_it;
717 }
718 }
719
720 if (ev->event & IPC_HANDLE_POLL_HUP) {
721 goto close_it;
722 }
723
724 return;
725
726 close_it:
727 free(ev->cookie);
728 close(ev->handle);
729 }
730
731 /*
732 * echo service port event handler
733 */
echo_handle_port(const uevent_t * ev)734 static void echo_handle_port(const uevent_t* ev) {
735 uuid_t peer_uuid;
736 struct echo_chan_state* chan_st;
737 const struct tipc_srv* srv = get_srv_state(ev)->service;
738
739 if (handle_port_errors(ev))
740 return;
741
742 if (ev->event & IPC_HANDLE_POLL_READY) {
743 handle_t chan;
744
745 /* incomming connection: accept it */
746 int rc = accept(ev->handle, &peer_uuid);
747 if (rc < 0) {
748 TLOGI("failed (%d) to accept on port %d\n", rc, ev->handle);
749 return;
750 }
751 chan = (handle_t)rc;
752
753 chan_st = calloc(1, sizeof(struct echo_chan_state) +
754 sizeof(struct echo_msg) * srv->msg_num);
755 if (!chan_st) {
756 TLOGI("failed (%d) to callocate state for chan %d\n", rc, chan);
757 close(chan);
758 return;
759 }
760
761 /* init state */
762 chan_st->msg_max_num = srv->msg_num;
763 chan_st->handler.proc = srv->chan_handler;
764 chan_st->handler.priv = chan_st;
765
766 /* attach it to handle */
767 rc = set_cookie(chan, &chan_st->handler);
768 if (rc) {
769 TLOGI("failed (%d) to set_cookie on chan %d\n", rc, chan);
770 free(chan_st);
771 close(chan);
772 return;
773 }
774 }
775 }
776
777 /***************************************************************************/
778
779 /*
780 * uuid service port event handler
781 */
uuid_handle_port(const uevent_t * ev)782 static void uuid_handle_port(const uevent_t* ev) {
783 ipc_msg_t msg;
784 struct iovec iov;
785 uuid_t peer_uuid;
786
787 if (handle_port_errors(ev))
788 return;
789
790 if (ev->event & IPC_HANDLE_POLL_READY) {
791 handle_t chan;
792
793 /* incomming connection: accept it */
794 int rc = accept(ev->handle, &peer_uuid);
795 if (rc < 0) {
796 TLOGI("failed (%d) to accept on port %d\n", rc, ev->handle);
797 return;
798 }
799 chan = (handle_t)rc;
800
801 /* send interface uuid */
802 iov.iov_base = &peer_uuid;
803 iov.iov_len = sizeof(peer_uuid);
804 msg.num_iov = 1;
805 msg.iov = &iov;
806 msg.num_handles = 0;
807 msg.handles = NULL;
808 rc = send_msg(chan, &msg);
809 if (rc < 0) {
810 TLOGI("failed (%d) to send_msg for chan (%d)\n", rc, chan);
811 }
812
813 /* and close channel */
814 close(chan);
815 }
816 }
817
818 /***************************************************************************/
819
820 /*
821 * Dispatch event
822 */
dispatch_event(const uevent_t * ev)823 static void dispatch_event(const uevent_t* ev) {
824 assert(ev);
825
826 if (ev->event == IPC_HANDLE_POLL_NONE) {
827 /* not really an event, do nothing */
828 TLOGI("got an empty event\n");
829 return;
830 }
831
832 if (ev->handle == INVALID_IPC_HANDLE) {
833 /* not a valid handle */
834 TLOGI("got an event (0x%x) with invalid handle (%d)", ev->event,
835 ev->handle);
836 return;
837 }
838
839 /* check if we have handler */
840 struct tipc_event_handler* handler = ev->cookie;
841 if (handler && handler->proc) {
842 /* invoke it */
843 handler->proc(ev);
844 return;
845 }
846
847 /* no handler? close it */
848 TLOGI("no handler for event (0x%x) with handle %d\n", ev->event,
849 ev->handle);
850 close(ev->handle);
851
852 return;
853 }
854
855 /*
856 * Main entry point of service task
857 */
main(void)858 int main(void) {
859 int rc;
860 uevent_t event;
861
862 /* Initialize service */
863 rc = init_services();
864 if (rc != NO_ERROR) {
865 TLOGI("Failed (%d) to init service", rc);
866 kill_services();
867 return -1;
868 }
869
870 /* handle events */
871 while (!stopped) {
872 event.handle = INVALID_IPC_HANDLE;
873 event.event = 0;
874 event.cookie = NULL;
875 rc = wait_any(&event, INFINITE_TIME);
876 if (rc < 0) {
877 TLOGI("wait_any failed (%d)", rc);
878 continue;
879 }
880 if (rc == NO_ERROR) { /* got an event */
881 dispatch_event(&event);
882 }
883 }
884
885 kill_services();
886 return 0;
887 }
888