package connections import ( "errors" "git.mascherari.press/cwtch/peer/fetch" "git.mascherari.press/cwtch/peer/listen" "git.mascherari.press/cwtch/peer/send" "git.mascherari.press/cwtch/protocol" "github.com/s-rah/go-ricochet" "github.com/s-rah/go-ricochet/channels" "github.com/s-rah/go-ricochet/connection" "github.com/s-rah/go-ricochet/identity" "github.com/s-rah/go-ricochet/utils" "log" "time" ) type PeerServerConnection struct { connection.AutoConnectionHandler Server string state ConnectionState connection connection.Connection GroupMessageHandler func(string, *protocol.GroupMessage) } func NewPeerServerConnection(serverhostname string) *PeerServerConnection { psc := new(PeerServerConnection) psc.Server = serverhostname psc.Init() return psc } // GetState returns the current connection state func (psc *PeerServerConnection) GetState() ConnectionState { return psc.state } // Run manages the setup and teardown of a peer server connection func (psc *PeerServerConnection) Run() error { log.Printf("Connecting to %v", psc.Server) rc, err := goricochet.Open(psc.Server) if err == nil { rc.TraceLog(true) psc.connection = *rc psc.state = CONNECTED pk, err := utils.GeneratePrivateKey() if err == nil { _, err := connection.HandleOutboundConnection(&psc.connection).ProcessAuthAsClient(identity.Initialize("cwtchpeer", pk)) if err == nil { psc.state = AUTHENTICATED go func() { psc.connection.Do(func() error { psc.connection.RequestOpenChannel("im.cwtch.server.fetch", &fetch.CwtchPeerFetchChannel{Handler: psc}) return nil }) psc.connection.Do(func() error { psc.connection.RequestOpenChannel("im.cwtch.server.listen", &listen.CwtchPeerListenChannel{Handler: psc}) return nil }) }() psc.connection.Process(psc) } } } psc.state = FAILED return err } // Break makes Run() return and prevents processing, but doesn't close the connection. func (psc *PeerServerConnection) Break() error { return psc.connection.Break() } func (psc *PeerServerConnection) SendGroupMessage(gm *protocol.GroupMessage) { for psc.state != AUTHENTICATED { time.Sleep(time.Second * 2) } log.Printf("Opening a Channel to Send") psc.connection.Do(func() error { psc.connection.RequestOpenChannel("im.cwtch.server.send", &send.CwtchPeerSendChannel{}) return nil }) log.Printf("Waiting...") // TODO We have to wait to receive the channel result before we can continue // We should have a better mechanism for this kindof interaction log.Printf("CWTCH PEER Sending...") send: time.Sleep(time.Second * 2) err := psc.connection.Do(func() error { channel := psc.connection.Channel("im.cwtch.server.send", channels.Outbound) if channel == nil { return errors.New("No Channel") } sendchannel, ok := channel.Handler.(*send.CwtchPeerSendChannel) if ok { sendchannel.SendGroupMessage(gm) } else { return errors.New("Failed") } return nil }) for err != nil { log.Printf("CHANNEL ERROR %v", err) goto send } log.Printf("Done") } func (psc *PeerServerConnection) HandleGroupMessage(gm *protocol.GroupMessage) { log.Printf("Received Group Message: %v", gm) psc.GroupMessageHandler(psc.Server, gm) }