BFCP episode #4

This commit is contained in:
bossiel 2014-04-25 03:23:23 +00:00
parent 50cc03eb04
commit 4ad4ed6cbe
6 changed files with 548 additions and 28 deletions

View File

@ -25,15 +25,24 @@
TBFCP_BEGIN_DECLS
struct tbfcp_session_s;
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_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_remote(struct tbfcp_session_s* p_self, const char* pc_ip, tnet_port_t u_port);
TINYBFCP_API int tbfcp_session_set_natt_ctx(struct tbfcp_session_s* p_self, struct tnet_nat_context_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_profile_2(enum tnet_socket_type_e e_socket_type, 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_send_pkt(struct tbfcp_session_s* p_self, const struct tbfcp_pkt_s* pc_pkt);
TBFCP_END_DECLS

View File

@ -66,7 +66,7 @@ TBFCP_BEGIN_DECLS
#endif /* kBfcpProfileDTLS */
#if !defined(kBfcpTransportDefault)
# define kBfcpTransportDefault tnet_socket_type_tcp_ipv4
# define kBfcpTransportDefault tnet_socket_type_udp_ipv4
#endif /* kBfcpTransportDefault */
#if !defined(kBfcpTransportFriendlyName)
@ -78,6 +78,43 @@ TBFCP_BEGIN_DECLS
#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 |

View File

@ -0,0 +1,41 @@
/* 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
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 */

View File

@ -18,7 +18,7 @@
*/
#include "tinybfcp/tbfcp_session.h"
#include "tinybfcp/tbfcp_pkt.h"
#include "tinybfcp/tbfcp_types.h"
#include "tinybfcp/tbfcp_utils.h"
#include "tsk_time.h"
#include "tsk_timer.h"
@ -34,6 +34,20 @@ typedef struct tbfcp_session_s {
tsk_bool_t b_stopping;
tsk_bool_t b_prepared;
// 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;
@ -45,6 +59,7 @@ typedef struct tbfcp_session_s {
tnet_port_t u_remote_port;
struct sockaddr_storage remote_addr;
struct tnet_nat_context_s* p_natt_ctx;
struct tnet_ice_ctx_s* p_ice_ctx;
struct tnet_transport_s* p_transport;
@ -71,10 +86,15 @@ typedef enum _bfcp_timer_type_e {
}
_bfcp_timer_type_t;
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_cb(const tnet_transport_event_t* e);
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);
int tbfcp_session_create(tnet_socket_type_t e_socket_type, const char* pc_local_ip, tbfcp_session_t** pp_self)
{
@ -178,7 +198,7 @@ int tbfcp_session_prepare(tbfcp_session_t* p_self)
return -3;
}
// set transport callback
if ((ret = tnet_transport_set_callback(p_self->p_transport, _tbfcp_session_transport_layer_cb, p_self))) {
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;
@ -245,6 +265,10 @@ int tbfcp_session_start(tbfcp_session_t* p_self)
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))) {
@ -254,12 +278,38 @@ int tbfcp_session_start(tbfcp_session_t* p_self)
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;
@ -307,7 +357,18 @@ bail:
return ret;
}
int tbfcp_session_set_remote(tbfcp_session_t* p_self, const char* pc_ip, tnet_port_t u_port)
int tbfcp_session_set_natt_ctx(tbfcp_session_t* p_self, struct tnet_nat_context_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");
@ -319,41 +380,94 @@ int tbfcp_session_set_remote(tbfcp_session_t* p_self, const char* pc_ip, tnet_po
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_session_get_profile_2(pc_self->e_socket_type, ppc_profile);
return tbfcp_utils_get_profile(pc_self->e_socket_type, ppc_profile);
}
int tbfcp_session_get_profile_2(enum tnet_socket_type_e e_socket_type, const char** ppc_profile)
int tbfcp_session_get_local_role(const tbfcp_session_t* pc_self, enum tbfcp_role_e *pe_role_local)
{
if (!ppc_profile) {
if (!pc_self || !pe_role_local) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
*pe_role_local = pc_self->e_role_local;
return 0;
}
if (TNET_SOCKET_TYPE_IS_DTLS(e_socket_type)) {
*ppc_profile = kBfcpProfileDTLS;
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;
}
if (TNET_SOCKET_TYPE_IS_UDP(e_socket_type)) {
*ppc_profile = kBfcpProfileUDP;
return 0;
*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;
}
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;
*ppc_ip = pc_self->p_local_public_ip;
*pu_port = pc_self->u_local_public_port;
return 0;
}
static int _tbfcp_session_send_buff(tbfcp_session_t* p_self, const void* pc_buff_ptr, tsk_size_t u_buff_size)
@ -436,6 +550,97 @@ bail:
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:
break;
}
// FIXME
_tbfcp_session_send_FloorRequest(p_self);
_tbfcp_session_send_FloorRequest(p_self);
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)
{
@ -514,9 +719,37 @@ static int _tbfcp_session_timer_callback(const void* pc_arg, tsk_timer_id_t time
return 0;
}
static int _tbfcp_session_transport_layer_cb(const tnet_transport_event_t* e)
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;
return 0;
}
@ -533,6 +766,8 @@ static tsk_object_t* tbfcp_session_ctor(tsk_object_t * self, va_list * app)
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;
@ -552,6 +787,7 @@ static tsk_object_t* tbfcp_session_dtor(tsk_object_t * self)
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_safeobj_deinit(p_session);

View File

@ -0,0 +1,189 @@
/* 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()
{
return (rand() ^ rand()) % 0xFFFF;
}

View File

@ -190,6 +190,10 @@
RelativePath=".\src\tbfcp_session.c"
>
</File>
<File
RelativePath=".\src\tbfcp_utils.c"
>
</File>
</Filter>
<Filter
Name="include(*.h)"
@ -212,6 +216,10 @@
RelativePath=".\include\tinybfcp\tbfcp_types.h"
>
</File>
<File
RelativePath=".\include\tinybfcp\tbfcp_utils.h"
>
</File>
<File
RelativePath=".\include\tinybfcp.h"
>