package xmpp import ( "context" "crypto/tls" "crypto/x509" "encoding/xml" "io" "log" ) type SessionConnect struct{} type SessionDisconnect struct{} type SessionShouldDisconnect struct{} type session struct { jid string pwd string in chan any out chan<- any transport *tls.Conn tx *xml.Encoder rx chan any resourceReq string } func StartSession(out chan<- any, jid string, pwd string) (in chan<- any) { s := session{} s.jid = jid s.pwd = pwd s.in = make(chan any) s.out = out s.rx = make(chan any, 0) go s.run() return s.in } func (s *session) run() { err := s.startTransport() if err != nil { return } defer s.transport.Close() ctx, cancel := context.WithCancel(context.Background()) cpy := s.rx go runRx(ctx, cpy, s.transport) defer cancel() lw := logger{"[TX] "} w := io.MultiWriter(s.transport, lw) s.tx = xml.NewEncoder(w) defer s.tx.Close() openStream(s.tx, s.jid) defer closeStream(s.tx) s.out <- SessionConnect{} // TODO this should be sent after initial presence defer func() { s.out <- SessionDisconnect{} }() for { select { case e := <-s.rx: handle(s, e) case signal := <-s.in: switch signal.(type) { case SessionShouldDisconnect: return } } } } func (s *session) startTransport() error { domain := domainpart(s.jid) roots, err := x509.SystemCertPool() if err != nil { log.Println(err) return err } s.transport, err = tls.Dial("tcp", domain+":"+"5223", &tls.Config{RootCAs: roots}) if err != nil { log.Println(err) return err } return nil }