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
,
155 PCEP_MESSAGE_LENGTH
);
159 if (read_ret
!= read_len
) {
162 "%s: pcep_msg_read: Did not manage to read enough data (%d != %d) fd [%d]",
163 __func__
, read_ret
, read_len
, sock_fd
);
168 msg
= pcep_decode_message(buffer
+ buffer_read
);
169 buffer_read
+= msg_length
;
174 dll_append(msg_list
, msg
);
181 struct pcep_message
*pcep_msg_get(double_linked_list
*msg_list
, uint8_t type
)
183 if (msg_list
== NULL
) {
187 double_linked_list_node
*node
;
188 for (node
= msg_list
->head
; node
!= NULL
; node
= node
->next_node
) {
189 if (((struct pcep_message
*)node
->data
)->msg_header
->type
191 return (struct pcep_message
*)node
->data
;
198 struct pcep_message
*pcep_msg_get_next(double_linked_list
*list
,
199 struct pcep_message
*current
,
202 if (list
== NULL
|| current
== NULL
) {
206 if (list
->head
== NULL
) {
210 double_linked_list_node
*node
;
211 for (node
= list
->head
; node
!= NULL
; node
= node
->next_node
) {
212 if (node
->data
== current
) {
216 if (((struct pcep_message
*)node
->data
)->msg_header
->type
218 return (struct pcep_message
*)node
->data
;
225 struct pcep_object_header
*pcep_obj_get(double_linked_list
*list
,
226 uint8_t object_class
)
232 if (list
->head
== NULL
) {
236 double_linked_list_node
*obj_item
;
237 for (obj_item
= list
->head
; obj_item
!= NULL
;
238 obj_item
= obj_item
->next_node
) {
239 if (((struct pcep_object_header
*)obj_item
->data
)->object_class
241 return (struct pcep_object_header
*)obj_item
->data
;
248 struct pcep_object_header
*pcep_obj_get_next(double_linked_list
*list
,
249 struct pcep_object_header
*current
,
250 uint8_t object_class
)
252 if (list
== NULL
|| current
== NULL
) {
256 if (list
->head
== NULL
) {
260 double_linked_list_node
*node
;
261 for (node
= list
->head
; node
!= NULL
; node
= node
->next_node
) {
262 if (node
->data
== current
) {
266 if (((struct pcep_object_header
*)node
->data
)->object_class
268 return (struct pcep_object_header
*)node
->data
;
275 void pcep_obj_free_tlv(struct pcep_object_tlv_header
*tlv
)
277 /* Specific TLV freeing */
279 case PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID
:
280 if (((struct pcep_object_tlv_speaker_entity_identifier
*)tlv
)
281 ->speaker_entity_id_list
283 dll_destroy_with_data_memtype(
285 pcep_object_tlv_speaker_entity_identifier
*)
287 ->speaker_entity_id_list
,
292 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY
:
293 if (((struct pcep_object_tlv_path_setup_type_capability
*)tlv
)
296 dll_destroy_with_data_memtype(
298 pcep_object_tlv_path_setup_type_capability
*)
304 if (((struct pcep_object_tlv_path_setup_type_capability
*)tlv
)
307 dll_destroy_with_data_memtype(
309 pcep_object_tlv_path_setup_type_capability
*)
320 pceplib_free(PCEPLIB_MESSAGES
, tlv
);
323 void pcep_obj_free_object(struct pcep_object_header
*obj
)
325 /* Iterate the TLVs and free each one */
326 if (obj
->tlv_list
!= NULL
) {
327 struct pcep_object_tlv_header
*tlv
;
328 while ((tlv
= (struct pcep_object_tlv_header
*)
329 dll_delete_first_node(obj
->tlv_list
))
331 pcep_obj_free_tlv(tlv
);
334 dll_destroy(obj
->tlv_list
);
337 /* Specific object freeing */
338 switch (obj
->object_class
) {
339 case PCEP_OBJ_CLASS_ERO
:
340 case PCEP_OBJ_CLASS_IRO
:
341 case PCEP_OBJ_CLASS_RRO
: {
342 if (((struct pcep_object_ro
*)obj
)->sub_objects
!= NULL
) {
343 double_linked_list_node
*node
=
344 ((struct pcep_object_ro
*)obj
)
346 for (; node
!= NULL
; node
= node
->next_node
) {
347 struct pcep_object_ro_subobj
*ro_subobj
=
348 (struct pcep_object_ro_subobj
*)
350 if (ro_subobj
->ro_subobj_type
351 == RO_SUBOBJ_TYPE_SR
) {
352 if (((struct pcep_ro_subobj_sr
*)
356 dll_destroy_with_data_memtype(
365 dll_destroy_with_data_memtype(
366 ((struct pcep_object_ro
*)obj
)->sub_objects
,
371 case PCEP_OBJ_CLASS_SVEC
:
372 if (((struct pcep_object_svec
*)obj
)->request_id_list
!= NULL
) {
373 dll_destroy_with_data_memtype(
374 ((struct pcep_object_svec
*)obj
)
380 case PCEP_OBJ_CLASS_SWITCH_LAYER
:
381 if (((struct pcep_object_switch_layer
*)obj
)->switch_layer_rows
383 dll_destroy_with_data_memtype(
384 ((struct pcep_object_switch_layer
*)obj
)
394 pceplib_free(PCEPLIB_MESSAGES
, obj
);
397 void pcep_msg_free_message(struct pcep_message
*message
)
399 /* Iterate the objects and free each one */
400 if (message
->obj_list
!= NULL
) {
401 struct pcep_object_header
*obj
;
402 while ((obj
= (struct pcep_object_header
*)
403 dll_delete_first_node(message
->obj_list
))
405 pcep_obj_free_object(obj
);
408 dll_destroy(message
->obj_list
);
411 if (message
->msg_header
!= NULL
) {
412 pceplib_free(PCEPLIB_MESSAGES
, message
->msg_header
);
415 if (message
->encoded_message
!= NULL
) {
416 pceplib_free(PCEPLIB_MESSAGES
, message
->encoded_message
);
419 pceplib_free(PCEPLIB_MESSAGES
, message
);
422 void pcep_msg_free_message_list(double_linked_list
*list
)
424 /* Iterate the messages and free each one */
425 struct pcep_message
*msg
;
426 while ((msg
= (struct pcep_message
*)dll_delete_first_node(list
))
428 pcep_msg_free_message(msg
);
434 const char *get_message_type_str(uint8_t type
)
437 (type
> PCEP_TYPE_INITIATE
) ? PCEP_TYPE_INITIATE
+ 1 : type
;
439 return message_type_strs
[msg_type
];
442 const char *get_object_class_str(uint8_t class)
444 uint8_t object_class
=
445 (class > PCEP_OBJ_CLASS_SRP
) ? PCEP_OBJ_CLASS_SRP
+ 1 : class;
447 return object_class_strs
[object_class
];
450 /* Expecting a list of struct pcep_message pointers */
451 void pcep_msg_print(double_linked_list
*msg_list
)
453 double_linked_list_node
*node
;
454 for (node
= msg_list
->head
; node
!= NULL
; node
= node
->next_node
) {
455 struct pcep_message
*msg
= (struct pcep_message
*)node
->data
;
456 pcep_log(LOG_INFO
, "%s: PCEP_MSG %s", __func__
,
457 get_message_type_str(msg
->msg_header
->type
));
459 double_linked_list_node
*obj_node
=
460 (msg
->obj_list
== NULL
? NULL
: msg
->obj_list
->head
);
461 for (; obj_node
!= NULL
; obj_node
= obj_node
->next_node
) {
462 struct pcep_object_header
*obj_header
=
463 ((struct pcep_object_header
*)obj_node
->data
);
465 LOG_INFO
, "%s: PCEP_OBJ %s", __func__
,
466 get_object_class_str(obj_header
->object_class
));
471 int pcep_msg_send(int sock_fd
, struct pcep_message
*msg
)
476 int msg_length
= ntohs(msg
->encoded_message_length
);
477 if (msg_length
> PCEP_MESSAGE_LENGTH
) {
478 pcep_log(LOG_ERR
, "%s: Not sended, size(% d) exceed max(% d) ",
479 __func__
, msg_length
, PCEP_MESSAGE_LENGTH
);
483 return write(sock_fd
, msg
->encoded_message
, msg_length
);