Subversion Repositories HelenOS

Rev

Rev 2946 | Rev 3471 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2946 Rev 3435
1
/*
1
/*
2
 * Copyright (c) 2008 Jiri Svoboda
2
 * Copyright (c) 2008 Jiri Svoboda
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup sctrace
29
/** @addtogroup trace
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <stdio.h>
35
#include <stdio.h>
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 "ipcp.h"
41
#include "ipcp.h"
42
 
42
 
43
#define IPCP_CALLID_SYNC 0
43
#define IPCP_CALLID_SYNC 0
44
 
44
 
45
typedef struct {
45
typedef struct {
46
    int phone_hash;
46
    int phone_hash;
47
    ipc_call_t question;
47
    ipc_call_t question;
48
 
48
 
49
    int call_hash;
49
    int call_hash;
50
 
50
 
51
    link_t link;
51
    link_t link;
52
} pending_call_t;
52
} pending_call_t;
53
 
53
 
54
typedef struct {
54
typedef struct {
55
    int server;
55
    int server;
56
    proto_t *proto;
56
    proto_t *proto;
57
} connection_t;
57
} connection_t;
58
 
58
 
59
#define MAX_PHONE 64
59
#define MAX_PHONE 64
60
connection_t connections[MAX_PHONE];
60
connection_t connections[MAX_PHONE];
61
int have_conn[MAX_PHONE];
61
int have_conn[MAX_PHONE];
62
 
62
 
63
#define PCALL_TABLE_CHAINS 32
63
#define PCALL_TABLE_CHAINS 32
64
hash_table_t pending_calls;
64
hash_table_t pending_calls;
65
 
65
 
66
static hash_index_t pending_call_hash(unsigned long key[]);
66
static hash_index_t pending_call_hash(unsigned long key[]);
67
static int pending_call_compare(unsigned long key[], hash_count_t keys,
67
static int pending_call_compare(unsigned long key[], hash_count_t keys,
68
    link_t *item);
68
    link_t *item);
69
static void pending_call_remove_callback(link_t *item);
69
static void pending_call_remove_callback(link_t *item);
70
 
70
 
71
hash_table_operations_t pending_call_ops = {
71
hash_table_operations_t pending_call_ops = {
72
    .hash = pending_call_hash,
72
    .hash = pending_call_hash,
73
    .compare = pending_call_compare,
73
    .compare = pending_call_compare,
74
    .remove_callback = pending_call_remove_callback
74
    .remove_callback = pending_call_remove_callback
75
};
75
};
76
 
76
 
77
 
77
 
78
static hash_index_t pending_call_hash(unsigned long key[])
78
static hash_index_t pending_call_hash(unsigned long key[])
79
{
79
{
80
//  printf("pending_call_hash\n");
80
//  printf("pending_call_hash\n");
81
    return key[0] % PCALL_TABLE_CHAINS;
81
    return key[0] % PCALL_TABLE_CHAINS;
82
}
82
}
83
 
83
 
84
static int pending_call_compare(unsigned long key[], hash_count_t keys,
84
static int pending_call_compare(unsigned long key[], hash_count_t keys,
85
    link_t *item)
85
    link_t *item)
86
{
86
{
87
    pending_call_t *hs;
87
    pending_call_t *hs;
88
 
88
 
89
//  printf("pending_call_compare\n");
89
//  printf("pending_call_compare\n");
90
    hs = hash_table_get_instance(item, pending_call_t, link);
90
    hs = hash_table_get_instance(item, pending_call_t, link);
91
 
91
 
92
    return key[0] == hs->call_hash;
92
    return key[0] == hs->call_hash;
93
}
93
}
94
 
94
 
95
static void pending_call_remove_callback(link_t *item)
95
static void pending_call_remove_callback(link_t *item)
96
{
96
{
97
//  printf("pending_call_remove_callback\n");
97
//  printf("pending_call_remove_callback\n");
98
}
98
}
99
 
99
 
100
 
100
 
101
void ipcp_connection_set(int phone, int server, proto_t *proto)
101
void ipcp_connection_set(int phone, int server, proto_t *proto)
102
{
102
{
103
    if (phone <0 || phone >= MAX_PHONE) return;
103
    if (phone <0 || phone >= MAX_PHONE) return;
104
    connections[phone].server = server;
104
    connections[phone].server = server;
105
    connections[phone].proto = proto;
105
    connections[phone].proto = proto;
106
    have_conn[phone] = 1;
106
    have_conn[phone] = 1;
107
}
107
}
108
 
108
 
109
void ipcp_connection_clear(int phone)
109
void ipcp_connection_clear(int phone)
110
{
110
{
111
    have_conn[phone] = 0;
111
    have_conn[phone] = 0;
112
    connections[phone].server = 0;
112
    connections[phone].server = 0;
113
    connections[phone].proto = NULL;
113
    connections[phone].proto = NULL;
114
}
114
}
115
 
115
 
116
static void ipc_m_print(proto_t *proto, ipcarg_t method)
116
static void ipc_m_print(proto_t *proto, ipcarg_t method)
117
{
117
{
118
    ipc_m_desc_t *desc;
118
    ipc_m_desc_t *desc;
119
    oper_t *oper;
119
    oper_t *oper;
120
 
120
 
121
    /* FIXME: too slow */
