Changeset 9b1baac in mainline for uspace/srv/ns


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().

Location:
uspace/srv/ns
Files:
5 edited

Legend:

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

    redc64c0 r9b1baac  
    5454static list_t cs_req;
    5555
    56 errno_t clonable_init(void)
     56errno_t ns_clonable_init(void)
    5757{
    5858        list_initialize(&cs_req);
     
    6161
    6262/** Return true if @a service is clonable. */
    63 bool service_clonable(service_t service)
     63bool ns_service_is_clonable(service_t service, iface_t iface)
    6464{
    65         return (service == SERVICE_LOADER);
     65        return (service == SERVICE_LOADER) && (iface == INTERFACE_LOADER);
    6666}
    6767
    6868/** Register clonable service.
    6969 *
    70  * @param service Service to be registered.
    71  * @param phone   Phone to be used for connections to the service.
    72  * @param call    Pointer to call structure.
     70 * @param call Pointer to call structure.
    7371 *
    7472 */
    75 void register_clonable(service_t service, sysarg_t phone, ipc_call_t *call)
     73void ns_clonable_register(ipc_call_t *call)
    7674{
    7775        link_t *req_link = list_first(&cs_req);
     
    8785
    8886        /* Currently we can only handle a single type of clonable service. */
    89         assert(csr->service == SERVICE_LOADER);
     87        assert(ns_service_is_clonable(csr->service, csr->iface));
    9088
    9189        async_answer_0(call, EOK);
     
    113111 *
    114112 */
    115 void connect_to_clonable(service_t service, iface_t iface, ipc_call_t *call)
     113void ns_clonable_forward(service_t service, iface_t iface, ipc_call_t *call)
    116114{
    117         assert(service == SERVICE_LOADER);
     115        assert(ns_service_is_clonable(service, iface));
    118116
    119117        cs_req_t *csr = malloc(sizeof(cs_req_t));
  • uspace/srv/ns/clonable.h

    redc64c0 r9b1baac  
    3939#include <stdbool.h>
    4040
    41 extern errno_t clonable_init(void);
     41extern errno_t ns_clonable_init(void);
    4242
    43 extern bool service_clonable(service_t);
    44 extern void register_clonable(service_t, sysarg_t, ipc_call_t *);
    45 extern void connect_to_clonable(service_t, iface_t, ipc_call_t *);
     43extern bool ns_service_is_clonable(service_t, iface_t);
     44extern void ns_clonable_register(ipc_call_t *);
     45extern void ns_clonable_forward(service_t, iface_t, ipc_call_t *);
    4646
    4747#endif
  • uspace/srv/ns/ns.c

    redc64c0 r9b1baac  
    6161                 * Client requests to be connected to a service.
    6262                 */
    63                 if (service_clonable(service)) {
    64                         connect_to_clonable(service, iface, icall);
     63                if (ns_service_is_clonable(service, iface)) {
     64                        ns_clonable_forward(service, iface, icall);
    6565                } else {
    66                         connect_to_service(service, iface, icall);
     66                        ns_service_forward(service, iface, icall);
    6767                }
     68
    6869                return;
    6970        }
     
    7273
    7374        while (true) {
    74                 process_pending_conn();
     75                ns_pending_conn_process();
    7576
    7677                async_get_call(&call);
     
    8283
    8384                service_t service;
    84                 sysarg_t phone;
    8585
    8686                switch (IPC_GET_IMETHOD(call)) {
    8787                case NS_REGISTER:
    8888                        service = IPC_GET_ARG1(call);
    89                         phone = IPC_GET_ARG5(call);
     89                        iface = IPC_GET_ARG2(call);
    9090
    9191                        /*
    9292                         * Server requests service registration.
    9393                         */
    94                         if (service_clonable(service)) {
    95                                 register_clonable(service, phone, &call);
     94                        if (ns_service_is_clonable(service, iface)) {
     95                                ns_clonable_register(&call);
    9696                                continue;
    9797                        } else {
    98                                 retval = register_service(service, phone, &call);
     98                                retval = ns_service_register(service, iface);
    9999                        }
    100100
     101                        break;
     102                case NS_REGISTER_BROKER:
     103                        service = IPC_GET_ARG1(call);
     104                        retval = ns_service_register_broker(service);
    101105                        break;
    102106                case NS_PING:
     
    115119                        break;
    116120                default:
    117                         printf("ns: method not supported\n");
     121                        printf("%s: Method not supported (%" PRIun ")\n",
     122                            NAME, IPC_GET_IMETHOD(call));
    118123                        retval = ENOTSUP;
    119124                        break;
     
    130135        printf("%s: HelenOS IPC Naming Service\n", NAME);
    131136
    132         errno_t rc = service_init();
     137        errno_t rc = ns_service_init();
    133138        if (rc != EOK)
    134139                return rc;
    135140
    136         rc = clonable_init();
     141        rc = ns_clonable_init();
    137142        if (rc != EOK)
    138143                return rc;
  • 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
  • uspace/srv/ns/service.h

    redc64c0 r9b1baac  
    3838#include <abi/ipc/interfaces.h>
    3939
    40 extern errno_t service_init(void);
    41 extern void process_pending_conn(void);
     40extern errno_t ns_service_init(void);
     41extern void ns_pending_conn_process(void);
    4242
    43 extern errno_t register_service(service_t, sysarg_t, ipc_call_t *);
    44 extern void connect_to_service(service_t, iface_t, ipc_call_t *);
     43extern errno_t ns_service_register(service_t, iface_t);
     44extern errno_t ns_service_register_broker(service_t);
     45extern void ns_service_forward(service_t, iface_t, ipc_call_t *);
    4546
    4647#endif
Note: See TracChangeset for help on using the changeset viewer.