Subversion Repositories HelenOS

Rev

Rev 3435 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3435 Rev 3471
Line 36... Line 36...
36
#include <stdlib.h>
36
#include <stdlib.h>
37
#include <libadt/hash_table.h>
37
#include <libadt/hash_table.h>
38
 
38
 
39
#include "ipc_desc.h"
39
#include "ipc_desc.h"
40
#include "proto.h"
40
#include "proto.h"
-
 
41
#include "trace.h"
41
#include "ipcp.h"
42
#include "ipcp.h"
42
 
43
 
43
#define IPCP_CALLID_SYNC 0
44
#define IPCP_CALLID_SYNC 0
44
 
45
 
45
typedef struct {
46
typedef struct {
46
    int phone_hash;
47
    ipcarg_t phone_hash;
47
    ipc_call_t question;
48
    ipc_call_t question;
-
 
49
    oper_t *oper;
48
 
50
 
49
    int call_hash;
51
    ipc_callid_t call_hash;
50
 
52
 
51
    link_t link;
53
    link_t link;
52
} pending_call_t;
54
} pending_call_t;
53
 
55
 
54
typedef struct {
56
typedef struct {
Line 61... Line 63...
61
int have_conn[MAX_PHONE];
63
int have_conn[MAX_PHONE];
62
 
64
 
63
#define PCALL_TABLE_CHAINS 32
65
#define PCALL_TABLE_CHAINS 32
64
hash_table_t pending_calls;
66
hash_table_t pending_calls;
65
 
67
 
-
 
68
/*
-
 
69
 * Pseudo-protocols
-
 
70
 */
-
 
71
proto_t *proto_system;      /**< Protocol describing system IPC methods. */
-
 
72
proto_t *proto_unknown;     /**< Protocol with no known methods. */
-
 
73
 
66
static hash_index_t pending_call_hash(unsigned long key[]);
74
static hash_index_t pending_call_hash(unsigned long key[]);
67
static int pending_call_compare(unsigned long key[], hash_count_t keys,
75
static int pending_call_compare(unsigned long key[], hash_count_t keys,
68
    link_t *item);
76
    link_t *item);
69
static void pending_call_remove_callback(link_t *item);
77
static void pending_call_remove_callback(link_t *item);
70
 
78
 
Line 87... Line 95...
87
    pending_call_t *hs;
95
    pending_call_t *hs;
88
 
96
 
89
//  printf("pending_call_compare\n");
97
//  printf("pending_call_compare\n");
90
    hs = hash_table_get_instance(item, pending_call_t, link);
98
    hs = hash_table_get_instance(item, pending_call_t, link);
91
 
99
 
-
 
100
    // FIXME: this will fail if sizeof(long) < sizeof(void *).
92
    return key[0] == hs->call_hash;
101
    return key[0] == hs->call_hash;
93
}
102
}
94
 
103
 
95
static void pending_call_remove_callback(link_t *item)
104
static void pending_call_remove_callback(link_t *item)
96
{
105
{
Line 113... Line 122...
113
    connections[phone].proto = NULL;
122
    connections[phone].proto = NULL;
114
}
123
}
115
 
124
 
116
static void ipc_m_print(proto_t *proto, ipcarg_t method)
125
static void ipc_m_print(proto_t *proto, ipcarg_t method)
117
{
126
{
118
    ipc_m_desc_t *desc;
-
 
119
    oper_t *oper;
127
    oper_t *oper;
120
 
128
 
121
    /* FIXME: too slow */
129
    /* Try system methods first */
122
    desc = ipc_methods;
-
 
123
    while (desc->number != 0) {
-
 
124
        if (desc->number == method) {
-
 
125
            printf("%s (%d)", desc->name, method);
130
    oper = proto_get_oper(proto_system, method);
126
            return;
-
 
127
        }
-
 
128
 
131
 
-
 
132
    if (oper == NULL && proto != NULL) {
-
 
133
        /* Not a system method, try the user protocol. */
129
        ++desc;
134
        oper = proto_get_oper(proto, method);
130
    }
135
    }
131
 
136
 
132
    if (proto != NULL) {
-
 
133
        oper = proto_get_oper(proto, method);
-
 
134
        if (oper != NULL) {
137
    if (oper != NULL) {
135
            printf("%s (%d)", oper->name, method);
138
        printf("%s (%ld)", oper->name, method);
136
            return;
139
        return;
137
        }
-
 
138
    }
140
    }
139
 
141
 
140
    printf("%d", method);
142
    printf("%ld", method);
141
}
143
}
142
 