121
    /* FIXME: too slow */
122
    desc = ipc_methods;
122
    desc = ipc_methods;
123
    while (desc->number != 0) {
123
    while (desc->number != 0) {
124
        if (desc->number == method) {
124
        if (desc->number == method) {
125
            printf("%s (%d)", desc->name, method);
125
            printf("%s (%d)", desc->name, method);
126
            return;
126
            return;
127
        }
127
        }
128
 
128
 
129
        ++desc;
129
        ++desc;
130
    }
130
    }
131
 
131
 
132
    if (proto != NULL) {
132
    if (proto != NULL) {
133
        oper = proto_get_oper(proto, method);
133
        oper = proto_get_oper(proto, method);
134
        if (oper != NULL) {
134
        if (oper != NULL) {
135
            printf("%s (%d)", oper->name, method);
135
            printf("%s (%d)", oper->name, method);
136
            return;
136
            return;
137
        }
137
        }
138
    }
138
    }
139
 
139
 
140
    printf("%d", method);
140
    printf("%d", method);
141
}
141
}
142
 
142
 
143
void ipcp_init(void)
143
void ipcp_init(void)
144
{
144
{
145
    hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
145
    hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
146
}
146
}
147
 
147
 
148
void ipcp_cleanup(void)
148
void ipcp_cleanup(void)
149
{
149
{
150
    hash_table_destroy(&pending_calls);
150
    hash_table_destroy(&pending_calls);
151
}
151
}
152
 
152
 
153
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
153
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
154
{
154
{
155
    pending_call_t *pcall;
155
    pending_call_t *pcall;
156
    proto_t *proto;
156
    proto_t *proto;
157
    unsigned long key[1];
157
    unsigned long key[1];
158
 
158
 
159
    if (have_conn[phone]) proto = connections[phone].proto;
159
    if (have_conn[phone]) proto = connections[phone].proto;
160
    else proto = NULL;
160
    else proto = NULL;
161
 
161
 
162
//  printf("ipcp_call_out()\n");
162
//  printf("ipcp_call_out()\n");
163
    printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone,
163
    printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone,
164
        (proto ? proto->name : "n/a"));
164
        (proto ? proto->name : "n/a"));
165
    ipc_m_print(proto, IPC_GET_METHOD(*call));
165
    ipc_m_print(proto, IPC_GET_METHOD(*call));
166
    printf(" args: (%u, %u, %u, %u, %u)\n",
166
    printf(" args: (%u, %u, %u, %u, %u)\n",
167
        IPC_GET_ARG1(*call),
167
        IPC_GET_ARG1(*call),
168
        IPC_GET_ARG2(*call),
168
        IPC_GET_ARG2(*call),
169
        IPC_GET_ARG3(*call),
169
        IPC_GET_ARG3(*call),
170
        IPC_GET_ARG4(*call),
170
        IPC_GET_ARG4(*call),
171
        IPC_GET_ARG5(*call)
171
        IPC_GET_ARG5(*call)
172
    );
172
    );
173
 
173
 
174
    /* Store call in hash table for response matching */
174
    /* Store call in hash table for response matching */
175
 
175
 
176
    pcall = malloc(sizeof(pending_call_t));
176
    pcall = malloc(sizeof(pending_call_t));
177
    pcall->phone_hash = phone;
177
    pcall->phone_hash = phone;
178
    pcall->question = *call;
178
    pcall->question = *call;
179
    pcall->call_hash = hash;
179
    pcall->call_hash = hash;
180
 
180
 
181
    key[0] = hash;
181
    key[0] = hash;
182
 
182
 
183
    hash_table_insert(&pending_calls, key, &pcall->link);
183
    hash_table_insert(&pending_calls, key, &pcall->link);
184
}
184
}
185
 
185
 
