summaryrefslogblamecommitdiffstats
path: root/src/client/unencrypted.rs
blob: 4aa9c63e294bcebc7850182c9da8ae4ddb53133f (plain) (tree)
1
2
3
4
5
6
7
8
9
10

             
                
                                
                
                         
  


                                                
                            
 


                                  
                  
                  

                             
                                                     





                                         
                                                         










                                                        
                           




                                                          
                                                                

                                                                                    
 
                           
 










                                                                                                 
                     









































                                                                                             
                 






























                                                                                       
         
     








































                                                                                                
 
use std::str;

use quick_xml::{
    events::{BytesStart, Event},
    name::QName,
    se, NsReader, Writer,
};
use tokio::io::{BufReader, ReadHalf, WriteHalf};
use tokio::net::TcpStream;
use tokio_native_tls::native_tls::TlsConnector;
use try_map::FallibleMapExt;

use crate::error::JabberError;
use crate::stanza::stream::Stream;
use crate::stanza::DECLARATION;
use crate::Jabber;
use crate::Result;

pub struct JabberClient<'j> {
    reader: NsReader<BufReader<ReadHalf<TcpStream>>>,
    writer: Writer<WriteHalf<TcpStream>>,
    jabber: &'j mut Jabber<'j>,
}

impl<'j> JabberClient<'j> {
    pub fn new(
        reader: NsReader<BufReader<ReadHalf<TcpStream>>>,
        writer: Writer<WriteHalf<TcpStream>>,
        jabber: &'j mut Jabber<'j>,
    ) -> Self {
        Self {
            reader,
            writer,
            jabber,
        }
    }

    pub async fn start_stream(&mut self) -> Result<()> {
        // client to server

        // declaration
        self.writer.write_event_async(DECLARATION).await?;

        // opening stream element
        let server = &self.jabber.server.to_owned().try_into()?;
        let stream_element = Stream::new_client(None, server, None, "en");
        se::to_writer_with_root(&mut self.writer, "stream:stream", &stream_element);

        // server to client

        // may or may not send a declaration
        let buf = Vec::new();
        let mut first_event = self.reader.read_resolved_event_into_async(&mut buf).await?;
        match first_event {
            (quick_xml::name::ResolveResult::Unbound, Event::Decl(e)) => {
                if let Ok(version) = e.version() {
                    if version.as_ref() == b"1.0" {
                        first_event = self.reader.read_resolved_event_into_async(&mut buf).await?
                    } else {
                        // todo: error
                        todo!()
                    }
                } else {
                    first_event = self.reader.read_resolved_event_into_async(&mut buf).await?
                }
            }
            _ => (),
        }

        // receive stream element and validate
        let stream_response: Stream;
        match first_event {
            (quick_xml::name::ResolveResult::Bound(ns), Event::Start(e)) => {
                if ns.0 == crate::stanza::stream::XMLNS.as_bytes() {
                    // stream_response = Stream::new(
                    //     e.try_get_attribute("from")?.try_map(|attribute| {
                    //         str::from_utf8(attribute.value.as_ref())?
                    //             .try_into()?
                    //             .as_ref()
                    //     })?,
                    //     e.try_get_attribute("to")?.try_map(|attribute| {
                    //         str::from_utf8(attribute.value.as_ref())?
                    //             .try_into()?
                    //             .as_ref()
                    //     })?,
                    //     e.try_get_attribute("id")?.try_map(|attribute| {
                    //         str::from_utf8(attribute.value.as_ref())?
                    //             .try_into()?
                    //             .as_ref()
                    //     })?,
                    //     e.try_get_attribute("version")?.try_map(|attribute| {
                    //         str::from_utf8(attribute.value.as_ref())?
                    //             .try_into()?
                    //             .as_ref()
                    //     })?,
                    //     e.try_get_attribute("lang")?.try_map(|attribute| {
                    //         str::from_utf8(attribute.value.as_ref())?
                    //             .try_into()?
                    //             .as_ref()
                    //     })?,
                    // );
                    return Ok(());
                } else {
                    return Err(JabberError::BadStream);
                }
            }
            // TODO: errors for incorrect namespace
            (quick_xml::name::ResolveResult::Unbound, Event::Decl(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::Start(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::End(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::Empty(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::Text(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::CData(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::Comment(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::Decl(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::PI(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::DocType(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unknown(_), Event::Eof) => todo!(),
            (quick_xml::name::ResolveResult::Unbound, Event::Start(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unbound, Event::End(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unbound, Event::Empty(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unbound, Event::Text(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unbound, Event::CData(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unbound, Event::Comment(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unbound, Event::PI(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unbound, Event::DocType(_)) => todo!(),
            (quick_xml::name::ResolveResult::Unbound, Event::Eof) => todo!(),
            (quick_xml::name::ResolveResult::Bound(_), Event::End(_)) => todo!(),
            (quick_xml::name::ResolveResult::Bound(_), Event::Empty(_)) => todo!(),
            (quick_xml::name::ResolveResult::Bound(_), Event::Text(_)) => todo!(),
            (quick_xml::name::ResolveResult::Bound(_), Event::CData(_)) => todo!(),
            (quick_xml::name::ResolveResult::Bound(_), Event::Comment(_)) => todo!(),
            (quick_xml::name::ResolveResult::Bound(_), Event::Decl(_)) => todo!(),
            (quick_xml::name::ResolveResult::Bound(_), Event::PI(_)) => todo!(),
            (quick_xml::name::ResolveResult::Bound(_), Event::DocType(_)) => todo!(),
            (quick_xml::name::ResolveResult::Bound(_), Event::Eof) => todo!(),
        }
    }

    // pub async fn get_features(&mut self) -> Result<Vec<StreamFeature>> {
    //     Element::read(&mut self.reader).await?.try_into()
    // }

    // pub async fn starttls(mut self) -> Result<super::encrypted::JabberClient<'j>> {
    //     let mut starttls_element = BytesStart::new("starttls");
    //     starttls_element.push_attribute(("xmlns", "urn:ietf:params:xml:ns:xmpp-tls"));
    //     self.writer
    //         .write_event_async(Event::Empty(starttls_element))
    //         .await
    //         .unwrap();
    //     let mut buf = Vec::new();
    //     match self.reader.read_event_into_async(&mut buf).await.unwrap() {
    //         Event::Empty(e) => match e.name() {
    //             QName(b"proceed") => {
    //                 let connector = TlsConnector::new().unwrap();
    //                 let stream = self
    //                     .reader
    //                     .into_inner()
    //                     .into_inner()
    //                     .unsplit(self.writer.into_inner());
    //                 if let Ok(tlsstream) = tokio_native_tls::TlsConnector::from(connector)
    //                     .connect(&self.jabber.server, stream)
    //                     .await
    //                 {
    //                     let (read, write) = tokio::io::split(tlsstream);
    //                     let reader = Reader::from_reader(BufReader::new(read));
    //                     let writer = Writer::new(write);
    //                     let mut client =
    //                         super::encrypted::JabberClient::new(reader, writer, self.jabber);
    //                     client.start_stream().await?;
    //                     return Ok(client);
    //                 }
    //             }
    //             QName(_) => return Err(JabberError::TlsNegotiation),
    //         },
    //         _ => return Err(JabberError::TlsNegotiation),
    //     }
    //     Err(JabberError::TlsNegotiation)
    // }
}