Subversion Repositories HelenOS

Rev

Rev 2882 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2882 Rev 2894
-
 
1
/*
-
 
2
 * Copyright (c) 2008 Jiri Svoboda
-
 
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
 
1
/** @addtogroup sctrace
29
/** @addtogroup sctrace
2
 * @{
30
 * @{
3
 */
31
 */
4
/** @file
32
/** @file
5
 */
33
 */
6
 
34
 
7
#include <stdio.h>
35
#include <stdio.h>
8
#include <stdlib.h>
36
#include <stdlib.h>
9
#include <libadt/hash_table.h>
37
#include <libadt/hash_table.h>
10
 
38
 
11
#include "ipc_desc.h"
39
#include "ipc_desc.h"
12
#include "proto.h"
40
#include "proto.h"
13
#include "ipcp.h"
41
#include "ipcp.h"
14
 
42
 
15
#define IPCP_CALLID_SYNC 0
43
#define IPCP_CALLID_SYNC 0
16
 
44
 
17
typedef struct {
45
typedef struct {
18
    int phone_hash;
46
    int phone_hash;
19
    ipc_call_t question;
47
    ipc_call_t question;
20
 
48
 
21
    int call_hash;
49
    int call_hash;
22
 
50
 
23
    link_t link;
51
    link_t link;
24
} pending_call_t;
52
} pending_call_t;
25
 
53
 
26
typedef struct {
54
typedef struct {
27
    int server;
55
    int server;
28
    proto_t *proto;
56
    proto_t *proto;
29
} connection_t;
57
} connection_t;
30
 
58
 
31
#define MAX_PHONE 64
59
#define MAX_PHONE 64
32
connection_t connections[MAX_PHONE];
60
connection_t connections[MAX_PHONE];
33
int have_conn[MAX_PHONE];
61
int have_conn[MAX_PHONE];
34
 
62
 
35
#define PCALL_TABLE_CHAINS 32
63
#define PCALL_TABLE_CHAINS 32
36
hash_table_t pending_calls;
64
hash_table_t pending_calls;
37
 
65
 
38
hash_index_t pending_call_hash(unsigned long key[])
66
hash_index_t pending_call_hash(unsigned long key[])
39
{
67
{
40
//  printf("pending_call_hash\n");
68
//  printf("pending_call_hash\n");
41
    return key[0] % PCALL_TABLE_CHAINS;
69
    return key[0] % PCALL_TABLE_CHAINS;
42
}
70
}
43
 
71
 
44
int pending_call_compare(unsigned long key[], hash_count_t keys,
72
int pending_call_compare(unsigned long key[], hash_count_t keys,
45
    link_t *item)
73
    link_t *item)
46
{
74
{
47
    pending_call_t *hs;
75
    pending_call_t *hs;
48
 
76
 
49
//  printf("pending_call_compare\n");
77
//  printf("pending_call_compare\n");
50
    hs = hash_table_get_instance(item, pending_call_t, link);
78
    hs = hash_table_get_instance(item, pending_call_t, link);
51
 
79
 
52
    return key[0] == hs->call_hash;
80
    return key[0] == hs->call_hash;
53
}
81
}
54
 
82
 
55
void pending_call_remove_callback(link_t *item)
83
void pending_call_remove_callback(link_t *item)
56
{
84
{
57
//  printf("pending_call_remove_callback\n");
85
//  printf("pending_call_remove_callback\n");
58
}
86
}
59
 
87
 
60
hash_table_operations_t pending_call_ops = {
88
hash_table_operations_t pending_call_ops = {
61
    .hash = pending_call_hash,
89
    .hash = pending_call_hash,
62
    .compare = pending_call_compare,
90
    .compare = pending_call_compare,
63
    .remove_callback = pending_call_remove_callback
91
    .remove_callback = pending_call_remove_callback
64
};
92
};
65
 
93
 
66
void ipcp_connection_set(int phone, int server, proto_t *proto)
94
void ipcp_connection_set(int phone, int server, proto_t *proto)
67
{
95
{
68
    if (phone <0 || phone >= MAX_PHONE) return;
96
    if (phone <0 || phone >= MAX_PHONE) return;
69
    connections[phone].server = server;
97
    connections[phone].server = server;
70
    connections[phone].proto = proto;
98
    connections[phone].proto = proto;
71
    have_conn[phone] = 1;
99
    have_conn[phone] = 1;
72
}
100
}
73
 
101
 
74
void ipcp_connection_clear(int phone)
102
void ipcp_connection_clear(int phone)
75
{
103
{
76
    have_conn[phone] = 0;
104
    have_conn[phone] = 0;
77
    connections[phone].server = 0;
105
    connections[phone].server = 0;
78
    connections[phone].proto = NULL;
106
    connections[phone].proto = NULL;
79
}
107
}
80
 
