1 /* 2 * Copyright (C) 2019 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 #pragma once 18 19 #include <lib/tipc/tipc.h> 20 #include <lk/compiler.h> 21 #include <lk/list.h> 22 #include <stddef.h> 23 24 __BEGIN_CDECLS 25 26 /** 27 * DOC: Theory of Operation 28 * 29 * This module implements TIPC service framework that supports 30 * hosting multiple TIPC services within single applications in a 31 * unified manner. The service set is semi-static, it can be instantiated 32 * at runtime but individual services are not expected to terminate once 33 * instantiated. 34 * 35 * An individual TIPC service consists of one or more TIPC ports that external 36 * clients can connect to. All ports for the same service share the same set 37 * of user provided ops (callbacks) that framework invokes to handle requests 38 * in a uniform way. 39 40 * Each port can be configured individually to accept connections only from 41 * predefined set of clients identified by UUIDs. 42 * 43 * Each service can be configured to accept only limited number of connection 44 * across all ports within service. 45 * 46 * It is expected that application would make the following sequence of calls: 47 * 48 * - call tipc_hset_create function to create handle set 49 * 50 * - allocate statically or dynamically and initialize one or more tipc_port 51 * structures describing set of ports related to particular services 52 * 53 * - allocate statically or dynamically and initialize tipc_srv_ops struct 54 * containing pointers for service specific callbacks. 55 * 56 * - call tipc_add_service to add service to service set. Multiple services 57 * can be added to the same service set. 58 * 59 * - call tipc_run_event_loop to run them. This routine is not expected 60 * to return unless unrecoverable condition is encountered. 61 */ 62 63 /** 64 * struct tipc_port_acl - tipc port ACL descriptor 65 * @flags: a combination of IPC_PORT_ALLOW_XXX_CONNECT flags that will be 66 * directly passed to underlying port_create call. 67 * @uuid_num: number of entries in an array pointed by @uuids field 68 * @uuids: pointer to array of pointers to uuids of apps allowed to connect 69 * @extra_data: pointer to extra data associated with this ACL structure, which 70 * can be used in application specific way. 71 * 72 * Note: @uuid_num parameter can be 0 to indicate that there is no filtering by 73 * UUID and connection from any client will be accepted. In this case @uuids 74 * parameter is ignored and can be set NULL. 75 */ 76 struct tipc_port_acl { 77 uint32_t flags; 78 uint32_t uuid_num; 79 const struct uuid** uuids; 80 const void* extra_data; 81 }; 82 83 /** 84 * struct tipc_port - TIPC port descriptor 85 * @name: port name 86 * @msg_max_size: max message size supported 87 * @msg_queue_len: max number of messages in queue 88 * @acl: pointer to &struct tipc_port_acl specifying ACL rules 89 * @priv: port specific private data 90 * 91 * Note: @acl is a required parameter for specifying any port even if 92 * service does not require access control. 93 */ 94 struct tipc_port { 95 const char* name; 96 uint32_t msg_max_size; 97 uint32_t msg_queue_len; 98 const struct tipc_port_acl* acl; 99 const void* priv; 100 }; 101 102 /** 103 * struct tipc_srv_ops - service specific ops (callbacks) 104 * @on_connect: is invoked when a new connection is established. 105 * @on_message: is invoked when a new message is available 106 * @on_disconnect: is invoked when the peer terminates connection 107 * @on_channel_cleanup: is invoked to cleanup user allocated state 108 * 109 * The overall call flow is as follow: 110 * 111 * Upon receiving a connection request from client framework accepts it and 112 * validates against configured ACL rules. If connection is allowed, the 113 * framework allocates a channel tracking structure and invokes an optional 114 * @on_connect callback if specified. The user who choose to implement this 115 * callback can allocate its own tracking structure and return pointer to that 116 * through @ctx_p parameter. After that this pointer will be associated with 117 * particular channel and it will be passed to all other callbacks. 118 * 119 * Upon receiving a message directed to particular channel, a corresponding 120 * @on_message callback is invoked so this message can be handled according 121 * with application specific protocol. The @on_message call back is a 122 * mandatory in this implementation. 123 * 124 * Upon receiving a disconnect request an optional @on_disconnect callback is 125 * invoked to indicate that peer closed connection. At this point the channel 126 * is still alive but in disconnected state, it will be closed by framework 127 * after control returns from executing this callback. 128 * 129 * The @on_channel_cleanup callback is invoked by framework to give the user 130 * a chance to release channel specific resources if allocated by 131 * @on_connect callback, after the channel have been closed. This 132 * callback is mandatory if the user implements @on_connect callback and 133 * allocates per channel state. 134 * 135 * The @on_send_unblocked callback is invoked when a channel becomes unblocked 136 * for sending after an earlier %ERR_NOT_ENOUGH_BUFFER error code returned 137 * by tipc_send1() or ipc_send_msg(). 138 * 139 * Note: an application implementing these callbacks MUST not close channel 140 * received as @chan parameter directly, instead it should return an error 141 * and the channel will be closed by the framework. 142 * 143 */ 144 struct tipc_srv_ops { 145 int (*on_connect)(const struct tipc_port* port, 146 handle_t chan, 147 const struct uuid* peer, 148 void** ctx_p); 149 150 int (*on_message)(const struct tipc_port* port, handle_t chan, void* ctx); 151 152 void (*on_disconnect)(const struct tipc_port* port, 153 handle_t chan, 154 void* ctx); 155 156 void (*on_channel_cleanup)(void* ctx); 157 158 int (*on_send_unblocked)(const struct tipc_port* port, 159 handle_t chan, 160 void* ctx); 161 }; 162 163 /** 164 * tipc_add_service() - Add new service to service set 165 * @hset: pointer to handle set to add service to 166 * @ports: an array of &struct tipc_port describing ports for this 167 * service 168 * @num_ports: number of ports in array pointed by @ports 169 * @max_chan_cnt: max number of active connections allowed for this service, 0 170 * for no limit. 171 * @ops: pointer to &struct tipc_srv_ops with service specific 172 * callbacks 173 * 174 * Note: the caller retain an ownership of structures pointed by @ports 175 * parameters and should not modify these structures in any way after the 176 * service has beed instantiated. Also, the caller is responsible for keeping 177 * them alive while service is running. The same is true for handle set. In 178 * addition, the caller should not invoke any direct operations on handle set 179 * outside of API's provided by this framework. 180 * 181 * Return: 0 on success, negative error code otherwise 182 */ 183 int tipc_add_service(struct tipc_hset* hset, 184 const struct tipc_port* ports, 185 uint32_t num_ports, 186 uint32_t max_chan_cnt, 187 const struct tipc_srv_ops* ops); 188 189 __END_CDECLS 190