Changeset 9b1baac in mainline for uspace/srv/ns/service.c


Ignore:
Timestamp:
2018-07-18T08:35:42Z (7 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0b05082
Parents:
edc64c0
Message:

ns: register service interfaces individually

Each service interface is now registered individually with the naming
service. This adds a degree of type safety, potentially allows the
individual interfaces to be implemented by independent tasks and moves
the code slightly closer to the full-fledged ports design.

Broker services (e.g. the location service) can still register a
fallback port for receiving connections to all interface types
explicitly using service_register_broker().

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/ns/service.c

    redc64c0 r9b1baac  
    4747        service_t service;
    4848
     49        /** Interface hash table */
     50        hash_table_t iface_hash_table;
     51
     52        /** Broker session to the service */
     53        async_sess_t *broker_sess;
     54} hashed_service_t;
     55
     56/** Interface hash table item. */
     57typedef struct {
     58        ht_link_t link;
     59
     60        /** Interface ID */
     61        iface_t iface;
     62
    4963        /** Session to the service */
    5064        async_sess_t *sess;
    51 } hashed_service_t;
     65} hashed_iface_t;
    5266
    5367static size_t service_key_hash(void *key)
     
    7084
    7185        return service->service == *(service_t *) key;
     86}
     87
     88static size_t iface_key_hash(void *key)
     89{
     90        return *(iface_t *) key;
     91}
     92
     93static size_t iface_hash(const ht_link_t *item)
     94{
     95        hashed_iface_t *iface =
     96            hash_table_get_inst(item, hashed_iface_t, link);
     97
     98        return iface->iface;
     99}
     100
     101static bool iface_key_equal(void *key, const ht_link_t *item)
     102{
     103        hashed_iface_t *iface =
     104            hash_table_get_inst(item, hashed_iface_t, link);
     105
     106        return iface->iface == *(iface_t *) key;
    72107}
    73108
     
    81116};
    82117
     118/** Operations for interface hash table. */
     119static hash_table_ops_t iface_hash_table_ops = {
     120        .hash = iface_hash,
     121        .key_hash = iface_key_hash,
     122        .key_equal = iface_key_equal,
     123        .equal = NULL,
     124        .remove_callback = NULL
     125};
     126
    83127/** Service hash table structure. */
    84128static hash_table_t service_hash_table;
     
    94138static list_t pending_conn;
    95139
    96 errno_t service_init(void)
     140errno_t ns_service_init(void)
    97141{
    98142        if (!hash_table_create(&service_hash_table, 0, 0,
     
    107151}
    108152
     153static void ns_forward(async_sess_t *sess, ipc_call_t *call, iface_t iface)
     154{
     155        async_exch_t *exch = async_exchange_begin(sess);
     156        async_forward_fast(call, exch, iface, IPC_GET_ARG3(*call), 0,
     157            IPC_FF_NONE);
     158        async_exchange_end(exch);
     159}
     160
    109161/** Process pending connection requests */
    110 void process_pending_conn(void)
     162void ns_pending_conn_process(void)
    111163{
    112164loop:
    113165        list_foreach(pending_conn, link, pending_conn_t, pending) {
    114                 ht_link_t *link = hash_table_find(&service_hash_table, &pending->service);
     166                ht_link_t *link =
     167                    hash_table_find(&service_hash_table, &pending->service);
    115168                if (!link)
    116169                        continue;
    117170
    118                 hashed_service_t *hashed_service = hash_table_get_inst(link, hashed_service_t, link);
    119                 async_exch_t *exch = async_exchange_begin(hashed_service->sess);
    120                 async_forward_fast(&pending->call, exch, pending->iface,
    121                     IPC_GET_ARG3(pending->call), 0, IPC_FF_NONE);
    122                 async_exchange_end(exch);
     171                hashed_service_t *hashed_service =
     172                    hash_table_get_inst(link, hashed_service_t, link);
     173
     174                link = hash_table_find(&hashed_service->iface_hash_table,
     175                    &pending->iface);
     176                if (!link) {
     177                        if (hashed_service->broker_sess != NULL) {
     178                                ns_forward(hashed_service->broker_sess, &pending->call,
     179                                    pending->iface);
     180
     181                                list_remove(&pending->link);
     182                                free(pending);
     183
     184                                goto loop;
     185                        }
     186
     187                        continue;
     188                }
     189
     190                hashed_iface_t *hashed_iface =
     191                    hash_table_get_inst(link, hashed_iface_t, link);
     192
     193                ns_forward(hashed_iface->sess, &pending->call, pending->iface);
    123194
    124195                list_remove(&pending->link);
     
    129200}
    130201
     202/** Register interface to a service.
     203 *
     204 * @param service Service to which the interface belongs.
     205 * @param iface   Interface to be registered.
     206 *
     207 * @return Zero on success or a value from @ref errno.h.
     208 *
     209 */
     210static errno_t ns_iface_register(hashed_service_t *hashed_service, iface_t iface)
     211{
     212        ht_link_t *link = hash_table_find(&hashed_service->iface_hash_table,
     213            &iface);
     214        if (link)
     215                return EEXIST;
     216
     217        hashed_iface_t *hashed_iface =
     218            (hashed_iface_t *) malloc(sizeof(hashed_iface_t));
     219        if (!hashed_iface)
     220                return ENOMEM;
     221
     222        hashed_iface->iface = iface;
     223        hashed_iface->sess = async_callback_receive(EXCHANGE_SERIALIZE);
     224        if (hashed_iface->sess == NULL) {
     225                free(hashed_iface);
     226                return EIO;
     227        }
     228
     229        hash_table_insert(&hashed_service->iface_hash_table,
     230            &hashed_iface->link);
     231        return EOK;
     232}
     233
     234/** Register broker to a service.
     235 *
     236 * @param service Service to which the broker belongs.
     237 *
     238 * @return Zero on success or a value from @ref errno.h.
     239 *
     240 */
     241static errno_t ns_broker_register(hashed_service_t *hashed_service)
     242{
     243        if (hashed_service->broker_sess != NULL)
     244                return EEXIST;
     245
     246        hashed_service->broker_sess = async_callback_receive(EXCHANGE_SERIALIZE);
     247        if (hashed_service->broker_sess == NULL)
     248                return EIO;
     249
     250        return EOK;
     251}
     252
    131253/** Register service.
    132254 *
    133255 * @param service Service to be registered.
    134  * @param phone   Phone to be used for connections to the service.
    135  * @param call    Pointer to call structure.
     256 * @param iface   Interface to be registered.
    136257 *
    137258 * @return Zero on success or a value from @ref errno.h.
    138259 *
    139260 */
    140 errno_t register_service(service_t service, sysarg_t phone, ipc_call_t *call)
    141 {
    142         if (hash_table_find(&service_hash_table, &service))
    143                 return EEXIST;
     261errno_t ns_service_register(service_t service, iface_t iface)
     262{
     263        ht_link_t *link = hash_table_find(&service_hash_table, &service);
     264
     265        if (link) {
     266                hashed_service_t *hashed_service =
     267                    hash_table_get_inst(link, hashed_service_t, link);
     268
     269                assert(hashed_service->service == service);
     270
     271                return ns_iface_register(hashed_service, iface);
     272        }
    144273
    145274        hashed_service_t *hashed_service =
     
    148277                return ENOMEM;
    149278
     279        if (!hash_table_create(&hashed_service->iface_hash_table, 0, 0,
     280            &iface_hash_table_ops)) {
     281                free(hashed_service);
     282                return ENOMEM;
     283        }
     284
     285        hashed_service->broker_sess = NULL;
    150286        hashed_service->service = service;
    151         hashed_service->sess = async_callback_receive(EXCHANGE_SERIALIZE);
    152         if (hashed_service->sess == NULL)
    153                 return EIO;
     287        errno_t rc = ns_iface_register(hashed_service, iface);
     288        if (rc != EOK) {
     289                free(hashed_service);
     290                return rc;
     291        }
    154292
    155293        hash_table_insert(&service_hash_table, &hashed_service->link);
     294        return EOK;
     295}
     296
     297/** Register broker service.
     298 *
     299 * @param service Broker service to be registered.
     300 *
     301 * @return Zero on success or a value from @ref errno.h.
     302 *
     303 */
     304errno_t ns_service_register_broker(service_t service)
     305{
     306        ht_link_t *link = hash_table_find(&service_hash_table, &service);
     307
     308        if (link) {
     309                hashed_service_t *hashed_service =
     310                    hash_table_get_inst(link, hashed_service_t, link);
     311
     312                assert(hashed_service->service == service);
     313
     314                return ns_broker_register(hashed_service);
     315        }
     316
     317        hashed_service_t *hashed_service =
     318            (hashed_service_t *) malloc(sizeof(hashed_service_t));
     319        if (!hashed_service)
     320                return ENOMEM;
     321
     322        if (!hash_table_create(&hashed_service->iface_hash_table, 0, 0,
     323            &iface_hash_table_ops)) {
     324                free(hashed_service);
     325                return ENOMEM;
     326        }
     327
     328        hashed_service->broker_sess = NULL;
     329        hashed_service->service = service;
     330        errno_t rc = ns_broker_register(hashed_service);
     331        if (rc != EOK) {
     332                free(hashed_service);
     333                return rc;
     334        }
     335
     336        hash_table_insert(&service_hash_table, &hashed_service->link);
     337        return EOK;
     338}
     339
     340/** Add pending connection */
     341static errno_t ns_pending_conn_add(service_t service, iface_t iface,
     342    ipc_call_t *call)
     343{
     344        pending_conn_t *pending =
     345            (pending_conn_t *) malloc(sizeof(pending_conn_t));
     346        if (!pending)
     347                return ENOMEM;
     348
     349        link_initialize(&pending->link);
     350        pending->service = service;
     351        pending->iface = iface;
     352        pending->call = *call;
     353
     354        list_append(&pending->link, &pending_conn);
    156355        return EOK;
    157356}
     
    166365 *
    167366 */
    168 void connect_to_service(service_t service, iface_t iface, ipc_call_t *call)
     367void ns_service_forward(service_t service, iface_t iface, ipc_call_t *call)
    169368{
    170369        sysarg_t flags = IPC_GET_ARG4(*call);
     
    175374                if (flags & IPC_FLAG_BLOCKING) {
    176375                        /* Blocking connection, add to pending list */
    177                         pending_conn_t *pending =
    178                             (pending_conn_t *) malloc(sizeof(pending_conn_t));
    179                         if (!pending) {
    180                                 retval = ENOMEM;
    181                                 goto out;
    182                         }
    183 
    184                         link_initialize(&pending->link);
    185                         pending->service = service;
    186                         pending->iface = iface;
    187                         pending->call = *call;
    188 
    189                         list_append(&pending->link, &pending_conn);
     376                        errno_t rc = ns_pending_conn_add(service, iface, call);
     377                        if (rc == EOK)
     378                                return;
     379
     380                        retval = rc;
     381                        goto out;
     382                }
     383
     384                retval = ENOENT;
     385                goto out;
     386        }
     387
     388        hashed_service_t *hashed_service =
     389            hash_table_get_inst(link, hashed_service_t, link);
     390
     391        link = hash_table_find(&hashed_service->iface_hash_table, &iface);
     392        if (!link) {
     393                if (hashed_service->broker_sess != NULL) {
     394                        ns_forward(hashed_service->broker_sess, call, iface);
    190395                        return;
    191396                }
    192397
     398                if (flags & IPC_FLAG_BLOCKING) {
     399                        /* Blocking connection, add to pending list */
     400                        errno_t rc = ns_pending_conn_add(service, iface, call);
     401                        if (rc == EOK)
     402                                return;
     403
     404                        retval = rc;
     405                        goto out;
     406                }
     407
    193408                retval = ENOENT;
    194409                goto out;
    195410        }
    196411
    197         hashed_service_t *hashed_service = hash_table_get_inst(link, hashed_service_t, link);
    198         async_exch_t *exch = async_exchange_begin(hashed_service->sess);
    199         async_forward_fast(call, exch, iface, IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
    200         async_exchange_end(exch);
     412        hashed_iface_t *hashed_iface =
     413            hash_table_get_inst(link, hashed_iface_t, link);
     414
     415        ns_forward(hashed_iface->sess, call, iface);
    201416        return;
    202417
Note: See TracChangeset for help on using the changeset viewer.