summaryrefslogtreecommitdiffstats
path: root/tinyBFCP
diff options
context:
space:
mode:
Diffstat (limited to 'tinyBFCP')
-rw-r--r--tinyBFCP/AStyle.sh1
-rw-r--r--tinyBFCP/Makefile.am22
-rw-r--r--tinyBFCP/include/tinybfcp.h26
-rw-r--r--tinyBFCP/include/tinybfcp/tbfcp_attr.h98
-rw-r--r--tinyBFCP/include/tinybfcp/tbfcp_pkt.h107
-rw-r--r--tinyBFCP/include/tinybfcp/tbfcp_session.h72
-rw-r--r--tinyBFCP/include/tinybfcp/tbfcp_types.h207
-rw-r--r--tinyBFCP/include/tinybfcp/tbfcp_utils.h43
-rw-r--r--tinyBFCP/include/tinybfcp_config.h80
-rw-r--r--tinyBFCP/src/tbfcp_attr.c674
-rw-r--r--tinyBFCP/src/tbfcp_pkt.c585
-rw-r--r--tinyBFCP/src/tbfcp_session.c1041
-rw-r--r--tinyBFCP/src/tbfcp_utils.c191
-rw-r--r--tinyBFCP/test/stdafx.c22
-rw-r--r--tinyBFCP/test/stdafx.h31
-rw-r--r--tinyBFCP/test/targetver.h36
-rw-r--r--tinyBFCP/test/test.c82
-rw-r--r--tinyBFCP/test/test.vcproj221
-rw-r--r--tinyBFCP/test/test_parser.h215
-rw-r--r--tinyBFCP/test/test_session.h62
-rw-r--r--tinyBFCP/tinyBFCP.pc.in15
-rw-r--r--tinyBFCP/tinyBFCP.sln68
-rw-r--r--tinyBFCP/tinyBFCP.vcproj245
-rw-r--r--tinyBFCP/version.rc102
24 files changed, 4246 insertions, 0 deletions
diff --git a/tinyBFCP/AStyle.sh b/tinyBFCP/AStyle.sh
new file mode 100644
index 0000000..5bf8859
--- /dev/null
+++ b/tinyBFCP/AStyle.sh
@@ -0,0 +1 @@
+../thirdparties/win32/bin/AStyle.exe --style=k/r --lineend=linux --mode=c --add-brackets --break-closing-brackets --recursive "*.c" "*.h" \ No newline at end of file
diff --git a/tinyBFCP/Makefile.am b/tinyBFCP/Makefile.am
new file mode 100644
index 0000000..c7a6779
--- /dev/null
+++ b/tinyBFCP/Makefile.am
@@ -0,0 +1,22 @@
+lib_LTLIBRARIES = libtinyBFCP.la
+libtinyBFCP_la_LIBADD = ../tinySAK/libtinySAK.la ../tinyNET/libtinyNET.la
+libtinyBFCP_la_CPPFLAGS = -Iinclude -I../tinySAK/src -I../tinyNET/src
+
+libtinyBFCP_la_SOURCES = \
+ src/tbfcp_attr.c\
+ src/tbfcp_pkt.c\
+ src/tbfcp_session.c\
+ src/tbfcp_utils.c
+
+libtinyBFCP_la_LDFLAGS = $LDFLAGS -no-undefined
+if TARGET_OS_IS_ANDROID
+libtinyBFCP_la_LDFLAGS += -static
+endif
+
+_includedir = $(includedir)/tinybfcp
+_include_HEADERS = include/*.h
+__includedir = $(includedir)/tinybfcp/tinybfcp
+__include_HEADERS = include/tinybfcp/*.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = tinyBFCP.pc
diff --git a/tinyBFCP/include/tinybfcp.h b/tinyBFCP/include/tinybfcp.h
new file mode 100644
index 0000000..e6d02a8
--- /dev/null
+++ b/tinyBFCP/include/tinybfcp.h
@@ -0,0 +1,26 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TBFCP_TINYBFCP_H
+#define TBFCP_TINYBFCP_H
+
+#include "tinybfcp/tbfcp_pkt.h"
+#include "tinybfcp/tbfcp_attr.h"
+#include "tinybfcp/tbfcp_session.h"
+
+#endif /* TBFCP_TINYBFCP_H */
diff --git a/tinyBFCP/include/tinybfcp/tbfcp_attr.h b/tinyBFCP/include/tinybfcp/tbfcp_attr.h
new file mode 100644
index 0000000..c83f805
--- /dev/null
+++ b/tinyBFCP/include/tinybfcp/tbfcp_attr.h
@@ -0,0 +1,98 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TBFCP_ATTR_H
+#define TBFCP_ATTR_H
+
+#include "tinybfcp_config.h"
+#include "tinybfcp/tbfcp_types.h"
+
+#include "tsk_object.h"
+#include "tsk_list.h"
+
+TBFCP_BEGIN_DECLS
+
+#if !defined(TBFCP_ATTR_HDR_SIZE_IN_OCTETS)
+# define TBFCP_ATTR_HDR_SIZE_IN_OCTETS 2 /* 2 Octets: Type(7bits),M(1bit),Length(8bits) */
+#endif /* TBFCP_ATTR_HDR_SIZE_IN_OCTETS */
+
+// RFC4582 - 5.2. Attribute Format
+typedef struct tbfcp_attr_hdr_xs {
+ enum tbfcp_attribute_type_e type; // 7bits
+ unsigned M:1; // Mandatory // 1bit
+ uint8_t length; // 8bits excluding any padding defined for specific attributes
+} tbfcp_attr_hdr_xt;
+
+typedef struct tbfcp_attr_s {
+ TSK_DECLARE_OBJECT;
+ struct tbfcp_attr_s* pc_base;
+ struct tbfcp_attr_hdr_xs hdr;
+ enum tbfcp_attribute_format_e format;
+} tbfcp_attr_t;
+#define TBFCP_DECLARE_ATTR struct tbfcp_attr_s __base__
+#define TBFCP_ATTR(p_self) ((struct tbfcp_attr_s*)(p_self))
+typedef tsk_list_t tbfcp_attrs_L_t;
+TINYBFCP_API int tbfcp_attr_get_size_in_octetunits_without_padding(const struct tbfcp_attr_s* pc_self, tsk_size_t* p_size);
+TINYBFCP_API int tbfcp_attr_get_size_in_octetunits_with_padding(const struct tbfcp_attr_s* pc_self, tsk_size_t* p_size);
+TINYBFCP_API int tbfcp_attr_write_without_padding(const struct tbfcp_attr_s* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written);
+TINYBFCP_API int tbfcp_attr_write_with_padding(const struct tbfcp_attr_s* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written);
+TINYBFCP_API int tbfcp_attr_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_consumed_octets, struct tbfcp_attr_s** pp_attr);
+
+typedef struct tbfcp_attr_unsigned16_s {
+ TBFCP_DECLARE_ATTR;
+ uint16_t Unsigned16;
+} tbfcp_attr_unsigned16_t;
+#define TBFCP_ATTR_UNSIGNED16(p_self) ((struct tbfcp_attr_unsigned16_s*)(p_self))
+TINYBFCP_API int tbfcp_attr_unsigned16_create(enum tbfcp_attribute_type_e type, unsigned M, uint16_t Unsigned16, struct tbfcp_attr_unsigned16_s** pp_self);
+
+typedef struct tbfcp_attr_octetstring16_s {
+ TBFCP_DECLARE_ATTR;
+ uint8_t OctetString16[2];
+} tbfcp_attr_octetstring16_t;
+#define TBFCP_ATTR_OCTETSTRING16(p_self) ((struct tbfcp_attr_octetstring16_s*)(p_self))
+TINYBFCP_API int tbfcp_attr_octetstring16_create(enum tbfcp_attribute_type_e type, unsigned M, uint8_t OctetString16[2], struct tbfcp_attr_octetstring16_s** pp_self);
+
+typedef struct tbfcp_attr_octetstring_s {
+ TBFCP_DECLARE_ATTR;
+ uint8_t *OctetString;
+ uint8_t OctetStringLength; // Length in octet excluding any paddding
+} tbfcp_attr_octetstring_t;
+#define TBFCP_ATTR_OCTETSTRING(p_self) ((struct tbfcp_attr_octetstring_s*)(p_self))
+TINYBFCP_API int tbfcp_attr_octetstring_create(enum tbfcp_attribute_type_e type, unsigned M, const uint8_t *OctetString, uint8_t OctetStringLength, struct tbfcp_attr_octetstring_s** pp_self);
+
+typedef struct tbfcp_attr_grouped_s {
+ TBFCP_DECLARE_ATTR;
+ union {
+ uint16_t BeneficiaryID; // 5.2.14. BENEFICIARY-INFORMATION
+ uint16_t FloorRequestID; // 5.2.15. FLOOR-REQUEST-INFORMATION && 5.2.18. OVERALL-REQUEST-STATUS
+ uint16_t RequestedbyID; // 5.2.16. REQUESTED-BY-INFORMATION
+ uint16_t FloorID; // 5.2.17. FLOOR-REQUEST-STATUS
+ } extra_hdr;
+ uint8_t extra_hdr_size_in_octets;
+ tbfcp_attrs_L_t *p_list_attrs;
+} tbfcp_attr_grouped_t;
+#define TBFCP_ATTR_GROUPED(p_self) ((struct tbfcp_attr_grouped_s*)(p_self))
+TINYBFCP_API int tbfcp_attr_grouped_create(enum tbfcp_attribute_type_e type, unsigned M, struct tbfcp_attr_grouped_s** pp_self);
+TINYBFCP_API int tbfcp_attr_grouped_create_u16(enum tbfcp_attribute_type_e type, unsigned M, uint16_t extra_hdr_u16_val, struct tbfcp_attr_grouped_s** pp_self);
+TINYBFCP_API int tbfcp_attr_grouped_add_attr(struct tbfcp_attr_grouped_s* p_self, struct tbfcp_attr_s** p_attr);
+TINYBFCP_API int tbfcp_attr_grouped_find_at(const struct tbfcp_attr_grouped_s* pc_self, enum tbfcp_attribute_format_e e_format, tsk_size_t u_index, const struct tbfcp_attr_s** ppc_attr);
+
+TBFCP_END_DECLS
+
+#endif /* TBFCP_ATTR_H */
+
diff --git a/tinyBFCP/include/tinybfcp/tbfcp_pkt.h b/tinyBFCP/include/tinybfcp/tbfcp_pkt.h
new file mode 100644
index 0000000..92353cc
--- /dev/null
+++ b/tinyBFCP/include/tinybfcp/tbfcp_pkt.h
@@ -0,0 +1,107 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TBFCP_PKT_H
+#define TBFCP_PKT_H
+
+#include "tinybfcp_config.h"
+#include "tinybfcp/tbfcp_types.h"
+#include "tinybfcp/tbfcp_attr.h"
+
+#include "tsk_object.h"
+#include "tsk_list.h"
+
+TBFCP_BEGIN_DECLS
+
+#if !defined(TBFCP_PKT_HDR_SIZE_IN_OCTETS)
+# define TBFCP_PKT_HDR_SIZE_IN_OCTETS 12
+#endif /* TBFCP_PKT_HDR_SIZE_IN_OCTETS */
+
+typedef tsk_list_t tbfcp_pkts_L_t;
+typedef struct tbfcp_pkt_s {
+ TSK_DECLARE_OBJECT;
+
+ struct {
+ // rfc4582 - 5.1. COMMON-HEADER Format
+ unsigned ver:3;
+ unsigned reserved:5;
+ enum tbfcp_primitive_e primitive; // 8bits
+ uint16_t pay_len; // 16bits: the length of the message in 4-octet units, excluding the common header
+ uint32_t conf_id;
+ uint16_t transac_id;
+ uint16_t user_id;
+ } hdr;
+ int (*f_add_attr)(struct tbfcp_pkt_s* p_self, struct tbfcp_attr_s** pp_attr);
+ tbfcp_attrs_L_t *p_list_attrs;
+}
+tbfcp_pkt_t;
+#define TBFCP_DECLARE_PKT struct tbfcp_pkt_s __base__
+#define TBFCP_PKT(p_self) ((struct tbfcp_pkt_s*)(p_self))
+TINYBFCP_API int tbfcp_pkt_add_attr(struct tbfcp_pkt_s* p_self, struct tbfcp_attr_s** pp_attr);
+TINYBFCP_API int tbfcp_pkt_create_empty(enum tbfcp_primitive_e primitive, struct tbfcp_pkt_s** pp_self);
+TINYBFCP_API int tbfcp_pkt_create(enum tbfcp_primitive_e primitive, uint32_t conf_id, uint16_t transac_id, uint16_t user_id, struct tbfcp_pkt_s** pp_self);
+TINYBFCP_API int tbfcp_pkt_get_size_in_octetunits_without_padding(const struct tbfcp_pkt_s* pc_self, tsk_size_t* p_size);
+TINYBFCP_API int tbfcp_pkt_get_size_in_octetunits_with_padding(const struct tbfcp_pkt_s* pc_self, tsk_size_t* p_size);
+TINYBFCP_API int tbfcp_pkt_write_with_padding(const struct tbfcp_pkt_s* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written);
+TINYBFCP_API int tbfcp_pkt_is_complete(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t *pb_is_complete);
+TINYBFCP_API int tbfcp_pkt_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, struct tbfcp_pkt_s** pp_pkt);
+TINYBFCP_API int tbfcp_pkt_attr_find_at(const struct tbfcp_pkt_s* pc_self, enum tbfcp_attribute_format_e e_format, tsk_size_t u_index, const struct tbfcp_attr_s** ppc_attr);
+#define tbfcp_pkt_attr_find_first(pc_self, e_format, ppc_attr) tbfcp_pkt_attr_find_at(pc_self, e_format, 0, ppc_attr)
+
+/***** rfc4582 - 5.3.1. FloorRequest *****/
+#define tbfcp_pkt_create_FloorRequest(conf_id, transac_id, user_id, pp_self) tbfcp_pkt_create(tbfcp_primitive_FloorRequest, (conf_id), (transac_id), (user_id), (pp_self))
+#define tbfcp_pkt_create_empty_FloorRequest(p_self) tbfcp_pkt_create_empty(TBFCP_PKT(p_self), tbfcp_primitive_FloorRequest)
+TINYBFCP_API int tbfcp_pkt_create_FloorRequest_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_id, struct tbfcp_pkt_s** pp_self);
+
+/***** rfc4582 - 5.3.2. FloorRelease *****/
+#define tbfcp_pkt_create_FloorRelease(conf_id, transac_id, user_id, pp_self) tbfcp_pkt_create(tbfcp_primitive_FloorRelease, (conf_id), (transac_id), (user_id), (pp_self))
+#define tbfcp_pkt_create_empty_FloorRelease(p_self) tbfcp_pkt_create_empty(TBFCP_PKT(p_self), tbfcp_primitive_FloorRelease)
+TINYBFCP_API int tbfcp_pkt_create_FloorRelease_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_req_id, struct tbfcp_pkt_s** pp_self);
+
+
+/**** rfc4582 - 5.3.4. FloorRequestStatus *****/
+#define tbfcp_pkt_create_FloorRequestStatus(conf_id, transac_id, user_id, pp_self) tbfcp_pkt_create(tbfcp_primitive_FloorRequestStatus, (conf_id), (transac_id), (user_id), (pp_self))
+#define tbfcp_pkt_create_empty_FloorRequestStatus(p_self) tbfcp_pkt_create_empty(TBFCP_PKT(p_self), tbfcp_primitive_FloorRequestStatus)
+TINYBFCP_API int tbfcp_pkt_create_FloorRequestStatus_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_req_id, struct tbfcp_pkt_s** pp_self);
+
+/**** rfc4582 - 5.3.11. Hello ***/
+#define tbfcp_pkt_create_Hello(conf_id, transac_id, user_id, pp_self) tbfcp_pkt_create(tbfcp_primitive_Hello, (conf_id), (transac_id), (user_id), (pp_self))
+#define tbfcp_pkt_create_empty_Hello(p_self) tbfcp_pkt_create_empty(TBFCP_PKT(p_self), tbfcp_primitive_Hello)
+
+/**** 5.3.12. HelloAck ***/
+#define tbfcp_pkt_create_HelloAck(conf_id, transac_id, user_id, pp_self) tbfcp_pkt_create(tbfcp_primitive_HelloAck, (conf_id), (transac_id), (user_id), (pp_self))
+#define tbfcp_pkt_create_empty_HelloAck(p_self) tbfcp_pkt_create_empty(TBFCP_PKT(p_self), tbfcp_primitive_HelloAck)
+TINYBFCP_API int tbfcp_pkt_create_HelloAck_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, struct tbfcp_pkt_s** pp_self);
+
+#if 0
+// rfc4582 - 5.3.1. FloorRequest
+typedef struct tbfcp_pkt_FloorRequest_s {
+ TBFCP_DECLARE_PKT;
+ struct tbfcp_attr_unsigned16_s* p_floor_id; // First [FLOOR-ID]. Others will be in "p_list_exts".
+ struct tbfcp_attr_unsigned16_s* p_beneficiary_id; // [BENEFICIARY-ID]
+ struct tbfcp_attr_octetstring_s* p_participant_provided_info; // [PARTICIPANT-PROVIDED-INFO]
+ struct tbfcp_attr_octetstring16_s* p_priority; // [PRIORITY]
+} tbfcp_pkt_FloorRequest_t;
+TINYBFCP_API int tbfcp_pkt_FloorRequest_create_empty(struct tbfcp_pkt_FloorRequest_s** pp_self);
+TINYBFCP_API int tbfcp_pkt_FloorRequest_create(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_id, struct tbfcp_pkt_FloorRequest_s** pp_self);
+#endif
+
+TBFCP_END_DECLS
+
+#endif /* TBFCP_PKT_H */
+
diff --git a/tinyBFCP/include/tinybfcp/tbfcp_session.h b/tinyBFCP/include/tinybfcp/tbfcp_session.h
new file mode 100644
index 0000000..82e57f6
--- /dev/null
+++ b/tinyBFCP/include/tinybfcp/tbfcp_session.h
@@ -0,0 +1,72 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TBFCP_SESSION_H
+#define TBFCP_SESSION_H
+
+#include "tinybfcp_config.h"
+#include "tinybfcp/tbfcp_types.h"
+
+#include "tinynet.h"
+
+TBFCP_BEGIN_DECLS
+
+struct tbfcp_session_s;
+struct tbfcp_pkt_s;
+
+typedef enum tbfcp_session_event_type_e
+{
+ tbfcp_session_event_type_inf_inc_msg,
+ tbfcp_session_event_type_err_send_timedout
+}
+tbfcp_session_event_type_t;
+
+typedef struct tbfcp_session_event_xs {
+ enum tbfcp_session_event_type_e e_type;
+ const struct tbfcp_pkt_s* pc_pkt;
+ const void* pc_usr_data;
+} tbfcp_session_event_xt;
+
+typedef int (*tbfcp_session_callback_f)(const struct tbfcp_session_event_xs *e);
+
+TINYBFCP_API int tbfcp_session_create(enum tnet_socket_type_e e_socket_type, const char* pc_local_ip, struct tbfcp_session_s** pp_self);
+TINYBFCP_API int tbfcp_session_create_2(struct tnet_ice_ctx_s* p_ice_ctx, struct tbfcp_session_s** pp_self);
+TINYBFCP_API int tbfcp_session_set_callback(struct tbfcp_session_s* p_self, tbfcp_session_callback_f f_fun, const void* pc_usr_data);
+TINYBFCP_API int tbfcp_session_set_ice_ctx(struct tbfcp_session_s* p_self, struct tnet_ice_ctx_s* p_ice_ctx);
+TINYBFCP_API int tbfcp_session_prepare(struct tbfcp_session_s* p_self);
+TINYBFCP_API int tbfcp_session_start(struct tbfcp_session_s* p_self);
+TINYBFCP_API int tbfcp_session_pause(struct tbfcp_session_s* p_self);
+TINYBFCP_API int tbfcp_session_stop(struct tbfcp_session_s* p_self);
+TINYBFCP_API int tbfcp_session_set_natt_ctx(struct tbfcp_session_s* p_self, struct tnet_nat_ctx_s* p_natt_ctx);
+TINYBFCP_API int tbfcp_session_set_remote_address(struct tbfcp_session_s* p_self, const char* pc_ip, tnet_port_t u_port);
+TINYBFCP_API int tbfcp_session_set_remote_role(struct tbfcp_session_s* p_self, enum tbfcp_role_e e_role_remote);
+TINYBFCP_API int tbfcp_session_set_remote_setup(struct tbfcp_session_s* p_self, enum tbfcp_setup_e e_setup_remote);
+TINYBFCP_API int tbfcp_session_set_conf_ids(struct tbfcp_session_s* p_self, uint32_t u_conf_id, uint16_t u_user_id, uint16_t u_floor_id);
+TINYBFCP_API int tbfcp_session_get_profile(const struct tbfcp_session_s* pc_self, const char** ppc_profile);
+TINYBFCP_API int tbfcp_session_get_local_role(const struct tbfcp_session_s* pc_self, enum tbfcp_role_e *pe_role_local);
+TINYBFCP_API int tbfcp_session_get_local_setup(const struct tbfcp_session_s* pc_self, enum tbfcp_setup_e *pe_setup_local);
+TINYBFCP_API int tbfcp_session_get_local_address(const struct tbfcp_session_s* pc_self, const char** ppc_ip, tnet_port_t *pu_port);
+TINYBFCP_API int tbfcp_session_create_pkt_Hello(struct tbfcp_session_s* p_self, struct tbfcp_pkt_s** pp_pkt);
+TINYBFCP_API int tbfcp_session_create_pkt_FloorRequest(struct tbfcp_session_s* p_self, struct tbfcp_pkt_s** pp_pkt);
+TINYBFCP_API int tbfcp_session_create_pkt_FloorRelease(struct tbfcp_session_s* p_self, struct tbfcp_pkt_s** pp_pkt);
+TINYBFCP_API int tbfcp_session_send_pkt(struct tbfcp_session_s* p_self, const struct tbfcp_pkt_s* pc_pkt);
+
+TBFCP_END_DECLS
+
+#endif /* TBFCP_SESSION_H */
+
diff --git a/tinyBFCP/include/tinybfcp/tbfcp_types.h b/tinyBFCP/include/tinybfcp/tbfcp_types.h
new file mode 100644
index 0000000..561d7be
--- /dev/null
+++ b/tinyBFCP/include/tinybfcp/tbfcp_types.h
@@ -0,0 +1,207 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TBFCP_TYPES_H
+#define TBFCP_TYPES_H
+
+#include "tinybfcp_config.h"
+
+TBFCP_BEGIN_DECLS
+
+#if !defined(kBfcpFieldMYes)
+# define kBfcpFieldMYes 1
+#endif /* kBfcpFieldMYes */
+#if !defined(kBfcpFieldMNo)
+# define kBfcpFieldMNo 0
+#endif /* kBfcpFieldMNo */
+
+// draft-ietf-bfcpbis-rfc4582bis-11 - 8.3.3. Timer Values
+#if !defined(kBfcpTimerT1)
+# define kBfcpTimerT1 500
+#endif /* kBfcpTimerT1 */
+#if !defined(kBfcpTimerT2)
+# define kBfcpTimerT2 10000
+#endif /* kBfcpTimerT1 */
+#if !defined(kBfcpTimerT1MaxTries)
+# define kBfcpTimerT1MaxTries 4 // draft says #3 but we use #4
+#endif /* kBfcpTimerT1MaxTries */
+#if !defined(kBfcpTimerT1Max)
+# define kBfcpTimerT1Max (kBfcpTimerT1 * kBfcpTimerT1MaxTries)
+#endif /* kBfcpTimerT1 */
+
+#if !defined(kBfcpTcpTimerReconnect)
+# define kBfcpTcpTimerReconnect 5000 // Try to reconnect the TCP/TLS socket every 5seconds if unexpectedly disconnected
+#endif /* kBfcpTcpTimerReconnect */
+
+#if !defined(kBfcpTimerKeepAlive)
+# define kBfcpTimerKeepAlive 30000 // Send Hello message every 30 seconds
+#endif /* kBfcpTimerKeepAlive */
+
+
+// RFC4582 - 11.1. Registration of the 'TCP/BFCP' and 'TCP/TLS/BFCP' SDP 'proto' Values
+#if !defined (kBfcpProfileTLS)
+# define kBfcpProfileTLS "TCP/TLS/BFCP"
+#endif /* kBfcpProfileTLS */
+#if !defined (kBfcpProfileTCP)
+# define kBfcpProfileTCP "TCP/BFCP"
+#endif /* kBfcpProfileTCP */
+// draft-ietf-bfcpbis-rfc4582bis-11 - 5.4. Registration of SDP 'proto' Values (11.1)
+#if !defined (kBfcpProfileUDP)
+# define kBfcpProfileUDP "UDP/BFCP"
+#endif /* kBfcpProfileUDP */
+#if !defined (kBfcpProfileDTLS)
+# define kBfcpProfileDTLS "UDP/TLS/BFCP"
+#endif /* kBfcpProfileDTLS */
+
+#if !defined(kBfcpTransportDefault)
+# define kBfcpTransportDefault tnet_socket_type_udp_ipv4
+#endif /* kBfcpTransportDefault */
+
+#if !defined(kBfcpTransportFriendlyName)
+# define kBfcpTransportFriendlyName "BFCP Session"
+#endif /* kBfcpTransportFriendlyName */
+
+#if !defined(kBfcpBuffMinPad)
+# define kBfcpBuffMinPad 40 // to make the buffer kasher
+#endif /* kBfcpBuffMinPad */
+
+
+// rfc4583 - 4. Floor Control Server Determination
+#if !defined(kBfcpRoleC)
+# define kBfcpRoleC "c-only"
+#endif /* kBfcpRoleC */
+#if !defined(kBfcpRoleS)
+# define kBfcpRoleS "s-only"
+#endif /* kBfcpRoleS */
+#if !defined(kBfcpRoleCS)
+# define kBfcpRoleCS "c-s"
+#endif /* kBfcpRoleCS */
+#if !defined(kBfcpRoleDefault)
+# define kBfcpRoleDefault tbfcp_role_c_only // For know the stack works in client mode only
+#endif /* kBfcpRoleDefault */
+typedef enum tbfcp_role_e {
+ tbfcp_role_c_only = (1 << 0),
+ tbfcp_role_s_only = (1 << 1),
+ tbfcp_role_c_s = (tbfcp_role_c_only | tbfcp_role_s_only)
+} tbfcp_role_t;
+
+typedef enum tbfcp_setup_e {
+ tbfcp_setup_active = (1 << 0),
+ tbfcp_setup_passive = (1 << 1),
+ tbfcp_setup_actpass = (tbfcp_setup_active | tbfcp_setup_passive),
+} tbfcp_setup_t;
+#if !defined(kBfcpSetupDefault)
+# define kBfcpSetupDefault tbfcp_setup_actpass
+#endif /* kBfcpSetupDefault */
+#if !defined(kBfcpSetupActPass)
+# define kBfcpSetupActPass "actpass"
+#endif /* kBfcpSetupActPass */
+#if !defined(kBfcpSetupActive)
+# define kBfcpSetupActive "active"
+#endif /* kBfcpSetupActive */
+#if !defined(kBfcpSetupPassive)
+# define kBfcpSetupPassive "passive"
+#endif /* kBfcpSetupPassive */
+
+// RFC4582 - 5.1. COMMON-HEADER Format
+typedef enum tbfcp_primitive_e {
+ tbfcp_primitive_FloorRequest = 1, // | P -> S |
+ tbfcp_primitive_FloorRelease = 2, // | P -> S |
+ tbfcp_primitive_FloorRequestQuery = 3, // | P -> S ; Ch -> S |
+ tbfcp_primitive_FloorRequestStatus = 4, // | P <- S ; Ch <- S |
+ tbfcp_primitive_UserQuery = 5, // | P -> S ; Ch -> S |
+ tbfcp_primitive_UserStatus = 6, // | P <- S ; Ch <- S |
+ tbfcp_primitive_FloorQuery = 7, // | P -> S ; Ch -> S |
+ tbfcp_primitive_FloorStatus = 8, // | P <- S ; Ch <- S |
+ tbfcp_primitive_ChairAction = 9, // | Ch -> S |
+ tbfcp_primitive_ChairActionAck = 10, // | Ch <- S |
+ tbfcp_primitive_Hello = 11, // | P -> S ; Ch -> S |
+ tbfcp_primitive_HelloAck = 12, // | P <- S ; Ch <- S |
+ tbfcp_primitive_Error = 13, // | P <- S ; Ch <- S
+ //!\ Update tbfcp_pkt_create_HelloAck_2() if an entry is added or remove
+} tbfcp_primitive_t;
+
+// RFC4582 - 5.2. Attribute Format
+typedef enum tbfcp_attribute_type_e {
+ tbfcp_attribute_type_BENEFICIARY_ID = 1, // | Unsigned16 |
+ tbfcp_attribute_type_FLOOR_ID = 2, // | Unsigned16 |
+ tbfcp_attribute_type_FLOOR_REQUEST_ID = 3, // | Unsigned16 |
+ tbfcp_attribute_type_PRIORITY = 4, // | OctetString16 |
+ tbfcp_attribute_type_REQUEST_STATUS = 5, // | OctetString16 |
+ tbfcp_attribute_type_ERROR_CODE = 6, // | OctetString |
+ tbfcp_attribute_type_ERROR_INFO = 7, // | OctetString |
+ tbfcp_attribute_type_PARTICIPANT_PROVIDED_INFO = 8, // | OctetString |
+ tbfcp_attribute_type_STATUS_INFO = 9, // | OctetString |
+ tbfcp_attribute_type_SUPPORTED_ATTRIBUTES = 10, // | OctetString |
+ tbfcp_attribute_type_SUPPORTED_PRIMITIVES = 11, // | OctetString |
+ tbfcp_attribute_type_USER_DISPLAY_NAME = 12, // | OctetString |
+ tbfcp_attribute_type_USER_URI = 13, // | OctetString |
+ tbfcp_attribute_type_BENEFICIARY_INFORMATION = 14, // | Grouped |
+ tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION = 15, // | Grouped |
+ tbfcp_attribute_type_REQUESTED_BY_INFORMATION = 16, // | Grouped |
+ tbfcp_attribute_type_FLOOR_REQUEST_STATUS = 17, // | Grouped |
+ tbfcp_attribute_type_OVERALL_REQUEST_STATUS = 18, // | Grouped
+ //!\ Update tbfcp_pkt_create_HelloAck_2() if an entry is added or remove
+} tbfcp_attribute_type_t;
+
+// RFC4582 - 5.2. Attribute Format
+typedef enum tbfcp_attribute_format_e {
+ tbfcp_attribute_format_Unknown,
+ tbfcp_attribute_format_Unsigned16,
+ tbfcp_attribute_format_OctetString16,
+ tbfcp_attribute_format_OctetString,
+ tbfcp_attribute_format_Grouped,
+} tbfcp_attribute_format_t;
+
+// RFC4582 - 5.2.4. PRIORITY
+typedef enum tbfcp_prio_e {
+ tbfcp_prio_Lowest = 0,
+ tbfcp_prio_Low = 1,
+ tbfcp_prio_Normal = 2,
+ tbfcp_prio_High = 3,
+ tbfcp_prio_Highest = 4
+} tbfcp_prio_t;
+
+// RFC4582 - 5.2.5. REQUEST-STATUS
+typedef enum tbfcp_reqstatus_e {
+ tbfcp_reqstatus_Pending = 1,
+ tbfcp_reqstatus_Accepted = 2,
+ tbfcp_reqstatus_Granted = 3,
+ tbfcp_reqstatus_Denied = 4,
+ tbfcp_reqstatus_Cancelled = 5,
+ tbfcp_reqstatus_Released = 6,
+ tbfcp_reqstatus_Revoked = 7
+} tbfcp_reqstatus_t;
+
+// RFC4582 - 5.2.6. ERROR-CODE
+typedef enum tbfcp_err_code_e {
+ tbfcp_err_code_Conference_does_not_Exist = 1,
+ tbfcp_err_code_User_does_not_Exist = 2,
+ tbfcp_err_code_Unknown_Primitive = 3,
+ tbfcp_err_code_Unknown_Mandatory_Attribute = 4,
+ tbfcp_err_code_Unauthorized_Operation = 5,
+ tbfcp_err_code_Invalid_Floor_ID = 6,
+ tbfcp_err_code_Floor_Request_ID_Does_Not_Exist = 7,
+ tbfcp_err_code_You_have_Already_Reached_the_Maximum_Number_of_OngoingFloor_Requests_for_this_Floor = 9,
+ tbfcp_err_code_Use_TLS = 10,
+} tbfcp_err_code_t;
+
+TBFCP_END_DECLS
+
+#endif /* TBFCP_TYPES_H */
+
diff --git a/tinyBFCP/include/tinybfcp/tbfcp_utils.h b/tinyBFCP/include/tinybfcp/tbfcp_utils.h
new file mode 100644
index 0000000..98c23c3
--- /dev/null
+++ b/tinyBFCP/include/tinybfcp/tbfcp_utils.h
@@ -0,0 +1,43 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TBFCP_UTILS_H
+#define TBFCP_UTILS_H
+
+#include "tinybfcp_config.h"
+#include "tinybfcp/tbfcp_types.h"
+
+#include "tsk_common.h"
+
+TBFCP_BEGIN_DECLS
+
+enum tnet_socket_type_e;
+
+TINYBFCP_API int tbfcp_utils_get_profile(enum tnet_socket_type_e e_socket_type, const char** ppc_profile);
+TINYBFCP_API int tbfcp_utils_get_role(enum tbfcp_role_e e_role, const char** ppc_role);
+TINYBFCP_API int tbfcp_utils_parse_role(const char* pc_role, enum tbfcp_role_e* pe_role);
+TINYBFCP_API int tbfcp_utils_get_setup(enum tbfcp_role_e e_setup, const char** ppc_setup);
+TINYBFCP_API int tbfcp_utils_parse_setup(const char* pc_setup, enum tbfcp_setup_e* pe_setup);
+TINYBFCP_API int tbfcp_utils_is_role_acceptable(enum tbfcp_role_e e_role_local, enum tbfcp_role_e e_role_proposed, tsk_bool_t *pb_acceptable);
+TINYBFCP_API int tbfcp_utils_is_setup_acceptable(enum tbfcp_setup_e e_setup_local, enum tbfcp_setup_e e_setup_proposed, tsk_bool_t *pb_acceptable);
+TINYBFCP_API uint16_t tbfcp_utils_rand_u16();
+
+TBFCP_END_DECLS
+
+#endif /* TBFCP_UTILS_H */
+
diff --git a/tinyBFCP/include/tinybfcp_config.h b/tinyBFCP/include/tinybfcp_config.h
new file mode 100644
index 0000000..582b785
--- /dev/null
+++ b/tinyBFCP/include/tinybfcp_config.h
@@ -0,0 +1,80 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TINYBFCP_CONFIG_H
+#define TINYBFCP_CONFIG_H
+
+#ifdef __SYMBIAN32__
+#undef _WIN32 /* Because of WINSCW */
+#endif
+
+// Windows (XP/Vista/7/CE and Windows Mobile) macro definition
+#if defined(WIN32)|| defined(_WIN32) || defined(_WIN32_WCE)
+# define TBFCP_UNDER_WINDOWS 1
+# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY == WINAPI_FAMILY_APP)
+# define TBFCP_UNDER_WINDOWS_RT 1
+# endif
+#endif
+
+#if (TBFCP_UNDER_WINDOWS || defined(__SYMBIAN32__)) && defined(TINYBFCP_EXPORTS)
+# define TINYBFCP_API __declspec(dllexport)
+# define TINYBFCP_GEXTERN extern __declspec(dllexport)
+#elif (TBFCP_UNDER_WINDOWS || defined(__SYMBIAN32__)) && !defined(TINYBFCP_IMPORTS_IGNORE)
+# define TINYBFCP_API __declspec(dllimport)
+# define TINYBFCP_GEXTERN __declspec(dllimport)
+#else
+# define TINYBFCP_API
+# define TINYBFCP_GEXTERN extern
+#endif
+
+/* Guards against C++ name mangling
+*/
+#ifdef __cplusplus
+# define TBFCP_BEGIN_DECLS extern "C" {
+# define TBFCP_END_DECLS }
+#else
+# define TBFCP_BEGIN_DECLS
+# define TBFCP_END_DECLS
+#endif
+
+/* Disable some well-known warnings
+*/
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+/* Detecting C99 compilers
+ */
+#if (__STDC_VERSION__ == 199901L) && !defined(__C99__)
+# define __C99__
+#endif
+
+#include <stdint.h>
+#ifdef __SYMBIAN32__
+#include <stdlib.h>
+#endif
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined(TBFCP_VERSION)
+# define TBFCP_VERSION 1
+#endif /* TBFCP_VERSION */
+
+#endif // TINYBFCP_CONFIG_H
diff --git a/tinyBFCP/src/tbfcp_attr.c b/tinyBFCP/src/tbfcp_attr.c
new file mode 100644
index 0000000..7b5359a
--- /dev/null
+++ b/tinyBFCP/src/tbfcp_attr.c
@@ -0,0 +1,674 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "tinybfcp/tbfcp_attr.h"
+
+#include "tnet_endianness.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#define kWithoutPadding tsk_false
+#define kWithPadding tsk_true
+
+#define ALIGN_ON_32BITS(size_in_octes) if (((size_in_octes) & 3)) (size_in_octes) += (4 - ((size_in_octes) & 3));
+#define ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(p_buffer, size_in_octes) \
+ if (((size_in_octes) & 3)) { \
+ int c = (4 - ((size_in_octes) & 3)); \
+ memset(p_buffer, 0, c); \
+ (size_in_octes) += c; \
+ }
+
+
+static enum tbfcp_attribute_format_e _tbfcp_attr_get_format(enum tbfcp_attribute_type_e type)
+{
+ switch (type) {
+ case tbfcp_attribute_type_BENEFICIARY_ID:
+ case tbfcp_attribute_type_FLOOR_ID:
+ case tbfcp_attribute_type_FLOOR_REQUEST_ID:
+ return tbfcp_attribute_format_Unsigned16;
+ case tbfcp_attribute_type_PRIORITY:
+ case tbfcp_attribute_type_REQUEST_STATUS:
+ return tbfcp_attribute_format_OctetString16;
+ case tbfcp_attribute_type_ERROR_CODE:
+ case tbfcp_attribute_type_ERROR_INFO:
+ case tbfcp_attribute_type_PARTICIPANT_PROVIDED_INFO:
+ case tbfcp_attribute_type_STATUS_INFO:
+ case tbfcp_attribute_type_SUPPORTED_ATTRIBUTES:
+ case tbfcp_attribute_type_SUPPORTED_PRIMITIVES:
+ case tbfcp_attribute_type_USER_DISPLAY_NAME:
+ case tbfcp_attribute_type_USER_URI:
+ return tbfcp_attribute_format_OctetString;
+ case tbfcp_attribute_type_BENEFICIARY_INFORMATION:
+ case tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION:
+ case tbfcp_attribute_type_REQUESTED_BY_INFORMATION:
+ case tbfcp_attribute_type_FLOOR_REQUEST_STATUS:
+ case tbfcp_attribute_type_OVERALL_REQUEST_STATUS:
+ return tbfcp_attribute_format_Grouped;
+ default:
+ return tbfcp_attribute_format_Unknown;
+
+ }
+}
+
+static int _tbfcp_attr_get_size_in_octetunits(const tbfcp_attr_t* pc_self, tsk_bool_t with_padding, tsk_size_t* p_size)
+{
+ if (!pc_self || !p_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ switch (pc_self->format) {
+ case tbfcp_attribute_format_Unsigned16:
+ case tbfcp_attribute_format_OctetString16: {
+ *p_size = (TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 2);
+ if (with_padding) {
+ ALIGN_ON_32BITS(*p_size);
+ }
+ return 0;
+ }
+ case tbfcp_attribute_format_OctetString: {
+ *p_size = (TBFCP_ATTR_HDR_SIZE_IN_OCTETS + ((const tbfcp_attr_octetstring_t*)pc_self)->OctetStringLength);
+ if (with_padding) {
+ ALIGN_ON_32BITS(*p_size);
+ }
+ return 0;
+ }
+ case tbfcp_attribute_format_Grouped: {
+ int ret;
+ tsk_size_t n_size;
+ const tbfcp_attr_grouped_t* _pc_self = (const tbfcp_attr_grouped_t*)pc_self;
+ const tsk_list_item_t* pc_item;
+ const tbfcp_attr_t* pc_attr;
+ *p_size = TBFCP_ATTR_HDR_SIZE_IN_OCTETS + _pc_self->extra_hdr_size_in_octets;
+ tsk_list_foreach(pc_item, _pc_self->p_list_attrs) {
+ if ((pc_attr = (const tbfcp_attr_t*)pc_item->data)) {
+ if ((ret = tbfcp_attr_get_size_in_octetunits_without_padding(pc_attr, &n_size))) {
+ return ret;
+ }
+ *p_size += n_size;
+ }
+ }
+ if (with_padding) {
+ ALIGN_ON_32BITS(*p_size);
+ }
+ return 0;
+ }
+ default: {
+ TSK_DEBUG_WARN("Attribute format=%d is unknown. Don't be surprised if something goes wrong.", pc_self->format);
+ *p_size = (TBFCP_ATTR_HDR_SIZE_IN_OCTETS + pc_self->hdr.length);
+ if (with_padding) {
+ ALIGN_ON_32BITS(*p_size);
+ }
+ return 0;
+ }
+ }
+}
+
+int tbfcp_attr_get_size_in_octetunits_without_padding(const tbfcp_attr_t* pc_self, tsk_size_t* p_size)
+{
+ return _tbfcp_attr_get_size_in_octetunits(pc_self, kWithoutPadding, p_size);
+}
+
+int tbfcp_attr_get_size_in_octetunits_with_padding(const tbfcp_attr_t* pc_self, tsk_size_t* p_size)
+{
+ return _tbfcp_attr_get_size_in_octetunits(pc_self, kWithPadding, p_size);
+}
+
+static int _tbfcp_attr_write(const tbfcp_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t with_padding, tsk_size_t *p_written)
+{
+ tsk_size_t n_min_req_size;
+ int ret;
+ if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = _tbfcp_attr_get_size_in_octetunits(pc_self, with_padding, &n_min_req_size))) {
+ return ret;
+ }
+ if (n_min_req_size > n_buff_size) {
+ TSK_DEBUG_ERROR("Buffer too short %u<%u", n_buff_size, n_min_req_size);
+ return -2;
+ }
+
+ p_buff_ptr[0] = ((uint8_t)pc_self->hdr.type) << 1;
+ p_buff_ptr[0] |= (pc_self->hdr.M & 0x01);
+
+ switch (pc_self->format) {
+ case tbfcp_attribute_format_Unsigned16:
+ case tbfcp_attribute_format_OctetString16: {
+ *p_written = TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 2;
+ p_buff_ptr[1] = (uint8_t)*p_written;
+ if (pc_self->format == tbfcp_attribute_format_Unsigned16) {
+ *((uint16_t*)&p_buff_ptr[2]) = tnet_htons(((const tbfcp_attr_unsigned16_t*)pc_self)->Unsigned16);
+ }
+ else {
+ p_buff_ptr[2] = ((const tbfcp_attr_octetstring16_t*)pc_self)->OctetString16[0];
+ p_buff_ptr[3] = ((const tbfcp_attr_octetstring16_t*)pc_self)->OctetString16[1];
+ }
+ if (with_padding) {
+ ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written);
+ }
+ return 0;
+ }
+ case tbfcp_attribute_format_OctetString: {
+ const tbfcp_attr_octetstring_t* _pc_self = (const tbfcp_attr_octetstring_t*)pc_self;
+ *p_written = TBFCP_ATTR_HDR_SIZE_IN_OCTETS + ((_pc_self->OctetStringLength && _pc_self->OctetString) ? _pc_self->OctetStringLength : 0);
+ p_buff_ptr[1] = (uint8_t)*p_written;
+ if (_pc_self->OctetStringLength && _pc_self->OctetString) {
+ memcpy(&p_buff_ptr[2], _pc_self->OctetString, _pc_self->OctetStringLength);
+ }
+ if (with_padding) {
+ ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written);
+ }
+ return 0;
+ }
+ case tbfcp_attribute_format_Grouped: {
+ int ret;
+ tsk_size_t n_written;
+ const tbfcp_attr_grouped_t* _pc_self = (const tbfcp_attr_grouped_t*)pc_self;
+ const tsk_list_item_t* pc_item;
+ const tbfcp_attr_t* pc_attr;
+ if (_pc_self->extra_hdr_size_in_octets && _pc_self->extra_hdr_size_in_octets != 2) {
+ TSK_DEBUG_ERROR("extra_hdr_size_in_octets=%u not valid", _pc_self->extra_hdr_size_in_octets); // for now only 2byte extra values is supported
+ return -2;
+ }
+ if ((ret = tbfcp_attr_get_size_in_octetunits_without_padding(pc_self, p_written))) {
+ return ret;
+ }
+ p_buff_ptr[1] = (uint8_t)*p_written;
+ p_buff_ptr += 2;
+ n_buff_size -= 2;
+ if (_pc_self->extra_hdr_size_in_octets) {
+ *((uint16_t*)p_buff_ptr) = tnet_htons_2(&_pc_self->extra_hdr);
+ p_buff_ptr += _pc_self->extra_hdr_size_in_octets;
+ n_buff_size -= _pc_self->extra_hdr_size_in_octets;
+ }
+ tsk_list_foreach(pc_item, _pc_self->p_list_attrs) {
+ if ((pc_attr = (const tbfcp_attr_t*)pc_item->data)) {
+ if ((ret = _tbfcp_attr_write(pc_attr, p_buff_ptr, n_buff_size, kWithoutPadding, &n_written))) {
+ return ret;
+ }
+ p_buff_ptr += n_written;
+ n_buff_size -= n_written;
+ }
+ }
+ if (with_padding) {
+ ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written);
+ }
+ return 0;
+ }
+ default: {
+ TSK_DEBUG_ERROR("Attribute format=%d is unknown.", pc_self->format);
+ return -2;
+ }
+ }
+}
+
+int tbfcp_attr_write_without_padding(const tbfcp_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written)
+{
+ return _tbfcp_attr_write(pc_self, p_buff_ptr, n_buff_size, kWithoutPadding, p_written);
+}
+
+int tbfcp_attr_write_with_padding(const tbfcp_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written)
+{
+ return _tbfcp_attr_write(pc_self, p_buff_ptr, n_buff_size, kWithPadding, p_written);
+}
+
+int tbfcp_attr_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_consumed_octets, tbfcp_attr_t** pp_attr)
+{
+ uint8_t M, Length, PadLength;
+ tbfcp_attribute_type_t Type;
+ tbfcp_attribute_format_t Format;
+ int ret;
+ if (!pc_buff_ptr || !n_buff_size || !pp_attr || !p_consumed_octets) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (n_buff_size < TBFCP_ATTR_HDR_SIZE_IN_OCTETS) {
+ TSK_DEBUG_ERROR("Buffer too short(%u)", n_buff_size);
+ return -2;
+ }
+
+ Length = pc_buff_ptr[1];
+ if (Length > n_buff_size) {
+ TSK_DEBUG_ERROR("Buffer too short(%u). Length=%u", n_buff_size, Length);
+ return -3;
+ }
+
+ PadLength = (Length & 0x03) ? (4 - (Length & 0x03)) : 0;
+
+ *pp_attr = tsk_null;
+ *p_consumed_octets = Length + PadLength;
+
+ Type = (pc_buff_ptr[0] >> 1) & 0x7F;
+ M = (pc_buff_ptr[0] & 0x01);
+ Format = _tbfcp_attr_get_format(Type);
+ if (Format == tbfcp_attribute_format_Unknown) {
+ return 0;
+ }
+
+ if (Format == tbfcp_attribute_format_Unsigned16) {
+ uint16_t Unsigned16 = tnet_ntohs_2(&pc_buff_ptr[2]);
+ if ((ret = tbfcp_attr_unsigned16_create(Type, M, Unsigned16, (tbfcp_attr_unsigned16_t**)pp_attr))) {
+ return ret;
+ }
+ }
+ else if (Format == tbfcp_attribute_format_OctetString16) {
+ uint8_t OctetString16[2];
+ OctetString16[0] = pc_buff_ptr[2];
+ OctetString16[1] = pc_buff_ptr[3];
+ if ((ret = tbfcp_attr_octetstring16_create(Type, M, OctetString16, (tbfcp_attr_octetstring16_t**)pp_attr))) {
+ return ret;
+ }
+ }
+ else if (Format == tbfcp_attribute_format_OctetString) {
+ const uint8_t *OctetString = &pc_buff_ptr[TBFCP_ATTR_HDR_SIZE_IN_OCTETS];
+ uint8_t OctetStringLength = (Length - TBFCP_ATTR_HDR_SIZE_IN_OCTETS);
+ if ((ret = tbfcp_attr_octetstring_create(Type, M, OctetString, OctetStringLength, (tbfcp_attr_octetstring_t**)pp_attr))) {
+ return ret;
+ }
+ }
+ else if (Format == tbfcp_attribute_format_Grouped) {
+ tbfcp_attr_grouped_t* p_attr;
+ if ((ret = tbfcp_attr_grouped_create(Type, M, &p_attr))) {
+ return ret;
+ }
+ *pp_attr = (tbfcp_attr_t*)p_attr;
+ switch (Type) {
+ case tbfcp_attribute_type_BENEFICIARY_INFORMATION: {
+ p_attr->extra_hdr_size_in_octets = 2;
+ p_attr->extra_hdr.BeneficiaryID = tnet_ntohs_2(&pc_buff_ptr[2]);
+ break;
+ }
+ case tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION: {
+ p_attr->extra_hdr_size_in_octets = 2;
+ p_attr->extra_hdr.FloorRequestID = tnet_ntohs_2(&pc_buff_ptr[2]);
+ break;
+ }
+ case tbfcp_attribute_type_REQUESTED_BY_INFORMATION: {
+ p_attr->extra_hdr_size_in_octets = 2;
+ p_attr->extra_hdr.RequestedbyID = tnet_ntohs_2(&pc_buff_ptr[2]);
+ break;
+ }
+ case tbfcp_attribute_type_FLOOR_REQUEST_STATUS: {
+ p_attr->extra_hdr_size_in_octets = 2;
+ p_attr->extra_hdr.FloorID = tnet_ntohs_2(&pc_buff_ptr[2]);
+ break;
+ }
+ case tbfcp_attribute_type_OVERALL_REQUEST_STATUS: {
+ p_attr->extra_hdr_size_in_octets = 2;
+ p_attr->extra_hdr.FloorRequestID = tnet_ntohs_2(&pc_buff_ptr[2]);
+ break;
+ }
+ default: {
+ return 0;
+ }
+ }
+ if ((TBFCP_ATTR_HDR_SIZE_IN_OCTETS + p_attr->extra_hdr_size_in_octets) < Length) {
+ tsk_size_t n_consumed_octets, PayloadLength = Length;
+ PayloadLength -= TBFCP_ATTR_HDR_SIZE_IN_OCTETS + p_attr->extra_hdr_size_in_octets;
+ pc_buff_ptr += TBFCP_ATTR_HDR_SIZE_IN_OCTETS + p_attr->extra_hdr_size_in_octets;
+ if (PayloadLength >= TBFCP_ATTR_HDR_SIZE_IN_OCTETS) {
+ do {
+ if ((ret = tbfcp_attr_read(pc_buff_ptr, PayloadLength, &n_consumed_octets, (tbfcp_attr_t**)&p_attr))) {
+ break;
+ }
+ if ((ret = tbfcp_attr_grouped_add_attr((tbfcp_attr_grouped_t*)(*pp_attr), (tbfcp_attr_t**)&p_attr))) {
+ TSK_OBJECT_SAFE_FREE(p_attr);
+ break;
+ }
+ pc_buff_ptr += n_consumed_octets;
+ PayloadLength -= n_consumed_octets;
+ }
+ while (PayloadLength >= TBFCP_ATTR_HDR_SIZE_IN_OCTETS);
+ }
+ }
+ }
+ else {
+ TSK_DEBUG_ERROR("%d not valid attribute format", Format);
+ return -4;
+ }
+ return 0;
+}
+
+
+static int _tbfcp_attr_init(tbfcp_attr_t* p_self, tbfcp_attribute_type_t type, unsigned M, uint8_t length)
+{
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!p_self->pc_base) {
+ p_self->pc_base = p_self;
+ }
+ p_self->hdr.type = type;
+ p_self->hdr.M = M;
+ p_self->hdr.length = length;
+ if ((p_self->format = _tbfcp_attr_get_format(type)) == tbfcp_attribute_format_Unknown) {
+ TSK_DEBUG_WARN("Attribute type=%d is unknown...setting its format to UNKNOWN. Don't be surprised if something goes wrong.", type);
+ }
+
+ return 0;
+}
+
+
+/*************** tbfcp_attr_unsigned16 *******************/
+int tbfcp_attr_unsigned16_create(tbfcp_attribute_type_t type, unsigned M, uint16_t Unsigned16, tbfcp_attr_unsigned16_t** pp_self)
+{
+ extern const tsk_object_def_t *tbfcp_attr_unsigned16_def_t;
+ tbfcp_attr_unsigned16_t* p_self;
+ int ret;
+ if (!pp_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(p_self = tsk_object_new(tbfcp_attr_unsigned16_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create 'tbfcp_attr_unsigned16_def_t' object");
+ return -2;
+ }
+ if ((ret = _tbfcp_attr_init(TBFCP_ATTR(p_self), type, M, TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 2))) {
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -3;
+ }
+ if (TBFCP_ATTR(p_self)->format != tbfcp_attribute_format_Unsigned16) {
+ TSK_DEBUG_ERROR("Format mismatch");
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -4;
+ }
+ p_self->Unsigned16 = Unsigned16;
+ *pp_self = p_self;
+ return 0;
+}
+
+static tsk_object_t* tbfcp_attr_unsigned16_ctor(tsk_object_t * self, va_list * app)
+{
+ tbfcp_attr_unsigned16_t *p_u16 = (tbfcp_attr_unsigned16_t *)self;
+ if (p_u16) {
+ }
+ return self;
+}
+static tsk_object_t* tbfcp_attr_unsigned16_dtor(tsk_object_t * self)
+{
+ tbfcp_attr_unsigned16_t *p_u16 = (tbfcp_attr_unsigned16_t *)self;
+ if (p_u16) {
+ TSK_DEBUG_INFO("*** BFCP Attribute(Unsigned16) destroyed ***");
+
+ }
+ return self;
+}
+static int tbfcp_attr_unsigned16_cmp(const tsk_object_t *_att1, const tsk_object_t *_att2)
+{
+ const tbfcp_attr_unsigned16_t *pc_att1 = (const tbfcp_attr_unsigned16_t *)_att1;
+ const tbfcp_attr_unsigned16_t *pc_att2 = (const tbfcp_attr_unsigned16_t *)_att2;
+
+ return (int)(pc_att1-pc_att2);
+}
+static const tsk_object_def_t tbfcp_attr_unsigned16_def_s = {
+ sizeof(tbfcp_attr_unsigned16_t),
+ tbfcp_attr_unsigned16_ctor,
+ tbfcp_attr_unsigned16_dtor,
+ tbfcp_attr_unsigned16_cmp,
+};
+const tsk_object_def_t *tbfcp_attr_unsigned16_def_t = &tbfcp_attr_unsigned16_def_s;
+
+
+
+
+/*************** tbfcp_attr_octetstring16 *******************/
+int tbfcp_attr_octetstring16_create(tbfcp_attribute_type_t type, unsigned M, uint8_t OctetString16[2], tbfcp_attr_octetstring16_t** pp_self)
+{
+ extern const tsk_object_def_t *tbfcp_attr_octetstring16_def_t;
+ tbfcp_attr_octetstring16_t* p_self;
+ int ret;
+ if (!pp_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(p_self = tsk_object_new(tbfcp_attr_octetstring16_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create 'tbfcp_attr_octetstring16_def_t' object");
+ return -2;
+ }
+ if ((ret = _tbfcp_attr_init(TBFCP_ATTR(p_self), type, M, TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 2))) {
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -3;
+ }
+ if (TBFCP_ATTR(p_self)->format != tbfcp_attribute_format_OctetString16) {
+ TSK_DEBUG_ERROR("Format mismatch");
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -4;
+ }
+ p_self->OctetString16[0] = OctetString16[0];
+ p_self->OctetString16[1] = OctetString16[1];
+ *pp_self = p_self;
+ return 0;
+}
+
+static tsk_object_t* tbfcp_attr_octetstring16_ctor(tsk_object_t * self, va_list * app)
+{
+ tbfcp_attr_octetstring16_t *p_os16 = (tbfcp_attr_octetstring16_t *)self;
+ if (p_os16) {
+ }
+ return self;
+}
+static tsk_object_t* tbfcp_attr_octetstring16_dtor(tsk_object_t * self)
+{
+ tbfcp_attr_octetstring16_t *p_os16 = (tbfcp_attr_octetstring16_t *)self;
+ if (p_os16) {
+ TSK_DEBUG_INFO("*** BFCP Attribute(OctetString16) destroyed ***");
+
+ }
+ return self;
+}
+static int tbfcp_attr_octetstring16_cmp(const tsk_object_t *_att1, const tsk_object_t *_att2)
+{
+ const tbfcp_attr_octetstring16_t *pc_att1 = (const tbfcp_attr_octetstring16_t *)_att1;
+ const tbfcp_attr_octetstring16_t *pc_att2 = (const tbfcp_attr_octetstring16_t *)_att2;
+
+ return (int)(pc_att1-pc_att2);
+}
+static const tsk_object_def_t tbfcp_attr_octetstring16_def_s = {
+ sizeof(tbfcp_attr_octetstring16_t),
+ tbfcp_attr_octetstring16_ctor,
+ tbfcp_attr_octetstring16_dtor,
+ tbfcp_attr_octetstring16_cmp,
+};
+const tsk_object_def_t *tbfcp_attr_octetstring16_def_t = &tbfcp_attr_octetstring16_def_s;
+
+
+/*************** tbfcp_attr_octetstring *******************/
+int tbfcp_attr_octetstring_create(tbfcp_attribute_type_t type, unsigned M, const uint8_t *OctetString, uint8_t OctetStringLength, tbfcp_attr_octetstring_t** pp_self)
+{
+ extern const tsk_object_def_t *tbfcp_attr_octetstring_def_t;
+ tbfcp_attr_octetstring_t* p_self;
+ int ret;
+ if (!pp_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(p_self = tsk_object_new(tbfcp_attr_octetstring_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create 'tbfcp_attr_octetstring_def_t' object");
+ return -2;
+ }
+ if ((ret = _tbfcp_attr_init(TBFCP_ATTR(p_self), type, M, (TBFCP_ATTR_HDR_SIZE_IN_OCTETS + OctetStringLength)))) {
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -3;
+ }
+ if (TBFCP_ATTR(p_self)->format != tbfcp_attribute_format_OctetString) {
+ TSK_DEBUG_ERROR("Format mismatch");
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -4;
+ }
+ if (OctetStringLength) {
+ if (!(p_self->OctetString = tsk_malloc(OctetStringLength))) {
+ TSK_DEBUG_ERROR("Failed to alloc %u octets", OctetStringLength);
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -5;
+ }
+ if (OctetString) {
+ memcpy(p_self->OctetString, OctetString, OctetStringLength);
+ }
+ p_self->OctetStringLength = OctetStringLength;
+ }
+ else {
+ TBFCP_ATTR(p_self)->hdr.length = TBFCP_ATTR_HDR_SIZE_IN_OCTETS;
+ p_self->OctetStringLength = 0;
+ }
+ *pp_self = p_self;
+ return 0;
+}
+
+static tsk_object_t* tbfcp_attr_octetstring_ctor(tsk_object_t * self, va_list * app)
+{
+ tbfcp_attr_octetstring_t *p_os = (tbfcp_attr_octetstring_t *)self;
+ if (p_os) {
+ }
+ return self;
+}
+static tsk_object_t* tbfcp_attr_octetstring_dtor(tsk_object_t * self)
+{
+ tbfcp_attr_octetstring_t *p_os = (tbfcp_attr_octetstring_t *)self;
+ if (p_os) {
+ TSK_DEBUG_INFO("*** BFCP Attribute(OctetString) destroyed ***");
+ TSK_SAFE_FREE(p_os->OctetString);
+ }
+ return self;
+}
+static int tbfcp_attr_octetstring_cmp(const tsk_object_t *_att1, const tsk_object_t *_att2)
+{
+ const tbfcp_attr_octetstring_t *pc_att1 = (const tbfcp_attr_octetstring_t *)_att1;
+ const tbfcp_attr_octetstring_t *pc_att2 = (const tbfcp_attr_octetstring_t *)_att2;
+
+ return (int)(pc_att1-pc_att2);
+}
+static const tsk_object_def_t tbfcp_attr_octetstring_def_s = {
+ sizeof(tbfcp_attr_octetstring_t),
+ tbfcp_attr_octetstring_ctor,
+ tbfcp_attr_octetstring_dtor,
+ tbfcp_attr_octetstring_cmp,
+};
+const tsk_object_def_t *tbfcp_attr_octetstring_def_t = &tbfcp_attr_octetstring_def_s;
+
+
+
+/*************** tbfcp_attr_grouped *******************/
+int tbfcp_attr_grouped_create(tbfcp_attribute_type_t type, unsigned M, tbfcp_attr_grouped_t** pp_self)
+{
+ extern const tsk_object_def_t *tbfcp_attr_grouped_def_t;
+ tbfcp_attr_grouped_t* p_self;
+ int ret;
+ if (!pp_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(p_self = tsk_object_new(tbfcp_attr_grouped_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create 'tbfcp_attr_grouped_def_t' object");
+ return -2;
+ }
+ if ((ret = _tbfcp_attr_init(TBFCP_ATTR(p_self), type, M, TBFCP_ATTR_HDR_SIZE_IN_OCTETS + 0))) {
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -3;
+ }
+ if (TBFCP_ATTR(p_self)->format != tbfcp_attribute_format_Grouped) {
+ TSK_DEBUG_ERROR("Format mismatch");
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -4;
+ }
+ if (!(p_self->p_list_attrs = tsk_list_create())) {
+ TSK_DEBUG_ERROR("Failed to create empty list");
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return -5;
+ }
+
+ *pp_self = p_self;
+ return 0;
+}
+
+int tbfcp_attr_grouped_create_u16(tbfcp_attribute_type_t type, unsigned M, uint16_t extra_hdr_u16_val, tbfcp_attr_grouped_t** pp_self)
+{
+ int ret;
+ if ((ret = tbfcp_attr_grouped_create(type, M, pp_self))) {
+ return ret;
+ }
+ *((uint16_t*)&(*pp_self)->extra_hdr) = extra_hdr_u16_val;
+ (*pp_self)->extra_hdr_size_in_octets = 2;
+ return 0;
+}
+
+int tbfcp_attr_grouped_add_attr(tbfcp_attr_grouped_t* p_self, tbfcp_attr_t** p_attr)
+{
+ if (!p_self || !p_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ tsk_list_push_back_data(p_self->p_list_attrs, (void**)p_attr);
+ return 0;
+}
+
+int tbfcp_attr_grouped_find_at(const struct tbfcp_attr_grouped_s* pc_self, enum tbfcp_attribute_format_e e_format, tsk_size_t u_index, const struct tbfcp_attr_s** ppc_attr)
+{
+ tsk_size_t _u_index = 0;
+ const tsk_list_item_t *pc_item;
+ const struct tbfcp_attr_s* pc_attr;
+ if (!pc_self || !ppc_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *ppc_attr = tsk_null;
+ tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
+ pc_attr = (const struct tbfcp_attr_s*)pc_item->data;
+ if (!pc_attr || pc_attr->format != e_format) {
+ continue;
+ }
+ if (_u_index++ >= u_index) {
+ *ppc_attr = pc_attr;
+ break;
+ }
+ }
+ return 0;
+}
+
+static tsk_object_t* tbfcp_attr_grouped_ctor(tsk_object_t * self, va_list * app)
+{
+ tbfcp_attr_grouped_t *p_gr = (tbfcp_attr_grouped_t *)self;
+ if (p_gr) {
+ }
+ return self;
+}
+static tsk_object_t* tbfcp_attr_grouped_dtor(tsk_object_t * self)
+{
+ tbfcp_attr_grouped_t *p_gr = (tbfcp_attr_grouped_t *)self;
+ if (p_gr) {
+ TSK_DEBUG_INFO("*** BFCP Attribute(Grouped) destroyed ***");
+ TSK_OBJECT_SAFE_FREE(p_gr->p_list_attrs);
+ }
+ return self;
+}
+static int tbfcp_attr_grouped_cmp(const tsk_object_t *_att1, const tsk_object_t *_att2)
+{
+ const tbfcp_attr_grouped_t *pc_att1 = (const tbfcp_attr_grouped_t *)_att1;
+ const tbfcp_attr_grouped_t *pc_att2 = (const tbfcp_attr_grouped_t *)_att2;
+
+ return (int)(pc_att1-pc_att2);
+}
+static const tsk_object_def_t tbfcp_attr_grouped_def_s = {
+ sizeof(tbfcp_attr_grouped_t),
+ tbfcp_attr_grouped_ctor,
+ tbfcp_attr_grouped_dtor,
+ tbfcp_attr_grouped_cmp,
+};
+const tsk_object_def_t *tbfcp_attr_grouped_def_t = &tbfcp_attr_grouped_def_s;
diff --git a/tinyBFCP/src/tbfcp_pkt.c b/tinyBFCP/src/tbfcp_pkt.c
new file mode 100644
index 0000000..0adff65
--- /dev/null
+++ b/tinyBFCP/src/tbfcp_pkt.c
@@ -0,0 +1,585 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "tinybfcp/tbfcp_pkt.h"
+
+#include "tnet_endianness.h"
+
+#include "tsk_debug.h"
+
+#define SWITCH_CASE_TAKE_ATTR(type, cat, field) \
+ case (type): \
+ if (!p_self->##field) { \
+ p_self->##field = (cat)*pp_attr, *pp_attr = tsk_null; \
+ return 0; \
+ } \
+ break;
+
+static int _tbfcp_pkt_add_attr(tbfcp_pkt_t* p_self, tbfcp_attr_t** pp_attr)
+{
+ if (!p_self || !pp_attr || !*pp_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ tsk_list_push_back_data(p_self->p_list_attrs, (void**)pp_attr);
+ return 0;
+}
+
+static int _tbfcp_pkt_deinit(tbfcp_pkt_t *p_self)
+{
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ TSK_OBJECT_SAFE_FREE(p_self->p_list_attrs);
+ return 0;
+}
+
+static int _tbfcp_pkt_init(tbfcp_pkt_t *p_self, tbfcp_primitive_t primitive, uint32_t conf_id, uint16_t transac_id, uint16_t user_id)
+{
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if (!p_self->p_list_attrs && !(p_self->p_list_attrs = tsk_list_create())) {
+ TSK_DEBUG_ERROR("Failed to create list");
+ return -2;
+ }
+ if (!p_self->f_add_attr) {
+ p_self->f_add_attr = _tbfcp_pkt_add_attr;
+ }
+
+ p_self->hdr.ver = TBFCP_VERSION;
+ p_self->hdr.reserved = 0;
+ p_self->hdr.primitive = primitive;
+ p_self->hdr.conf_id = conf_id;
+ p_self->hdr.transac_id = transac_id;
+ p_self->hdr.user_id = user_id;
+
+ return 0;
+}
+#define _tbfcp_pkt_init_empty(p_self, primitive) _tbfcp_pkt_init((p_self), (primitive), 0, 0, 0)
+
+static int _tbfcp_pkt_init_2(tbfcp_pkt_t *p_self, tbfcp_primitive_t primitive)
+{
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if (!p_self->p_list_attrs && !(p_self->p_list_attrs = tsk_list_create())) {
+ TSK_DEBUG_ERROR("Failed to create list");
+ return -2;
+ }
+
+ p_self->hdr.ver = TBFCP_VERSION;
+ p_self->hdr.reserved = 0;
+ p_self->hdr.primitive = primitive;
+
+ return 0;
+}
+
+int tbfcp_pkt_add_attr(tbfcp_pkt_t* p_self, tbfcp_attr_t** pp_attr)
+{
+ if (!p_self || !pp_attr || !*pp_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (p_self->f_add_attr) {
+ return p_self->f_add_attr(p_self, pp_attr);
+ }
+ return _tbfcp_pkt_add_attr(p_self, pp_attr);
+}
+
+
+int tbfcp_pkt_create_empty(tbfcp_primitive_t primitive, tbfcp_pkt_t** pp_self)
+{
+ extern const tsk_object_def_t *tbfcp_pkt_def_t;
+ tbfcp_pkt_t* p_self;
+ int ret;
+
+ if (!pp_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(p_self = tsk_object_new(tbfcp_pkt_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create object 'tbfcp_pkt_def_t'");
+ return -2;
+ }
+ if ((ret = _tbfcp_pkt_init_empty(p_self, primitive))) {
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return ret;
+ }
+ *pp_self = p_self;
+ return 0;
+}
+
+int tbfcp_pkt_create(tbfcp_primitive_t primitive, uint32_t conf_id, uint16_t transac_id, uint16_t user_id, tbfcp_pkt_t** pp_self)
+{
+ int ret;
+
+ if ((ret = tbfcp_pkt_create_empty(primitive, pp_self))) {
+ return ret;
+ }
+ if ((ret = _tbfcp_pkt_init((*pp_self), primitive, conf_id, transac_id, user_id))) {
+ TSK_OBJECT_SAFE_FREE((*pp_self));
+ return ret;
+ }
+ return ret;
+}
+
+int tbfcp_pkt_get_size_in_octetunits_without_padding(const tbfcp_pkt_t* pc_self, tsk_size_t* p_size)
+{
+ const tsk_list_item_t* pc_item;
+ const tbfcp_attr_t* pc_attr;
+ tsk_size_t n_size;
+ int ret;
+ if (!pc_self || !p_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *p_size = TBFCP_PKT_HDR_SIZE_IN_OCTETS;
+ tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
+ if ((pc_attr = (const tbfcp_attr_t*)pc_item->data)) {
+ if ((ret = tbfcp_attr_get_size_in_octetunits_without_padding(pc_attr, &n_size))) {
+ return ret;
+ }
+ *p_size += n_size;
+ }
+ }
+ return 0;
+}
+
+int tbfcp_pkt_get_size_in_octetunits_with_padding(const tbfcp_pkt_t* pc_self, tsk_size_t* p_size)
+{
+ const tsk_list_item_t* pc_item;
+ const tbfcp_attr_t* pc_attr;
+ tsk_size_t n_size;
+ int ret;
+ if (!pc_self || !p_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *p_size = TBFCP_PKT_HDR_SIZE_IN_OCTETS;
+ tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
+ if ((pc_attr = (const tbfcp_attr_t*)pc_item->data)) {
+ if ((ret = tbfcp_attr_get_size_in_octetunits_with_padding(pc_attr, &n_size))) {
+ return ret;
+ }
+ *p_size += n_size;
+ }
+ }
+ return 0;
+}
+
+int tbfcp_pkt_write_with_padding(const tbfcp_pkt_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written)
+{
+ const tsk_list_item_t* pc_item;
+ const tbfcp_attr_t* pc_attr;
+ tsk_size_t n_size;
+ int ret;
+ if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tbfcp_pkt_get_size_in_octetunits_with_padding(pc_self, p_written))) {
+ return ret;
+ }
+ if ((n_buff_size < *p_written)) {
+ TSK_DEBUG_ERROR("Buffer too short: %u<%u", n_buff_size, *p_written);
+ return -1;
+ }
+
+ p_buff_ptr[0] = (((uint8_t)pc_self->hdr.ver) << 5) | (pc_self->hdr.reserved & 0x7F);
+ p_buff_ptr[1] = (uint8_t)pc_self->hdr.primitive;
+ *((uint32_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)((*p_written - TBFCP_PKT_HDR_SIZE_IN_OCTETS) >> 2));
+ *((uint32_t*)&p_buff_ptr[4]) = (uint32_t)tnet_htonl(pc_self->hdr.conf_id);
+ *((uint16_t*)&p_buff_ptr[8]) = tnet_htons(pc_self->hdr.transac_id);
+ *((uint16_t*)&p_buff_ptr[10]) = tnet_htons(pc_self->hdr.user_id);
+
+ p_buff_ptr += TBFCP_PKT_HDR_SIZE_IN_OCTETS;
+ n_buff_size -= TBFCP_PKT_HDR_SIZE_IN_OCTETS;
+
+ tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
+ if ((pc_attr = (const tbfcp_attr_t*)pc_item->data)) {
+ if ((ret = tbfcp_attr_write_with_padding(pc_attr, p_buff_ptr, n_buff_size, &n_size))) {
+ return ret;
+ }
+ p_buff_ptr += n_size;
+ n_buff_size -= n_size;
+ }
+ }
+ return 0;
+}
+
+// Useful to check TCP stream contains at least a complete BFCP packet
+int tbfcp_pkt_is_complete(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t *pb_is_complete)
+{
+ if (!pb_is_complete) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *pb_is_complete = tsk_false;
+ if (pc_buff_ptr && n_buff_size >= TBFCP_PKT_HDR_SIZE_IN_OCTETS) {
+ tsk_size_t n_paylen_in_octets = (tnet_ntohs_2(&pc_buff_ptr[2]) << 2);
+ *pb_is_complete = ((n_buff_size - TBFCP_PKT_HDR_SIZE_IN_OCTETS) >= n_paylen_in_octets);
+ }
+ return 0;
+}
+
+int tbfcp_pkt_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tbfcp_pkt_t** pp_pkt)
+{
+ tsk_bool_t b_is_complete;
+ tsk_size_t PayloadLengthInOctets;
+ tbfcp_primitive_t Primitive;
+ uint32_t ConferenceID;
+ uint16_t TransactionID, UserID;
+ int ret, Ver;
+ if (!pc_buff_ptr || !n_buff_size || !pp_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tbfcp_pkt_is_complete(pc_buff_ptr, n_buff_size, &b_is_complete))) {
+ return ret;
+ }
+ if (!b_is_complete) {
+ TSK_DEBUG_ERROR("Buffer too short(%u)", n_buff_size);
+ return -2;
+ }
+ Ver = (pc_buff_ptr[0] >> 5) & 0x07;
+ if (Ver != TBFCP_VERSION) {
+ TSK_DEBUG_ERROR("Version(%d)<>%d", Ver, TBFCP_VERSION);
+ return -3;
+ }
+ Primitive = (tbfcp_primitive_t)pc_buff_ptr[1];
+ PayloadLengthInOctets = (tnet_ntohs_2(&pc_buff_ptr[2]) << 2);
+ ConferenceID = (uint32_t)tnet_ntohl_2(&pc_buff_ptr[4]);
+ TransactionID = tnet_ntohs_2(&pc_buff_ptr[8]);
+ UserID = tnet_ntohs_2(&pc_buff_ptr[10]);
+
+ if((ret = tbfcp_pkt_create(Primitive, ConferenceID, TransactionID, UserID, pp_pkt))) {
+ return ret;
+ }
+
+ if (PayloadLengthInOctets > 0) {
+ tbfcp_attr_t* p_attr;
+ tsk_size_t n_consumed_octets;
+ pc_buff_ptr += TBFCP_PKT_HDR_SIZE_IN_OCTETS;
+ do {
+ if ((ret = tbfcp_attr_read(pc_buff_ptr, PayloadLengthInOctets, &n_consumed_octets, &p_attr))) {
+ return ret;
+ }
+ if ((ret = tbfcp_pkt_add_attr((*pp_pkt), &p_attr))) {
+ TSK_OBJECT_SAFE_FREE((*pp_pkt));
+ return ret;
+ }
+ PayloadLengthInOctets -= n_consumed_octets;
+ pc_buff_ptr += n_consumed_octets;
+ }
+ while (PayloadLengthInOctets >= TBFCP_ATTR_HDR_SIZE_IN_OCTETS);
+ }
+
+ return 0;
+}
+
+int tbfcp_pkt_attr_find_at(const struct tbfcp_pkt_s* pc_self, enum tbfcp_attribute_format_e e_format, tsk_size_t u_index, const struct tbfcp_attr_s** ppc_attr)
+{
+ tsk_size_t _u_index = 0;
+ const tsk_list_item_t *pc_item;
+ const struct tbfcp_attr_s* pc_attr;
+ if (!pc_self || !ppc_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *ppc_attr = tsk_null;
+ tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
+ pc_attr = (const struct tbfcp_attr_s*)pc_item->data;
+ if (!pc_attr || pc_attr->format != e_format) {
+ continue;
+ }
+ if (_u_index++ >= u_index) {
+ *ppc_attr = pc_attr;
+ break;
+ }
+ }
+ return 0;
+}
+
+
+static tsk_object_t* tbfcp_pkt_ctor(tsk_object_t * self, va_list * app)
+{
+ tbfcp_pkt_t *p_pkt = (tbfcp_pkt_t *)self;
+ if (p_pkt) {
+ p_pkt->f_add_attr = _tbfcp_pkt_add_attr;
+ if (!(p_pkt->p_list_attrs = tsk_list_create())) {
+ TSK_DEBUG_ERROR("Failed to create list");
+ return tsk_null;
+ }
+ }
+ return self;
+}
+static tsk_object_t* tbfcp_pkt_dtor(tsk_object_t * self)
+{
+ tbfcp_pkt_t *p_pkt = (tbfcp_pkt_t *)self;
+ if (p_pkt) {
+ TSK_DEBUG_INFO("*** BFCP Packet destroyed ***");
+ TSK_OBJECT_SAFE_FREE(p_pkt->p_list_attrs);
+ }
+
+ return self;
+}
+static int tbfcp_pkt_cmp(const tsk_object_t *_pk1, const tsk_object_t *_pk2)
+{
+ const tbfcp_pkt_t *pc_pk1 = (const tbfcp_pkt_t *)_pk1;
+ const tbfcp_pkt_t *pc_pk2 = (const tbfcp_pkt_t *)_pk2;
+
+ return (int)(pc_pk1-pc_pk2);
+}
+static const tsk_object_def_t tbfcp_pkt_def_s = {
+ sizeof(tbfcp_pkt_t),
+ tbfcp_pkt_ctor,
+ tbfcp_pkt_dtor,
+ tbfcp_pkt_cmp,
+};
+const tsk_object_def_t *tbfcp_pkt_def_t = &tbfcp_pkt_def_s;
+
+
+/***** rfc4582 - 5.3.1. FloorRequest *****/
+int tbfcp_pkt_create_FloorRequest_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_id, tbfcp_pkt_t** pp_self)
+{
+ int ret;
+ tbfcp_attr_unsigned16_t* p_floor_id;
+ if ((ret = tbfcp_pkt_create_FloorRequest(conf_id, transac_id, user_id, pp_self))) {
+ return ret;
+ }
+ if ((ret = tbfcp_attr_unsigned16_create(tbfcp_attribute_type_FLOOR_ID, kBfcpFieldMYes, floor_id, &p_floor_id))) {
+ return ret;
+ }
+ if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_floor_id))) {
+ TSK_OBJECT_SAFE_FREE(p_floor_id);
+ return ret;
+ }
+ return 0;
+}
+
+/***** rfc4582 - 5.3.2. FloorRelease *****/
+int tbfcp_pkt_create_FloorRelease_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_req_id, tbfcp_pkt_t** pp_self)
+{
+ int ret;
+ tbfcp_attr_unsigned16_t* p_floor_req_id;
+ if ((ret = tbfcp_pkt_create_FloorRelease(conf_id, transac_id, user_id, pp_self))) {
+ return ret;
+ }
+ if ((ret = tbfcp_attr_unsigned16_create(tbfcp_attribute_type_FLOOR_REQUEST_ID, kBfcpFieldMYes, floor_req_id, &p_floor_req_id))) {
+ return ret;
+ }
+ if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_floor_req_id))) {
+ TSK_OBJECT_SAFE_FREE(p_floor_req_id);
+ return ret;
+ }
+ return 0;
+}
+
+/**** rfc4582 - 5.3.4. FloorRequestStatus *****/
+int tbfcp_pkt_create_FloorRequestStatus_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_req_id, tbfcp_pkt_t** pp_self)
+{
+ int ret;
+ tbfcp_attr_grouped_t* p_floor_req_info;
+ if ((ret = tbfcp_pkt_create_FloorRequestStatus(conf_id, transac_id, user_id, pp_self))) {
+ return ret;
+ }
+ if ((ret = tbfcp_attr_grouped_create_u16(tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION, kBfcpFieldMNo, floor_req_id, &p_floor_req_info))) {
+ return ret;
+ }
+ if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_floor_req_info))) {
+ TSK_OBJECT_SAFE_FREE(p_floor_req_info);
+ return ret;
+ }
+ return 0;
+}
+
+/**** 5.3.12. HelloAck ***/
+int tbfcp_pkt_create_HelloAck_2(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, struct tbfcp_pkt_s** pp_self)
+{
+ tsk_size_t u;
+ int ret;
+ tbfcp_attr_octetstring_t *p_supp_attr, *p_supp_prim;
+ static const uint8_t* kNullOctetStringPtr = tsk_null;
+ static const tbfcp_primitive_t __supp_prims[] = {
+ tbfcp_primitive_FloorRequest,
+ tbfcp_primitive_FloorRelease,
+ tbfcp_primitive_FloorRequestQuery,
+ tbfcp_primitive_FloorRequestStatus,
+ tbfcp_primitive_UserQuery,
+ tbfcp_primitive_UserStatus,
+ tbfcp_primitive_FloorQuery,
+ tbfcp_primitive_FloorStatus,
+ tbfcp_primitive_ChairAction,
+ tbfcp_primitive_ChairActionAck,
+ tbfcp_primitive_Hello,
+ tbfcp_primitive_HelloAck,
+ tbfcp_primitive_Error,
+ };
+ static const tsk_size_t __supp_prims_count = sizeof(__supp_prims)/sizeof(__supp_prims[0]);
+ static const tbfcp_attribute_type_t __supp_attrs[] = {
+ tbfcp_attribute_type_BENEFICIARY_ID,
+ tbfcp_attribute_type_FLOOR_ID,
+ tbfcp_attribute_type_FLOOR_REQUEST_ID,
+ tbfcp_attribute_type_PRIORITY,
+ tbfcp_attribute_type_REQUEST_STATUS,
+ tbfcp_attribute_type_ERROR_CODE,
+ tbfcp_attribute_type_ERROR_INFO,
+ tbfcp_attribute_type_PARTICIPANT_PROVIDED_INFO,
+ tbfcp_attribute_type_STATUS_INFO,
+ tbfcp_attribute_type_SUPPORTED_ATTRIBUTES,
+ tbfcp_attribute_type_SUPPORTED_PRIMITIVES,
+ tbfcp_attribute_type_USER_DISPLAY_NAME,
+ tbfcp_attribute_type_USER_URI,
+ tbfcp_attribute_type_BENEFICIARY_INFORMATION,
+ tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION,
+ tbfcp_attribute_type_REQUESTED_BY_INFORMATION,
+ tbfcp_attribute_type_FLOOR_REQUEST_STATUS,
+ tbfcp_attribute_type_OVERALL_REQUEST_STATUS,
+ };
+ static const tsk_size_t __supp_attrs_count = sizeof(__supp_attrs)/sizeof(__supp_attrs[0]);
+
+ if ((ret = tbfcp_pkt_create_HelloAck(conf_id, transac_id, user_id, pp_self))) {
+ return ret;
+ }
+ /* SUPPORTED-ATTRIBUTES */
+ if ((ret = tbfcp_attr_octetstring_create(tbfcp_attribute_type_SUPPORTED_ATTRIBUTES, kBfcpFieldMNo, kNullOctetStringPtr, (uint8_t)__supp_attrs_count, &p_supp_attr))) {
+ return ret;
+ }
+ for (u = 0; u < p_supp_attr->OctetStringLength; ++u) {
+ p_supp_attr->OctetString[u] = (__supp_attrs[u] << 1/*R*/);
+ }
+ if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_supp_attr))) {
+ TSK_OBJECT_SAFE_FREE(p_supp_attr);
+ return ret;
+ }
+ /* SUPPORTED-PRIMITIVES */
+ if ((ret = tbfcp_attr_octetstring_create(tbfcp_attribute_type_SUPPORTED_PRIMITIVES, kBfcpFieldMNo, kNullOctetStringPtr, (uint8_t)__supp_prims_count, &p_supp_prim))) {
+ return ret;
+ }
+ for (u = 0; u < p_supp_prim->OctetStringLength; ++u) {
+ p_supp_prim->OctetString[u] = __supp_prims[u];
+ }
+ if ((ret = tbfcp_pkt_add_attr(*pp_self, (tbfcp_attr_t**)&p_supp_prim))) {
+ TSK_OBJECT_SAFE_FREE(p_supp_prim);
+ return ret;
+ }
+ return 0;
+}
+
+#if 0
+/***** rfc4582 - 5.3.1. FloorRequest *****/
+static int _tbfcp_pkt_FloorRequest_add_attr(tbfcp_pkt_t* _p_self, tbfcp_attr_t** pp_attr)
+{
+ tbfcp_pkt_FloorRequest_t* p_self = (tbfcp_pkt_FloorRequest_t*)_p_self;
+ if (!p_self || !pp_attr || !*pp_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ switch ((*pp_attr)->hdr.type) {
+ SWITCH_CASE_TAKE_ATTR(tbfcp_attribute_type_FLOOR_ID, struct tbfcp_attr_unsigned16_s*, p_floor_id);
+ SWITCH_CASE_TAKE_ATTR(tbfcp_attribute_type_BENEFICIARY_ID, struct tbfcp_attr_unsigned16_s*, p_beneficiary_id);
+ SWITCH_CASE_TAKE_ATTR(tbfcp_attribute_type_PARTICIPANT_PROVIDED_INFO, struct tbfcp_attr_octetstring_s*, p_participant_provided_info);
+ SWITCH_CASE_TAKE_ATTR(tbfcp_attribute_type_PRIORITY, struct tbfcp_attr_octetstring16_s*, p_priority);
+ }
+ return _tbfcp_pkt_add_attr(_p_self, pp_attr);
+}
+
+int tbfcp_pkt_FloorRequest_create_empty(tbfcp_pkt_FloorRequest_t** pp_self)
+{
+ extern const tsk_object_def_t *tbfcp_pkt_FloorRequest_def_t;
+ tbfcp_pkt_FloorRequest_t* p_self;
+ int ret;
+
+ if (!pp_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(p_self = tsk_object_new(tbfcp_pkt_FloorRequest_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create object 'tbfcp_pkt_FloorRequest_def_t'");
+ return -2;
+ }
+ if ((ret = _tbfcp_pkt_init_empty_FloorRequest(p_self))) {
+ TSK_OBJECT_SAFE_FREE(p_self);
+ return ret;
+ }
+ *pp_self = p_self;
+ return 0;
+}
+
+int tbfcp_pkt_FloorRequest_create(uint32_t conf_id, uint16_t transac_id, uint16_t user_id, uint16_t floor_id, tbfcp_pkt_FloorRequest_t** pp_self)
+{
+ int ret;
+
+ if ((ret = tbfcp_pkt_FloorRequest_create_empty(pp_self))) {
+ return ret;
+ }
+ if ((ret = _tbfcp_pkt_init_FloorRequest((*pp_self), conf_id, transac_id, user_id))) {
+ TSK_OBJECT_SAFE_FREE((*pp_self));
+ return ret;
+ }
+ if ((ret = tbfcp_attr_unsigned16_create(tbfcp_attribute_type_FLOOR_ID, kBfcpFieldMYes, floor_id, &(*pp_self)->p_floor_id))) {
+ TSK_OBJECT_SAFE_FREE((*pp_self));
+ return ret;
+ }
+ return ret;
+}
+
+static tsk_object_t* tbfcp_pkt_FloorRequest_ctor(tsk_object_t * self, va_list * app)
+{
+ tbfcp_pkt_FloorRequest_t *p_pkt = (tbfcp_pkt_FloorRequest_t *)self;
+ if (p_pkt) {
+ TBFCP_PKT(p_pkt)->f_add_attr = _tbfcp_pkt_FloorRequest_add_attr;
+ }
+ return self;
+}
+static tsk_object_t* tbfcp_pkt_FloorRequest_dtor(tsk_object_t * self)
+{
+ tbfcp_pkt_FloorRequest_t *p_pkt = (tbfcp_pkt_FloorRequest_t *)self;
+ if (p_pkt) {
+ TSK_DEBUG_INFO("*** BFCP Packet(FloorRequest) destroyed ***");
+ _tbfcp_pkt_deinit(TBFCP_PKT(p_pkt)); // dtor(base)
+ TSK_OBJECT_SAFE_FREE(p_pkt->p_floor_id);
+ TSK_OBJECT_SAFE_FREE(p_pkt->p_beneficiary_id);
+ TSK_OBJECT_SAFE_FREE(p_pkt->p_participant_provided_info);
+ TSK_OBJECT_SAFE_FREE(p_pkt->p_priority);
+ }
+
+ return self;
+}
+static int tbfcp_pkt_FloorRequest_cmp(const tsk_object_t *_pk1, const tsk_object_t *_pk2)
+{
+ const tbfcp_pkt_FloorRequest_t *pc_pk1 = (const tbfcp_pkt_FloorRequest_t *)_pk1;
+ const tbfcp_pkt_FloorRequest_t *pc_pk2 = (const tbfcp_pkt_FloorRequest_t *)_pk2;
+
+ return (int)(pc_pk1-pc_pk2);
+}
+static const tsk_object_def_t tbfcp_pkt_FloorRequest_def_s = {
+ sizeof(tbfcp_pkt_FloorRequest_t),
+ tbfcp_pkt_FloorRequest_ctor,
+ tbfcp_pkt_FloorRequest_dtor,
+ tbfcp_pkt_FloorRequest_cmp,
+};
+const tsk_object_def_t *tbfcp_pkt_FloorRequest_def_t = &tbfcp_pkt_FloorRequest_def_s;
+#endif \ No newline at end of file
diff --git a/tinyBFCP/src/tbfcp_session.c b/tinyBFCP/src/tbfcp_session.c
new file mode 100644
index 0000000..0a2169b
--- /dev/null
+++ b/tinyBFCP/src/tbfcp_session.c
@@ -0,0 +1,1041 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "tinybfcp/tbfcp_session.h"
+#include "tinybfcp/tbfcp_pkt.h"
+#include "tinybfcp/tbfcp_utils.h"
+
+#include "tsk_time.h"
+#include "tsk_timer.h"
+#include "tsk_object.h"
+#include "tsk_memory.h"
+#include "tsk_safeobj.h"
+#include "tsk_debug.h"
+
+typedef struct tbfcp_udp_pkt_s {
+ TSK_DECLARE_OBJECT;
+ struct {
+ tsk_timer_id_t u_id;
+ uint64_t u_timeout;
+ } timer;
+ tbfcp_pkt_t *p_pkt;
+} tbfcp_udp_pkt_t;
+typedef tsk_list_t tbfcp_udp_pkts_L_t;
+
+typedef struct tbfcp_session_s {
+ TSK_DECLARE_OBJECT;
+
+ tsk_bool_t b_started;
+ tsk_bool_t b_stopping;
+ tsk_bool_t b_prepared;
+
+ tbfcp_udp_pkts_L_t *p_list_udp_pkts;
+
+ struct {
+ tbfcp_session_callback_f f_fun;
+ struct tbfcp_session_event_xs e;
+ } cb;
+
+ // Values received from the server in the 200 OK. Attributes from rfc4583
+ struct {
+ uint32_t u_conf_id;
+ uint16_t u_user_id;
+ uint16_t u_floor_id;
+ }
+ conf_ids;
+
+ enum tbfcp_role_e e_role_local;
+ enum tbfcp_role_e e_role_remote;
+
+ enum tbfcp_setup_e e_setup_local;
+ enum tbfcp_setup_e e_setup_remote;
+
+ enum tnet_socket_type_e e_socket_type;
+ char* p_local_ip;
+ tnet_port_t u_local_port;
+
+ char* p_local_public_ip;
+ tnet_port_t u_local_public_port;
+
+ char* p_remote_ip;
+ tnet_port_t u_remote_port;
+ struct sockaddr_storage remote_addr;
+
+ struct tnet_nat_ctx_s* p_natt_ctx;
+ struct tnet_ice_ctx_s* p_ice_ctx;
+ struct tnet_transport_s* p_transport;
+
+ uint8_t* p_buff_send_ptr;
+ tsk_size_t u_buff_send_size;
+
+ struct {
+ tsk_timer_manager_handle_t* ph_global;
+ tsk_timer_id_t id_T1; // For UDP only
+ uint64_t u_timeout_T1;
+ tsk_timer_id_t id_T2; // For UDP only
+ uint64_t u_timeout_T2;
+ tsk_timer_id_t id_TcpReconnect; // For TCP/TLS only
+ uint64_t u_timeout_TcpReconnect;
+ } timer;
+
+ TSK_DECLARE_SAFEOBJ;
+} tbfcp_session_t;
+
+typedef enum _bfcp_timer_type_e {
+ _bfcp_timer_type_T1, // draft-ietf-bfcpbis-rfc4582bis-11 - 4.16. Timer Values (8.3.3) - Initial request retransmission timer (0.5s)
+ _bfcp_timer_type_T2, // draft-ietf-bfcpbis-rfc4582bis-11 - 4.16. Timer Values (8.3.3) - Response retransmission timer (10s)
+ _bfcp_timer_type_TcpReconnect, // Try to reconnect the TCP/TLS socket every X seconds if unexpectedly disconnected
+}
+_bfcp_timer_type_t;
+
+static int _tbfcp_udp_pkt_create(const tbfcp_pkt_t *pc_pkt, tbfcp_udp_pkt_t** pp_pkt);
+
+static int _tbfcp_session_send_pkt(tbfcp_session_t* p_self, const tbfcp_pkt_t* pc_pkt);
+static int _tbfcp_session_send_Hello(struct tbfcp_session_s* p_self);
+static int _tbfcp_session_send_HelloAck(struct tbfcp_session_s* p_self, const tbfcp_pkt_t *pc_hello);
+static int _tbfcp_session_send_FloorRequest(struct tbfcp_session_s* p_self);
+static int _tbfcp_session_process_incoming_pkt(struct tbfcp_session_s* p_self, const tbfcp_pkt_t *pc_pkt);
+static int _tbfcp_session_socket_type_make_valid(enum tnet_socket_type_e e_in_st, enum tnet_socket_type_e *pe_out_st);
+static int _tbfcp_session_timer_callback(const void* pc_arg, tsk_timer_id_t timer_id);
+static int _tbfcp_session_timer_schedule(struct tbfcp_session_s* p_self, _bfcp_timer_type_t e_timer, uint64_t u_timeout);
+static int _tbfcp_session_transport_layer_dgram_cb(const tnet_transport_event_t* e);
+static int _tbfcp_session_transport_layer_stream_cb(const tnet_transport_event_t* e);
+
+#define _tbfcp_session_raise(_p_self, _e_type, _pc_pkt) \
+ if ((_p_self)->cb.f_fun) { \
+ (_p_self)->cb.e.e_type = (_e_type); \
+ (_p_self)->cb.e.pc_pkt = (_pc_pkt); \
+ (_p_self)->cb.f_fun(&_p_self->cb.e); \
+ }
+#define _tbfcp_session_raise_inf_inc_msg(_p_self, _pc_pkt) _tbfcp_session_raise(_p_self, tbfcp_session_event_type_inf_inc_msg, _pc_pkt)
+#define _tbfcp_session_raise_err_send_timedout(_p_self, _pc_pkt) _tbfcp_session_raise(_p_self, tbfcp_session_event_type_err_send_timedout, _pc_pkt)
+
+static int __pred_find_udp_pkt_by_timer(const tsk_list_item_t *item, const void *u64_id) {
+ if (item && item->data) {
+ return (int)(((const struct tbfcp_udp_pkt_s *)item->data)->timer.u_id - *((const uint64_t*)u64_id));
+ }
+ return -1;
+}
+static int __pred_find_udp_pkt_by_transac_id(const tsk_list_item_t *item, const void *u16_transac_id) {
+ if (item && item->data) {
+ return (int)(((const struct tbfcp_udp_pkt_s *)item->data)->p_pkt->hdr.transac_id - *((const uint16_t*)u16_transac_id));
+ }
+ return -1;
+}
+
+int tbfcp_session_create(tnet_socket_type_t e_socket_type, const char* pc_local_ip, tbfcp_session_t** pp_self)
+{
+ extern const tsk_object_def_t *tbfcp_session_def_t;
+ int ret;
+ tnet_socket_type_t e_st;
+ tbfcp_session_t* p_self;
+
+ if (!pp_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = _tbfcp_session_socket_type_make_valid(e_socket_type, &e_st))) {
+ return ret;
+ }
+ if (!(p_self = tsk_object_new(tbfcp_session_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create 'tbfcp_session_def_t' object");
+ return -2;
+ }
+ p_self->e_socket_type = e_st;
+ tsk_strupdate(&p_self->p_local_ip, pc_local_ip);
+ *pp_self = p_self;
+ return 0;
+}
+
+int tbfcp_session_create_2(struct tnet_ice_ctx_s* p_ice_ctx, tbfcp_session_t** pp_self)
+{
+ tnet_socket_type_t e_st;
+ const char* pc_local_ip;
+ int ret;
+ if (!pp_self || !p_ice_ctx) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // TODO: ICE expect RTP and RTCP comp-ids only
+ TSK_DEBUG_ERROR("Not supported yet");
+ return -2;
+
+ // TODO: For now ICE works with UDP (and DTLS) only
+ e_st = tnet_ice_ctx_use_ipv6(p_ice_ctx) ? tnet_socket_type_udp_ipv4 : tnet_socket_type_udp_ipv6;
+ pc_local_ip = tnet_ice_ctx_use_ipv6(p_ice_ctx) ? "::1" : "127.0.0.1";
+ if ((ret = _tbfcp_session_socket_type_make_valid(e_st, &e_st))) {
+ return ret;
+ }
+ if ((ret = tbfcp_session_create(e_st, pc_local_ip, pp_self))) {
+ return ret;
+ }
+ (*pp_self)->p_ice_ctx = tsk_object_ref(p_ice_ctx);
+ return 0;
+}
+
+int tbfcp_session_set_callback(struct tbfcp_session_s* p_self, tbfcp_session_callback_f f_fun, const void* pc_usr_data)
+{
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ p_self->cb.f_fun = f_fun;
+ p_self->cb.e.pc_usr_data = pc_usr_data;
+ return 0;
+}
+
+int tbfcp_session_set_ice_ctx(tbfcp_session_t* p_self, struct tnet_ice_ctx_s* p_ice_ctx)
+{
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ TSK_OBJECT_SAFE_FREE(p_self->p_ice_ctx);
+ if (p_ice_ctx) {
+ p_self->p_ice_ctx = tsk_object_ref(p_ice_ctx);
+ }
+ return 0;
+}
+
+int tbfcp_session_prepare(tbfcp_session_t* p_self)
+{
+ int ret = 0;
+ const char *bfcp_local_ip;
+ tnet_port_t bfcp_local_port;
+
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // lock()
+ tsk_safeobj_lock(p_self);
+
+ if (p_self->b_prepared) {
+ TSK_DEBUG_INFO("BFCP session already prepared");
+ goto bail;
+ }
+ if (p_self->p_transport) {
+ TSK_DEBUG_ERROR("BFCP session already has a transport. Unexpected.");
+ ret = -2;
+ goto bail;
+ }
+
+ bfcp_local_ip = TNET_SOCKET_HOST_ANY;
+ bfcp_local_port = TNET_SOCKET_PORT_ANY;
+
+ /*if (p_self->p_ice_ctx) {
+ // Get Sockets when the transport is started
+ bfcp_local_ip = tnet_ice_ctx_use_ipv6(p_self->p_ice_ctx) ? "::1" : "127.0.0.1";
+ }
+ else*/ {
+ // create transport
+ if (!p_self->p_transport && !(p_self->p_transport = tnet_transport_create(p_self->p_local_ip, p_self->u_local_port, p_self->e_socket_type, kBfcpTransportFriendlyName))) {
+ TSK_DEBUG_ERROR("Failed to create %s Transport", kBfcpTransportFriendlyName);
+ return -3;
+ }
+ // set transport callback
+ if ((ret = tnet_transport_set_callback(p_self->p_transport, TNET_SOCKET_TYPE_IS_DGRAM(p_self->e_socket_type) ? _tbfcp_session_transport_layer_dgram_cb : _tbfcp_session_transport_layer_stream_cb, p_self))) {
+ goto bail;
+ }
+ bfcp_local_ip = p_self->p_transport->master->ip;
+ bfcp_local_port = p_self->p_transport->master->port;
+ }
+
+ tsk_strupdate(&p_self->p_local_public_ip, bfcp_local_ip);
+ p_self->u_local_public_port = bfcp_local_port;
+
+ p_self->b_prepared = tsk_true;
+
+bail:
+ // unlock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+int tbfcp_session_start(tbfcp_session_t* p_self)
+{
+ int ret;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // lock()
+ tsk_safeobj_lock(p_self);
+
+ if (p_self->b_started) {
+ TSK_DEBUG_INFO("BFCP session already started");
+ ret = 0;
+ goto bail;
+ }
+
+ if (!p_self->b_prepared) {
+ TSK_DEBUG_ERROR("BFCP session not prepared yet");
+ ret = -2;
+ goto bail;
+ }
+
+ // start global timer manager - nothing will be done if already started by another component
+ if ((ret = tsk_timer_manager_start(p_self->timer.ph_global))) {
+ TSK_DEBUG_ERROR("Failed to start timer");
+ goto bail;
+ }
+
+ // check remote IP address validity
+ if ((tsk_striequals(p_self->p_remote_ip, "0.0.0.0") || tsk_striequals(p_self->p_remote_ip, "::"))) { // most likely loopback testing
+ tnet_ip_t source = {0};
+ tsk_bool_t updated = tsk_false;
+ if (p_self->p_transport && p_self->p_transport->master) {
+ updated = (tnet_getbestsource(p_self->p_transport->master->ip, p_self->p_transport->master->port, p_self->p_transport->master->type, &source) == 0);
+ }
+ // Not allowed to send data to "0.0.0.0"
+ TSK_DEBUG_INFO("BFCP remote IP contains not allowed value ...changing to '%s'", updated ? source : "oops");
+ if (updated) {
+ tsk_strupdate(&p_self->p_remote_ip, source);
+ }
+ }
+ // init remote remote addr
+ if ((ret = tnet_sockaddr_init(p_self->p_remote_ip, p_self->u_remote_port, p_self->p_transport->master->type, &p_self->remote_addr))) {
+ tnet_transport_shutdown(p_self->p_transport);
+ TSK_OBJECT_SAFE_FREE(p_self->p_transport);
+ TSK_DEBUG_ERROR("Invalid BFCP host:port [%s:%u]", p_self->p_remote_ip, p_self->u_remote_port);
+ goto bail;
+ }
+ if ((ret = tnet_transport_set_natt_ctx(p_self->p_transport, p_self->p_natt_ctx))) {
+ TSK_DEBUG_ERROR("Failed to start to set NATT ctx for the %s transport", kBfcpTransportFriendlyName);
+ goto bail;
+ }
+
+ // start the transport
+ if ((ret = tnet_transport_start(p_self->p_transport))) {
+ TSK_DEBUG_ERROR("Failed to start the %s transport", kBfcpTransportFriendlyName);
+ goto bail;
+ }
+
+ p_self->b_started = tsk_true;
+
+ // Send hello now if UDP/DTLS. Otherwise (TCP/TLS), wait for the connection to complete.
+ //if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->e_socket_type)) {
+ // if ((ret = _tbfcp_session_send_Hello(p_self))) {
+ // goto bail;
+ // }
+ //}
+
+bail:
+ // unlock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+int tbfcp_session_pause(tbfcp_session_t* p_self)
+{
+ int ret = 0;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // lock()
+ tsk_safeobj_lock(p_self);
+
+ goto bail;
+
+bail:
+ // unlock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+int tbfcp_session_stop(tbfcp_session_t* p_self)
+{
+ int ret = 0;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // FIXME: send FloorRelease if a FloorRequest is pending
+
+ // lock()
+ tsk_safeobj_lock(p_self);
+
+ // stop the session if not already done
+ if (!p_self->b_started) {
+ TSK_DEBUG_INFO("BFCP session already stopped");
+ goto bail;
+ }
+
+ // remove all pending udp packets
+ tsk_list_clear_items(p_self->p_list_udp_pkts);
+
+ p_self->b_stopping = tsk_true;
+ // this is a global timer shared by many components -> stopping it won't remove
+ // all scheduled items as it could continue running if still used
+ if (TSK_TIMER_ID_IS_VALID(p_self->timer.id_T1)) {
+ tsk_timer_manager_cancel(p_self->timer.ph_global, p_self->timer.id_T1);
+ p_self->timer.id_T1 = TSK_INVALID_TIMER_ID;
+ }
+ if (TSK_TIMER_ID_IS_VALID(p_self->timer.id_T2)) {
+ tsk_timer_manager_cancel(p_self->timer.ph_global, p_self->timer.id_T2);
+ p_self->timer.id_T2 = TSK_INVALID_TIMER_ID;
+ }
+ if (TSK_TIMER_ID_IS_VALID(p_self->timer.id_TcpReconnect)) {
+ tsk_timer_manager_cancel(p_self->timer.ph_global, p_self->timer.id_TcpReconnect);
+ p_self->timer.id_TcpReconnect = TSK_INVALID_TIMER_ID;
+ }
+
+ // free transport to force next call to start() to create new one with new sockets
+ if (p_self->p_transport) {
+ tnet_transport_shutdown(p_self->p_transport);
+ TSK_OBJECT_SAFE_FREE(p_self->p_transport);
+ }
+
+ p_self->b_started = tsk_false;
+ p_self->b_stopping = tsk_false;
+ p_self->b_prepared = tsk_false;
+
+bail:
+ // unlock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+int tbfcp_session_set_natt_ctx(tbfcp_session_t* p_self, struct tnet_nat_ctx_s* p_natt_ctx)
+{
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ TSK_OBJECT_SAFE_FREE(p_self->p_natt_ctx);
+ p_self->p_natt_ctx = tsk_object_ref(p_natt_ctx);
+ return 0;
+}
+
+int tbfcp_session_set_remote_address(tbfcp_session_t* p_self, const char* pc_ip, tnet_port_t u_port)
+{
+ if (!p_self || !pc_ip /*|| u_port < 1024*/) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ // if ICE is enabled then, these values will be updated when the session start()s and call ice_init()
+ tsk_strupdate(&p_self->p_remote_ip, pc_ip);
+ p_self->u_remote_port = u_port;
+ return 0;
+}
+
+int tbfcp_session_set_remote_role(tbfcp_session_t* p_self, enum tbfcp_role_e e_role_remote)
+{
+ tsk_bool_t b_is_role_acceptable;
+ int ret;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tbfcp_utils_is_role_acceptable(p_self->e_role_local, e_role_remote, &b_is_role_acceptable))) {
+ return ret;
+ }
+ if (!b_is_role_acceptable) {
+ TSK_DEBUG_ERROR("%d not acceptable as remote role because local role = %d", e_role_remote, p_self->e_role_local);
+ return -2;
+ }
+ p_self->e_role_remote = e_role_remote;
+ return 0;
+}
+
+int tbfcp_session_set_remote_setup(struct tbfcp_session_s* p_self, enum tbfcp_setup_e e_setup_remote)
+{
+ tsk_bool_t b_is_setup_acceptable;
+ int ret;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tbfcp_utils_is_setup_acceptable(p_self->e_setup_local, e_setup_remote, &b_is_setup_acceptable))) {
+ return ret;
+ }
+ if (!b_is_setup_acceptable) {
+ TSK_DEBUG_ERROR("%d not acceptable as remote setup because local setup = %d", e_setup_remote, p_self->e_setup_local);
+ return -2;
+ }
+ p_self->e_setup_remote = e_setup_remote;
+ return 0;
+}
+
+int tbfcp_session_set_conf_ids(tbfcp_session_t* p_self, uint32_t u_conf_id, uint16_t u_user_id, uint16_t u_floor_id)
+{
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ p_self->conf_ids.u_conf_id = u_conf_id;
+ p_self->conf_ids.u_user_id = u_user_id;
+ p_self->conf_ids.u_floor_id = u_floor_id;
+ return 0;
+}
+
+int tbfcp_session_get_profile(const tbfcp_session_t* pc_self, const char** ppc_profile)
+{
+ if (!pc_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return tbfcp_utils_get_profile(pc_self->e_socket_type, ppc_profile);
+}
+
+int tbfcp_session_get_local_role(const tbfcp_session_t* pc_self, enum tbfcp_role_e *pe_role_local)
+{
+ if (!pc_self || !pe_role_local) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *pe_role_local = pc_self->e_role_local;
+ return 0;
+}
+
+int tbfcp_session_get_local_setup(const struct tbfcp_session_s* pc_self, enum tbfcp_setup_e *pe_setup_local)
+{
+ if (!pc_self || !pe_setup_local) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *pe_setup_local = pc_self->e_setup_local;
+ return 0;
+}
+
+int tbfcp_session_get_local_address(const tbfcp_session_t* pc_self, const char** ppc_ip, tnet_port_t *pu_port)
+{
+ if (!pc_self || !ppc_ip || !pu_port) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *ppc_ip = pc_self->p_local_public_ip;
+ *pu_port = pc_self->u_local_public_port;
+ return 0;
+}
+
+int tbfcp_session_create_pkt_Hello(struct tbfcp_session_s* p_self, struct tbfcp_pkt_s** pp_pkt)
+{
+ int ret;
+ if (!p_self || !pp_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ // lock()
+ tsk_safeobj_lock(p_self);
+ if ((ret = tbfcp_pkt_create_Hello(p_self->conf_ids.u_conf_id, tbfcp_utils_rand_u16(), p_self->conf_ids.u_user_id, pp_pkt))) {
+ goto bail;
+ }
+
+bail:
+ // lock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+int tbfcp_session_create_pkt_FloorRequest(struct tbfcp_session_s* p_self, struct tbfcp_pkt_s** pp_pkt)
+{
+ int ret;
+ if (!p_self || !pp_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ // lock()
+ tsk_safeobj_lock(p_self);
+ if ((ret = tbfcp_pkt_create_FloorRequest_2(p_self->conf_ids.u_conf_id, tbfcp_utils_rand_u16(), p_self->conf_ids.u_user_id, p_self->conf_ids.u_floor_id, pp_pkt))) {
+ goto bail;
+ }
+
+bail:
+ // lock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+int tbfcp_session_create_pkt_FloorRelease(struct tbfcp_session_s* p_self, struct tbfcp_pkt_s** pp_pkt)
+{
+ int ret;
+ if (!p_self || !pp_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ // lock()
+ tsk_safeobj_lock(p_self);
+ if ((ret = tbfcp_pkt_create_FloorRelease_2(p_self->conf_ids.u_conf_id, tbfcp_utils_rand_u16(), p_self->conf_ids.u_user_id, p_self->conf_ids.u_floor_id, pp_pkt))) {
+ goto bail;
+ }
+
+bail:
+ // lock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+static int _tbfcp_session_send_buff(tbfcp_session_t* p_self, const void* pc_buff_ptr, tsk_size_t u_buff_size)
+{
+ int ret = 0;
+ tsk_size_t u_sent_bytes = 0;
+ if (!p_self || !pc_buff_ptr || !u_buff_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // lock()
+ tsk_safeobj_lock(p_self);
+
+ if (!p_self->b_started) {
+ TSK_DEBUG_ERROR("BFCP session not started");
+ ret = -2;
+ goto bail;
+ }
+
+ if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->e_socket_type)) {
+ u_sent_bytes = tnet_transport_sendto(p_self->p_transport, p_self->p_transport->master->fd, (const struct sockaddr *)&p_self->remote_addr, pc_buff_ptr, u_buff_size);
+ }
+ else {
+ TSK_DEBUG_ERROR("Not implemented yet");
+ ret = -3;
+ goto bail;
+ }
+
+ if (u_sent_bytes != u_buff_size) {
+ TSK_DEBUG_ERROR("Failed to send %u bytes. Only %u sent", u_buff_size, u_sent_bytes);
+ ret = -2;
+ goto bail;
+ }
+
+bail:
+ // unlock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+int tbfcp_session_send_pkt(tbfcp_session_t* p_self, const tbfcp_pkt_t* pc_pkt)
+{
+ int ret = 0;
+ tbfcp_udp_pkt_t *p_udp_pkt = tsk_null;
+ if (!p_self || !pc_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // lock()
+ tsk_safeobj_lock(p_self);
+
+ if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->e_socket_type)) {
+ const tsk_list_item_t* pc_item = tsk_list_find_item_by_pred(p_self->p_list_udp_pkts, __pred_find_udp_pkt_by_transac_id, &pc_pkt->hdr.transac_id);
+ if (pc_item) {
+ p_udp_pkt = tsk_object_ref(TSK_OBJECT(pc_item->data));
+ } else {
+ tbfcp_udp_pkt_t *_p_udp_pkt = tsk_null;
+ if ((ret = _tbfcp_udp_pkt_create(pc_pkt, &_p_udp_pkt))) {
+ goto bail;
+ }
+ p_udp_pkt = tsk_object_ref(_p_udp_pkt);
+ tsk_list_push_back_data(p_self->p_list_udp_pkts, (void**)&_p_udp_pkt);
+ }
+ }
+ else {
+ }
+
+ if ((ret = _tbfcp_session_send_pkt(p_self, pc_pkt))) {
+ goto bail;
+ }
+ if (p_udp_pkt) {
+ p_udp_pkt->timer.u_id = tsk_timer_manager_schedule(p_self->timer.ph_global, p_udp_pkt->timer.u_timeout, _tbfcp_session_timer_callback, p_self);
+ p_udp_pkt->timer.u_timeout += kBfcpTimerT1;
+ }
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_udp_pkt);
+ // unlock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+int _tbfcp_session_send_pkt(tbfcp_session_t* p_self, const tbfcp_pkt_t* pc_pkt)
+{
+ int ret;
+ tsk_size_t u_min_size;
+ if (!p_self || !pc_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // lock()
+ tsk_safeobj_lock(p_self);
+
+ if (!p_self->b_started) {
+ TSK_DEBUG_ERROR("BFCP session not started");
+ ret = -2;
+ goto bail;
+ }
+ if ((ret = tbfcp_pkt_get_size_in_octetunits_with_padding(pc_pkt, &u_min_size))) {
+ goto bail;
+ }
+ u_min_size += kBfcpBuffMinPad;
+ if (p_self->u_buff_send_size < u_min_size) {
+ if (!(p_self->p_buff_send_ptr = tsk_realloc(p_self->p_buff_send_ptr, u_min_size))) {
+ TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", u_min_size);
+ ret = -3;
+ p_self->u_buff_send_size = 0;
+ goto bail;
+ }
+ p_self->u_buff_send_size = u_min_size;
+ }
+
+ if ((ret = tbfcp_pkt_write_with_padding(pc_pkt, p_self->p_buff_send_ptr, p_self->u_buff_send_size, &u_min_size))) {
+ goto bail;
+ }
+ if ((ret = _tbfcp_session_send_buff(p_self, p_self->p_buff_send_ptr, u_min_size))) {
+ goto bail;
+ }
+
+bail:
+ // unlock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+int _tbfcp_session_send_Hello(tbfcp_session_t* p_self)
+{
+ tbfcp_pkt_t* p_pkt = tsk_null;
+ int ret;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tbfcp_pkt_create_Hello(p_self->conf_ids.u_conf_id, tbfcp_utils_rand_u16(), p_self->conf_ids.u_user_id, &p_pkt))) {
+ goto bail;
+ }
+ if ((ret = tbfcp_session_send_pkt(p_self, p_pkt))) {
+ goto bail;
+ }
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ return ret;
+}
+
+int _tbfcp_session_send_HelloAck(tbfcp_session_t* p_self, const tbfcp_pkt_t *pc_hello)
+{
+ tbfcp_pkt_t* p_pkt = tsk_null;
+ int ret;
+ if (!p_self || !pc_hello) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tbfcp_pkt_create_HelloAck_2(pc_hello->hdr.conf_id, pc_hello->hdr.transac_id, pc_hello->hdr.user_id, &p_pkt))) {
+ goto bail;
+ }
+ if ((ret = _tbfcp_session_send_pkt(p_self, p_pkt))) {
+ goto bail;
+ }
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ return ret;
+}
+
+static int _tbfcp_session_send_FloorRequest(tbfcp_session_t* p_self)
+{
+ tbfcp_pkt_t* p_pkt = tsk_null;
+ int ret;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tbfcp_pkt_create_FloorRequest_2(p_self->conf_ids.u_conf_id, tbfcp_utils_rand_u16(), p_self->conf_ids.u_user_id, p_self->conf_ids.u_floor_id, &p_pkt))) {
+ goto bail;
+ }
+ if ((ret = tbfcp_session_send_pkt(p_self, p_pkt))) {
+ goto bail;
+ }
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ return ret;
+}
+
+static int _tbfcp_session_process_incoming_pkt(tbfcp_session_t* p_self, const tbfcp_pkt_t *pc_pkt)
+{
+ int ret = 0;
+ if (!p_self || !pc_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // lock()
+ tsk_safeobj_lock(p_self);
+
+ switch (pc_pkt->hdr.primitive) {
+ case tbfcp_primitive_Hello:
+ if ((ret = _tbfcp_session_send_HelloAck(p_self, pc_pkt))) {
+ goto bail;
+ }
+ break;
+ case tbfcp_primitive_HelloAck:
+ default:
+ break;
+ }
+
+ // raise event
+ _tbfcp_session_raise_inf_inc_msg(p_self, pc_pkt);
+ // remove request
+ tsk_list_remove_item_by_pred(p_self->p_list_udp_pkts, __pred_find_udp_pkt_by_transac_id, &pc_pkt->hdr.transac_id);
+
+bail:
+ // unlock()
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+// clear junks (e.g. IPSec)
+static int _tbfcp_session_socket_type_make_valid(enum tnet_socket_type_e e_in_st, enum tnet_socket_type_e *pe_out_st)
+{
+ if (!pe_out_st) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (TNET_SOCKET_TYPE_IS_DTLS(e_in_st) || TNET_SOCKET_TYPE_IS_UDP(e_in_st) || TNET_SOCKET_TYPE_IS_TLS(e_in_st) || TNET_SOCKET_TYPE_IS_TCP(e_in_st)) {
+ *pe_out_st = e_in_st;
+ }
+ else {
+ *pe_out_st = kBfcpTransportDefault;
+ }
+ return 0;
+}
+
+static int _tbfcp_session_timer_schedule(tbfcp_session_t* p_self, _bfcp_timer_type_t e_timer, uint64_t u_timeout)
+{
+ int ret = 0;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ tsk_safeobj_lock(p_self); // must
+ switch (e_timer) {
+ case _bfcp_timer_type_T1:
+ if (!TSK_TIMER_ID_IS_VALID(p_self->timer.id_T1)) {
+ p_self->timer.id_T1 = tsk_timer_mgr_global_schedule(u_timeout, _tbfcp_session_timer_callback, p_self);
+ }
+ else {
+ TSK_DEBUG_ERROR("T1 timer is still valid");
+ ret = -3;
+ }
+ break;
+ case _bfcp_timer_type_T2:
+ if (!TSK_TIMER_ID_IS_VALID(p_self->timer.id_T2)) {
+ p_self->timer.id_T2 = tsk_timer_mgr_global_schedule(u_timeout, _tbfcp_session_timer_callback, p_self);
+ }
+ else {
+ TSK_DEBUG_ERROR("T2 timer is still valid");
+ ret = -3;
+ }
+ break;
+ case _bfcp_timer_type_TcpReconnect:
+ if (!TSK_TIMER_ID_IS_VALID(p_self->timer.id_TcpReconnect)) {
+ p_self->timer.id_TcpReconnect = tsk_timer_mgr_global_schedule(u_timeout, _tbfcp_session_timer_callback, p_self);
+ }
+ else {
+ TSK_DEBUG_ERROR("TcpReconnect timer is still valid");
+ ret = -3;
+ }
+ break;
+ default:
+ TSK_DEBUG_ERROR("%d not valid BFCP timer", e_timer);
+ ret = -2;
+ break;
+ }
+ tsk_safeobj_unlock(p_self);
+ return ret;
+}
+
+static int _tbfcp_session_timer_callback(const void* pc_arg, tsk_timer_id_t timer_id)
+{
+ tbfcp_session_t* p_session = (tbfcp_session_t*)pc_arg;
+ const tsk_list_item_t* pc_item;
+ tsk_safeobj_lock(p_session); // must
+ if (!p_session->b_started) goto bail;
+ pc_item = tsk_list_find_item_by_pred(p_session->p_list_udp_pkts, __pred_find_udp_pkt_by_timer, &timer_id);
+ if (pc_item) {
+ tbfcp_udp_pkt_t* pc_udp_pkt = (tbfcp_udp_pkt_t*)pc_item->data;
+ if (pc_udp_pkt->timer.u_timeout <= kBfcpTimerT1Max) {
+ tbfcp_session_send_pkt(p_session, pc_udp_pkt->p_pkt);
+ }
+ else {
+ // raise event
+ _tbfcp_session_raise_err_send_timedout(p_session, pc_udp_pkt->p_pkt);
+ // remove pkt
+ tsk_list_remove_item_by_pred(p_session->p_list_udp_pkts, __pred_find_udp_pkt_by_timer, &timer_id);
+ }
+ }
+#if 0
+ if (p_session->timer.id_T1 == timer_id) {
+ p_session->timer.id_T1 = TSK_INVALID_TIMER_ID;
+ // OnExpire(session, EVENT_BYE);
+ }
+ else if (p_session->timer.id_T2 == timer_id) {
+ p_session->timer.id_T2 = TSK_INVALID_TIMER_ID;
+ // OnExpire(session, EVENT_REPORT);
+ }
+#endif
+bail:
+ tsk_safeobj_unlock(p_session);
+ return 0;
+}
+
+static int _tbfcp_session_transport_layer_dgram_cb(const tnet_transport_event_t* e)
+{
+ tbfcp_session_t* p_session = (tbfcp_session_t*)e->callback_data;
+ int ret;
+ tbfcp_pkt_t* p_pkt = tsk_null;
+ switch(e->type){
+ case event_data: {
+ break;
+ }
+ case event_closed:
+ case event_connected:
+ default:{
+ return 0;
+ }
+ }
+
+ if ((ret = tbfcp_pkt_read(e->data, e->size, &p_pkt))) {
+ goto bail;
+ }
+ if ((ret = _tbfcp_session_process_incoming_pkt(p_session, p_pkt))) {
+ goto bail;
+ }
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ return ret;
+}
+
+static int _tbfcp_session_transport_layer_stream_cb(const tnet_transport_event_t* e)
+{
+ // tbfcp_session_t* p_session = (tbfcp_session_t*)e->callback_data;
+ TSK_DEBUG_ERROR("Not implemented yet");
+ return -1;
+}
+
+static tsk_object_t* tbfcp_session_ctor(tsk_object_t * self, va_list * app)
+{
+ tbfcp_session_t *p_session = (tbfcp_session_t *)self;
+ if (p_session) {
+ p_session->timer.id_T1 = TSK_INVALID_TIMER_ID;
+ p_session->timer.id_T2 = TSK_INVALID_TIMER_ID;
+ if (!(p_session->p_list_udp_pkts = tsk_list_create())) {
+ TSK_DEBUG_ERROR("Failed to create en empty list");
+ return tsk_null;
+ }
+ // get a handle for the global timer manager
+ if (!(p_session->timer.ph_global = tsk_timer_mgr_global_ref())) {
+ TSK_DEBUG_ERROR("Failed to get a reference to the global timer");
+ return tsk_null;
+ }
+ p_session->u_local_port = TNET_SOCKET_PORT_ANY;
+ p_session->e_role_local = kBfcpRoleDefault;
+ p_session->e_setup_local = kBfcpSetupDefault;
+ tsk_safeobj_init(p_session);
+ }
+ return self;
+}
+static tsk_object_t* tbfcp_session_dtor(tsk_object_t * self)
+{
+ tbfcp_session_t *p_session = (tbfcp_session_t *)self;
+ if (p_session) {
+ TSK_DEBUG_INFO("*** BFCP session destroyed ***");
+ // stop the session if not already done
+ tbfcp_session_stop(p_session);
+ // release the handle for the global timer manager
+ tsk_timer_mgr_global_unref(&p_session->timer.ph_global);
+
+ TSK_FREE(p_session->p_local_ip);
+ TSK_FREE(p_session->p_local_public_ip);
+ TSK_FREE(p_session->p_remote_ip);
+ TSK_FREE(p_session->p_buff_send_ptr);
+ TSK_OBJECT_SAFE_FREE(p_session->p_natt_ctx);
+ TSK_OBJECT_SAFE_FREE(p_session->p_ice_ctx);
+ TSK_OBJECT_SAFE_FREE(p_session->p_transport);
+ TSK_OBJECT_SAFE_FREE(p_session->p_list_udp_pkts);
+ tsk_safeobj_deinit(p_session);
+ }
+
+ return self;
+}
+static int tbfcp_session_cmp(const tsk_object_t *_pss1, const tsk_object_t *_pss2)
+{
+ const tbfcp_session_t *pc_ss1 = (const tbfcp_session_t *)_pss1;
+ const tbfcp_session_t *pc_ss2 = (const tbfcp_session_t *)_pss2;
+ return (int)(pc_ss1 - pc_ss2);
+}
+static const tsk_object_def_t tbfcp_session_def_s = {
+ sizeof(tbfcp_session_t),
+ tbfcp_session_ctor,
+ tbfcp_session_dtor,
+ tbfcp_session_cmp,
+};
+const tsk_object_def_t *tbfcp_session_def_t = &tbfcp_session_def_s;
+
+
+
+static int _tbfcp_udp_pkt_create(const tbfcp_pkt_t *pc_pkt, tbfcp_udp_pkt_t** pp_pkt)
+{
+ extern const tsk_object_def_t *tbfcp_udp_pkt_def_t;
+ if (!pc_pkt || !pp_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *pp_pkt = tsk_object_new(tbfcp_udp_pkt_def_t);
+ if (!(*pp_pkt)) {
+ TSK_DEBUG_ERROR("Failed to create object with type= 'tbfcp_udp_pkt_def_t'");
+ return -2;
+ }
+ (*pp_pkt)->p_pkt = tsk_object_ref(TSK_OBJECT(pc_pkt));
+ return 0;
+}
+
+static tsk_object_t* tbfcp_udp_pkt_ctor(tsk_object_t * self, va_list * app)
+{
+ tbfcp_udp_pkt_t *p_udp_pkt = (tbfcp_udp_pkt_t *)self;
+ if (p_udp_pkt) {
+ p_udp_pkt->timer.u_timeout = kBfcpTimerT1;
+ p_udp_pkt->timer.u_id = TSK_INVALID_TIMER_ID;
+ }
+ return self;
+}
+static tsk_object_t* tbfcp_udp_pkt_dtor(tsk_object_t * self)
+{
+ tbfcp_udp_pkt_t *p_udp_pkt = (tbfcp_udp_pkt_t *)self;
+ if (p_udp_pkt) {
+ TSK_OBJECT_SAFE_FREE(p_udp_pkt->p_pkt);
+ TSK_DEBUG_INFO("*** tbfcp_udp_pkt_t destroyed ***");
+ }
+ return self;
+}
+static const tsk_object_def_t tbfcp_udp_pkt_def_s = {
+ sizeof(tbfcp_udp_pkt_t),
+ tbfcp_udp_pkt_ctor,
+ tbfcp_udp_pkt_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tbfcp_udp_pkt_def_t = &tbfcp_udp_pkt_def_s;
diff --git a/tinyBFCP/src/tbfcp_utils.c b/tinyBFCP/src/tbfcp_utils.c
new file mode 100644
index 0000000..7c0ff25
--- /dev/null
+++ b/tinyBFCP/src/tbfcp_utils.c
@@ -0,0 +1,191 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "tinybfcp/tbfcp_utils.h"
+
+#include "tinynet.h"
+#include "tsk_string.h"
+#include "tsk_debug.h"
+
+int tbfcp_utils_get_profile(enum tnet_socket_type_e e_socket_type, const char** ppc_profile)
+{
+ if (!ppc_profile) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if (TNET_SOCKET_TYPE_IS_DTLS(e_socket_type)) {
+ *ppc_profile = kBfcpProfileDTLS;
+ return 0;
+ }
+ if (TNET_SOCKET_TYPE_IS_UDP(e_socket_type)) {
+ *ppc_profile = kBfcpProfileUDP;
+ return 0;
+ }
+ if (TNET_SOCKET_TYPE_IS_TLS(e_socket_type)) {
+ *ppc_profile = kBfcpProfileTLS;
+ return 0;
+ }
+ if (TNET_SOCKET_TYPE_IS_TCP(e_socket_type)) {
+ *ppc_profile = kBfcpProfileTCP;
+ return 0;
+ }
+ TSK_DEBUG_ERROR("%d not supported as valid socket type for BFCP sessions", e_socket_type);
+ return -2;
+}
+
+int tbfcp_utils_get_role(enum tbfcp_role_e e_role, const char** ppc_role)
+{
+ if (!ppc_role) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ switch (e_role) {
+ case tbfcp_role_c_only:
+ *ppc_role = kBfcpRoleC;
+ return 0;
+ case tbfcp_role_s_only:
+ *ppc_role = kBfcpRoleS;
+ return 0;
+ case tbfcp_role_c_s:
+ *ppc_role = kBfcpRoleCS;
+ return 0;
+ default:
+ TSK_DEBUG_ERROR("%d not valid BFCP role", e_role);
+ return -2;
+ }
+}
+
+int tbfcp_utils_parse_role(const char* pc_role, enum tbfcp_role_e* pe_role)
+{
+ if (!pc_role || !pe_role) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (tsk_striequals(pc_role, kBfcpRoleC)) {
+ *pe_role = tbfcp_role_c_only;
+ return 0;
+ }
+ if (tsk_striequals(pc_role, kBfcpRoleS)) {
+ *pe_role = tbfcp_role_s_only;
+ return 0;
+ }
+ if (tsk_striequals(pc_role, kBfcpRoleCS)) {
+ *pe_role = tbfcp_role_c_s;
+ return 0;
+ }
+ TSK_DEBUG_ERROR("%s not valid BFCP role", pc_role);
+ return -2;
+}
+
+int tbfcp_utils_get_setup(enum tbfcp_role_e e_setup, const char** ppc_setup)
+{
+ if (!ppc_setup) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ switch (e_setup) {
+ case tbfcp_setup_actpass:
+ *ppc_setup = kBfcpSetupActPass;
+ return 0;
+ case tbfcp_setup_active:
+ *ppc_setup = kBfcpSetupActive;
+ return 0;
+ case tbfcp_setup_passive:
+ *ppc_setup = kBfcpSetupPassive;
+ return 0;
+ default:
+ TSK_DEBUG_ERROR("%d not valid BFCP setup", e_setup);
+ return -2;
+ }
+}
+
+int tbfcp_utils_parse_setup(const char* pc_setup, enum tbfcp_setup_e* pe_setup)
+{
+ if (!pc_setup || !pe_setup) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (tsk_striequals(pc_setup, kBfcpSetupActPass)) {
+ *pe_setup = tbfcp_setup_actpass;
+ return 0;
+ }
+ if (tsk_striequals(pc_setup, kBfcpSetupActive)) {
+ *pe_setup = tbfcp_setup_active;
+ return 0;
+ }
+ if (tsk_striequals(pc_setup, kBfcpSetupPassive)) {
+ *pe_setup = tbfcp_setup_passive;
+ return 0;
+ }
+ TSK_DEBUG_ERROR("%s not valid BFCP setup", pc_setup);
+ return -2;
+}
+
+int tbfcp_utils_is_role_acceptable(enum tbfcp_role_e e_role_local, enum tbfcp_role_e e_role_proposed, tsk_bool_t *pb_acceptable)
+{
+ if (!pb_acceptable) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ switch (e_role_local) {
+ case tbfcp_role_c_only:
+ *pb_acceptable = (e_role_proposed == tbfcp_role_s_only || e_role_proposed == tbfcp_role_c_s);
+ break;
+ case tbfcp_role_s_only:
+ *pb_acceptable = (e_role_proposed == tbfcp_role_c_only || e_role_proposed == tbfcp_role_c_s);
+ break;
+ case tbfcp_role_c_s:
+ *pb_acceptable = tsk_true;
+ break;
+ default:
+ *pb_acceptable = tsk_false;
+ break;
+ }
+ return 0;
+}
+
+int tbfcp_utils_is_setup_acceptable(enum tbfcp_setup_e e_setup_local, enum tbfcp_setup_e e_setup_proposed, tsk_bool_t *pb_acceptable)
+{
+ if (!pb_acceptable) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ switch (e_setup_local) {
+ case tbfcp_setup_active:
+ *pb_acceptable = (e_setup_proposed == tbfcp_setup_passive || e_setup_proposed == tbfcp_setup_actpass);
+ break;
+ case tbfcp_setup_passive:
+ *pb_acceptable = (e_setup_proposed == tbfcp_setup_active || e_setup_proposed == tbfcp_setup_actpass);
+ break;
+ case tbfcp_setup_actpass:
+ *pb_acceptable = tsk_true;
+ break;
+ default:
+ *pb_acceptable = tsk_false;
+ break;
+ }
+ return 0;
+}
+
+uint16_t tbfcp_utils_rand_u16()
+{
+ static long __rand = 0;
+ long num = tsk_atomic_inc(&__rand);
+ return ((num % 0xFF) << 8) | (tsk_time_epoch() % 0xFF);
+}
diff --git a/tinyBFCP/test/stdafx.c b/tinyBFCP/test/stdafx.c
new file mode 100644
index 0000000..68df985
--- /dev/null
+++ b/tinyBFCP/test/stdafx.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/tinyBFCP/test/stdafx.h b/tinyBFCP/test/stdafx.h
new file mode 100644
index 0000000..d747cb8
--- /dev/null
+++ b/tinyBFCP/test/stdafx.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TEST_TINYBFCP_STDAFX_H
+#define TEST_TINYBFCP_STDAFX_H
+
+#include "targetver.h"
+
+#include <stdio.h>
+
+#if (defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE)) && !defined(__SYMBIAN32__)
+#include <tchar.h>
+#endif
+
+// TODO: reference additional headers your program requires here
+#endif /* TEST_TINYHTTP_STDAFX_H */
diff --git a/tinyBFCP/test/targetver.h b/tinyBFCP/test/targetver.h
new file mode 100644
index 0000000..0bebc33
--- /dev/null
+++ b/tinyBFCP/test/targetver.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef _TEST_TINYBFCP_VER
+#define _TEST_TINYBFCP_VER
+
+#if (defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE)) && !defined(__SYMBIAN32__)
+// The following macros define the minimum required platform. The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
+// your application. The macros work by enabling all features available on platform versions up to and
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#endif
+
+#endif
diff --git a/tinyBFCP/test/test.c b/tinyBFCP/test/test.c
new file mode 100644
index 0000000..4ec5bdf
--- /dev/null
+++ b/tinyBFCP/test/test.c
@@ -0,0 +1,82 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "stdafx.h"
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "tinynet.h"
+#include "tsk.h"
+
+#define kConfId 1927375685
+#define kTransacId 32871
+#define kUserId 18177
+#define kFloorId 10665
+#define kFloorReqId 2
+#define kReqStatus 3 // Granted
+#define kQueuePosition 0
+#define kUserDisplayName "Mamadou DIOP"
+#define kUserUri "Mamadou DIOP@TEST.COM"
+#define kRemoteIP "192.168.0.28"
+#define kRemotePort 5060
+#define kLocalIP "192.168.0.37"
+#define kLocalPort 5060
+
+#define kNullOctetStringPtr 0
+
+#define BAIL_IF_ERR(expr) { int _ret_; if ((_ret_) = (expr)) { TSK_DEBUG_ERROR("Error %d", (_ret_)); goto bail; } }
+
+#define LOOP 0
+
+#define RUN_TEST_ALL 0
+#define RUN_TEST_PARSER 0
+#define RUN_TEST_SESSION 1
+
+#include "test_parser.h"
+#include "test_session.h"
+
+
+#ifdef _WIN32_WCE
+int _tmain(int argc, _TCHAR* argv[])
+#else
+int main()
+#endif
+{
+ tnet_startup();
+
+ do {
+ /* Print copyright information */
+ printf("Doubango Project\nCopyright (C) 2014 Mamadou Diop \n\n");
+
+#if RUN_TEST_PARSER || RUN_TEST_ALL
+ test_parser();
+#endif
+#if RUN_TEST_SESSION || RUN_TEST_ALL
+ test_session();
+#endif
+ }
+ while(LOOP);
+
+ tnet_cleanup();
+
+ getchar();
+
+ return 0;
+}
+
diff --git a/tinyBFCP/test/test.vcproj b/tinyBFCP/test/test.vcproj
new file mode 100644
index 0000000..4949dc7
--- /dev/null
+++ b/tinyBFCP/test/test.vcproj
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="test"
+ ProjectGUID="{3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}"
+ RootNamespace="test"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\thirdparties\win32\include;..\..\tinyBFCP\include;..\..\tinySAK\src;..\..\tinyNET\src"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(OutDir)\tinySAK.lib $(OutDir)\tinyBFCP.lib $(OutDir)\tinyNET.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\thirdparties\win32\include;..\..\tinyBFCP\include;..\..\tinySAK\src;..\..\tinyNET\src"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(OutDir)\tinySAK.lib $(OutDir)\tinyBFCP.lib $(OutDir)\tinyNET.lib"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\stdafx.c"
+ >
+ </File>
+ <File
+ RelativePath=".\test.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\targetver.h"
+ >
+ </File>
+ <File
+ RelativePath=".\test_parser.h"
+ >
+ </File>
+ <File
+ RelativePath=".\test_session.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tinyBFCP/test/test_parser.h b/tinyBFCP/test/test_parser.h
new file mode 100644
index 0000000..baf9603
--- /dev/null
+++ b/tinyBFCP/test/test_parser.h
@@ -0,0 +1,215 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TEST_TINYBFCP_PARSER_H
+#define TEST_TINYBFCP_PARSER_H
+
+#include "tinybfcp.h"
+
+#define SEND_BUFF(buff_ptr, buff_size) \
+ { \
+ struct sockaddr_storage addr_to; \
+ tnet_socket_t* socket = tnet_socket_create(kLocalIP, kLocalPort, tnet_socket_type_udp_ipv4); \
+ tnet_sockaddr_init(kRemoteIP, kRemotePort, tnet_socket_type_udp_ipv4, &addr_to); \
+ tnet_sockfd_sendto(socket->fd, (const struct sockaddr *)&addr_to, (buff_ptr), (buff_size)); \
+ TSK_OBJECT_SAFE_FREE(socket); \
+ } \
+
+
+uint8_t __parse_buff_write_ptr[1200];
+static const tsk_size_t __parse_buff_write_size = sizeof(__parse_buff_write_ptr)/sizeof(__parse_buff_write_ptr[0]);
+uint8_t __parse_buff_read_ptr[1200];
+static const tsk_size_t __parse_buff_read_size = sizeof(__parse_buff_read_ptr)/sizeof(__parse_buff_read_ptr[0]);
+
+static int test_parser_buff_cmp(const uint8_t* pc_buf1_ptr, tsk_size_t n_buff1_size, const uint8_t* pc_buf2_ptr, tsk_size_t n_buff2_size)
+{
+ int ret;
+ tsk_size_t u;
+ if (!pc_buf1_ptr || !pc_buf2_ptr || (n_buff1_size != n_buff2_size)) {
+ return -1;
+ }
+ for (u = 0; u < n_buff1_size; ++u) {
+ if ((ret = (pc_buf1_ptr[u] - pc_buf2_ptr[u]))) {
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int test_parser_add_user_info(tbfcp_pkt_t* p_pkt)
+{
+ tbfcp_attr_octetstring_t* p_attr = tsk_null;
+ if (!p_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ BAIL_IF_ERR(tbfcp_attr_octetstring_create(tbfcp_attribute_type_USER_DISPLAY_NAME, kBfcpFieldMNo, kUserDisplayName, tsk_strlen(kUserDisplayName), &p_attr));
+ BAIL_IF_ERR(tbfcp_pkt_add_attr(p_pkt, (tbfcp_attr_t**)&p_attr));
+ BAIL_IF_ERR(tbfcp_attr_octetstring_create(tbfcp_attribute_type_USER_URI, kBfcpFieldMNo, kUserUri, tsk_strlen(kUserUri), &p_attr));
+ BAIL_IF_ERR(tbfcp_pkt_add_attr(p_pkt, (tbfcp_attr_t**)&p_attr));
+ return 0;
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_attr);
+ return -1;
+}
+
+static void test_parser_Hello()
+{
+ tbfcp_pkt_t* p_pkt = tsk_null;
+ tsk_size_t n_written_bytes, n_read_bytes;
+
+ (n_read_bytes);
+
+ BAIL_IF_ERR(tbfcp_pkt_create_Hello(kConfId, kTransacId, kUserId, &p_pkt));
+ BAIL_IF_ERR(test_parser_add_user_info(p_pkt));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_write_ptr, __parse_buff_write_size, &n_written_bytes));
+ //SEND_BUFF(__parse_buff_write_ptr, n_written_bytes);
+
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ BAIL_IF_ERR(tbfcp_pkt_read(__parse_buff_write_ptr, n_written_bytes, &p_pkt));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_read_ptr, __parse_buff_read_size, &n_read_bytes));
+ //SEND_BUFF(__parse_buff_read_ptr, n_read_bytes);
+
+ BAIL_IF_ERR(test_parser_buff_cmp(__parse_buff_write_ptr, n_written_bytes, __parse_buff_read_ptr, n_read_bytes));
+ TSK_DEBUG_INFO("test_parser_Hello...OK");
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+}
+
+static void test_parser_HelloAck()
+{
+ tbfcp_pkt_t* p_pkt = tsk_null;
+ tsk_size_t n_written_bytes, n_read_bytes;
+
+ (n_read_bytes);
+
+ BAIL_IF_ERR(tbfcp_pkt_create_HelloAck_2(kConfId, kTransacId, kUserId, &p_pkt));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_write_ptr, __parse_buff_write_size, &n_written_bytes));
+ //SEND_BUFF(__parse_buff_write_ptr, n_written_bytes);
+
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ BAIL_IF_ERR(tbfcp_pkt_read(__parse_buff_write_ptr, n_written_bytes, &p_pkt));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_read_ptr, __parse_buff_read_size, &n_read_bytes));
+ //SEND_BUFF(__parse_buff_read_ptr, n_read_bytes);
+
+ BAIL_IF_ERR(test_parser_buff_cmp(__parse_buff_write_ptr, n_written_bytes, __parse_buff_read_ptr, n_read_bytes));
+ TSK_DEBUG_INFO("test_parser_HelloAck...OK");
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+}
+
+static void test_parser_FloorRequest()
+{
+ tbfcp_pkt_t* p_pkt = tsk_null;
+ tsk_size_t n_written_bytes, n_read_bytes;
+
+ (n_read_bytes);
+
+ BAIL_IF_ERR(tbfcp_pkt_create_FloorRequest_2(kConfId, kTransacId, kUserId, kFloorId, &p_pkt));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_write_ptr, __parse_buff_write_size, &n_written_bytes));
+ //SEND_BUFF(__parse_buff_write_ptr, n_written_bytes);
+
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ BAIL_IF_ERR(tbfcp_pkt_read(__parse_buff_write_ptr, n_written_bytes, &p_pkt));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_read_ptr, __parse_buff_read_size, &n_read_bytes));
+ //SEND_BUFF(__parse_buff_read_ptr, n_read_bytes);
+
+ BAIL_IF_ERR(test_parser_buff_cmp(__parse_buff_write_ptr, n_written_bytes, __parse_buff_read_ptr, n_read_bytes));
+ TSK_DEBUG_INFO("test_parser_FloorRequest...OK");
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+}
+
+static void test_parser_FloorRequestStatus()
+{
+ tbfcp_pkt_t* p_pkt = tsk_null;
+ tbfcp_attr_grouped_t* p_floor_req_info = tsk_null;
+ tbfcp_attr_grouped_t* p_overal_req_status = tsk_null;
+ tbfcp_attr_octetstring16_t* p_req_status = tsk_null;
+ tbfcp_attr_grouped_t* p_floor_req_status = tsk_null;
+ tsk_size_t n_written_bytes, n_read_bytes;
+ static uint8_t ReqStatusOctesString16[2] = { kReqStatus, kQueuePosition };
+
+ (n_read_bytes);
+
+ // PKT$FLOOR_REQUEST_INFORMATION"OVERALL_REQUEST_STATUS'REQUEST_STATUS',FLOOR_REQUEST_STATUS"$
+
+ BAIL_IF_ERR(tbfcp_pkt_create_FloorRequestStatus(kConfId, kTransacId, kUserId, &p_pkt));
+ BAIL_IF_ERR(tbfcp_attr_grouped_create_u16(tbfcp_attribute_type_FLOOR_REQUEST_INFORMATION, kBfcpFieldMNo, kFloorReqId, &p_floor_req_info));
+ BAIL_IF_ERR(tbfcp_attr_grouped_create_u16(tbfcp_attribute_type_OVERALL_REQUEST_STATUS, kBfcpFieldMNo, kFloorReqId, &p_overal_req_status));
+ BAIL_IF_ERR(tbfcp_attr_octetstring16_create(tbfcp_attribute_type_REQUEST_STATUS, kBfcpFieldMNo, ReqStatusOctesString16, &p_req_status));
+ BAIL_IF_ERR(tbfcp_attr_grouped_add_attr(p_overal_req_status, (tbfcp_attr_t**)&p_req_status));
+ BAIL_IF_ERR(tbfcp_attr_grouped_add_attr(p_floor_req_info,(tbfcp_attr_t**) &p_overal_req_status));
+ BAIL_IF_ERR(tbfcp_attr_grouped_create_u16(tbfcp_attribute_type_FLOOR_REQUEST_STATUS, kBfcpFieldMNo, kFloorId, &p_floor_req_status));
+ BAIL_IF_ERR(tbfcp_attr_grouped_add_attr(p_floor_req_info, (tbfcp_attr_t**)&p_floor_req_status));
+ BAIL_IF_ERR(tbfcp_pkt_add_attr(p_pkt, (tbfcp_attr_t**)&p_floor_req_info));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_write_ptr, __parse_buff_write_size, &n_written_bytes));
+ //SEND_BUFF(__parse_buff_write_ptr, n_written_bytes);
+
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ BAIL_IF_ERR(tbfcp_pkt_read(__parse_buff_write_ptr, n_written_bytes, &p_pkt));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_read_ptr, __parse_buff_read_size, &n_read_bytes));
+ //SEND_BUFF(__parse_buff_read_ptr, n_read_bytes);
+
+ BAIL_IF_ERR(test_parser_buff_cmp(__parse_buff_write_ptr, n_written_bytes, __parse_buff_read_ptr, n_read_bytes));
+ TSK_DEBUG_INFO("test_parser_FloorRequestStatus...OK");
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ TSK_OBJECT_SAFE_FREE(p_floor_req_info);
+ TSK_OBJECT_SAFE_FREE(p_overal_req_status);
+ TSK_OBJECT_SAFE_FREE(p_req_status);
+ TSK_OBJECT_SAFE_FREE(p_floor_req_status);
+}
+
+static void test_parser_FloorRelease()
+{
+ tbfcp_pkt_t* p_pkt = tsk_null;
+ tsk_size_t n_written_bytes, n_read_bytes;
+
+ BAIL_IF_ERR(tbfcp_pkt_create_FloorRelease_2(kConfId, kTransacId, kUserId, kFloorReqId, &p_pkt));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_write_ptr, __parse_buff_write_size, &n_written_bytes));
+ //SEND_BUFF(__parse_buff_write_ptr, n_written_bytes);
+
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ BAIL_IF_ERR(tbfcp_pkt_read(__parse_buff_write_ptr, n_written_bytes, &p_pkt));
+ BAIL_IF_ERR(tbfcp_pkt_write_with_padding(p_pkt, __parse_buff_read_ptr, __parse_buff_read_size, &n_read_bytes));
+ //SEND_BUFF(__parse_buff_read_ptr, n_read_bytes);
+
+ BAIL_IF_ERR(test_parser_buff_cmp(__parse_buff_write_ptr, n_written_bytes, __parse_buff_read_ptr, n_read_bytes));
+ TSK_DEBUG_INFO("test_parser_FloorRelease...OK");
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+}
+
+static void test_parser()
+{
+ test_parser_Hello();
+ test_parser_HelloAck();
+ test_parser_FloorRequest();
+ test_parser_FloorRequestStatus();
+ test_parser_FloorRelease();
+}
+
+#endif /* TEST_TINYBFCP_PARSER_H */
diff --git a/tinyBFCP/test/test_session.h b/tinyBFCP/test/test_session.h
new file mode 100644
index 0000000..0ec239c
--- /dev/null
+++ b/tinyBFCP/test/test_session.h
@@ -0,0 +1,62 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TEST_TINYBFCP_SESSION_H
+#define TEST_TINYBFCP_SESSION_H
+
+#include "tinybfcp.h"
+
+static void test_session_tcp()
+{
+}
+
+static void test_session_udp()
+{
+ struct tbfcp_session_s* p_session = tsk_null;
+ tbfcp_pkt_t* p_pkt = tsk_null;
+
+ BAIL_IF_ERR(tbfcp_session_create(tnet_socket_type_udp_ipv4, kLocalIP, &p_session));
+ BAIL_IF_ERR(tbfcp_session_set_remote(p_session, kRemoteIP, kRemotePort));
+ BAIL_IF_ERR(tbfcp_session_prepare(p_session));
+ BAIL_IF_ERR(tbfcp_session_start(p_session));
+ TSK_DEBUG_INFO("PRESS ENTER to continue");
+ getchar();
+
+ BAIL_IF_ERR(tbfcp_pkt_create_FloorRequest_2(kConfId, kTransacId, kUserId, kFloorId, &p_pkt));
+ BAIL_IF_ERR(tbfcp_session_send_pkt(p_session, p_pkt));
+ TSK_DEBUG_INFO("PRESS ENTER to continue");
+ getchar();
+
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ BAIL_IF_ERR(tbfcp_pkt_create_Hello(kConfId, kTransacId, kUserId, &p_pkt));
+ BAIL_IF_ERR(tbfcp_session_send_pkt(p_session, p_pkt));
+ TSK_DEBUG_INFO("PRESS ENTER to continue");
+ getchar();
+
+bail:
+ TSK_OBJECT_SAFE_FREE(p_pkt);
+ TSK_OBJECT_SAFE_FREE(p_session);
+}
+
+static void test_session()
+{
+ test_session_tcp();
+ test_session_udp();
+}
+
+#endif /* TEST_TINYBFCP_SESSION_H */
diff --git a/tinyBFCP/tinyBFCP.pc.in b/tinyBFCP/tinyBFCP.pc.in
new file mode 100644
index 0000000..37d4117
--- /dev/null
+++ b/tinyBFCP/tinyBFCP.pc.in
@@ -0,0 +1,15 @@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+Name : libtinyBFCP
+Description : Doubango Telecom tinyBFCP (BFCP protocol) library
+Version : @PACKAGE_VERSION@
+Requires:
+Requires.private: tinySAK = @PACKAGE_VERSION@ tinyNET = @PACKAGE_VERSION@
+Conflicts:
+Cflags : -I${includedir}/tinybfcp
+Libs : -L${libdir} -ltinyBFCP
+Libs.private:
+
diff --git a/tinyBFCP/tinyBFCP.sln b/tinyBFCP/tinyBFCP.sln
new file mode 100644
index 0000000..06ce19e
--- /dev/null
+++ b/tinyBFCP/tinyBFCP.sln
@@ -0,0 +1,68 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyBFCP", "tinyBFCP.vcproj", "{78605D89-4D51-41AC-AFE2-061B4CAB81F1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7522A458-92F4-4259-B906-E84C2A65D9F1} = {7522A458-92F4-4259-B906-E84C2A65D9F1}
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA} = {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcproj", "{3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7522A458-92F4-4259-B906-E84C2A65D9F1} = {7522A458-92F4-4259-B906-E84C2A65D9F1}
+ {78605D89-4D51-41AC-AFE2-061B4CAB81F1} = {78605D89-4D51-41AC-AFE2-061B4CAB81F1}
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA} = {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinySAK", "..\tinySAK\tinySAK.vcproj", "{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyNET", "..\tinyNET\tinyNET.vcproj", "{7522A458-92F4-4259-B906-E84C2A65D9F1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA} = {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Static_Debug|Win32 = Static_Debug|Win32
+ Static_Release|Win32 = Static_Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {78605D89-4D51-41AC-AFE2-061B4CAB81F1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {78605D89-4D51-41AC-AFE2-061B4CAB81F1}.Debug|Win32.Build.0 = Debug|Win32
+ {78605D89-4D51-41AC-AFE2-061B4CAB81F1}.Release|Win32.ActiveCfg = Release|Win32
+ {78605D89-4D51-41AC-AFE2-061B4CAB81F1}.Release|Win32.Build.0 = Release|Win32
+ {78605D89-4D51-41AC-AFE2-061B4CAB81F1}.Static_Debug|Win32.ActiveCfg = Debug|Win32
+ {78605D89-4D51-41AC-AFE2-061B4CAB81F1}.Static_Debug|Win32.Build.0 = Debug|Win32
+ {78605D89-4D51-41AC-AFE2-061B4CAB81F1}.Static_Release|Win32.ActiveCfg = Release|Win32
+ {78605D89-4D51-41AC-AFE2-061B4CAB81F1}.Static_Release|Win32.Build.0 = Release|Win32
+ {3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}.Debug|Win32.Build.0 = Debug|Win32
+ {3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}.Release|Win32.ActiveCfg = Release|Win32
+ {3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}.Release|Win32.Build.0 = Release|Win32
+ {3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}.Static_Debug|Win32.ActiveCfg = Debug|Win32
+ {3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}.Static_Debug|Win32.Build.0 = Debug|Win32
+ {3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}.Static_Release|Win32.ActiveCfg = Release|Win32
+ {3FC1411B-9B7E-4078-9BD5-70EB663ECF5F}.Static_Release|Win32.Build.0 = Release|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Win32.Build.0 = Debug|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Win32.ActiveCfg = Release|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Win32.Build.0 = Release|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Static_Debug|Win32.ActiveCfg = Static_Debug|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Static_Debug|Win32.Build.0 = Static_Debug|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Static_Release|Win32.ActiveCfg = Static_Release|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Static_Release|Win32.Build.0 = Static_Release|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Debug|Win32.Build.0 = Debug|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Release|Win32.ActiveCfg = Release|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Release|Win32.Build.0 = Release|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Static_Debug|Win32.ActiveCfg = Debug|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Static_Debug|Win32.Build.0 = Debug|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Static_Release|Win32.ActiveCfg = Release|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Static_Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tinyBFCP/tinyBFCP.vcproj b/tinyBFCP/tinyBFCP.vcproj
new file mode 100644
index 0000000..86f9605
--- /dev/null
+++ b/tinyBFCP/tinyBFCP.vcproj
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="tinyBFCP"
+ ProjectGUID="{78605D89-4D51-41AC-AFE2-061B4CAB81F1}"
+ RootNamespace="tinyBFCP"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\thirdparties\win32\include;..\tinyBFCP\include;..\tinySAK\src;..\tinyNET\src"
+ PreprocessorDefinitions="DEBUG_LEVEL=DEBUG_LEVEL_INFO;WIN32;_WIN32_WINNT=0x0501;_DEBUG;_WINDOWS;_USRDLL;TINYBFCP_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(OutDir)\tinySAK.lib $(OutDir)\tinyNET.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\thirdparties\win32\include;..\tinyBFCP\include;..\tinySAK\src;..\tinyNET\src"
+ PreprocessorDefinitions="_WIN32_WINNT=0x0501;WIN32;NDEBUG;_WINDOWS;_USRDLL;TINYBFCP_EXPORTS"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="0"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(OutDir)\tinySAK.lib $(OutDir)\tinyNET.lib"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="source(*.c)"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\src\tbfcp_attr.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tbfcp_pkt.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tbfcp_session.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tbfcp_utils.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="include(*.h)"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\include\tinybfcp\tbfcp_attr.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinybfcp\tbfcp_pkt.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinybfcp\tbfcp_session.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinybfcp\tbfcp_types.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinybfcp\tbfcp_utils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinybfcp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinybfcp_config.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="resources(*.rc)"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\version.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tinyBFCP/version.rc b/tinyBFCP/version.rc
new file mode 100644
index 0000000..fd931a5
--- /dev/null
+++ b/tinyBFCP/version.rc
@@ -0,0 +1,102 @@
+// Microsoft Visual C++ generated resource script.
+//
+// #include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 2.0.0.1156
+ PRODUCTVERSION 2.0.0.1156
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Doubango telecom"
+ VALUE "FileDescription", "Doubango IMS Framework"
+ VALUE "FileVersion", "2.0.0.1156"
+ VALUE "InternalName", "tinyhttp.dll"
+ VALUE "LegalCopyright", "(c) 2010-2014 Doubango Telecom. All rights reserved."
+ VALUE "OriginalFilename", "tinybfcp.dll"
+ VALUE "ProductName", "Doubango IMS Framework"
+ VALUE "ProductVersion", "2.0.0.1156"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
OpenPOWER on IntegriCloud