108
 
81
static void ipc_m_print(proto_t *proto, ipcarg_t method)
109
static void ipc_m_print(proto_t *proto, ipcarg_t method)
82
{
110
{
83
    ipc_m_desc_t *desc;
111
    ipc_m_desc_t *desc;
84
    oper_t *oper;
112
    oper_t *oper;
85
 
113
 
86
    /* FIXME: too slow */
114
    /* FIXME: too slow */
87
    desc = ipc_methods;
115
    desc = ipc_methods;
88
    while (desc->number != 0) {
116
    while (desc->number != 0) {
89
        if (desc->number == method) {
117
        if (desc->number == method) {
90
            printf("%s (%d)", desc->name, method);
118
            printf("%s (%d)", desc->name, method);
91
            return;
119
            return;
92
        }
120
        }
93
 
121
 
94
        ++desc;
122
        ++desc;
95
    }
123
    }
96
 
124
 
97
    if (proto != NULL) {
125
    if (proto != NULL) {
98
        oper = proto_get_oper(proto, method);
126
        oper = proto_get_oper(proto, method);
99
        if (oper != NULL) {
127
        if (oper != NULL) {
100
            printf("%s (%d)", oper->name, method);
128
            printf("%s (%d)", oper->name, method);
101
            return;
129
            return;
102
        }
130
        }
103
    }
131
    }
104
 
132
 
105
    printf("%d", method);
133
    printf("%d", method);
106
}
134
}
107
 
135
 
108
void ipcp_init(void)
136
void ipcp_init(void)
109
{
137
{
110
    hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
138
    hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
111
}
139
}
112
 
140
 
113
void ipcp_cleanup(void)
141
void ipcp_cleanup(void)
114
{
142
{
115
    hash_table_destroy(&pending_calls);
143
    hash_table_destroy(&pending_calls);
116
}
144
}
117
 
145
 
118
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
146
void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
119
{
147
{
120
    pending_call_t *pcall;
148
    pending_call_t *pcall;
121
    proto_t *proto;
149
    proto_t *proto;
122
 
150
 
123
    if (have_conn[phone]) proto = connections[phone].proto;
151
    if (have_conn[phone]) proto = connections[phone].proto;
124
    else proto = NULL;
152
    else proto = NULL;
125
 
153
 
126
//  printf("ipcp_call_out()\n");
154
//  printf("ipcp_call_out()\n");
127
    printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone,
155
    printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone,
128
        (proto ? proto->name : "n/a"));
156
        (proto ? proto->name : "n/a"));
129
    ipc_m_print(proto, IPC_GET_METHOD(*call));
157
    ipc_m_print(proto, IPC_GET_METHOD(*call));
130
    printf(" args: (%u, %u, %u, %u, %u)\n",
158
    printf(" args: (%u, %u, %u, %u, %u)\n",
131
        IPC_GET_ARG1(*call),
159
        IPC_GET_ARG1(*call),
132
        IPC_GET_ARG2(*call),
160
        IPC_GET_ARG2(*call),
133
        IPC_GET_ARG3(*call),
161
        IPC_GET_ARG3(*call),
134
        IPC_GET_ARG4(*call),
162
        IPC_GET_ARG4(*call),
135
        IPC_GET_ARG5(*call)
163
        IPC_GET_ARG5(*call)
136
    );
164
    );
137
 
165
 
138
    /* Store call in hash table for response matching */
166
    /* Store call in hash table for response matching */
139
 
167
 
140
    pcall = malloc(sizeof(pending_call_t));
168
    pcall = malloc(sizeof(pending_call_t));
141
    pcall->phone_hash = phone;
169
    pcall->phone_hash = phone;
142
    pcall->question = *call;
170
    pcall->question = *call;
143
    pcall->call_hash = hash;
171
    pcall->call_hash = hash;
144
 
172
 
145
    hash_table_insert(&pending_calls, &pcall->call_hash, &pcall->link);
173
    hash_table_insert(&pending_calls, &pcall->call_hash, &pcall->link);
146
}
174
}
147
 
175
 
