Subversion Repositories HelenOS

Rev

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

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