Rev 1335 | Rev 1338 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1335 | Rev 1336 | ||
---|---|---|---|
Line 43... | Line 43... | ||
43 | 43 | ||
44 | #define NAME "NS" |
44 | #define NAME "NS" |
45 | 45 | ||
46 | #define NS_HASH_TABLE_CHAINS 20 |
46 | #define NS_HASH_TABLE_CHAINS 20 |
47 | 47 | ||
- | 48 | static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call); |
|
- | 49 | static int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid); |
|
- | 50 | ||
48 | /* Static functions implementing NS hash table operations. */ |
51 | /* Static functions implementing NS hash table operations. */ |
49 | static hash_index_t ns_hash(unsigned long *key); |
52 | static hash_index_t ns_hash(unsigned long *key); |
50 | static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item); |
53 | static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item); |
- | 54 | static void ns_remove(link_t *item); |
|
51 | 55 | ||
52 | /** Operations for NS hash table. */ |
56 | /** Operations for NS hash table. */ |
53 | static hash_table_operations_t ns_hash_table_ops = { |
57 | static hash_table_operations_t ns_hash_table_ops = { |
54 | .hash = ns_hash, |
58 | .hash = ns_hash, |
55 | .compare = ns_compare, |
59 | .compare = ns_compare, |
56 | .remove_callback = NULL |
60 | .remove_callback = ns_remove |
57 | }; |
61 | }; |
58 | 62 | ||
59 | /** NS hash table structure. */ |
63 | /** NS hash table structure. */ |
60 | static hash_table_t ns_hash_table; |
64 | static hash_table_t ns_hash_table; |
61 | 65 | ||
62 | /** NS hash table item. */ |
66 | /** NS hash table item. */ |
63 | typedef struct { |
67 | typedef struct { |
64 | link_t link; |
68 | link_t link; |
65 | ipcarg_t service; /**< Number of the service. */ |
69 | ipcarg_t service; /**< Number of the service. */ |
66 | ipcarg_t phone; /**< Phone registered with the service. */ |
70 | ipcarg_t phone; /**< Phone registered with the service. */ |
- | 71 | ipcarg_t in_phone_hash; /**< Incoming phone hash. */ |
|
67 | } hashed_service_t; |
72 | } hashed_service_t; |
68 | 73 | ||
69 | /* |
74 | /* |
70 | irq_cmd_t msim_cmds[1] = { |
75 | irq_cmd_t msim_cmds[1] = { |
71 | { CMD_MEM_READ_1, (void *)0xB0000000, 0 } |
76 | { CMD_MEM_READ_1, (void *)0xB0000000, 0 } |
Line 98... | Line 103... | ||
98 | 103 | ||
99 | ipcarg_t retval, arg1, arg2; |
104 | ipcarg_t retval, arg1, arg2; |
100 | 105 | ||
101 | printf("%s: Name service started.\n", NAME); |
106 | printf("%s: Name service started.\n", NAME); |
102 | 107 | ||
103 | if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 1, &ns_hash_table_ops)) { |
108 | if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, &ns_hash_table_ops)) { |
104 | printf("%s: cannot create hash table\n", NAME); |
109 | printf("%s: cannot create hash table\n", NAME); |
105 | return ENOMEM; |
110 | return ENOMEM; |
106 | } |
111 | } |
107 | 112 | ||
108 | 113 | ||
109 | // ipc_register_irq(2, &msim_kbd); |
114 | // ipc_register_irq(2, &msim_kbd); |
110 | // ipc_register_irq(1, &i8042_kbd); |
115 | // ipc_register_irq(1, &i8042_kbd); |
111 | while (1) { |
116 | while (1) { |
112 | callid = ipc_wait_for_call(&call, 0); |
117 | callid = ipc_wait_for_call(&call, 0); |
113 | printf("NS: Call phone=%lX...", call.phoneid); |
118 | printf("NS: Call in_phone_hash=%lX...", call.in_phone_hash); |
114 | switch (IPC_GET_METHOD(call)) { |
119 | switch (IPC_GET_METHOD(call)) { |
115 | case IPC_M_AS_SEND: |
120 | case IPC_M_AS_SEND: |
116 | as = (char *)IPC_GET_ARG2(call); |
121 | as = (char *)IPC_GET_ARG2(call); |
117 | printf("Received as: %P, size:%d\n", as, IPC_GET_ARG3(call)); |
122 | printf("Received as: %P, size:%d\n", as, IPC_GET_ARG3(call)); |
118 | retval = ipc_answer(callid, 0,(sysarg_t)(1024*1024), 0); |
123 | retval = ipc_answer(callid, 0,(sysarg_t)(1024*1024), 0); |
Line 128... | Line 133... | ||
128 | break; |
133 | break; |
129 | case IPC_M_PHONE_HUNGUP: |
134 | case IPC_M_PHONE_HUNGUP: |
130 | printf("Phone hung up.\n"); |
135 | printf("Phone hung up.\n"); |
131 | retval = 0; |
136 | retval = 0; |
132 | break; |
137 | break; |
133 | case IPC_M_CONNECT_TO_ME:; |
138 | case IPC_M_CONNECT_TO_ME: |
134 | /* |
139 | /* |
135 | * Request for registration of a service. |
140 | * Server requests service registration. |
136 | */ |
141 | */ |
137 | ipcarg_t service; |
- | |
138 | ipcarg_t phone; |
- | |
139 | hashed_service_t *hs; |
- | |
140 | - | ||
141 | service = IPC_GET_ARG1(call); |
142 | retval = register_service(IPC_GET_ARG1(call), IPC_GET_ARG3(call), &call); |
142 | phone = IPC_GET_ARG3(call); |
143 | ping_phone = IPC_GET_ARG3(call); |
143 | printf("Registering service %d on phone %d...", service, phone); |
- | |
144 | - | ||
145 | hs = (hashed_service_t *) malloc(sizeof(hashed_service_t)); |
- | |
146 | if (!hs) { |
- | |
147 | printf("Failed to register service %d.\n", service); |
- | |
148 | } |
- | |
149 | - | ||
150 | link_initialize(&hs->link); |
- | |
151 | hs->service = service; |
- | |
152 | hs->phone = phone; |
- | |
153 | hash_table_insert(&ns_hash_table, (unsigned long *) &service, &hs->link); |
- | |
154 | - | ||
155 | ping_phone = phone; |
- | |
156 | retval = 0; |
- | |
157 | break; |
144 | break; |
158 | case IPC_M_CONNECT_ME_TO: |
145 | case IPC_M_CONNECT_ME_TO: |
- | 146 | /* |
|
159 | printf("Connectme(%P)to: %zd\n", |
147 | * Client requests to be connected to a service. |
- | 148 | */ |
|
160 | IPC_GET_ARG3(call), IPC_GET_ARG1(call)); |
149 | retval = connect_to_service(IPC_GET_ARG1(call), &call, callid); |
161 | retval = 0; |
- | |
162 | break; |
150 | break; |
163 | case NS_PING: |
151 | case NS_PING: |
164 | printf("Ping...%P %P\n", IPC_GET_ARG1(call), |
152 | printf("Ping...%P %P\n", IPC_GET_ARG1(call), |
165 | IPC_GET_ARG2(call)); |
153 | IPC_GET_ARG2(call)); |
166 | retval = 0; |
154 | retval = 0; |
Line 186... | Line 174... | ||
186 | ipc_answer(callid, retval, arg1, arg2); |
174 | ipc_answer(callid, retval, arg1, arg2); |
187 | } |
175 | } |
188 | } |
176 | } |
189 | } |
177 | } |
190 | 178 | ||
- | 179 | /** Register server. |
|
- | 180 | * |
|
- | 181 | * @param service Service to be registered. |
|
- | 182 | * @param phone phone Phone to be used for connections to the service. |
|
- | 183 | * @param call Pointer to call structure. |
|
- | 184 | * |
|
- | 185 | * @return Zero on success or a value from @ref errno.h. |
|
- | 186 | */ |
|
- | 187 | int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call) |
|
- | 188 | { |
|
- | 189 | unsigned long keys[3] = { service, call->in_phone_hash, 0 }; |
|
- | 190 | hashed_service_t *hs; |
|
- | 191 | ||
- | 192 | printf("Registering service %d on phone %d...", service, phone); |
|
- | 193 | ||
- | 194 | if (hash_table_find(&ns_hash_table, keys)) { |
|
- | 195 | printf("Service %d already registered.\n", service); |
|
- | 196 | return EEXISTS; |
|
- | 197 | } |
|
- | 198 | ||
- | 199 | hs = (hashed_service_t *) malloc(sizeof(hashed_service_t)); |
|
- | 200 | if (!hs) { |
|
- | 201 | printf("Failed to register service %d.\n", service); |
|
- | 202 | return ENOMEM; |
|
- | 203 | } |
|
- | 204 | ||
- | 205 | link_initialize(&hs->link); |
|
- | 206 | hs->service = service; |
|
- | 207 | hs->phone = phone; |
|
- | 208 | hs->in_phone_hash = call->in_phone_hash; |
|
- | 209 | hash_table_insert(&ns_hash_table, keys, &hs->link); |
|
- | 210 | ||
- | 211 | return 0; |
|
- | 212 | } |
|
- | 213 | ||
- | 214 | /** Connect client to service. |
|
- | 215 | * |
|
- | 216 | * @param service Service to be connected to. |
|
- | 217 | * @param call Pointer to call structure. |
|
- | 218 | * @param callid Call ID of the request. |
|
- | 219 | * |
|
- | 220 | * @return Zero on success or a value from @ref errno.h. |
|
- | 221 | */ |
|
- | 222 | int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid) |
|
- | 223 | { |
|
- | 224 | unsigned long keys[3] = { service, 0, 0 }; |
|
- | 225 | link_t *hlp; |
|
- | 226 | hashed_service_t *hs; |
|
- | 227 | ||
- | 228 | hlp = hash_table_find(&ns_hash_table, keys); |
|
- | 229 | if (!hlp) { |
|
- | 230 | printf("Service %d noty registered.\n", service); |
|
- | 231 | return ENOENT; |
|
- | 232 | } |
|
- | 233 | hs = hash_table_get_instance(hlp, hashed_service_t, link); |
|
- | 234 | printf("Connecting in_phone_hash=%lX to service at phone %d...", call->in_phone_hash, hs->phone); |
|
- | 235 | return ipc_forward_fast(callid, hs->phone, 0, 0); |
|
- | 236 | } |
|
- | 237 | ||
191 | /** Compute hash index into NS hash table. |
238 | /** Compute hash index into NS hash table. |
192 | * |
239 | * |
193 | * @param key Pointer to single key (i.e. service number). |
240 | * @param key Pointer keys. However, only the first key (i.e. service number) |
- | 241 | * is used to compute the hash index. |
|
194 | * @return Hash index corresponding to *key. |
242 | * @return Hash index corresponding to key[0]. |
195 | */ |
243 | */ |
196 | hash_index_t ns_hash(unsigned long *key) |
244 | hash_index_t ns_hash(unsigned long *key) |
197 | { |
245 | { |
198 | assert(key); |
246 | assert(key); |
199 | return *key % NS_HASH_TABLE_CHAINS; |
247 | return *key % NS_HASH_TABLE_CHAINS; |
200 | } |
248 | } |
201 | 249 | ||
202 | /** Compare a key with hashed item. |
250 | /** Compare a key with hashed item. |
203 | * |
251 | * |
- | 252 | * This compare function always ignores the third key. |
|
- | 253 | * It exists only to make it possible to remove records |
|
- | 254 | * originating from connection with key[1] in_phone_hash |
|
- | 255 | * value. Note that this is close to being classified |
|
- | 256 | * as a nasty hack. |
|
- | 257 | * |
|
204 | * @param key Single key pointer. |
258 | * @param key Array of keys. |
205 | * @param keys Must be 1. |
259 | * @param keys Must be lesser or equal to 3. |
206 | * @param item Pointer to a hash table item. |
260 | * @param item Pointer to a hash table item. |
207 | * @return Non-zero if the key matches the item, zero otherwise. |
261 | * @return Non-zero if the key matches the item, zero otherwise. |
208 | */ |
262 | */ |
209 | int ns_compare(unsigned long *key, hash_count_t keys, link_t *item) |
263 | int ns_compare(unsigned long key[], hash_count_t keys, link_t *item) |
210 | { |
264 | { |
211 | hashed_service_t *hs; |
265 | hashed_service_t *hs; |
212 | 266 | ||
213 | assert(key); |
267 | assert(key); |
214 | assert(keys == 1); |
268 | assert(keys <= 3); |
215 | assert(item); |
269 | assert(item); |
216 | 270 | ||
217 | hs = hash_table_get_instance(item, hashed_service_t, link); |
271 | hs = hash_table_get_instance(item, hashed_service_t, link); |
218 | 272 | ||
- | 273 | if (keys == 2) |
|
- | 274 | return key[1] == hs->in_phone_hash; |
|
- | 275 | else |
|
219 | return *key == hs->service; |
276 | return key[0] == hs->service; |
- | 277 | } |
|
- | 278 | ||
- | 279 | /** Perform actions after removal of item from the hash table. |
|
- | 280 | * |
|
- | 281 | * @param item Item that was removed from the hash table. |
|
- | 282 | */ |
|
- | 283 | void ns_remove(link_t *item) |
|
- | 284 | { |
|
- | 285 | assert(item); |
|
- | 286 | free(hash_table_get_instance(item, hashed_service_t, link)); |
|
220 | } |
287 | } |