148
static void parse_answer(pending_call_t *pcall, ipc_call_t *answer)
176
static void parse_answer(pending_call_t *pcall, ipc_call_t *answer)
149
{
177
{
150
    int phone;
178
    int phone;
151
    ipcarg_t method;
179
    ipcarg_t method;
152
    ipcarg_t service;
180
    ipcarg_t service;
153
    int retval;
181
    int retval;
154
    static proto_t proto_unknown = { .name = "unknown" };
182
    static proto_t proto_unknown = { .name = "unknown" };
155
    proto_t *proto;
183
    proto_t *proto;
156
    int cphone;
184
    int cphone;
157
 
185
 
158
//  printf("parse_answer\n");
186
//  printf("parse_answer\n");
159
 
187
 
160
    phone = pcall->phone_hash;
188
    phone = pcall->phone_hash;
161
    method = IPC_GET_METHOD(pcall->question);
189
    method = IPC_GET_METHOD(pcall->question);
162
    retval = IPC_GET_RETVAL(*answer);
190
    retval = IPC_GET_RETVAL(*answer);
163
    printf("phone=%d, method=%d, retval=%d\n",
191
    printf("phone=%d, method=%d, retval=%d\n",
164
        phone, method, retval);
192
        phone, method, retval);
165
 
193
 
166
    if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
194
    if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
167
        /* Connected to a service (through NS) */
195
        /* Connected to a service (through NS) */
168
        service = IPC_GET_ARG1(pcall->question);
196
        service = IPC_GET_ARG1(pcall->question);
169
        proto = proto_get_by_srv(service);
197
        proto = proto_get_by_srv(service);
170
        if (proto == NULL) proto = &proto_unknown;
198
        if (proto == NULL) proto = &proto_unknown;
171
 
199
 
172
        cphone = IPC_GET_ARG5(*answer);
200
        cphone = IPC_GET_ARG5(*answer);
173
        printf("registering connection (phone %d, protocol: %s)\n", cphone,
201
        printf("registering connection (phone %d, protocol: %s)\n", cphone,
174
            proto->name);
202
            proto->name);
175
        ipcp_connection_set(cphone, 0, proto);
203
        ipcp_connection_set(cphone, 0, proto);
176
    }
204
    }
177
}
205
}
178
 
206
 
179
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
207
void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
180
{
208
{
181
    link_t *item;
209
    link_t *item;
182
    pending_call_t *pcall;
210
    pending_call_t *pcall;
183
 
211
 
184
//  printf("ipcp_call_in()\n");
212
//  printf("ipcp_call_in()\n");
185
/*  printf("phone: %d, method: ", call->in_phone_hash);
213
/*  printf("phone: %d, method: ", call->in_phone_hash);
186
    ipc_m_print(IPC_GET_METHOD(*call));
214
    ipc_m_print(IPC_GET_METHOD(*call));
187
    printf(" args: (%u, %u, %u, %u, %u)\n",
215
    printf(" args: (%u, %u, %u, %u, %u)\n",
188
        IPC_GET_ARG1(*call),
216
        IPC_GET_ARG1(*call),
189
        IPC_GET_ARG2(*call),
217
        IPC_GET_ARG2(*call),
190
        IPC_GET_ARG3(*call),
218
        IPC_GET_ARG3(*call),
191
        IPC_GET_ARG4(*call),
219
        IPC_GET_ARG4(*call),
192
        IPC_GET_ARG5(*call)
220
        IPC_GET_ARG5(*call)
193
    );*/
221
    );*/
194
 
222
 
195
    if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
223
    if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
196
        /* Not a response */
224
        /* Not a response */
197
        printf("Not a response (hash %d)\n", hash);
225
        printf("Not a response (hash %d)\n", hash);
198
        return;
226
        return;
199
    }
227
    }
200
 
228
 
201
    hash = hash & ~IPC_CALLID_ANSWERED;
229
    hash = hash & ~IPC_CALLID_ANSWERED;
202
 
230
 
203
    item = hash_table_find(&pending_calls, &hash);
231
    item = hash_table_find(&pending_calls, &hash);
204
    if (item == NULL) return; // No matching question found
232
    if (item == NULL) return; // No matching question found
205
   
233
   
206
    pcall = hash_table_get_instance(item, pending_call_t, link);
234
    pcall = hash_table_get_instance(item, pending_call_t, link);
207
 
235
 
208
    printf("response matched to question\n");
236
    printf("response matched to question\n");
209
    hash_table_remove(&pending_calls, &hash, 1);
237
    hash_table_remove(&pending_calls, &hash, 1);
210
 
238
 
211
    parse_answer(pcall, call);
239
    parse_answer(pcall, call);
212
    free(pcall);
240
    free(pcall);
213
}
241
}
214
 
242
 
215
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
243
void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
216
{
244
{
217
    ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
245
    ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
218
    ipcp_call_in(answer, IPCP_CALLID_SYNC);
246
    ipcp_call_in(answer, IPCP_CALLID_SYNC);
219
}
247
}
220
 
248
 
221
void ipcp_hangup(int phone, int rc)
249
void ipcp_hangup(int phone, int rc)
222
{
250
{
223
    printf("hangup phone %d -> %d\n", phone, rc);
251
    printf("hangup phone %d -> %d\n", phone, rc);
224
    ipcp_connection_clear(phone);
252
    ipcp_connection_clear(phone);
225
}
253
}
226
 
254
 
227
/** @}
255
/** @}
228
 */
256
 */
229
 
257