ef0c28f90c079faebb63bbbb2858f025e7f14154
[ric-plt/lib/rmr.git] / src / common / src / mbuf_api.c
1 // : vi ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4         Copyright (c) 2019 Nokia 
5         Copyright (c) 2018-2019 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20
21 /*
22         Mnemonic:       mbuf_api.c
23         Abstract:       These are common functions which work only on the mbuf and 
24                                 thus (because they do not touch an endpoint or context) 
25                                 can be agnostic to the underlying transport.
26
27         Author:         E. Scott Daniels
28         Date:           8 February 2019
29 */
30
31 #include <stdlib.h>
32 #include <netdb.h>                      // uint* types
33 #include <errno.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <stdio.h>
37
38 #include "rmr.h"                                // things the users see
39 #include "rmr_agnostic.h"               // agnostic things (must be included before private)
40
41
42 // ---------- some wrappers need explicit copy-in functions, also header field setters -----
43
44 /*
45         Allow the user programme to set the meid in the header.  The meid is a fixed 
46         length buffer in the header and thus we must ensure it is not overrun. If
47         the  user gives a source buffer that is too large, we truncate. The return
48         value is the number of bytes copied, or -1 for absolute failure (bad pointer
49         etc.).  Errno is set:
50                 EINVAL id poitner, buf or buf header are bad.
51                 EOVERFLOW if the bytes given would have overrun
52         
53 */
54 extern int rmr_bytes2meid( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
55         uta_mhdr_t* hdr;
56
57         if( src == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
58                 errno = EINVAL;
59                 return -1;
60         }
61
62         errno = 0;
63         if( len > RMR_MAX_MEID ) {
64                 len = RMR_MAX_MEID;
65                 errno = EOVERFLOW;
66         }
67
68         hdr = (uta_mhdr_t *) mbuf->header;
69         memcpy( hdr->meid, src, len );
70
71         return len;
72 }
73
74 /*
75         Allows the user programme to set the meid from a string. The end of string
76         (nil) will be included UNLESS the total length including the end of string
77         would exceed the size of the space in the header for the meid.  The return
78         value is RMR_OK for success and !RMR_OK on failure. Errno will be set
79         on error.
80 */
81 extern int rmr_str2meid( rmr_mbuf_t* mbuf, unsigned char const* str ) {
82         int len;                // len moved -- we do validate
83
84         if( str == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
85                 errno = EINVAL;
86                 return RMR_ERR_BADARG;
87         }
88
89         errno = 0;
90         if( (len = strlen( (char *) str )) > RMR_MAX_MEID-1 ) {
91                 errno = EOVERFLOW;
92                 return RMR_ERR_OVERFLOW;
93         }
94         
95         rmr_bytes2meid( mbuf, str, len+1 );
96         return RMR_OK;
97 }
98
99
100
101 /*
102         This will copy n bytes from source into the payload. If len is larger than
103         the payload only the bytes which will fit are copied, The user should 
104         check errno on return to determine success or failure.
105 */
106 extern void rmr_bytes2payload( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
107         if( src == NULL  ||  mbuf == NULL || mbuf->payload == NULL ) {
108                 errno = EINVAL;
109                 return;
110         }
111
112         errno = 0;
113         mbuf->state = RMR_OK;
114         if( len > mbuf->alloc_len - sizeof( uta_mhdr_t ) ) {
115                 mbuf->state = RMR_ERR_OVERFLOW;
116                 errno = EMSGSIZE;
117                 len = mbuf->alloc_len - sizeof( uta_mhdr_t );
118         }
119
120         mbuf->len = len;
121         memcpy( mbuf->payload, src, len );
122 }
123
124 /*
125         This will copy a nil terminated string to the mbuf payload. The buffer length
126         is set to the string length.
127 */
128 extern void rmr_str2payload( rmr_mbuf_t* mbuf, unsigned char const* str ) {
129         rmr_bytes2payload( mbuf, str, strlen( (char *) str ) + 1 );
130 }
131
132
133 /*
134         Allow the user programme to set the xaction field in the header.  The xaction
135         is a fixed length buffer in the header and thus we must ensure it is not overrun.
136         If the  user gives a source buffer that is too large, we truncate. The return
137         value is the number of bytes copied, or -1 for absolute failure (bad pointer
138         etc.).  Errno is set:
139                 EINVAL id poitner, buf or buf header are bad.
140                 EOVERFLOW if the bytes given would have overrun
141         
142 */
143 extern int rmr_bytes2xact( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
144         uta_mhdr_t* hdr;
145
146         if( src == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
147                 errno = EINVAL;
148                 return -1;
149         }
150
151         errno = 0;
152         if( len > RMR_MAX_XID ) {
153                 len = RMR_MAX_XID;
154                 errno = EOVERFLOW;
155         }
156
157         hdr = (uta_mhdr_t *) mbuf->header;
158         memcpy( hdr->xid, src, len );
159
160         return len;
161 }
162
163
164
165 /*
166         Allows the user programme to set the xaction (xid) field from a string. The end
167         of string (nil) will be included UNLESS the total length including the end of string
168         would exceed the size of the space in the header for the xaction.  The return
169         value is RMR_OK for success and !RMR_OK on failure. Errno will be set
170         on error.
171 */
172 extern int rmr_str2xact( rmr_mbuf_t* mbuf, unsigned char const* str ) {
173         int len;                // len moved -- we do validate
174
175         if( str == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
176                 errno = EINVAL;
177                 return RMR_ERR_BADARG;
178         }
179
180         errno = 0;
181         if( (len = strlen( (char *) str )) > RMR_MAX_XID-1 ) {
182                 errno = EOVERFLOW;
183                 return RMR_ERR_OVERFLOW;
184         }
185         
186         rmr_bytes2xact( mbuf, str, len+1 );
187         return RMR_OK;
188 }
189
190 /*
191         Extracts the meid (managed equipment) from the header and copies the bytes
192         to the user supplied area. If the user supplied pointer is nil, then
193         a buffer will be allocated and it is the user's responsibilty to free.
194         A pointer is returned to the destination memory (allocated or not)
195         for consistency. If the user programme supplies a destination it is
196         the responsibility of the programme to ensure that the space is large
197         enough.
198 */
199 extern unsigned char*  rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest ) {
200         uta_mhdr_t* hdr;
201
202         if( mbuf == NULL || mbuf->header == NULL ) {
203                 errno = EINVAL;
204                 return NULL;
205         }
206
207         if( ! dest ) {
208                 if( (dest = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID )) == NULL ) {
209                         errno = ENOMEM;
210                         return NULL;
211                 }
212         }
213
214         hdr = (uta_mhdr_t *) mbuf->header;
215         memcpy( dest, hdr->meid, RMR_MAX_XID );
216
217         return dest;
218 }
219
220 // ------------------- trace related access functions --------------------------------------
221 /*
222         The set_trace function will copy the supplied data for size bytes into the 
223         header.  If the header trace area is not large enough, a new one will be allocated
224         which will cause a payload copy based on the msg->len value (if 0 no payload
225         data is copied).
226
227         The return value is the number of bytes actually coppied. If 0 bytes are coppied
228         errno should indicate the reason. If 0 is returned and errno is 0, then size
229         passed was 0.  The state in the message is left UNCHANGED.
230 */
231 extern int rmr_set_trace( rmr_mbuf_t* msg, unsigned const char* data, int size ) {
232         uta_mhdr_t*     hdr;
233         rmr_mbuf_t* nm;                 // new message if larger is needed
234         int             len;
235         void*   old_tp_buf;             // if we need to realloc, must hold old to free
236         void*   old_hdr;
237
238         if( msg == NULL ) {
239                 errno = EINVAL;
240                 return 0;
241         }
242
243         errno = 0;
244         if( size <= 0 ) {
245                 return 0;
246         }
247         
248         hdr = (uta_mhdr_t *) msg->header;
249         len = RMR_TR_LEN( hdr );
250
251         if( len != size ) {                                                     // different sized trace data, must realloc the buffer
252                 nm = rmr_realloc_msg( msg, size );              // realloc with changed trace size
253                 old_tp_buf = msg->tp_buf;
254                 old_hdr = msg->header;
255
256                 msg->tp_buf = nm->tp_buf;                               // reference the reallocated buffer
257                 msg->header = nm->header;
258                 msg->id = NULL;                                                 // currently unused
259                 msg->xaction = nm->xaction;
260                 msg->payload = nm->payload;
261
262                 nm->tp_buf = old_tp_buf;                                // set to free
263                 nm->header = old_hdr;                                   // nano frees on hdr, so must set both
264                 rmr_free_msg( nm );
265
266                 hdr = (uta_mhdr_t *) msg->header;               // header WILL be different
267                 len = RMR_TR_LEN( hdr );
268         }
269
270         memcpy( TRACE_ADDR( hdr ), data, size );
271         
272         return size;
273 }
274
275
276 /*
277         Copies the trace bytes from the message header into the buffer provided by 
278         the user. If the trace data in the header is less than size, then only
279         that number of bytes are copied, else exactly size bytes are copied. The
280         number actually copied is returned.
281 */
282 extern int rmr_get_trace( rmr_mbuf_t* msg, unsigned char* dest, int size ) {
283         uta_mhdr_t*     hdr = NULL;
284         int n2copy = 0;
285
286         if( msg == NULL ) {
287                 return 0;
288         }
289
290         if( size <= 0 || dest == NULL ) {
291                 return 0;
292         }
293
294         hdr = msg->header;
295         if( (n2copy = size < RMR_TR_LEN( hdr ) ? size : RMR_TR_LEN( hdr )) <= 0  ) {
296                 return 0;
297         }
298
299         memcpy( dest, TRACE_ADDR( hdr ), n2copy );
300
301         return n2copy;
302 }
303
304 /*
305         Returns the number of bytes currently allocated for trace data in the message
306         buffer.
307 */
308 extern int rmr_get_trlen( rmr_mbuf_t* msg ) {
309         uta_mhdr_t*     hdr;
310
311         if( msg == NULL ) {
312                 return 0;
313         }
314
315         hdr = msg->header;
316
317         return RMR_TR_LEN( hdr );
318 }