~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to uspace/lib/c/generic/iplink_srv.c

MergeĀ mainlineĀ changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2012 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
 
 
29
/** @addtogroup libc
 
30
 * @{
 
31
 */
 
32
/**
 
33
 * @file
 
34
 * @brief IP link server stub
 
35
 */
 
36
#include <errno.h>
 
37
#include <ipc/iplink.h>
 
38
#include <stdlib.h>
 
39
#include <sys/types.h>
 
40
 
 
41
#include <inet/iplink_srv.h>
 
42
 
 
43
static void iplink_get_mtu_srv(iplink_srv_t *srv, ipc_callid_t callid,
 
44
    ipc_call_t *call)
 
45
{
 
46
        int rc;
 
47
        size_t mtu;
 
48
 
 
49
        rc = srv->ops->get_mtu(srv, &mtu);
 
50
        async_answer_1(callid, rc, mtu);
 
51
}
 
52
 
 
53
static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_callid_t callid,
 
54
    ipc_call_t *call)
 
55
{
 
56
        int rc;
 
57
        iplink_srv_addr_t addr;
 
58
 
 
59
        addr.ipv4 = IPC_GET_ARG1(*call);
 
60
 
 
61
        rc = srv->ops->addr_add(srv, &addr);
 
62
        async_answer_0(callid, rc);
 
63
}
 
64
 
 
65
static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_callid_t callid,
 
66
    ipc_call_t *call)
 
67
{
 
68
        int rc;
 
69
        iplink_srv_addr_t addr;
 
70
 
 
71
        addr.ipv4 = IPC_GET_ARG1(*call);
 
72
 
 
73
        rc = srv->ops->addr_remove(srv, &addr);
 
74
        async_answer_0(callid, rc);
 
75
}
 
76
 
 
77
static void iplink_send_srv(iplink_srv_t *srv, ipc_callid_t callid,
 
78
    ipc_call_t *call)
 
79
{
 
80
        iplink_srv_sdu_t sdu;
 
81
        int rc;
 
82
 
 
83
        sdu.lsrc.ipv4 = IPC_GET_ARG1(*call);
 
84
        sdu.ldest.ipv4 = IPC_GET_ARG2(*call);
 
85
 
 
86
        rc = async_data_write_accept(&sdu.data, false, 0, 0, 0, &sdu.size);
 
87
        if (rc != EOK) {
 
88
                async_answer_0(callid, rc);
 
89
                return;
 
90
        }
 
91
 
 
92
        rc = srv->ops->send(srv, &sdu);
 
93
        free(sdu.data);
 
94
        async_answer_0(callid, rc);
 
95
}
 
96
 
 
97
void iplink_srv_init(iplink_srv_t *srv)
 
98
{
 
99
        fibril_mutex_initialize(&srv->lock);
 
100
        srv->connected = false;
 
101
        srv->ops = NULL;
 
102
        srv->arg = NULL;
 
103
        srv->client_sess = NULL;
 
104
}
 
105
 
 
106
int iplink_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 
107
{
 
108
        iplink_srv_t *srv = (iplink_srv_t *)arg;
 
109
        int rc;
 
110
 
 
111
        fibril_mutex_lock(&srv->lock);
 
112
        if (srv->connected) {
 
113
                fibril_mutex_unlock(&srv->lock);
 
114
                async_answer_0(iid, EBUSY);
 
115
                return EBUSY;
 
116
        }
 
117
 
 
118
        srv->connected = true;
 
119
        fibril_mutex_unlock(&srv->lock);
 
120
 
 
121
        /* Accept the connection */
 
122
        async_answer_0(iid, EOK);
 
123
 
 
124
        async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
 
125
        if (sess == NULL)
 
126
                return ENOMEM;
 
127
 
 
128
        srv->client_sess = sess;
 
129
 
 
130
        rc = srv->ops->open(srv);
 
131
        if (rc != EOK)
 
132
                return rc;
 
133
 
 
134
        while (true) {
 
135
                ipc_call_t call;
 
136
                ipc_callid_t callid = async_get_call(&call);
 
137
                sysarg_t method = IPC_GET_IMETHOD(call);
 
138
 
 
139
                if (!method) {
 
140
                        /* The other side has hung up */
 
141
                        async_answer_0(callid, EOK);
 
142
                        break;
 
143
                }
 
144
 
 
145
                switch (method) {
 
146
                case IPLINK_GET_MTU:
 
147
                        iplink_get_mtu_srv(srv, callid, &call);
 
148
                        break;
 
149
                case IPLINK_SEND:
 
150
                        iplink_send_srv(srv, callid, &call);
 
151
                        break;
 
152
                case IPLINK_ADDR_ADD:
 
153
                        iplink_addr_add_srv(srv, callid, &call);
 
154
                        break;
 
155
                case IPLINK_ADDR_REMOVE:
 
156
                        iplink_addr_remove_srv(srv, callid, &call);
 
157
                        break;
 
158
                default:
 
159
                        async_answer_0(callid, EINVAL);
 
160
                }
 
161
        }
 
162
 
 
163
        return srv->ops->close(srv);
 
164
}
 
165
 
 
166
int iplink_ev_recv(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
 
167
{
 
168
        if (srv->client_sess == NULL)
 
169
                return EIO;
 
170
 
 
171
        async_exch_t *exch = async_exchange_begin(srv->client_sess);
 
172
 
 
173
        ipc_call_t answer;
 
174
        aid_t req = async_send_2(exch, IPLINK_EV_RECV, sdu->lsrc.ipv4,
 
175
            sdu->ldest.ipv4, &answer);
 
176
        int rc = async_data_write_start(exch, sdu->data, sdu->size);
 
177
        async_exchange_end(exch);
 
178
 
 
179
        if (rc != EOK) {
 
180
                async_forget(req);
 
181
                return rc;
 
182
        }
 
183
 
 
184
        sysarg_t retval;
 
185
        async_wait_for(req, &retval);
 
186
        if (retval != EOK)
 
187
                return retval;
 
188
 
 
189
        return EOK;
 
190
}
 
191
 
 
192
/** @}
 
193
 */