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>
29 #include "pcep_msg_tools.h"
30 #include "pcep_msg_encoding.h"
31 #include "pcep_utils_logging.h"
32 #include "pcep_utils_memory.h"
34 static const char *message_type_strs
[] = {"NOT_IMPLEMENTED0",
47 "UNKOWN_MESSAGE_TYPE"};
49 static const char *object_class_strs
[] = {"NOT_IMPLEMENTED0",
89 "ASSOCIATION", /* 40 */
90 "UNKNOWN_MESSAGE_TYPE"};
93 double_linked_list
*pcep_msg_read(int sock_fd
)
96 uint8_t buffer
[PCEP_MESSAGE_LENGTH
] = {0};
97 uint16_t buffer_read
= 0;
100 ret
= read(sock_fd
, &buffer
, PCEP_MESSAGE_LENGTH
);
105 "%s: pcep_msg_read: Failed to read from socket fd [%d] errno [%d %s]",
106 __func__
, sock_fd
, errno
, strerror(errno
));
108 } else if (ret
== 0) {
109 pcep_log(LOG_INFO
, "%s: pcep_msg_read: Remote shutdown fd [%d]",
114 double_linked_list
*msg_list
= dll_initialize();
115 struct pcep_message
*msg
= NULL
;
117 while (((uint16_t)ret
- buffer_read
) >= MESSAGE_HEADER_LENGTH
) {
119 /* Get the Message header, validate it, and return the msg
122 pcep_decode_validate_msg_header(buffer
+ buffer_read
);
123 if (msg_length
< 0 || msg_length
> PCEP_MESSAGE_LENGTH
) {
124 /* If the message header is invalid, we cant keep
125 * reading since the length may be invalid */
128 "%s: pcep_msg_read: Received an invalid message fd [%d]",
133 /* Check if the msg_length is longer than what was read,
134 * in which case, we need to read the rest of the message. */
135 if ((ret
- buffer_read
) < msg_length
) {
136 int read_len
= (msg_length
- (ret
- buffer_read
));
140 "%s: pcep_msg_read: Message not fully read! Trying to read %d bytes more, fd [%d]",
141 __func__
, read_len
, sock_fd
);
143 if (PCEP_MESSAGE_LENGTH
- ret
- buffer_read
>= read_len
)
145 read(sock_fd
, &buffer
[ret
], read_len
);
149 "%s: Trying to read size (%d) offset (%d) in a buff of size (%d)",
150 __func__
, read_len
, ret
, PCEP_MESSAGE_LENGTH
);
154 if (read_ret
!= read_len
) {
157 "%s: pcep_msg_read: Did not manage to read enough data (%d != %d) fd [%d]",
158 __func__
, read_ret
, read_len
, sock_fd
);
163 msg
= pcep_decode_message(buffer
+ buffer_read
);
164 buffer_read
+= msg_length
;
169 dll_append(msg_list
, msg
);
176 struct pcep_message
*pcep_msg_get(double_linked_list
*msg_list
, uint8_t type
)
178 if (msg_list
== NULL
) {
182 double_linked_list_node
*node
;
183 for (node
= msg_list
->head
; node
!= NULL
; node
= node
->next_node
) {
184 if (((struct pcep_message
*)node
->data
)->msg_header
->type
186 return (struct pcep_message
*)node
->data
;
193 struct pcep_message
*pcep_msg_get_next(double_linked_list
*list
,
194 struct pcep_message
*current
,
197 if (list
== NULL
|| current
== NULL
) {
201 if (list
->head
== NULL
) {
205 double_linked_list_node
*node
;
206 for (node
= list
->head
; node
!= NULL
; node
= node
->next_node
) {
207 if (node
->data
== current
) {
211 if (((struct pcep_message
*)node
->data
)->msg_header
->type
213 return (struct pcep_message
*)node
->data
;
220 struct pcep_object_header
*pcep_obj_get(double_linked_list
*list
,
221 uint8_t object_class
)
227 if (list
->head
== NULL
) {
231 double_linked_list_node
*obj_item
;
232 for (obj_item
= list
->head
; obj_item
!= NULL
;
233 obj_item
= obj_item
->next_node
) {
234 if (((struct pcep_object_header
*)obj_item
->data
)->object_class
236 return (struct pcep_object_header
*)obj_item
->data
;
243 struct pcep_object_header
*pcep_obj_get_next(double_linked_list
*list
,
244 struct pcep_object_header
*current
,
245 uint8_t object_class
)
247 if (list
== NULL
|| current
== NULL
) {
251 if (list
->head
== NULL
) {
255 double_linked_list_node
*node
;
256 for (node
= list
->head
; node
!= NULL
; node
= node
->next_node
) {
257 if (node
->data
== current
) {
261 if (((struct pcep_object_header
*)node
->data
)->object_class
263 return (struct pcep_object_header
*)node
->data
;
270 void pcep_obj_free_tlv(struct pcep_object_tlv_header
*tlv
)
272 /* Specific TLV freeing */
274 case PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID
:
275 if (((struct pcep_object_tlv_speaker_entity_identifier
*)tlv
)
276 ->speaker_entity_id_list
278 dll_destroy_with_data_memtype(
280 pcep_object_tlv_speaker_entity_identifier
*)
282 ->speaker_entity_id_list
,
287 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY
:
288 if (((struct pcep_object_tlv_path_setup_type_capability
*)tlv
)
291 dll_destroy_with_data_memtype(
293 pcep_object_tlv_path_setup_type_capability
*)
299 if (((struct pcep_object_tlv_path_setup_type_capability
*)tlv
)
302 dll_destroy_with_data_memtype(
304 pcep_object_tlv_path_setup_type_capability
*)
315 pceplib_free(PCEPLIB_MESSAGES
, tlv
);
318 void pcep_obj_free_object(struct pcep_object_header
*obj
)
320 /* Iterate the TLVs and free each one */
321 if (obj
->tlv_list
!= NULL
) {
322 struct pcep_object_tlv_header
*tlv
;
323 while ((tlv
= (struct pcep_object_tlv_header
*)
324 dll_delete_first_node(obj
->tlv_list
))
326 pcep_obj_free_tlv(tlv
);
329 dll_destroy(obj
->tlv_list
);
332 /* Specific object freeing */
333 switch (obj
->object_class
) {
334 case PCEP_OBJ_CLASS_ERO
:
335 case PCEP_OBJ_CLASS_IRO
:
336 case PCEP_OBJ_CLASS_RRO
: {
337 if (((struct pcep_object_ro
*)obj
)->sub_objects
!= NULL
) {
338 double_linked_list_node
*node
=
339 ((struct pcep_object_ro
*)obj
)
341 for (; node
!= NULL
; node
= node
->next_node
) {
342 struct pcep_object_ro_subobj
*ro_subobj
=
343 (struct pcep_object_ro_subobj
*)
345 if (ro_subobj
->ro_subobj_type
346 == RO_SUBOBJ_TYPE_SR
) {
347 if (((struct pcep_ro_subobj_sr
*)
351 dll_destroy_with_data_memtype(
360 dll_destroy_with_data_memtype(
361 ((struct pcep_object_ro
*)obj
)->sub_objects
,
366 case PCEP_OBJ_CLASS_SVEC
:
367 if (((struct pcep_object_svec
*)obj
)->request_id_list
!= NULL
) {
368 dll_destroy_with_data_memtype(
369 ((struct pcep_object_svec
*)obj
)
375 case PCEP_OBJ_CLASS_SWITCH_LAYER
:
376 if (((struct pcep_object_switch_layer
*)obj
)->switch_layer_rows
378 dll_destroy_with_data_memtype(
379 ((struct pcep_object_switch_layer
*)obj
)
389 pceplib_free(PCEPLIB_MESSAGES
, obj
);
392 void pcep_msg_free_message(struct pcep_message
*message
)
394 /* Iterate the objects and free each one */
395 if (message
->obj_list
!= NULL
) {
396 struct pcep_object_header
*obj
;
397 while ((obj
= (struct pcep_object_header
*)
398 dll_delete_first_node(message
->obj_list
))
400 pcep_obj_free_object(obj
);
403 dll_destroy(message
->obj_list
);
406 if (message
->msg_header
!= NULL
) {
407 pceplib_free(PCEPLIB_MESSAGES
, message
->msg_header
);
410 if (message
->encoded_message
!= NULL
) {
411 pceplib_free(PCEPLIB_MESSAGES
, message
->encoded_message
);
414 pceplib_free(PCEPLIB_MESSAGES
, message
);
417 void pcep_msg_free_message_list(double_linked_list
*list
)
419 /* Iterate the messages and free each one */
420 struct pcep_message
*msg
;
421 while ((msg
= (struct pcep_message
*)dll_delete_first_node(list
))
423 pcep_msg_free_message(msg
);
429 const char *get_message_type_str(uint8_t type
)
432 (type
> PCEP_TYPE_INITIATE
) ? PCEP_TYPE_INITIATE
+ 1 : type
;
434 return message_type_strs
[msg_type
];
437 const char *get_object_class_str(uint8_t class)
439 uint8_t object_class
=
440 (class > PCEP_OBJ_CLASS_SRP
) ? PCEP_OBJ_CLASS_SRP
+ 1 : class;
442 return object_class_strs
[object_class
];
445 /* Expecting a list of struct pcep_message pointers */
446 void pcep_msg_print(double_linked_list
*msg_list
)
448 double_linked_list_node
*node
;
449 for (node
= msg_list
->head
; node
!= NULL
; node
= node
->next_node
) {
450 struct pcep_message
*msg
= (struct pcep_message
*)node
->data
;
451 pcep_log(LOG_INFO
, "%s: PCEP_MSG %s", __func__
,
452 get_message_type_str(msg
->msg_header
->type
));
454 double_linked_list_node
*obj_node
=
455 (msg
->obj_list
== NULL
? NULL
: msg
->obj_list
->head
);
456 for (; obj_node
!= NULL
; obj_node
= obj_node
->next_node
) {
457 struct pcep_object_header
*obj_header
=
458 ((struct pcep_object_header
*)obj_node
->data
);
460 LOG_INFO
, "%s: PCEP_OBJ %s", __func__
,
461 get_object_class_str(obj_header
->object_class
));
466 int pcep_msg_send(int sock_fd
, struct pcep_message
*msg
)
471 int msg_length
= ntohs(msg
->encoded_message_length
);
472 if (msg_length
> PCEP_MESSAGE_LENGTH
) {
473 pcep_log(LOG_ERR
, "%s: Not sended, size(% d) exceed max(% d) ",
474 __func__
, msg_length
, PCEP_MESSAGE_LENGTH
);
478 return write(sock_fd
, msg
->encoded_message
, msg_length
);