2
* Copyright (c) 2009 Lukas Mejdrech
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
29
/** @addtogroup libnet
34
* Packet client implementation.
41
#include <packet_client.h>
42
#include <packet_remote.h>
44
#include <net/packet.h>
45
#include <net/packet_header.h>
47
/** Copies the specified data to the beginning of the actual packet content.
49
* Pushes the content end if needed.
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.
58
int packet_copy_data(packet_t *packet, const void *data, size_t length)
60
if (!packet_is_valid(packet))
63
if (packet->data_start + length >= packet->length)
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;
73
/** Allocates the specified space right before the actual packet content and
74
* returns its pointer.
76
* @param[in] packet The packet to be used.
77
* @param[in] length The space length to be allocated at the beginning of the
79
* @return The pointer to the allocated memory.
80
* @return NULL if there is not enough memory left.
82
void *packet_prefix(packet_t *packet, size_t length)
84
if ((!packet_is_valid(packet)) ||
85
(packet->data_start - sizeof(packet_t) -
86
2 * (packet->dest_addr - packet->src_addr) < length)) {
90
packet->data_start -= length;
91
return (void *) packet + packet->data_start;
94
/** Allocates the specified space right after the actual packet content and
95
* returns its pointer.
97
* @param[in] packet The packet to be used.
98
* @param[in] length The space length to be allocated at the end of the
100
* @return The pointer to the allocated memory.
101
* @return NULL if there is not enough memory left.
103
void *packet_suffix(packet_t *packet, size_t length)
105
if ((!packet_is_valid(packet)) ||
106
(packet->data_end + length >= packet->length)) {
110
packet->data_end += length;
111
return (void *) packet + packet->data_end - length;
114
/** Trims the actual packet content by the specified prefix and suffix lengths.
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
121
* @return EOK on success.
122
* @return EINVAL if the packet is not valid.
123
* @return ENOMEM if there is not enough memory left.
125
int packet_trim(packet_t *packet, size_t prefix, size_t suffix)
127
if (!packet_is_valid(packet))
130
if (prefix + suffix > PACKET_DATA_LENGTH(packet))
133
packet->data_start += prefix;
134
packet->data_end -= suffix;
138
/** Returns the packet identifier.
140
* @param[in] packet The packet.
141
* @return The packet identifier.
142
* @return Zero if the packet is not valid.
144
packet_id_t packet_get_id(const packet_t *packet)
146
return packet_is_valid(packet) ? packet->packet_id : 0;
149
/** Returns the stored packet addresses and their length.
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.
158
int packet_get_addr(const packet_t *packet, uint8_t **src, uint8_t **dest)
160
if (!packet_is_valid(packet))
162
if (!packet->addr_len)
165
*src = (void *) packet + packet->src_addr;
167
*dest = (void *) packet + packet->dest_addr;
169
return packet->addr_len;
172
/** Returns the packet content length.
174
* @param[in] packet The packet.
175
* @return The packet content length in bytes.
176
* @return Zero if the packet is not valid.
178
size_t packet_get_data_length(const packet_t *packet)
180
if (!packet_is_valid(packet))
183
return PACKET_DATA_LENGTH(packet);
186
/** Returns the pointer to the beginning of the packet content.
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.
192
void *packet_get_data(const packet_t *packet)
194
if (!packet_is_valid(packet))
197
return (void *) packet + packet->data_start;
200
/** Sets the packet addresses.
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.
211
packet_set_addr(packet_t *packet, const uint8_t *src, const uint8_t *dest,
217
if (!packet_is_valid(packet))
220
allocated = PACKET_MAX_ADDRESS_LENGTH(packet);
221
if (allocated < addr_len)
224
padding = allocated - addr_len;
225
packet->addr_len = addr_len;
228
memcpy((void *) packet + packet->src_addr, src, addr_len);
230
bzero((void *) packet + packet->src_addr + addr_len,
233
bzero((void *) packet + packet->src_addr, allocated);
237
memcpy((void *) packet + packet->dest_addr, dest, addr_len);
239
bzero((void *) packet + packet->dest_addr + addr_len,
242
bzero((void *) packet + packet->dest_addr, allocated);
248
/** Return the packet copy.
250
* Copy the addresses, data, order and metric values.
251
* Queue placement is not copied.
253
* @param[in] sess Packet server module session.
254
* @param[in] packet Original packet.
256
* @return Packet copy.
257
* @return NULL on error.
260
packet_t *packet_get_copy(async_sess_t *sess, packet_t *packet)
262
if (!packet_is_valid(packet))
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));
275
uint8_t *dest = NULL;
276
size_t addrlen = packet_get_addr(packet, &src, &dest);
279
if ((packet_copy_data(copy, packet_get_data(packet),
280
PACKET_DATA_LENGTH(packet)) == EOK) &&
281
/* Copy addresses if present */
283
(packet_set_addr(copy, src, dest, addrlen) == EOK))) {
284
copy->order = packet->order;
285
copy->metric = packet->metric;
288
pq_release_remote(sess, copy->packet_id);