void NicerConnection::initializeGlobals() { std::lock_guard<std::mutex> guard(nicer_initialization_mutex); if (!nicer_initialized) { nicer_initialized = true; NR_reg_init(NR_REG_MODE_LOCAL); nr_crypto_openssl_set(); // Set the priorites for candidate type preferences. // These numbers come from RFC 5245 S. 4.1.2.2 NR_reg_set_uchar(const_cast<char *>(NR_ICE_REG_PREF_TYPE_SRV_RFLX), 100); NR_reg_set_uchar(const_cast<char *>(NR_ICE_REG_PREF_TYPE_PEER_RFLX), 110); NR_reg_set_uchar(const_cast<char *>(NR_ICE_REG_PREF_TYPE_HOST), 126); NR_reg_set_uchar(const_cast<char *>(NR_ICE_REG_PREF_TYPE_RELAYED), 5); NR_reg_set_uchar(const_cast<char *>(NR_ICE_REG_PREF_TYPE_RELAYED_TCP), 0); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.rl0"), 255); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.wi0"), 254); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.lo0"), 253); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.en1"), 252); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.en0"), 251); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.eth0"), 252); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.eth1"), 251); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.eth2"), 249); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.ppp"), 250); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.ppp0"), 249); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.en2"), 248); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.en3"), 247); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.em0"), 251); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.em1"), 252); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.vmnet0"), 240); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.vmnet1"), 241); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.vmnet3"), 239); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.vmnet4"), 238); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.vmnet5"), 237); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.vmnet6"), 236); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.vmnet7"), 235); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.vmnet8"), 234); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.virbr0"), 233); NR_reg_set_uchar(const_cast<char *>("ice.pref.interface.wlan0"), 232); NR_reg_set_uint4(const_cast<char *>("stun.client.maximum_transmits"), 7); NR_reg_set_uint4(const_cast<char *>(NR_ICE_REG_TRICKLE_GRACE_PERIOD), 5000); NR_reg_set_char(const_cast<char *>(NR_ICE_REG_ICE_TCP_DISABLE), true); NR_reg_set_char(const_cast<char *>(NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS), 1); } }
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name, bool offerer, bool set_interface_priorities) { RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer); // Initialize the crypto callbacks if (!initialized) { NR_reg_init(NR_REG_MODE_LOCAL); nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl; initialized = true; // Set the priorites for candidate type preferences NR_reg_set_uchar((char *)"ice.pref.type.srv_rflx",100); NR_reg_set_uchar((char *)"ice.pref.type.peer_rflx",105); NR_reg_set_uchar((char *)"ice.pref.type.prflx",99); NR_reg_set_uchar((char *)"ice.pref.type.host",125); NR_reg_set_uchar((char *)"ice.pref.type.relayed",126); if (set_interface_priorities) { NR_reg_set_uchar((char *)"ice.pref.interface.rl0", 255); NR_reg_set_uchar((char *)"ice.pref.interface.wi0", 254); NR_reg_set_uchar((char *)"ice.pref.interface.lo0", 253); NR_reg_set_uchar((char *)"ice.pref.interface.en1", 252); NR_reg_set_uchar((char *)"ice.pref.interface.en0", 251); NR_reg_set_uchar((char *)"ice.pref.interface.eth0", 252); NR_reg_set_uchar((char *)"ice.pref.interface.eth1", 251); NR_reg_set_uchar((char *)"ice.pref.interface.eth2", 249); NR_reg_set_uchar((char *)"ice.pref.interface.ppp", 250); NR_reg_set_uchar((char *)"ice.pref.interface.ppp0", 249); NR_reg_set_uchar((char *)"ice.pref.interface.en2", 248); NR_reg_set_uchar((char *)"ice.pref.interface.en3", 247); NR_reg_set_uchar((char *)"ice.pref.interface.em0", 251); NR_reg_set_uchar((char *)"ice.pref.interface.em1", 252); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet0", 240); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet1", 241); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet3", 239); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet4", 238); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet5", 237); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet6", 236); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet7", 235); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet8", 234); NR_reg_set_uchar((char *)"ice.pref.interface.virbr0", 233); NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232); } NR_reg_set_uint4((char *)"stun.client.maximum_transmits",4); } // Create the ICE context int r; UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER: NR_ICE_CTX_FLAGS_ANSWERER; flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION; r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags, &ctx->ctx_); if (r) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create ICE ctx for '" << name << "'"); return nullptr; } // Create the handler objects ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl(); ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair; ctx->ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready; ctx->ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed; ctx->ice_handler_vtbl_->ice_completed = &NrIceCtx::ice_completed; ctx->ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd; ctx->ice_handler_ = new nr_ice_handler(); ctx->ice_handler_->vtbl = ctx->ice_handler_vtbl_; ctx->ice_handler_->obj = ctx; // Create the peer ctx. Because we do not support parallel forking, we // only have one peer ctx. std::string peer_name = name + ":default"; r = nr_ice_peer_ctx_create(ctx->ctx_, ctx->ice_handler_, const_cast<char *>(peer_name.c_str()), &ctx->peer_); if (r) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create ICE peer ctx for '" << name << "'"); return nullptr; } nsresult rv; ctx->sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); if (!NS_SUCCEEDED(rv)) return nullptr; return ctx; }
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name, bool offerer, bool allow_loopback, bool tcp_enabled, bool allow_link_local, bool hide_non_default, Policy policy) { RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer, policy); // Initialize the crypto callbacks and logging stuff if (!initialized) { NR_reg_init(NR_REG_MODE_LOCAL); nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl; initialized = true; // Set the priorites for candidate type preferences. // These numbers come from RFC 5245 S. 4.1.2.2 NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX, 100); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX, 110); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST, 126); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED, 5); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX_TCP, 99); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX_TCP, 109); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST_TCP, 125); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED_TCP, 0); int32_t stun_client_maximum_transmits = 7; int32_t ice_trickle_grace_period = 5000; int32_t ice_tcp_so_sock_count = 3; int32_t ice_tcp_listen_backlog = 10; nsAutoCString force_net_interface; #ifndef MOZILLA_XPCOMRT_API nsresult res; nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &res); if (NS_SUCCEEDED(res)) { nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs); if (branch) { branch->GetIntPref( "media.peerconnection.ice.stun_client_maximum_transmits", &stun_client_maximum_transmits); branch->GetIntPref( "media.peerconnection.ice.trickle_grace_period", &ice_trickle_grace_period); branch->GetIntPref( "media.peerconnection.ice.tcp_so_sock_count", &ice_tcp_so_sock_count); branch->GetIntPref( "media.peerconnection.ice.tcp_listen_backlog", &ice_tcp_listen_backlog); branch->GetCharPref( "media.peerconnection.ice.force_interface", getter_Copies(force_net_interface)); } } #endif NR_reg_set_uint4((char *)"stun.client.maximum_transmits", stun_client_maximum_transmits); NR_reg_set_uint4((char *)NR_ICE_REG_TRICKLE_GRACE_PERIOD, ice_trickle_grace_period); NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT, ice_tcp_so_sock_count); NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG, ice_tcp_listen_backlog); NR_reg_set_char((char *)NR_ICE_REG_ICE_TCP_DISABLE, !tcp_enabled); if (allow_loopback) { NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1); } if (allow_link_local) { NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1); } if (force_net_interface.Length() > 0) { // Stupid cast.... but needed const nsCString& flat = PromiseFlatCString(static_cast<nsACString&>(force_net_interface)); NR_reg_set_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, const_cast<char*>(flat.get())); } } // Create the ICE context int r; UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER: NR_ICE_CTX_FLAGS_ANSWERER; flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION; if (policy == ICE_POLICY_RELAY) { flags |= NR_ICE_CTX_FLAGS_RELAY_ONLY; } if (hide_non_default) flags |= NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS; r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags, &ctx->ctx_); if (r) { MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name << "'"); return nullptr; } nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer(); if (!prioritizer) { MOZ_MTLOG(LogLevel::Error, "Couldn't create interface prioritizer."); return nullptr; } r = nr_ice_ctx_set_interface_prioritizer(ctx->ctx_, prioritizer); if (r) { MOZ_MTLOG(LogLevel::Error, "Couldn't set interface prioritizer."); return nullptr; } if (ctx->generating_trickle()) { r = nr_ice_ctx_set_trickle_cb(ctx->ctx_, &NrIceCtx::trickle_cb, ctx); if (r) { MOZ_MTLOG(ML_ERROR, "Couldn't set trickle cb for '" << name << "'"); return nullptr; } } // Create the handler objects ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl(); ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair; ctx->ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready; ctx->ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed; ctx->ice_handler_vtbl_->ice_completed = &NrIceCtx::ice_completed; ctx->ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd; ctx->ice_handler_vtbl_->ice_checking = &NrIceCtx::ice_checking; ctx->ice_handler_ = new nr_ice_handler(); ctx->ice_handler_->vtbl = ctx->ice_handler_vtbl_; ctx->ice_handler_->obj = ctx; // Create the peer ctx. Because we do not support parallel forking, we // only have one peer ctx. std::string peer_name = name + ":default"; r = nr_ice_peer_ctx_create(ctx->ctx_, ctx->ice_handler_, const_cast<char *>(peer_name.c_str()), &ctx->peer_); if (r) { MOZ_MTLOG(ML_ERROR, "Couldn't create ICE peer ctx for '" << name << "'"); return nullptr; } nsresult rv; ctx->sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); if (!NS_SUCCEEDED(rv)) return nullptr; return ctx; }
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name, bool offerer, bool set_interface_priorities, bool allow_loopback) { RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer); // Initialize the crypto callbacks and logging stuff if (!initialized) { NR_reg_init(NR_REG_MODE_LOCAL); RLogRingBuffer::CreateInstance(); nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl; initialized = true; // Set the priorites for candidate type preferences. // These numbers come from RFC 5245 S. 4.1.2.2 NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX, 100); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX, 110); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST, 126); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED, 5); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED_TCP, 0); if (set_interface_priorities) { NR_reg_set_uchar((char *)"ice.pref.interface.rl0", 255); NR_reg_set_uchar((char *)"ice.pref.interface.wi0", 254); NR_reg_set_uchar((char *)"ice.pref.interface.lo0", 253); NR_reg_set_uchar((char *)"ice.pref.interface.en1", 252); NR_reg_set_uchar((char *)"ice.pref.interface.en0", 251); NR_reg_set_uchar((char *)"ice.pref.interface.eth0", 252); NR_reg_set_uchar((char *)"ice.pref.interface.eth1", 251); NR_reg_set_uchar((char *)"ice.pref.interface.eth2", 249); NR_reg_set_uchar((char *)"ice.pref.interface.ppp", 250); NR_reg_set_uchar((char *)"ice.pref.interface.ppp0", 249); NR_reg_set_uchar((char *)"ice.pref.interface.en2", 248); NR_reg_set_uchar((char *)"ice.pref.interface.en3", 247); NR_reg_set_uchar((char *)"ice.pref.interface.em0", 251); NR_reg_set_uchar((char *)"ice.pref.interface.em1", 252); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet0", 240); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet1", 241); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet3", 239); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet4", 238); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet5", 237); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet6", 236); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet7", 235); NR_reg_set_uchar((char *)"ice.pref.interface.vmnet8", 234); NR_reg_set_uchar((char *)"ice.pref.interface.virbr0", 233); NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232); } NR_reg_set_uint4((char *)"stun.client.maximum_transmits",7); NR_reg_set_uint4((char *)NR_ICE_REG_TRICKLE_GRACE_PERIOD, 5000); if (allow_loopback) { NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1); } } // Create the ICE context int r; UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER: NR_ICE_CTX_FLAGS_ANSWERER; flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION; r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags, &ctx->ctx_); if (r) { MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name << "'"); return nullptr; } #ifdef USE_INTERFACE_PRIORITIZER nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer(); if (!prioritizer) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create interface prioritizer."); return nullptr; } r = nr_ice_ctx_set_interface_prioritizer(ctx->ctx_, prioritizer); if (r) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set interface prioritizer."); return nullptr; } #endif // USE_INTERFACE_PRIORITIZER if (ctx->generating_trickle()) { r = nr_ice_ctx_set_trickle_cb(ctx->ctx_, &NrIceCtx::trickle_cb, ctx); if (r) { MOZ_MTLOG(ML_ERROR, "Couldn't set trickle cb for '" << name << "'"); return nullptr; } } // Create the handler objects ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl(); ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair; ctx->ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready; ctx->ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed; ctx->ice_handler_vtbl_->ice_completed = &NrIceCtx::ice_completed; ctx->ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd; ctx->ice_handler_vtbl_->ice_checking = &NrIceCtx::ice_checking; ctx->ice_handler_ = new nr_ice_handler(); ctx->ice_handler_->vtbl = ctx->ice_handler_vtbl_; ctx->ice_handler_->obj = ctx; // Create the peer ctx. Because we do not support parallel forking, we // only have one peer ctx. std::string peer_name = name + ":default"; r = nr_ice_peer_ctx_create(ctx->ctx_, ctx->ice_handler_, const_cast<char *>(peer_name.c_str()), &ctx->peer_); if (r) { MOZ_MTLOG(ML_ERROR, "Couldn't create ICE peer ctx for '" << name << "'"); return nullptr; } nsresult rv; ctx->sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); if (!NS_SUCCEEDED(rv)) return nullptr; return ctx; }
void NrIceCtx::InitializeGlobals(bool allow_loopback, bool tcp_enabled, bool allow_link_local) { // Initialize the crypto callbacks and logging stuff if (!initialized) { NR_reg_init(NR_REG_MODE_LOCAL); nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl; initialized = true; // Set the priorites for candidate type preferences. // These numbers come from RFC 5245 S. 4.1.2.2 NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX, 100); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX, 110); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST, 126); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED, 5); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX_TCP, 99); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX_TCP, 109); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST_TCP, 125); NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED_TCP, 0); int32_t stun_client_maximum_transmits = 7; int32_t ice_trickle_grace_period = 5000; int32_t ice_tcp_so_sock_count = 3; int32_t ice_tcp_listen_backlog = 10; nsAutoCString force_net_interface; nsresult res; nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &res); if (NS_SUCCEEDED(res)) { nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs); if (branch) { branch->GetIntPref( "media.peerconnection.ice.stun_client_maximum_transmits", &stun_client_maximum_transmits); branch->GetIntPref( "media.peerconnection.ice.trickle_grace_period", &ice_trickle_grace_period); branch->GetIntPref( "media.peerconnection.ice.tcp_so_sock_count", &ice_tcp_so_sock_count); branch->GetIntPref( "media.peerconnection.ice.tcp_listen_backlog", &ice_tcp_listen_backlog); branch->GetCharPref( "media.peerconnection.ice.force_interface", getter_Copies(force_net_interface)); } } NR_reg_set_uint4((char *)"stun.client.maximum_transmits", stun_client_maximum_transmits); NR_reg_set_uint4((char *)NR_ICE_REG_TRICKLE_GRACE_PERIOD, ice_trickle_grace_period); NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT, ice_tcp_so_sock_count); NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG, ice_tcp_listen_backlog); NR_reg_set_char((char *)NR_ICE_REG_ICE_TCP_DISABLE, !tcp_enabled); if (allow_loopback) { NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1); } if (allow_link_local) { NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1); } if (force_net_interface.Length() > 0) { // Stupid cast.... but needed const nsCString& flat = PromiseFlatCString(static_cast<nsACString&>(force_net_interface)); NR_reg_set_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, const_cast<char*>(flat.get())); } } }