source: mainline/uspace/lib/net/generic/packet_client.c@ c3887ad

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c3887ad was 6b82009, checked in by Martin Decky <martin@…>, 14 years ago

networking stack: convert to the new async framework

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