Official cwtch.im peer and server implementations.
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.

peer_send_channel.go 2.8KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package send
  2. import (
  3. "errors"
  4. "git.mascherari.press/cwtch/protocol"
  5. "git.mascherari.press/cwtch/protocol/spam"
  6. "github.com/golang/protobuf/proto"
  7. "github.com/s-rah/go-ricochet/channels"
  8. "github.com/s-rah/go-ricochet/utils"
  9. "github.com/s-rah/go-ricochet/wire/control"
  10. )
  11. // CwtchPeerSendChannel is the peer implementation of im.cwtch.server.send
  12. type CwtchPeerSendChannel struct {
  13. channel *channels.Channel
  14. spamGuard spam.Guard
  15. challenge []byte
  16. }
  17. // Type returns the type string for this channel, e.g. "im.ricochet.server.send".
  18. func (cplc *CwtchPeerSendChannel) Type() string {
  19. return "im.cwtch.server.send"
  20. }
  21. // Closed is called when the channel is closed for any reason.
  22. func (cplc *CwtchPeerSendChannel) Closed(err error) {
  23. }
  24. // OnlyClientCanOpen - for Cwtch server channels only peers may open.
  25. func (cplc *CwtchPeerSendChannel) OnlyClientCanOpen() bool {
  26. return true
  27. }
  28. // Singleton - for Cwtch channels there can only be one instance per direction
  29. func (cplc *CwtchPeerSendChannel) Singleton() bool {
  30. return true
  31. }
  32. // Bidirectional - for Cwtch channels are not bidrectional
  33. func (cplc *CwtchPeerSendChannel) Bidirectional() bool {
  34. return false
  35. }
  36. // RequiresAuthentication - Cwtch channels require no auth
  37. func (cplc *CwtchPeerSendChannel) RequiresAuthentication() string {
  38. return "none"
  39. }
  40. // OpenInbound should never be called on peers.
  41. func (cplc *CwtchPeerSendChannel) OpenInbound(channel *channels.Channel, raw *Protocol_Data_Control.OpenChannel) ([]byte, error) {
  42. return nil, errors.New("client does not receive inbound listen channels")
  43. }
  44. // OpenOutbound is used to set up a new send channel and initialize spamguard
  45. func (cplc *CwtchPeerSendChannel) OpenOutbound(channel *channels.Channel) ([]byte, error) {
  46. cplc.spamGuard.Difficulty = 2
  47. cplc.channel = channel
  48. messageBuilder := new(utils.MessageBuilder)
  49. return messageBuilder.OpenChannel(channel.ID, cplc.Type()), nil
  50. }
  51. // OpenOutboundResult confirms the open channel request and sets the spamguard challenge
  52. func (cplc *CwtchPeerSendChannel) OpenOutboundResult(err error, crm *Protocol_Data_Control.ChannelResult) {
  53. if err == nil {
  54. if crm.GetOpened() {
  55. cplc.channel.Pending = false
  56. ce, _ := proto.GetExtension(crm, protocol.E_ServerNonce)
  57. cplc.challenge = ce.([]byte)[:]
  58. }
  59. }
  60. }
  61. // SendGroupMessage performs the spamguard proof of work and sends a message.
  62. func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) {
  63. sgsolve := cplc.spamGuard.SolveChallenge(cplc.challenge, gm.GetCiphertext())
  64. gm.Spamguard = sgsolve[:]
  65. csp := &protocol.CwtchServerPacket{
  66. GroupMessage: gm,
  67. }
  68. packet, _ := proto.Marshal(csp)
  69. cplc.channel.SendMessage(packet)
  70. cplc.channel.CloseChannel()
  71. }
  72. // Packet should never be
  73. func (cplc *CwtchPeerSendChannel) Packet(data []byte) {
  74. // If we receive a packet on this channel, close the connection
  75. cplc.channel.CloseChannel()
  76. }