source: mainline/ns/ns.c@ abda850

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since abda850 was abda850, checked in by Jakub Jermar <jakub@…>, 19 years ago

Sync with kernel.
Args for IPC_M_AS_AREA_SEND changed.

  • Property mode set to 100644
File size: 7.6 KB
Line 
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
34#include <ipc/ipc.h>
35#include <ipc/ns.h>
36#include <stdio.h>
37#include <unistd.h>
38#include <stdlib.h>
39#include <errno.h>
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
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
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);
54static void ns_remove(link_t *item);
55
56/** Operations for NS hash table. */
57static hash_table_operations_t ns_hash_table_ops = {
58 .hash = ns_hash,
59 .compare = ns_compare,
60 .remove_callback = ns_remove
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. */
71 ipcarg_t in_phone_hash; /**< Incoming phone hash. */
72} hashed_service_t;
73
74int static ping_phone;
75
76int main(int argc, char **argv)
77{
78 ipc_call_t call;
79 ipc_callid_t callid;
80 char *as_area;
81
82 ipcarg_t retval, arg1, arg2;
83
84// printf("%s: Naming service started.\n", NAME);
85
86 if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, &ns_hash_table_ops)) {
87// printf("%s: cannot create hash table\n", NAME);
88 return ENOMEM;
89 }
90
91 while (1) {
92 callid = ipc_wait_for_call(&call);
93// printf("NS: Call in_phone_hash=%lX...", call.in_phone_hash);
94 switch (IPC_GET_METHOD(call)) {
95 case IPC_M_AS_AREA_SEND:
96 as_area = (char *)IPC_GET_ARG1(call);
97// printf("Received as_area: %P, size:%d\n", as_area, IPC_GET_ARG2(call));
98 retval = ipc_answer_fast(callid, 0,(sysarg_t)(1024*1024), 0);
99 if (!retval) {
100// printf("Reading shared memory...");
101// printf("Text: %s", as_area);
102 } else
103// printf("Failed answer: %d\n", retval);
104 continue;
105 break;
106 case IPC_M_INTERRUPT:
107// printf("GOT INTERRUPT: %c\n", IPC_GET_ARG2(call));
108 break;
109 case IPC_M_PHONE_HUNGUP:
110// printf("Phone hung up.\n");
111 retval = 0;
112 break;
113 case IPC_M_CONNECT_TO_ME:
114 /*
115 * Server requests service registration.
116 */
117 retval = register_service(IPC_GET_ARG1(call), IPC_GET_ARG3(call), &call);
118 ping_phone = IPC_GET_ARG3(call);
119 break;
120 case IPC_M_CONNECT_ME_TO:
121 /*
122 * Client requests to be connected to a service.
123 */
124 retval = connect_to_service(IPC_GET_ARG1(call), &call, callid);
125 break;
126 case NS_HANGUP:
127// printf("Closing connection.\n");
128 retval = EHANGUP;
129 break;
130 case NS_PING:
131// printf("Ping...%P %P\n", IPC_GET_ARG1(call),
132// IPC_GET_ARG2(call));
133 retval = 0;
134 arg1 = 0xdead;
135 arg2 = 0xbeef;
136 break;
137 case NS_PING_SVC:
138// printf("NS:Pinging service %d\n", ping_phone);
139 ipc_call_sync(ping_phone, NS_PING, 0xbeef, 0);
140// printf("NS:Got pong\n");
141 break;
142 default:
143// printf("Unknown method: %zd\n", IPC_GET_METHOD(call));
144 retval = ENOENT;
145 break;
146 }
147 if (! (callid & IPC_CALLID_NOTIFICATION)) {
148// printf("Answering.\n");
149 ipc_answer_fast(callid, retval, arg1, arg2);
150 }
151 }
152}
153
154/** Register service.
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
167// printf("Registering service %d on phone %d...", service, phone);
168
169 if (hash_table_find(&ns_hash_table, keys)) {
170// printf("Service %d already registered.\n", service);
171 return EEXISTS;
172 }
173
174 hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
175 if (!hs) {
176// printf("Failed to register service %d.\n", service);
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) {
205// printf("Service %d not registered.\n", service);
206 return ENOENT;
207 }
208 hs = hash_table_get_instance(hlp, hashed_service_t, link);
209// printf("Connecting in_phone_hash=%lX to service at phone %d...", call->in_phone_hash, hs->phone);
210 return ipc_forward_fast(callid, hs->phone, 0, 0);
211}
212
213/** Compute hash index into NS hash table.
214 *
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].
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 *
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.
235 * @param item Pointer to a hash table item.
236 * @return Non-zero if the key matches the item, zero otherwise.
237 */
238int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)
239{
240 hashed_service_t *hs;
241
242 assert(key);
243 assert(keys <= 3);
244 assert(item);
245
246 hs = hash_table_get_instance(item, hashed_service_t, link);
247
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));
262}
Note: See TracBrowser for help on using the repository browser.