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 |