144
 
143
void ipcp_init(void)
145
void ipcp_init(void)
144
{
146
{
-
 
147
    ipc_m_desc_t *desc;
-
 
148
    oper_t *oper;
-
 
149
 
-
 
150
    val_type_t arg_def[OPER_MAX_ARGS] = {
-
 
151
        V_INTEGER,
-
 
152
        V_INTEGER,
-
 
153
        V_INTEGER,
-
 
154
        V_INTEGER,
-
 
155
        V_INTEGER      
-
 
156
    };
-
 
157
 
-
 
158
    /*
-
 
159
     * Create a pseudo-protocol 'unknown' that has no known methods.
-
 
160
     */
-
 
161
    proto_unknown = proto_new("unknown");
-
 
162
 
-
 
163
    /*
-
 
164
     * Create a pseudo-protocol 'system' defining names of system IPC
-
 
165
     * methods.
-
 
166
     */
-
 
167
    proto_system = proto_new("system");
-
 
168
 
-
 
169
    desc = ipc_methods;
-
 
170
    while (desc->number != 0) {
-
 
171
        oper = oper_new(desc->name, OPER_MAX_ARGS, arg_def, V_INTEGER,
-
 
172
            OPER_MAX_ARGS, arg_def);
-
 
173
        proto_add_oper(proto_system, desc->number, oper);
-
 
174
 
-
 
175
        ++desc;
-
 
176
    }
-
 
177
 
145
    hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
178
    hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
146
}
179
}
147
 
180
 
148
void ipcp_cleanup(void)
181
void ipcp_cleanup(void)
149
{
182
{
-
 
183
    proto_delete(proto_system);
150
    hash_table_destroy(&pending_calls);
184
    hash_table_destroy(&pending_calls);
151
}
185
}
152
 
186
 
153
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
187
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
154
{
188
{
155
    pending_call_t *pcall;
189
    pending_call_t *pcall;
156
    proto_t *proto;
190
    proto_t *proto;
157
    unsigned long key[1];
191
    unsigned long key[1];
-
 
192
    oper_t *oper;
-
 
193
    ipcarg_t *args;
-
 
194
    int i;
158
 
195
 
159
    if (have_conn[phone]) proto = connections[phone].proto;
196
    if (have_conn[phone]) proto = connections[phone].proto;
160
    else proto = NULL;
197
    else proto = NULL;
161
 
198
 
-
 
199
    args = call->args;
-
 
200
 
162
//  printf("ipcp_call_out()\n");
201
    if ((display_mask & DM_IPC) != 0) {
163
    printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone,
202
        printf("Call ID: 0x%lx, phone: %d, proto: %s, method: ", hash,
164
        (proto ? proto->name : "n/a"));
203
            phone, (proto ? proto->name : "n/a"));
165
    ipc_m_print(proto, IPC_GET_METHOD(*call));
204
        ipc_m_print(proto, IPC_GET_METHOD(*call));
166
    printf(" args: (%u, %u, %u, %u, %u)\n",
205
        printf(" args: (%lu, %lu, %lu, %lu, %lu)\n", args[1], args[2],
167
        IPC_GET_ARG1(*call),
206
            args[3], args[4], args[5]);
-
 
207
    }
-
 
208
 
-
 
209
 
-
 
210
    if ((display_mask & DM_USER) != 0) {
-
 
211
 
168
        IPC_GET_ARG2(*call),
212
        if (proto != NULL) {
169
        IPC_GET_ARG3(*call),
213
            oper = proto_get_oper(proto, IPC_GET_METHOD(*call));
-
 
214
        } else {
-
 
215
            oper = NULL;
-
 
216
        }
-
 
217
 
170
        IPC_GET_ARG4(*call),
218
        if (oper != NULL) {
-
 
219
 
-
 
220
            printf("%s(%d).%s", (proto ? proto->name : "n/a"),
-
 
221
                phone, (oper ? oper->name : "unknown"));
-
 
222
 
-
 
223
            putchar('(');
-
 
224
            for (i = 1; i <= oper->argc; ++i) {
171
        IPC_GET_ARG5(*call)
225
                if (i > 1) printf(", ");
-
 
226
                val_print(args[i], oper->arg_type[i - 1]);
-
 
227
            }
-
 
228
            putchar(')');
-
 
229
 
-
 
230
            if (oper->rv_type == V_VOID && oper->respc == 0) {
-
 
231
                /*
-
 
232
                 * No response data (typically the task will
-
 
233
                 * not be interested in the response).
-
 
234
                 * We will not display response.
-
 
235
                 */
-
 
236
                putchar('.');
-
 
237
            }
-
 
238
 
-
 
239
            putchar('\n');
172
    );
240
        }
-
 
241
    } else {
-
 
242
        oper = NULL;
-
 
243
    }
173
 
244
 
174
    /* Store call in hash table for response matching */
245
    /* Store call in hash table for response matching */
175
 
246
 
176
    pcall = malloc(sizeof(pending_call_t));
247
    pcall = malloc(sizeof(pending_call_t));
177
    pcall->phone_hash = phone;
248
    pcall->phone_hash = phone;
178
    pcall->question = *call;
249
    pcall->question = *call;
179
    pcall->call_hash = hash;
250
    pcall->call_hash = hash;
-
 
251
    pcall->oper = oper;
180
 
252
 
181
    key[0] = hash;
253
    key[0] = hash;
182
 
254
 
183
    hash_table_insert(&pending_calls, key, &pcall->link);
255
    hash_table_insert(&pending_calls, key, &pcall->link);
184
}
256
}
185
 
