Official cwtch.im peer and server implementations. https://cwtch.im
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
3.2KB

  1. package fetch
  2. import (
  3. "cwtch.im/cwtch/protocol"
  4. "errors"
  5. "git.openprivacy.ca/openprivacy/libricochet-go/channels"
  6. "git.openprivacy.ca/openprivacy/libricochet-go/utils"
  7. "git.openprivacy.ca/openprivacy/libricochet-go/wire/control"
  8. "github.com/golang/protobuf/proto"
  9. )
  10. // CwtchPeerFetchChannel is the peer implementation of the im.cwtch.server.fetch
  11. // channel.
  12. type CwtchPeerFetchChannel struct {
  13. channel *channels.Channel
  14. Handler CwtchPeerFetchChannelHandler
  15. }
  16. // CwtchPeerFetchChannelHandler should be implemented by peers to receive new messages.
  17. type CwtchPeerFetchChannelHandler interface {
  18. HandleGroupMessage(*protocol.GroupMessage)
  19. HandleFetchDone()
  20. }
  21. // Type returns the type string for this channel, e.g. "im.ricochet.server.fetch)
  22. func (cpfc *CwtchPeerFetchChannel) Type() string {
  23. return "im.cwtch.server.fetch"
  24. }
  25. // Closed is called when the channel is closed for any reason.
  26. func (cpfc *CwtchPeerFetchChannel) Closed(err error) {
  27. cpfc.Handler.HandleFetchDone()
  28. }
  29. // OnlyClientCanOpen - for Cwtch server channels only client can open
  30. func (cpfc *CwtchPeerFetchChannel) OnlyClientCanOpen() bool {
  31. return true
  32. }
  33. // Singleton - for Cwtch channels there can only be one instance per direction
  34. func (cpfc *CwtchPeerFetchChannel) Singleton() bool {
  35. return true
  36. }
  37. // Bidirectional - for Cwtch channels are not bidrectional
  38. func (cpfc *CwtchPeerFetchChannel) Bidirectional() bool {
  39. return false
  40. }
  41. // RequiresAuthentication - Cwtch server channels require no auth.
  42. func (cpfc *CwtchPeerFetchChannel) RequiresAuthentication() string {
  43. return "none"
  44. }
  45. // OpenInbound - cwtch server peer implementations shouldnever respond to inbound requests
  46. func (cpfc *CwtchPeerFetchChannel) OpenInbound(channel *channels.Channel, raw *Protocol_Data_Control.OpenChannel) ([]byte, error) {
  47. return nil, errors.New("client does not receive inbound listen channels")
  48. }
  49. // OpenOutbound sets up a new cwtch fetch channel
  50. func (cpfc *CwtchPeerFetchChannel) OpenOutbound(channel *channels.Channel) ([]byte, error) {
  51. cpfc.channel = channel
  52. messageBuilder := new(utils.MessageBuilder)
  53. return messageBuilder.OpenChannel(channel.ID, cpfc.Type()), nil
  54. }
  55. // OpenOutboundResult confirms a previous open channel request
  56. func (cpfc *CwtchPeerFetchChannel) OpenOutboundResult(err error, crm *Protocol_Data_Control.ChannelResult) {
  57. if err == nil {
  58. if crm.GetOpened() {
  59. cpfc.channel.Pending = false
  60. cpfc.FetchRequest()
  61. }
  62. }
  63. }
  64. // FetchRequest sends a FetchMessage to the Server.
  65. func (cpfc *CwtchPeerFetchChannel) FetchRequest() error {
  66. if cpfc.channel.Pending == false {
  67. fm := &protocol.FetchMessage{}
  68. csp := &protocol.CwtchServerPacket{
  69. FetchMessage: fm,
  70. }
  71. packet, _ := proto.Marshal(csp)
  72. cpfc.channel.SendMessage(packet)
  73. } else {
  74. return errors.New("channel isn't set up yet")
  75. }
  76. return nil
  77. }
  78. // Packet is called for each raw packet received on this channel.
  79. func (cpfc *CwtchPeerFetchChannel) Packet(data []byte) {
  80. csp := &protocol.CwtchServerPacket{}
  81. err := proto.Unmarshal(data, csp)
  82. if err == nil {
  83. if csp.GetGroupMessage() != nil {
  84. gm := csp.GetGroupMessage()
  85. // We create a new go routine here to avoid leaking any information about processing time
  86. // TODO Server can probably try to use this to DoS a peer
  87. cpfc.Handler.HandleGroupMessage(gm)
  88. }
  89. }
  90. }