Correct inability to extend payload for rts msg
[ric-plt/lib/rmr.git] / src / rmr / 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, or the transport
26                                 layer provides a transport specific function (e.g. payload 
27                                 reallocation).
28
29         Author:         E. Scott Daniels
30         Date:           8 February 2019
31 */
32
33 #include <stdlib.h>
34 #include <netdb.h>                      // uint* types
35 #include <errno.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <semaphore.h>
40
41 #include "rmr.h"                                // things the users see
42 #include "rmr_agnostic.h"               // agnostic things (must be included before private)
43
44
45 // ---------- some wrappers need explicit copy-in functions, also header field setters -----
46
47 /*
48         Allow the user programme to set the meid in the header.  The meid is a fixed
49         length buffer in the header and thus we must ensure it is not overrun. If
50         the  user gives a source buffer that is too large, we truncate. The return
51         value is the number of bytes copied, or -1 for absolute failure (bad pointer
52         etc.).  Errno is set:
53                 EINVAL id poitner, buf or buf header are bad.
54                 EOVERFLOW if the bytes given would have overrun
55
56 */
57 extern int rmr_bytes2meid( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
58         uta_mhdr_t* hdr;
59
60         if( src == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
61                 errno = EINVAL;
62                 return -1;
63         }
64
65         errno = 0;
66         if( len > RMR_MAX_MEID ) {
67                 len = RMR_MAX_MEID;
68                 errno = EOVERFLOW;
69         }
70
71         hdr = (uta_mhdr_t *) mbuf->header;
72         memcpy( hdr->meid, src, len );
73
74         return len;
75 }
76
77 /*
78         Allows the user programme to set the meid from a string. The end of string
79         (nil) will be included UNLESS the total length including the end of string
80         would exceed the size of the space in the header for the meid.  The return
81         value is RMR_OK for success and !RMR_OK on failure. Errno will be set
82         on error.
83 */
84 extern int rmr_str2meid( rmr_mbuf_t* mbuf, unsigned char const* str ) {
85         int len;                // len moved -- we do validate
86
87         if( str == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
88                 errno = EINVAL;
89                 return RMR_ERR_BADARG;
90         }
91
92         errno = 0;
93         if( (len = strlen( (char *) str )) > RMR_MAX_MEID-1 ) {
94                 errno = EOVERFLOW;
95                 return RMR_ERR_OVERFLOW;
96         }
97
98         rmr_bytes2meid( mbuf, str, len+1 );
99         return RMR_OK;
100 }
101
102
103
104 /*
105         This will copy n bytes from source into the payload. If len is larger than
106         the payload only the bytes which will fit are copied, The user should
107         check errno on return to determine success or failure.
108 */
109 extern void rmr_bytes2payload( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
110         if( src == NULL  ||  mbuf == NULL || mbuf->payload == NULL ) {
111                 errno = EINVAL;
112                 return;
113         }
114
115         errno = 0;
116         mbuf->state = RMR_OK;
117         if( len > mbuf->alloc_len - sizeof( uta_mhdr_t ) ) {
118                 mbuf->state = RMR_ERR_OVERFLOW;
119                 errno = EMSGSIZE;
120                 len = mbuf->alloc_len - sizeof( uta_mhdr_t );
121         }
122
123         mbuf->len = len;
124         memcpy( mbuf->payload, src, len );
125 }
126
127 /*
128         This will copy a nil terminated string to the mbuf payload. The buffer length
129         is set to the string length.
130 */
131 extern void rmr_str2payload( rmr_mbuf_t* mbuf, unsigned char const* str ) {
132         rmr_bytes2payload( mbuf, str, strlen( (char *) str ) + 1 );
133 }
134
135
136 /*
137         Allow the user programme to set the xaction field in the header.  The xaction
138         is a fixed length buffer in the header and thus we must ensure it is not overrun.
139         If the  user gives a source buffer that is too large, we truncate. The return
140         value is the number of bytes copied, or -1 for absolute failure (bad pointer
141         etc.).  Errno is set:
142                 EINVAL id poitner, buf or buf header are bad.
143                 EOVERFLOW if the bytes given would have overrun
144
145 */
146 extern int rmr_bytes2xact( rmr_mbuf_t* mbuf, unsigned char const* src, int len ) {
147         uta_mhdr_t* hdr;
148
149         if( src == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
150                 errno = EINVAL;
151                 return -1;
152         }
153
154         errno = 0;
155         if( len > RMR_MAX_XID ) {
156                 len = RMR_MAX_XID;
157                 errno = EOVERFLOW;
158         }
159
160         hdr = (uta_mhdr_t *) mbuf->header;
161         memcpy( hdr->xid, src, len );
162
163         return len;
164 }
165
166
167
168 /*
169         Allows the user programme to set the xaction (xid) field from a string. The end
170         of string (nil) will be included UNLESS the total length including the end of string
171         would exceed the size of the space in the header for the xaction.  The return
172         value is RMR_OK for success and !RMR_OK on failure. Errno will be set
173         on error.
174 */
175 extern int rmr_str2xact( rmr_mbuf_t* mbuf, unsigned char const* str ) {
176         int len;                // len moved -- we do validate
177
178         if( str == NULL  ||  mbuf == NULL || mbuf->header == NULL ) {
179                 errno = EINVAL;
180                 return RMR_ERR_BADARG;
181         }
182
183         errno = 0;
184         if( (len = strlen( (char *) str )) > RMR_MAX_XID-1 ) {
185                 errno = EOVERFLOW;
186                 return RMR_ERR_OVERFLOW;
187         }
188
189         rmr_bytes2xact( mbuf, str, len+1 );
190         return RMR_OK;
191 }
192
193 /*
194         Extracts the transaction bytes from the header and places into a
195         user supplied buffer (dest). The buffer must be at least RMR_MAX_XID
196         bytes in length as this function will copy the entire field (even if
197         the sender saved a shorter "string." If the user supplies a nil poniter
198         as the destination, a buffer is allocated; the caller must free when
199         finished.  The buffer will be exactly RMR_MAX_XID bytes long.
200
201         The return value is a pointer to the buffer that was filled (to
202         the dest buffer provided, or the buffer we allocated). If there is an
203         error, a nil pointer is returned, and errno should suggest the root
204         cause of the issue (invalid message or no memory).
205 */
206 extern unsigned char*  rmr_get_xact( rmr_mbuf_t* mbuf, unsigned char* dest ) {
207         errno = 0;
208
209         if( mbuf == NULL || mbuf->xaction == NULL ) {
210                 errno = EINVAL;
211                 return NULL;
212         }
213
214         if( ! dest ) {
215                 if( (dest = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_XID )) == NULL ) {
216                         errno = ENOMEM;
217                         return NULL;
218                 }
219         }
220
221         memcpy( dest, mbuf->xaction, RMR_MAX_XID );
222
223         return dest;
224 }
225
226 /*
227         Extracts the meid (managed equipment) from the header and copies the bytes
228         to the user supplied area. If the user supplied pointer is nil, then
229         a buffer will be allocated and it is the user's responsibilty to free.
230         A pointer is returned to the destination memory (allocated or not)
231         for consistency. If the user programme supplies a destination it is
232         the responsibility of the programme to ensure that the space is large
233         enough.
234 */
235 extern unsigned char*  rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest ) {
236         uta_mhdr_t* hdr;
237
238         errno = 0;
239
240         if( mbuf == NULL || mbuf->header == NULL ) {
241                 errno = EINVAL;
242                 return NULL;
243         }
244
245         if( ! dest ) {
246                 if( (dest = (unsigned char *) malloc( sizeof( unsigned char ) * RMR_MAX_MEID )) == NULL ) {
247                         errno = ENOMEM;
248                         return NULL;
249                 }
250         }
251
252         hdr = (uta_mhdr_t *) mbuf->header;
253         memcpy( dest, hdr->meid, RMR_MAX_MEID );
254
255         return dest;
256 }
257
258 // ------------------- trace related access functions --------------------------------------
259 /*
260         The set_trace function will copy the supplied data for size bytes into the
261         header.  If the header trace area is not large enough, a new one will be allocated
262         which will cause a payload copy based on the msg->len value (if 0 no payload
263         data is copied).
264
265         The return value is the number of bytes actually coppied. If 0 bytes are coppied
266         errno should indicate the reason. If 0 is returned and errno is 0, then size
267         passed was 0.  The state in the message is left UNCHANGED.
268 */
269 extern int rmr_set_trace( rmr_mbuf_t* msg, unsigned const char* data, int size ) {
270         uta_mhdr_t*     hdr;
271         rmr_mbuf_t* nm;                 // new message if larger is needed
272         int             len;
273         void*   old_tp_buf;             // if we need to realloc, must hold old to free
274         void*   old_hdr;
275
276         if( msg == NULL ) {
277                 errno = EINVAL;
278                 return 0;
279         }
280
281         errno = 0;
282         if( size <= 0 ) {
283                 return 0;
284         }
285
286         hdr = (uta_mhdr_t *) msg->header;
287         if( !hdr ) {
288                 errno = EINVAL;
289                 return 0;
290         }
291
292         len = RMR_TR_LEN( hdr );
293
294         if( len != size ) {                                                     // different sized trace data, must realloc the buffer
295                 nm = rmr_realloc_msg( msg, size );              // realloc with changed trace size
296                 old_tp_buf = msg->tp_buf;
297                 old_hdr = msg->header;
298
299                 msg->tp_buf = nm->tp_buf;                               // reference the reallocated buffer
300                 msg->header = nm->header;
301                 msg->id = NULL;                                                 // currently unused
302                 msg->xaction = nm->xaction;
303                 msg->payload = nm->payload;
304
305                 nm->tp_buf = old_tp_buf;                                // set to free
306                 nm->header = old_hdr;                                   // nano frees on hdr, so must set both
307                 rmr_free_msg( nm );
308
309                 hdr = (uta_mhdr_t *) msg->header;               // header WILL be different
310                 len = RMR_TR_LEN( hdr );
311         }
312
313         memcpy( TRACE_ADDR( hdr ), data, size );
314
315         return size;
316 }
317
318
319 /*
320         Returns a pointer (reference) to the trace data in the message. If sizeptr
321         is supplied, then the trace data size is assigned to the referenced
322         integer so that the caller doesn't need to make a second call to get the
323         value.
324
325         CAUTION:  user programmes should avoid writing to the referenced trace
326                         area (use rmr_set_trace() to avoid possible data overruns. This
327                         function is a convenience, and it is expected that users will
328                         use the trace data as read-only so as a copy is not necessary.
329 */
330 extern void* rmr_trace_ref( rmr_mbuf_t* msg, int* sizeptr ) {
331         uta_mhdr_t*     hdr = NULL;
332         int size = 0;
333
334         if( sizeptr != NULL ) {
335                 *sizeptr = 0;                                   // ensure reset if we bail
336         }
337
338         if( msg == NULL ) {
339                 return NULL;
340         }
341
342         hdr = msg->header;
343         if( (size = RMR_TR_LEN( hdr )) <= 0 ) {
344                 return NULL;
345         }
346
347         if( sizeptr != NULL ) {
348                 *sizeptr = size;
349         }
350
351         return (void *) TRACE_ADDR( hdr );
352 }
353
354 /*
355         Copies the trace bytes from the message header into the buffer provided by
356         the user. If the trace data in the header is less than size, then only
357         that number of bytes are copied, else exactly size bytes are copied. The
358         number actually copied is returned.
359 */
360 extern int rmr_get_trace( rmr_mbuf_t* msg, unsigned char* dest, int size ) {
361         uta_mhdr_t*     hdr = NULL;
362         int n2copy = 0;
363
364         if( msg == NULL ) {
365                 return 0;
366         }
367
368         if( size <= 0 || dest == NULL ) {
369                 return 0;
370         }
371
372         hdr = msg->header;
373         if( (n2copy = size < RMR_TR_LEN( hdr ) ? size : RMR_TR_LEN( hdr )) <= 0  ) {
374                 return 0;
375         }
376
377         memcpy( dest, TRACE_ADDR( hdr ), n2copy );
378
379         return n2copy;
380 }
381
382 /*
383         Returns the number of bytes currently allocated for trace data in the message
384         buffer.
385 */
386 extern int rmr_get_trlen( rmr_mbuf_t* msg ) {
387         uta_mhdr_t*     hdr;
388
389         if( msg == NULL ) {
390                 return 0;
391         }
392
393         hdr = msg->header;
394
395         return RMR_TR_LEN( hdr );
396 }
397
398 /*
399         Returns the string in the source portion of the header. This is assumed to be
400         something that can be used for direct sends (hostname:port). Regardless, it
401         will be a nil terminated, ascii string with max of 64 characters including
402         the final nil. So, the user must ensure that dest is at least 64 bytes.
403
404         As a convenience, the pointer to dest is returned on success; nil on failure
405         with errno set.
406 */
407 extern unsigned char* rmr_get_src( rmr_mbuf_t* msg, unsigned char* dest ) {
408         uta_mhdr_t*     hdr = NULL;
409
410         if( msg == NULL ) {
411                 errno = EINVAL;
412                 return NULL;
413         }
414
415         if( dest != NULL ) {
416                 hdr = msg->header;
417                 strcpy( dest, hdr->src );
418         }
419
420         return dest;
421 }
422
423 /*
424         Returns the string with the IP address as reported by the sender. This is
425         the IP address that the sender has sussed off of one of the interfaces
426         and cannot be guarenteed to be the acutal IP address which was used to
427         establish the connection.   The caller must provide a buffer of at least
428         64 bytes; the string will be nil terminated. A pointer to the user's buffer
429         is returned on success, nil on failure.
430 */
431 extern unsigned char* rmr_get_srcip( rmr_mbuf_t* msg, unsigned char* dest ) {
432         uta_mhdr_t*     hdr = NULL;
433         char*   rstr = NULL;
434
435         errno = EINVAL;
436
437         if( dest != NULL && msg != NULL ) {
438                 hdr = msg->header;
439                 if( HDR_VERSION( msg->header ) > 2 ) {          // src ip was not present in hdr until ver 3
440                         errno = 0;
441                         strcpy( dest, hdr->srcip );
442                         rstr = dest;
443                 } else  {
444                         errno = 0;
445                         strcpy( dest, hdr->src );                               // reutrn the name:port for old messages
446                         rstr = dest;
447                 }
448         }
449
450         return rstr;
451 }
452