257
 
186
static void parse_answer(pending_call_t *pcall, ipc_call_t *answer)
258
static void parse_answer(ipc_callid_t hash, pending_call_t *pcall,
-
 
259
    ipc_call_t *answer)
187
{
260
{
188
    int phone;
261
    ipcarg_t phone;
189
    ipcarg_t method;
262
    ipcarg_t method;
190
    ipcarg_t service;
263
    ipcarg_t service;
191
    int retval;
264
    ipcarg_t retval;
192
    static proto_t proto_unknown = { .name = "unknown" };
-
 
193
    proto_t *proto;
265
    proto_t *proto;
194
    int cphone;
266
    int cphone;
195
 
267
 
-
 
268
    ipcarg_t *resp;
-
 
269
    oper_t *oper;
-
 
270
    int i;
-
 
271
 
196
//  printf("parse_answer\n");
272
//  printf("parse_answer\n");
197
 
273
 
198
    phone = pcall->phone_hash;
274
    phone = pcall->phone_hash;
199
    method = IPC_GET_METHOD(pcall->question);
275
    method = IPC_GET_METHOD(pcall->question);
200
    retval = IPC_GET_RETVAL(*answer);
276
    retval = IPC_GET_RETVAL(*answer);
-
 
277
 
-
 
278
    resp = answer->args;
-
 
279
 
-
 
280
    if ((display_mask & DM_IPC) != 0) {
201
    printf("phone=%d, method=%d, retval=%d\n",
281
        printf("Response to 0x%lx: retval=%ld, args = (%lu, %lu, %lu, %lu, %lu)\n",
-
 
282
            hash, retval, IPC_GET_ARG1(*answer),
-
 
283
            IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer),
-
 
284
            IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer));
-
 
285
    }
-
 
286
 
-
 
287
    if ((display_mask & DM_USER) != 0) {
-
 
288
        oper = pcall->oper;
-
 
289
 
-
 
290
        if (oper != NULL && (oper->rv_type != V_VOID || oper->respc > 0)) {
-
 
291
            printf("->");
-
 
292
 
-
 
293
            if (oper->rv_type != V_VOID) {
-
 
294
                putchar(' ');
-
 
295
                val_print(retval, oper->rv_type);
-
 
296
            }
-
 
297
           
-
 
298
            if (oper->respc > 0) {
-
 
299
                putchar(' ');
-
 
300
                putchar('(');
-
 
301
                for (i = 1; i <= oper->respc; ++i) {
202
        phone, method, retval);
302
                    if (i > 1) printf(", ");
-
 
303
                    val_print(resp[i], oper->resp_type[i - 1]);
-
 
304
                }
-
 
305
                putchar(')');
-
 
306
            }
-
 
307
 
-
 
308
            putchar('\n');
-
 
309
        }
-
 
310
    }
203
 
311
 
