source: mainline/ns/ns.c@ 04552a80

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 04552a80 was 04552a80, checked in by Martin Decky <martin@…>, 19 years ago

code cleanup (somebody should read the coding style guide)
remove DONT_OPEN_STDIO (this has to be done in a different way, ppc32 linker segfaults on initiating extern variable)
remove deprecated libipc stuff

  • Property mode set to 100644
File size: 7.6 KB
RevLine 
[babe786]1/*
2 * Copyright (C) 2006 Ondrej Palkovsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * @file ns.c
31 * @brief Naming service for HelenOS IPC.
32 */
33
[38edb96]34#include <ipc/ipc.h>
35#include <ipc/ns.h>
[69cdeec]36#include <stdio.h>
37#include <unistd.h>
38#include <stdlib.h>
39#include <errno.h>
[babe786]40#include <assert.h>
41#include <libadt/list.h>
42#include <libadt/hash_table.h>
43
44#define NAME "NS"
45
46#define NS_HASH_TABLE_CHAINS 20
47
[043dcc27]48static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call);
49static int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid);
50
[babe786]51/* Static functions implementing NS hash table operations. */
52static hash_index_t ns_hash(unsigned long *key);
53static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item);
[043dcc27]54static void ns_remove(link_t *item);
[babe786]55
56/** Operations for NS hash table. */
57static hash_table_operations_t ns_hash_table_ops = {
58 .hash = ns_hash,
59 .compare = ns_compare,
[043dcc27]60 .remove_callback = ns_remove
[babe786]61};
62
63/** NS hash table structure. */
64static hash_table_t ns_hash_table;
65
66/** NS hash table item. */
67typedef struct {
68 link_t link;
69 ipcarg_t service; /**< Number of the service. */
70 ipcarg_t phone; /**< Phone registered with the service. */
[043dcc27]71 ipcarg_t in_phone_hash; /**< Incoming phone hash. */
[babe786]72} hashed_service_t;
73
74int static ping_phone;
[69cdeec]75
76int main(int argc, char **argv)
77{
78 ipc_call_t call;
79 ipc_callid_t callid;
[6efe0ddf]80 char *as_area;
[69cdeec]81
82 ipcarg_t retval, arg1, arg2;
83
[afa6e74]84// printf("%s: Naming service started.\n", NAME);
[babe786]85
[043dcc27]86 if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, &ns_hash_table_ops)) {
[afa6e74]87// printf("%s: cannot create hash table\n", NAME);
[babe786]88 return ENOMEM;
89 }
[250717cc]90
[69cdeec]91 while (1) {
[04a73cdf]92 callid = ipc_wait_for_call(&call);
[250717cc]93// printf("NS: Call in_phone_hash=%lX...", call.in_phone_hash);
[4c61e60]94 switch (IPC_GET_METHOD(call)) {
[6efe0ddf]95 case IPC_M_AS_AREA_SEND:
96 as_area = (char *)IPC_GET_ARG2(call);
[afa6e74]97// printf("Received as_area: %P, size:%d\n", as_area, IPC_GET_ARG3(call));
[250717cc]98 retval = ipc_answer_fast(callid, 0,(sysarg_t)(1024*1024), 0);
[8a568e3]99 if (!retval) {
[afa6e74]100// printf("Reading shared memory...");
101// printf("Text: %s", as_area);
[8a568e3]102 } else
[afa6e74]103// printf("Failed answer: %d\n", retval);
[8a568e3]104 continue;
105 break;
[6180b57]106 case IPC_M_INTERRUPT:
[afa6e74]107// printf("GOT INTERRUPT: %c\n", IPC_GET_ARG2(call));
[6180b57]108 break;
[7048773]109 case IPC_M_PHONE_HUNGUP:
[afa6e74]110// printf("Phone hung up.\n");
[7048773]111 retval = 0;
112 break;
[043dcc27]113 case IPC_M_CONNECT_TO_ME:
[babe786]114 /*
[043dcc27]115 * Server requests service registration.
[babe786]116 */
[043dcc27]117 retval = register_service(IPC_GET_ARG1(call), IPC_GET_ARG3(call), &call);
118 ping_phone = IPC_GET_ARG3(call);
[69cdeec]119 break;
[7048773]120 case IPC_M_CONNECT_ME_TO:
[043dcc27]121 /*
122 * Client requests to be connected to a service.
123 */
124 retval = connect_to_service(IPC_GET_ARG1(call), &call, callid);
[11eae82]125 break;
[108602e]126 case NS_HANGUP:
[afa6e74]127// printf("Closing connection.\n");
[108602e]128 retval = EHANGUP;
129 break;
[69cdeec]130 case NS_PING:
[afa6e74]131// printf("Ping...%P %P\n", IPC_GET_ARG1(call),
132// IPC_GET_ARG2(call));
[69cdeec]133 retval = 0;
134 arg1 = 0xdead;
135 arg2 = 0xbeef;
136 break;
137 case NS_PING_SVC:
[afa6e74]138// printf("NS:Pinging service %d\n", ping_phone);
[babe786]139 ipc_call_sync(ping_phone, NS_PING, 0xbeef, 0);
[afa6e74]140// printf("NS:Got pong\n");
[69cdeec]141 break;
142 default:
[afa6e74]143// printf("Unknown method: %zd\n", IPC_GET_METHOD(call));
[69cdeec]144 retval = ENOENT;
145 break;
146 }
[602ca36b]147 if (! (callid & IPC_CALLID_NOTIFICATION)) {
[250717cc]148// printf("Answering.\n");
149 ipc_answer_fast(callid, retval, arg1, arg2);
[602ca36b]150 }
[69cdeec]151 }
152}
[babe786]153
[108602e]154/** Register service.
[043dcc27]155 *
156 * @param service Service to be registered.
157 * @param phone phone Phone to be used for connections to the service.
158 * @param call Pointer to call structure.
159 *
160 * @return Zero on success or a value from @ref errno.h.
161 */
162int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)
163{
164 unsigned long keys[3] = { service, call->in_phone_hash, 0 };
165 hashed_service_t *hs;
166
[afa6e74]167// printf("Registering service %d on phone %d...", service, phone);
[043dcc27]168
169 if (hash_table_find(&ns_hash_table, keys)) {
[afa6e74]170// printf("Service %d already registered.\n", service);
[043dcc27]171 return EEXISTS;
172 }
173
174 hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
175 if (!hs) {
[afa6e74]176// printf("Failed to register service %d.\n", service);
[043dcc27]177 return ENOMEM;
178 }
179
180 link_initialize(&hs->link);
181 hs->service = service;
182 hs->phone = phone;
183 hs->in_phone_hash = call->in_phone_hash;
184 hash_table_insert(&ns_hash_table, keys, &hs->link);
185
186 return 0;
187}
188
189/** Connect client to service.
190 *
191 * @param service Service to be connected to.
192 * @param call Pointer to call structure.
193 * @param callid Call ID of the request.
194 *
195 * @return Zero on success or a value from @ref errno.h.
196 */
197int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)
198{
199 unsigned long keys[3] = { service, 0, 0 };
200 link_t *hlp;
201 hashed_service_t *hs;
202
203 hlp = hash_table_find(&ns_hash_table, keys);
204 if (!hlp) {
[250717cc]205// printf("Service %d not registered.\n", service);
[043dcc27]206 return ENOENT;
207 }
208 hs = hash_table_get_instance(hlp, hashed_service_t, link);
[afa6e74]209// printf("Connecting in_phone_hash=%lX to service at phone %d...", call->in_phone_hash, hs->phone);
[043dcc27]210 return ipc_forward_fast(callid, hs->phone, 0, 0);
211}
212
[babe786]213/** Compute hash index into NS hash table.
214 *
[043dcc27]215 * @param key Pointer keys. However, only the first key (i.e. service number)
216 * is used to compute the hash index.
217 * @return Hash index corresponding to key[0].
[babe786]218 */
219hash_index_t ns_hash(unsigned long *key)
220{
221 assert(key);
222 return *key % NS_HASH_TABLE_CHAINS;
223}
224
225/** Compare a key with hashed item.
226 *
[043dcc27]227 * This compare function always ignores the third key.
228 * It exists only to make it possible to remove records
229 * originating from connection with key[1] in_phone_hash
230 * value. Note that this is close to being classified
231 * as a nasty hack.
232 *
233 * @param key Array of keys.
234 * @param keys Must be lesser or equal to 3.
[babe786]235 * @param item Pointer to a hash table item.
236 * @return Non-zero if the key matches the item, zero otherwise.
237 */
[043dcc27]238int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)
[babe786]239{
240 hashed_service_t *hs;
241
242 assert(key);
[043dcc27]243 assert(keys <= 3);
[babe786]244 assert(item);
245
246 hs = hash_table_get_instance(item, hashed_service_t, link);
247
[043dcc27]248 if (keys == 2)
249 return key[1] == hs->in_phone_hash;
250 else
251 return key[0] == hs->service;
252}
253
254/** Perform actions after removal of item from the hash table.
255 *
256 * @param item Item that was removed from the hash table.
257 */
258void ns_remove(link_t *item)
259{
260 assert(item);
261 free(hash_table_get_instance(item, hashed_service_t, link));
[babe786]262}
Note: See TracBrowser for help on using the repository browser.