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