Subversion Repositories HelenOS

Rev

Rev 2882 | Rev 2946 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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