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