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 | } |