 = Reflect::get(&answer, &JsValue::from_str("sdp"))
       .efix()?
       .as_string()
       .ok_or("")?;

    let answer_description = session_desc_init.sdp(&answer_sdp);

    JsFuture::from(conn.set_local_description(answer_description))
       .await
       .efix()?;

    wait_for_ice_complete(conn.clone()).await;

    let answer = PeerSignal::Answer(conn.local_description().unwrap().sdp());
    signal_peer.send(answer);

    debug!("waiting for data channel to open");
    channel_ready_rx.next().await;

    Ok((signal_peer.id, data_channel))
}

fn create_rtc_peer_connection(ice_server_urls: Vec<String>) -> RtcPeerConnection {
    #[derive(Serialize)]
    pub struct IceServerConfig {
        pub urls: Vec<String>,
    }

    let mut peer_config: RtcConfiguration = RtcConfiguration::new();
    let ice_server_config = IceServerConfig {
        urls: ice_server_urls,
    };
    let ice_server_config_list = [ice_server_config];
    peer_config.ice_servers(&JsValue::from_serde(&ice_server_config_list).unwrap());
    RtcPeerConnection::new_with_configuration(&peer_config).unwrap()
}

async fn wait_for_ice_complete(conn: RtcPeerConnection) {
    if conn.ice_gathering_state() == RtcIceGatheringState::Complete {
        debug!("Ice already completed");
        return;
    }

    let (mut tx, mut rx) = futures_channel::mpsc::channel(1);

    let conn_clone = conn.clone();
    let onstatechange: Box<dyn FnMut(JsValue)> = Box::new(move |_| {
        if conn_clone.ice_gathering_state() == RtcIceGatheringState::Complete {
            tx.try_send(()).unwrap();
        }
    });

    let onstatechange = Closure::wrap(onstatechange);

    conn.set_onicegatheringstatechange(Some(onstatechange.as_ref().unchecked_ref()));

    rx.next().await;

    conn.set_onicegatheringstatechange(None);
    debug!("Ice completed");
}

fn create_data_channel(
    connection: RtcPeerConnection,
    incoming_tx: futures_channel::mpsc::UnboundedSender<(PeerId, Packet)>,
    peer_id: PeerId,
    mut channel_ready: futures_channel::mpsc::Sender<u8>,
) -> RtcDataChannel {
    let mut data_channel_config: RtcDataChannelInit = RtcDataChannelInit::new();
    data_channel_config.ordered(false);
    data_channel_config.max_retransmits(0);
    data_channel_config.negotiated(true);
    data_channel_config.id(0);

    let channel: RtcDataChannel =
        connection.create_data_channel_with_data_channel_dict("webudp", &data_channel_config);
    channel.set_binary_type(RtcDataChannelType::Arraybuffer);

    let channel_onmsg_func: Box<dyn FnMut(MessageEvent)> = Box::new(move |event: MessageEvent| {
        debug!("incoming {:?}", event);
        if let Ok(arraybuf) = event.data().dyn_into::<js_sys::ArrayBuffer>() {
            let uarray = js_sys::Uint8Array::new(&arraybuf);
            let body = uarray.to_vec();
            incoming_tx
               .unbounded_send((peer_id.clone(), body.into_boxed_slice()))
               .unwrap();
        }
    });
    let channel_onmsg_closure = Closure::wrap(channel_onmsg_func);
    channel.set_onmessage(Some(channel_onmsg_closure.as_ref().unchecked_ref()));
    channel_onmsg_closure.forget();

    let channel_onopen_func: Box<dyn FnMut(JsValue)> = Box::new(move |_| {
        debug!("Rtc data channel opened :D :D");
        channel_ready
           .try_send(1)
           .expect("failed to notify about open connection");
    });
    let channel_onopen_closure = Closure::wrap(channel_onopen_func);
    channel.set_onopen(Some(channel_onopen_closure.as_ref().unchecked_ref()));
    channel_onopen_closure.forget();

    channel
}

// Expect/unwrap is broken in select for some reason :/
fn check(res: &Result<(PeerId, RtcDataChannel), Box<dyn std::error::Error>>) {
    // but doing it inside a typed function works fine
    res.as_ref().expect("handshake failed");
}

// The bellow is just to wrap Result<JsValue, JsValue> into something sensible-ish

trait JsErrorExt<T> {
    fn efix(self) -> Result<T, Box<dyn std::error::Error>>;
}

impl<T> JsErrorExt<T> for Result<T, JsValue> {
    fn efix(self) -> Result<T, Box<dyn std::error::Error>> {
        self.map_err(|e| {
            let e: Box<dyn std::error::Error> = Box::new(JsError(e));
            e
        })
    }
}

#[derive(Debug)]
struct JsError(JsValue);

impl std::error::Error for JsError {}

impl std::fmt::Display for JsError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self.0)
    }
}
Colombo, June 1 (newsin.asia): Sri Lankan President Gotabaya Rajapaksa has ordered the concerned authorities to tow the wrecked X-PRESS PEARL Container ship into the deep seas off the coast of Colombo.
The Minister of Ports and Shipping Rohitha Abeygunawardena revealed details about the ill-fated vessel including its journey from the United Arab Emirates on May 09 to its arrival near the Port of Colombo on May 19.
Representatives from a number of fields, including shipping and environment, pointed out that the vessel was at risk of sinking. Their suggestion, then, was to take the vessel to the deep seas to minimize possible damage to the marine environment.
Accordingly, the President gave instructions to issue an immediate order to tow the vessel into the deep seas based on the powers vested with the Chairman of the Marine Environment Protection Authority and based on technical facts as well as the advice of the Attorney General.
The President stated that the decision taken should be based solely on technical facts and not on the basis of politics.
Ministers Douglas Devananda, Mahinda Amaraweera, State Minister Kanchana Wijesekera, Nalaka Godahewa, Attorney General Sanjaya Rajaratnam, Secretary to the President P. B. Jayasundera, Defence Secretary, Gen. (Retired) Kamal Gunaratne, Commanders of the Navy and Air Force and the officials of Ports Authority, Marine Environment Protection Authority, NARA and other line institutions were also present.Tucked just inside in the Alexandria city border, next to Springfield/Franconia, Cameron Station consists of condos, townhouses and single family homes. It offers convenience of retail and commercial development sprinkled amongst residential dwellings as well as a host of amenities including an outdoor pool, clubhouse, full gym facility and shuttle bus transportation to the Van Dorn St Metro. Ben Brenman Park blends scenic nature with fitness where you can view wildlife, walk or jog around the pond with fountains, picnic in the grassy areas and enjoy the playground and sports fields. The Farmers market (May-Nov) offers produce, meats and local crafters.From University of Florida, Gainesville, FL 32610.
Background: Meta-analyses are important for aggregating trial results to identify conclusions that cannot be made through separate examination. A thorough literature search is of utmost importance in constructing a meta-analysis. The PubMed interface from the National Library of Medicine is a cornerstone of many meta-analysis searches, and the largest component of PubMed is the MEDLINE database. Each article in this database has a unique entry with information about the study's participants and design. However, database entries are