186
static void parse_answer(pending_call_t *pcall, ipc_call_t *answer)
186
static void parse_answer(pending_call_t *pcall, ipc_call_t *answer)
187
{
187
{
188
    int phone;
188
    int phone;
189
    ipcarg_t method;
189
    ipcarg_t method;
190
    ipcarg_t service;
190
    ipcarg_t service;
191
    int retval;
191
    int retval;
192
    static proto_t proto_unknown = { .name = "unknown" };
192
    static proto_t proto_unknown = { .name = "unknown" };
193
    proto_t *proto;
193
    proto_t *proto;
194
    int cphone;
194
    int cphone;
195
 
195
 
196
//  printf("parse_answer\n");
196
//  printf("parse_answer\n");
197
 
197
 
198
    phone = pcall->phone_hash;
198
    phone = pcall->phone_hash;
199
    method = IPC_GET_METHOD(pcall->question);
199
    method = IPC_GET_METHOD(pcall->question);
200
    retval = IPC_GET_RETVAL(*answer);
200
    retval = IPC_GET_RETVAL(*answer);
201
    printf("phone=%d, method=%d, retval=%d\n",
201
    printf("phone=%d, method=%d, retval=%d\n",
202
        phone, method, retval);
202
        phone, method, retval);
203
 
203
 
204
    if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
204
    if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
205
        /* Connected to a service (through NS) */
205
        /* Connected to a service (through NS) */
206
        service = IPC_GET_ARG1(pcall->question);
206
        service = IPC_GET_ARG1(pcall->question);
207
        proto = proto_get_by_srv(service);
207
        proto = proto_get_by_srv(service);
208
        if (proto == NULL) proto = &proto_unknown;
208
        if (proto == NULL) proto = &proto_unknown;
209
 
209
 
210
        cphone = IPC_GET_ARG5(*answer);
210
        cphone = IPC_GET_ARG5(*answer);
211
        printf("registering connection (phone %d, protocol: %s)\n", cphone,
211
        printf("registering connection (phone %d, protocol: %s)\n", cphone,
212
            proto->name);
212
            proto->name);
213
        ipcp_connection_set(cphone, 0, proto);
213
        ipcp_connection_set(cphone, 0, proto);
214
    }
214
    }
215
}
215
}
216
 
216
 
217
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
217
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
218
{
218
{
219
    link_t *item;
219
    link_t *item;
220
    pending_call_t *pcall;
220
    pending_call_t *pcall;
221
    unsigned long key[1];
221
    unsigned long key[1];
222
 
222
 
223
//  printf("ipcp_call_in()\n");
223
//  printf("ipcp_call_in()\n");
224
/*  printf("phone: %d, method: ", call->in_phone_hash);
224
/*  printf("phone: %d, method: ", call->in_phone_hash);
225
    ipc_m_print(IPC_GET_METHOD(*call));
225
    ipc_m_print(IPC_GET_METHOD(*call));
226
    printf(" args: (%u, %u, %u, %u, %u)\n",
226
    printf(" args: (%u, %u, %u, %u, %u)\n",
227
        IPC_GET_ARG1(*call),
227
        IPC_GET_ARG1(*call),
228
        IPC_GET_ARG2(*call),
228
        IPC_GET_ARG2(*call),
229
        IPC_GET_ARG3(*call),
229
        IPC_GET_ARG3(*call),
230
        IPC_GET_ARG4(*call),
230
        IPC_GET_ARG4(*call),
231
        IPC_GET_ARG5(*call)
231
        IPC_GET_ARG5(*call)
232
    );*/
232
    );*/
233
 
233
 
234
    if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
234
    if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
235
        /* Not a response */
235
        /* Not a response */
236
        printf("Not a response (hash %d)\n", hash);
236
        printf("Not a response (hash %d)\n", hash);
237
        return;
237
        return;
238
    }
238
    }
239
 
239
 
240
    hash = hash & ~IPC_CALLID_ANSWERED;
240
    hash = hash & ~IPC_CALLID_ANSWERED;
241
    key[0] = hash;
241
    key[0] = hash;
242
 
242
 
243
    item = hash_table_find(&pending_calls, key);
243
    item = hash_table_find(&pending_calls, key);
244
    if (item == NULL) return; // No matching question found
244
    if (item == NULL) return; // No matching question found
245
   
245
   
246
    pcall = hash_table_get_instance(item, pending_call_t, link);
246
    pcall = hash_table_get_instance(item, pending_call_t, link);
247
 
247
 
248
    printf("response matched to question\n");
248
    printf("response matched to question\n");
249
    hash_table_remove(&pending_calls, key, 1);
249
    hash_table_remove(&pending_calls, key, 1);
250
 
250
 
251
    parse_answer(pcall, call);
251
    parse_answer(pcall, call);
252
    free(pcall);
252
    free(pcall);
253
}
253
}
254
 
254
 
255
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
255
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
256
{
256
{
257
    ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
257
    ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
258
    ipcp_call_in(answer, IPCP_CALLID_SYNC);
258
    ipcp_call_in(answer, IPCP_CALLID_SYNC);
259
}
259
}
260
 
260
 
261
void ipcp_hangup(int phone, int rc)
261
void ipcp_hangup(int phone, int rc)
262
{
262
{
263
    printf("hangup phone %d -> %d\n", phone, rc);
263
    printf("hangup phone %d -> %d\n", phone, rc);
264
    ipcp_connection_clear(phone);
264
    ipcp_connection_clear(phone);
265
}
265
}
266
 
266
 
267
/** @}
267
/** @}
268
 */
268
 */
269
 
269