2 * This file is part of the PCEPlib, a PCEP protocol library.
4 * Copyright (C) 2020 Volta Networks https://voltanet.io/
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * Author : Brady Johnson <brady@voltanet.io>
33 #include "pcep_msg_tools.h"
34 #include "pcep_msg_encoding.h"
35 #include "pcep_utils_logging.h"
36 #include "pcep_utils_memory.h"
38 static const char *message_type_strs
[] = {"NOT_IMPLEMENTED0",
51 "UNKOWN_MESSAGE_TYPE"};
53 static const char *object_class_strs
[] = {"NOT_IMPLEMENTED0",
93 "ASSOCIATION", /* 40 */
94 "UNKNOWN_MESSAGE_TYPE"};
97 double_linked_list
*pcep_msg_read(int sock_fd
)
100 uint8_t buffer
[PCEP_MESSAGE_LENGTH
] = {0};
101 uint16_t buffer_read
= 0;
104 ret
= read(sock_fd
, &buffer
, PCEP_MESSAGE_LENGTH
);
109 "%s: pcep_msg_read: Failed to read from socket fd [%d] errno [%d %s]",
110 __func__
, sock_fd
, errno
, strerror(errno
));
112 } else if (ret
== 0) {
113 pcep_log(LOG_INFO
, "%s: pcep_msg_read: Remote shutdown fd [%d]",
118 double_linked_list
*msg_list
= dll_initialize();
119 struct pcep_message
*msg
= NULL
;
121 while (((uint16_t)ret
- buffer_read
) >= MESSAGE_HEADER_LENGTH
) {
123 /* Get the Message header, validate it, and return the msg
126 pcep_decode_validate_msg_header(buffer
+ buffer_read
);
127 if (msg_length
< 0 || msg_length
> PCEP_MESSAGE_LENGTH
) {
128 /* If the message header is invalid, we cant keep
129 * reading since the length may be invalid */
132 "%s: pcep_msg_read: Received an invalid message fd [%d]",
137 /* Check if the msg_length is longer than what was read,
138 * in which case, we need to read the rest of the message. */
139 if ((ret
- buffer_read
) < msg_length
) {
140 int read_len
= (msg_length
- (ret
- buffer_read
));
144 "%s: pcep_msg_read: Message not fully read! Trying to read %d bytes more, fd [%d]",
145 __func__
, read_len
, sock_fd
);
147 if (PCEP_MESSAGE_LENGTH
- ret
- buffer_read
>= read_len
)
149 read(sock_fd
, &buffer
[ret
], read_len
);
153 "%s: Trying to read size (%d) offset (%d) in a buff of size (%d)",
154 __func__
, read_len
, ret
, PCEP_MESSAGE_LENGTH
);
158 if (read_ret
!= read_len
) {
161 "%s: pcep_msg_read: Did not manage to read enough data (%d != %d) fd [%d]",
162 __func__
, read_ret
, read_len
, sock_fd
);
167 msg
= pcep_decode_message(buffer
+ buffer_read
);
168 buffer_read
+= msg_length
;
173 dll_append(msg_list
, msg
);
180 struct pcep_message
*pcep_msg_get(double_linked_list
*msg_list
, uint8_t type
)
182 if (msg_list
== NULL
) {
186 double_linked_list_node
*node
;
187 for (node
= msg_list
->head
; node
!= NULL
; node
= node
->next_node
) {
188 if (((struct pcep_message
*)node
->data
)->msg_header
->type
190 return (struct pcep_message
*)node
->data
;
197 struct pcep_message
*pcep_msg_get_next(double_linked_list
*list
,
198 struct pcep_message
*current
,
201 if (list
== NULL
|| current
== NULL
) {
205 if (list
->head
== NULL
) {
209 double_linked_list_node
*node
;
210 for (node
= list
->head
; node
!= NULL
; node
= node
->next_node
) {
211 if (node
->data
== current
) {
215 if (((struct pcep_message
*)node
->data
)->msg_header
->type
217 return (struct pcep_message
*)node
->data
;
224 struct pcep_object_header
*pcep_obj_get(double_linked_list
*list
,
225 uint8_t object_class
)
231 if (list
->head
== NULL
) {
235 double_linked_list_node
*obj_item
;
236 for (obj_item
= list
->head
; obj_item
!= NULL
;
237 obj_item
= obj_item
->next_node
) {
238 if (((struct pcep_object_header
*)obj_item
->data
)->object_class
240 return (struct pcep_object_header
*)obj_item
->data
;
247 struct pcep_object_header
*pcep_obj_get_next(double_linked_list
*list
,
248 struct pcep_object_header
*current
,
249 uint8_t object_class
)
251 if (list
== NULL
|| current
== NULL
) {
255 if (list
->head
== NULL
) {
259 double_linked_list_node
*node
;
260 for (node
= list
->head
; node
!= NULL
; node
= node
->next_node
) {
261 if (node
->data
== current
) {
265 if (((struct pcep_object_header
*)node
->data
)->object_class
267 return (struct pcep_object_header
*)node
->data
;
274 void pcep_obj_free_tlv(struct pcep_object_tlv_header
*tlv
)
276 /* Specific TLV freeing */
278 case PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID
:
279 if (((struct pcep_object_tlv_speaker_entity_identifier
*)tlv
)
280 ->speaker_entity_id_list
282 dll_destroy_with_data_memtype(
284 pcep_object_tlv_speaker_entity_identifier
*)
286 ->speaker_entity_id_list
,
291 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY
:
292 if (((struct pcep_object_tlv_path_setup_type_capability
*)tlv
)
295 dll_destroy_with_data_memtype(
297 pcep_object_tlv_path_setup_type_capability
*)
303 if (((struct pcep_object_tlv_path_setup_type_capability
*)tlv
)
306 dll_destroy_with_data_memtype(
308 pcep_object_tlv_path_setup_type_capability
*)
319 pceplib_free(PCEPLIB_MESSAGES
, tlv
);
322 void pcep_obj_free_object(struct pcep_object_header
*obj
)
324 /* Iterate the TLVs and free each one */
325 if (obj
->tlv_list
!= NULL
) {
326 struct pcep_object_tlv_header
*tlv
;
327 while ((tlv
= (struct pcep_object_tlv_header
*)
328 dll_delete_first_node(obj
->tlv_list
))
330 pcep_obj_free_tlv(tlv
);
333 dll_destroy(obj
->tlv_list
);
336 /* Specific object freeing */
337 switch (obj
->object_class
) {
338 case PCEP_OBJ_CLASS_ERO
:
339 case PCEP_OBJ_CLASS_IRO
:
340 case PCEP_OBJ_CLASS_RRO
: {
341 if (((struct pcep_object_ro
*)obj
)->sub_objects
!= NULL
) {
342 double_linked_list_node
*node
=
343 ((struct pcep_object_ro
*)obj
)
345 for (; node
!= NULL
; node
= node
->next_node
) {
346 struct pcep_object_ro_subobj
*ro_subobj
=
347 (struct pcep_object_ro_subobj
*)
349 if (ro_subobj
->ro_subobj_type
350 == RO_SUBOBJ_TYPE_SR
) {
351 if (((struct pcep_ro_subobj_sr
*)
355 dll_destroy_with_data_memtype(
364 dll_destroy_with_data_memtype(
365 ((struct pcep_object_ro
*)obj
)->sub_objects
,
370 case PCEP_OBJ_CLASS_SVEC
:
371 if (((struct pcep_object_svec
*)obj
)->request_id_list
!= NULL
) {
372 dll_destroy_with_data_memtype(
373 ((struct pcep_object_svec
*)obj
)
379 case PCEP_OBJ_CLASS_SWITCH_LAYER
:
380 if (((struct pcep_object_switch_layer
*)obj
)->switch_layer_rows
382 dll_destroy_with_data_memtype(
383 ((struct pcep_object_switch_layer
*)obj
)
393 pceplib_free(PCEPLIB_MESSAGES
, obj
);
396 void pcep_msg_free_message(struct pcep_message
*message
)
398 /* Iterate the objects and free each one */
399 if (message
->obj_list
!= NULL
) {
400 struct pcep_object_header
*obj
;
401 while ((obj
= (struct pcep_object_header
*)
402 dll_delete_first_node(message
->obj_list
))
404 pcep_obj_free_object(obj
);
407 dll_destroy(message
->obj_list
);
410 if (message
->msg_header
!= NULL
) {
411 pceplib_free(PCEPLIB_MESSAGES
, message
->msg_header
);
414 if (message
->encoded_message
!= NULL
) {
415 pceplib_free(PCEPLIB_MESSAGES
, message
->encoded_message
);
418 pceplib_free(PCEPLIB_MESSAGES
, message
);
421 void pcep_msg_free_message_list(double_linked_list
*list
)
423 /* Iterate the messages and free each one */
424 struct pcep_message
*msg
;
425 while ((msg
= (struct pcep_message
*)dll_delete_first_node(list
))
427 pcep_msg_free_message(msg
);
433 const char *get_message_type_str(uint8_t type
)
436 (type
> PCEP_TYPE_INITIATE
) ? PCEP_TYPE_INITIATE
+ 1 : type
;
438 return message_type_strs
[msg_type
];
441 const char *get_object_class_str(uint8_t class)
443 uint8_t object_class
=
444 (class > PCEP_OBJ_CLASS_SRP
) ? PCEP_OBJ_CLASS_SRP
+ 1 : class;
446 return object_class_strs
[object_class
];
449 /* Expecting a list of struct pcep_message pointers */
450 void pcep_msg_print(double_linked_list
*msg_list
)
452 double_linked_list_node
*node
;
453 for (node
= msg_list
->head
; node
!= NULL
; node
= node
->next_node
) {
454 struct pcep_message
*msg
= (struct pcep_message
*)node
->data
;
455 pcep_log(LOG_INFO
, "%s: PCEP_MSG %s", __func__
,
456 get_message_type_str(msg
->msg_header
->type
));
458 double_linked_list_node
*obj_node
=
459 (msg
->obj_list
== NULL
? NULL
: msg
->obj_list
->head
);
460 for (; obj_node
!= NULL
; obj_node
= obj_node
->next_node
) {
461 struct pcep_object_header
*obj_header
=
462 ((struct pcep_object_header
*)obj_node
->data
);
464 LOG_INFO
, "%s: PCEP_OBJ %s", __func__
,
465 get_object_class_str(obj_header
->object_class
));
470 int pcep_msg_send(int sock_fd
, struct pcep_message
*msg
)
475 int msg_length
= ntohs(msg
->encoded_message_length
);
476 if (msg_length
> PCEP_MESSAGE_LENGTH
) {
477 pcep_log(LOG_ERR
, "%s: Not sended, size(% d) exceed max(% d) ",
478 __func__
, msg_length
, PCEP_MESSAGE_LENGTH
);
482 return write(sock_fd
, msg
->encoded_message
, msg_length
);