~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to uspace/lib/net/generic/packet_client.c

MergeĀ mainlineĀ changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2009 Lukas Mejdrech
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 libnet
30
 
 * @{
31
 
 */
32
 
 
33
 
/** @file
34
 
 * Packet client implementation.
35
 
 */
36
 
 
37
 
#include <errno.h>
38
 
#include <mem.h>
39
 
#include <unistd.h>
40
 
#include <sys/mman.h>
41
 
#include <packet_client.h>
42
 
#include <packet_remote.h>
43
 
 
44
 
#include <net/packet.h>
45
 
#include <net/packet_header.h>
46
 
 
47
 
/** Copies the specified data to the beginning of the actual packet content.
48
 
 *
49
 
 * Pushes the content end if needed.
50
 
 *
51
 
 * @param[in] packet    The packet to be filled.
52
 
 * @param[in] data      The data to be copied.
53
 
 * @param[in] length    The length of the copied data.
54
 
 * @return              EOK on success.
55
 
 * @return              EINVAL if the packet is not valid.
56
 
 * @return              ENOMEM if there is not enough memory left.
57
 
 */
58
 
int packet_copy_data(packet_t *packet, const void *data, size_t length)
59
 
{
60
 
        if (!packet_is_valid(packet))
61
 
                return EINVAL;
62
 
 
63
 
        if (packet->data_start + length >= packet->length)
64
 
                return ENOMEM;
65
 
 
66
 
        memcpy((void *) packet + packet->data_start, data, length);
67
 
        if (packet->data_start + length > packet->data_end) 
68
 
                packet->data_end = packet->data_start + length;
69
 
 
70
 
        return EOK;
71
 
}
72
 
 
73
 
/** Allocates the specified space right before the actual packet content and
74
 
 * returns its pointer.
75
 
 *
76
 
 * @param[in] packet    The packet to be used.
77
 
 * @param[in] length    The space length to be allocated at the beginning of the
78
 
 *                      packet content.
79
 
 * @return              The pointer to the allocated memory.
80
 
 * @return              NULL if there is not enough memory left.
81
 
 */
82
 
void *packet_prefix(packet_t *packet, size_t length)
83
 
{
84
 
        if ((!packet_is_valid(packet)) ||
85
 
            (packet->data_start - sizeof(packet_t) -
86
 
            2 * (packet->dest_addr - packet->src_addr) < length)) {
87
 
                return NULL;
88
 
        }
89
 
 
90
 
        packet->data_start -= length;
91
 
        return (void *) packet + packet->data_start;
92
 
}
93
 
 
94
 
/** Allocates the specified space right after the actual packet content and
95
 
 * returns its pointer.
96
 
 *
97
 
 * @param[in] packet    The packet to be used.
98
 
 * @param[in] length    The space length to be allocated at the end of the
99
 
 *                       packet content.
100
 
 * @return              The pointer to the allocated memory.
101
 
 * @return              NULL if there is not enough memory left.
102
 
 */
103
 
void *packet_suffix(packet_t *packet, size_t length)
104
 
{
105
 
        if ((!packet_is_valid(packet)) ||
106
 
            (packet->data_end + length >= packet->length)) {
107
 
                return NULL;
108
 
        }
109
 
 
110
 
        packet->data_end += length;
111
 
        return (void *) packet + packet->data_end - length;
112
 
}
113
 
 
114
 
/** Trims the actual packet content by the specified prefix and suffix lengths.
115
 
 *
116
 
 * @param[in] packet    The packet to be trimmed.
117
 
 * @param[in] prefix    The prefix length to be removed from the beginning of
118
 
 *                      the packet content.
119
 
 * @param[in] suffix    The suffix length to be removed from the end of the
120
 
 *                      packet content.
121
 
 * @return              EOK on success.
122
 
 * @return              EINVAL if the packet is not valid.
123
 
 * @return              ENOMEM if there is not enough memory left.
124
 
 */
125
 
int packet_trim(packet_t *packet, size_t prefix, size_t suffix)
126
 
{
127
 
        if (!packet_is_valid(packet))
128
 
                return EINVAL;
129
 
 
130
 
        if (prefix + suffix > PACKET_DATA_LENGTH(packet))
131
 
                return ENOMEM;
132
 
 
133
 
        packet->data_start += prefix;
134
 
        packet->data_end -= suffix;
135
 
        return EOK;
136
 
}
137
 
 
138
 
/** Returns the packet identifier.
139
 
 *
140
 
 * @param[in] packet    The packet.
141
 
 * @return              The packet identifier.
142
 
 * @return              Zero if the packet is not valid.
143
 
 */
144
 
packet_id_t packet_get_id(const packet_t *packet)
145
 
{
146
 
        return packet_is_valid(packet) ? packet->packet_id : 0;
147
 
}
148
 
 
149
 
/** Returns the stored packet addresses and their length.
150
 
 *
151
 
 * @param[in] packet    The packet.
152
 
 * @param[out] src      The source address. May be NULL if not desired.
153
 
 * @param[out] dest     The destination address. May be NULL if not desired.
154
 
 * @return              The stored addresses length.
155
 
 * @return              Zero if the addresses are not present.
156
 
 * @return              EINVAL if the packet is not valid.
157
 
 */
158
 
int packet_get_addr(const packet_t *packet, uint8_t **src, uint8_t **dest)
159
 
{
160
 
        if (!packet_is_valid(packet))
161
 
                return EINVAL;
162
 
        if (!packet->addr_len)
163
 
                return 0;
164
 
        if (src)
165
 
                *src = (void *) packet + packet->src_addr;
166
 
        if (dest)
167
 
                *dest = (void *) packet + packet->dest_addr;
168
 
 
169
 
        return packet->addr_len;
170
 
}
171
 
 
172
 
/** Returns the packet content length.
173
 
 *
174
 
 * @param[in] packet    The packet.
175
 
 * @return              The packet content length in bytes.
176
 
 * @return              Zero if the packet is not valid.
177
 
 */
178
 
size_t packet_get_data_length(const packet_t *packet)
179
 
{
180
 
        if (!packet_is_valid(packet))
181
 
                return 0;
182
 
 
183
 
        return PACKET_DATA_LENGTH(packet);
184
 
}
185
 
 
186
 
/** Returns the pointer to the beginning of the packet content.
187
 
 *
188
 
 * @param[in] packet    The packet.
189
 
 * @return              The pointer to the beginning of the packet content.
190
 
 * @return              NULL if the packet is not valid.
191
 
 */
192
 
void *packet_get_data(const packet_t *packet)
193
 
{
194
 
        if (!packet_is_valid(packet))
195
 
                return NULL;
196
 
 
197
 
        return (void *) packet + packet->data_start;
198
 
}
199
 
 
200
 
/** Sets the packet addresses.
201
 
 *
202
 
 * @param[in] packet    The packet.
203
 
 * @param[in] src       The new source address. May be NULL.
204
 
 * @param[in] dest      The new destination address. May be NULL.
205
 
 * @param[in] addr_len  The addresses length.
206
 
 * @return              EOK on success.
207
 
 * @return              EINVAL if the packet is not valid.
208
 
 * @return              ENOMEM if there is not enough memory left.
209
 
 */
210
 
int
211
 
packet_set_addr(packet_t *packet, const uint8_t *src, const uint8_t *dest,
212
 
    size_t addr_len)
213
 
{
214
 
        size_t padding;
215
 
        size_t allocated;
216
 
 
217
 
        if (!packet_is_valid(packet))
218
 
                return EINVAL;
219
 
 
220
 
        allocated = PACKET_MAX_ADDRESS_LENGTH(packet);
221
 
        if (allocated < addr_len)
222
 
                return ENOMEM;
223
 
 
224
 
        padding = allocated - addr_len;
225
 
        packet->addr_len = addr_len;
226
 
 
227
 
        if (src) {
228
 
                memcpy((void *) packet + packet->src_addr, src, addr_len);
229
 
                if (padding)
230
 
                        bzero((void *) packet + packet->src_addr + addr_len,
231
 
                            padding);
232
 
        } else {
233
 
                bzero((void *) packet + packet->src_addr, allocated);
234
 
        }
235
 
 
236
 
        if (dest) {
237
 
                memcpy((void *) packet + packet->dest_addr, dest, addr_len);
238
 
                if (padding)
239
 
                        bzero((void *) packet + packet->dest_addr + addr_len,
240
 
                            padding);
241
 
        } else {
242
 
                bzero((void *) packet + packet->dest_addr, allocated);
243
 
        }
244
 
 
245
 
        return EOK;
246
 
}
247
 
 
248
 
/** Return the packet copy.
249
 
 *
250
 
 * Copy the addresses, data, order and metric values.
251
 
 * Queue placement is not copied.
252
 
 *
253
 
 * @param[in] sess   Packet server module session.
254
 
 * @param[in] packet Original packet.
255
 
 *
256
 
 * @return Packet copy.
257
 
 * @return NULL on error.
258
 
 *
259
 
 */
260
 
packet_t *packet_get_copy(async_sess_t *sess, packet_t *packet)
261
 
{
262
 
        if (!packet_is_valid(packet))
263
 
                return NULL;
264
 
        
265
 
        /* Get a new packet */
266
 
        packet_t *copy = packet_get_4_remote(sess, PACKET_DATA_LENGTH(packet),
267
 
            PACKET_MAX_ADDRESS_LENGTH(packet), packet->max_prefix,
268
 
            PACKET_MIN_SUFFIX(packet));
269
 
        
270
 
        if (!copy)
271
 
                return NULL;
272
 
        
273
 
        /* Get addresses */
274
 
        uint8_t *src = NULL;
275
 
        uint8_t *dest = NULL;
276
 
        size_t addrlen = packet_get_addr(packet, &src, &dest);
277
 
        
278
 
        /* Copy data */
279
 
        if ((packet_copy_data(copy, packet_get_data(packet),
280
 
            PACKET_DATA_LENGTH(packet)) == EOK) &&
281
 
            /* Copy addresses if present */
282
 
            ((addrlen <= 0) ||
283
 
            (packet_set_addr(copy, src, dest, addrlen) == EOK))) {
284
 
                copy->order = packet->order;
285
 
                copy->metric = packet->metric;
286
 
                return copy;
287
 
        } else {
288
 
                pq_release_remote(sess, copy->packet_id);
289
 
                return NULL;
290
 
        }
291
 
}
292
 
 
293
 
/** @}
294
 
 */