204
    if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
312
    if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
205
        /* Connected to a service (through NS) */
313
        /* Connected to a service (through NS) */
206
        service = IPC_GET_ARG1(pcall->question);
314
        service = IPC_GET_ARG1(pcall->question);
207
        proto = proto_get_by_srv(service);
315
        proto = proto_get_by_srv(service);
208
        if (proto == NULL) proto = &proto_unknown;
316
        if (proto == NULL) proto = proto_unknown;
209
 
317
 
210
        cphone = IPC_GET_ARG5(*answer);
318
        cphone = IPC_GET_ARG5(*answer);
-
 
319
        if ((display_mask & DM_SYSTEM) != 0) {
211
        printf("registering connection (phone %d, protocol: %s)\n", cphone,
320
            printf("Registering connection (phone %d, protocol: %s)\n", cphone,
212
            proto->name);
321
                    proto->name);
-
 
322
        }
213
        ipcp_connection_set(cphone, 0, proto);
323
        ipcp_connection_set(cphone, 0, proto);
214
    }
324
    }
215
}
325
}
216
 
326
 
217
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
327
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
Line 219... Line 329...
219
    link_t *item;
329
    link_t *item;
220
    pending_call_t *pcall;
330
    pending_call_t *pcall;
221
    unsigned long key[1];
331
    unsigned long key[1];
222
 
332
 
223
//  printf("ipcp_call_in()\n");
333
//  printf("ipcp_call_in()\n");
224
/*  printf("phone: %d, method: ", call->in_phone_hash);
-
 
225
    ipc_m_print(IPC_GET_METHOD(*call));
-
 
226
    printf(" args: (%u, %u, %u, %u, %u)\n",
-
 
227
        IPC_GET_ARG1(*call),
-
 
228
        IPC_GET_ARG2(*call),
-
 
229
        IPC_GET_ARG3(*call),
-
 
230
        IPC_GET_ARG4(*call),
-
 
231
        IPC_GET_ARG5(*call)
-
 
232
    );*/
-
 
233
 
334
 
234
    if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
335
    if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
235
        /* Not a response */
336
        /* Not a response */
-
 
337
        if ((display_mask & DM_IPC) != 0) {
236
        printf("Not a response (hash %d)\n", hash);
338
            printf("Not a response (hash 0x%lx)\n", hash);
-
 
339
        }
237
        return;
340
        return;
238
    }
341
    }
239
 
342
 
240
    hash = hash & ~IPC_CALLID_ANSWERED;
343
    hash = hash & ~IPC_CALLID_ANSWERED;
241
    key[0] = hash;
344
    key[0] = hash;
242
 
345
 
243
    item = hash_table_find(&pending_calls, key);
346
    item = hash_table_find(&pending_calls, key);
244
    if (item == NULL) return; // No matching question found
347
    if (item == NULL) return; // No matching question found
-
 
348
 
-
 
349
    /*
-
 
350
     * Response matched to question.
-
 
351
     */
245
   
352
   
246
    pcall = hash_table_get_instance(item, pending_call_t, link);
353
    pcall = hash_table_get_instance(item, pending_call_t, link);
247
 
-
 
248
    printf("response matched to question\n");
-
 
249
    hash_table_remove(&pending_calls, key, 1);
354
    hash_table_remove(&pending_calls, key, 1);
250
 
355
 
251
    parse_answer(pcall, call);
356
    parse_answer(hash, pcall, call);
252
    free(pcall);
357
    free(pcall);
253
}
358
}
254
 
359
 
255
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
360
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
256
{
361
{
Line 258... Line 363...
258
    ipcp_call_in(answer, IPCP_CALLID_SYNC);
363
    ipcp_call_in(answer, IPCP_CALLID_SYNC);
259
}
364
}
260
 
365
 
261
void ipcp_hangup(int phone, int rc)
366
void ipcp_hangup(int phone, int rc)
262
{
367
{
-
 
368
    if ((display_mask & DM_SYSTEM) != 0) {
263
    printf("hangup phone %d -> %d\n", phone, rc);
369
        printf("Hang phone %d up -> %d\n", phone, rc);
264
    ipcp_connection_clear(phone);
370
        ipcp_connection_clear(phone);
-
 
371
    }
265
}
372
}
266
 
373
 
267
/** @}
374
/** @}
268
 */
375
 */