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.

224 lines
5.4KB

  1. package bridge
  2. import (
  3. "cwtch.im/cwtch/protocol/connections"
  4. "encoding/base64"
  5. "encoding/binary"
  6. "git.openprivacy.ca/openprivacy/libricochet-go/log"
  7. "cwtch.im/cwtch/event"
  8. "encoding/json"
  9. "os"
  10. "sync"
  11. "syscall"
  12. )
  13. /* pipeBridge creates a pair of named pipes
  14. Needs a call to new client and service to fully successfully open
  15. */
  16. const maxBufferSize = 1000
  17. type pipeBridge struct {
  18. infile, outfile string
  19. in, out *os.File
  20. read, write chan event.IPCMessage
  21. closedChan chan bool
  22. state connections.ConnectionState
  23. lock sync.Mutex
  24. }
  25. func newPipeBridge(inFilename, outFilename string) *pipeBridge {
  26. syscall.Mkfifo(inFilename, 0600)
  27. syscall.Mkfifo(outFilename, 0600)
  28. pb := &pipeBridge{infile: inFilename, outfile: outFilename, state: connections.DISCONNECTED}
  29. pb.read = make(chan event.IPCMessage, maxBufferSize)
  30. pb.write = make(chan event.IPCMessage, maxBufferSize)
  31. return pb
  32. }
  33. // NewPipeBridgeClient returns a pipe backed IPCBridge for a client
  34. func NewPipeBridgeClient(inFilename, outFilename string) event.IPCBridge {
  35. log.Debugf("Making new PipeBridge Client...\n")
  36. pb := newPipeBridge(inFilename, outFilename)
  37. go pb.clientConnectionManager()
  38. return pb
  39. }
  40. // NewPipeBridgeService returns a pipe backed IPCBridge for a service
  41. func NewPipeBridgeService(inFilename, outFilename string) (event.IPCBridge, error) {
  42. log.Debugf("Making new PipeBridge Service...\n")
  43. pb := newPipeBridge(inFilename, outFilename)
  44. go pb.serviceConnectionManager()
  45. log.Debugf("Successfully created new PipeBridge Service!\n")
  46. return pb, nil
  47. }
  48. func (pb *pipeBridge) clientConnectionManager() {
  49. for pb.state != connections.KILLED {
  50. pb.state = connections.CONNECTING
  51. var err error
  52. pb.in, err = os.OpenFile(pb.infile, os.O_RDONLY, 0600)
  53. if err != nil {
  54. pb.state = connections.DISCONNECTED
  55. continue
  56. }
  57. pb.out, err = os.OpenFile(pb.outfile, os.O_WRONLY, 0600)
  58. if err != nil {
  59. pb.state = connections.DISCONNECTED
  60. continue
  61. }
  62. log.Debugf("Successfully connected PipeBridge Client!\n")
  63. pb.handleConns()
  64. }
  65. }
  66. func (pb *pipeBridge) serviceConnectionManager() {
  67. for pb.state != connections.KILLED {
  68. pb.state = connections.CONNECTING
  69. var err error
  70. pb.out, err = os.OpenFile(pb.outfile, os.O_WRONLY, 0600)
  71. if err != nil {
  72. pb.state = connections.DISCONNECTED
  73. continue
  74. }
  75. pb.in, err = os.OpenFile(pb.infile, os.O_RDONLY, 0600)
  76. if err != nil {
  77. pb.state = connections.DISCONNECTED
  78. continue
  79. }
  80. log.Debugf("Successfully connected PipeBridge Service!\n")
  81. pb.handleConns()
  82. }
  83. }
  84. func (pb *pipeBridge) handleConns() {
  85. // auth?
  86. pb.state = connections.AUTHENTICATED
  87. pb.closedChan = make(chan bool, 5)
  88. log.Debugf("handleConns authed, 2xgo\n")
  89. go pb.handleRead()
  90. go pb.handleWrite()
  91. <-pb.closedChan
  92. log.Debugf("handleConns CLOSEDCHAN!!!!\n")
  93. if pb.state != connections.KILLED {
  94. pb.state = connections.FAILED
  95. }
  96. pb.in.Close()
  97. pb.out.Close()
  98. close(pb.write)
  99. close(pb.read)
  100. pb.read = make(chan event.IPCMessage, maxBufferSize)
  101. pb.write = make(chan event.IPCMessage, maxBufferSize)
  102. log.Debugf("handleConns done, exit\n")
  103. }
  104. func (pb *pipeBridge) handleWrite() {
  105. for {
  106. select {
  107. case message := <-pb.write:
  108. log.Debugf("handleWrite <- message: %v\n", message)
  109. if pb.state == connections.AUTHENTICATED {
  110. encMessage := &event.IPCMessage{Dest: message.Dest, Message: event.Event{EventType: message.Message.EventType, EventID: message.Message.EventID, Data: make(map[event.Field]string)}}
  111. for k, v := range message.Message.Data {
  112. encMessage.Message.Data[k] = base64.StdEncoding.EncodeToString([]byte(v))
  113. }
  114. messageJSON, _ := json.Marshal(encMessage)
  115. size := make([]byte, 2)
  116. binary.LittleEndian.PutUint16(size, uint16(len(messageJSON)))
  117. pb.out.Write(size)
  118. for pos := 0; pos < len(messageJSON); {
  119. n, err := pb.out.Write(messageJSON)
  120. if err != nil {
  121. log.Errorf("Writing out on pipeBridge: %v\n", err)
  122. pb.closedChan <- true
  123. return
  124. }
  125. pos += n
  126. }
  127. } else {
  128. return
  129. }
  130. }
  131. }
  132. }
  133. func (pb *pipeBridge) handleRead() {
  134. var n int
  135. size := make([]byte, 2)
  136. var err error
  137. for {
  138. log.Debugf("Waiting to handleRead()...\n")
  139. n, err = pb.in.Read(size)
  140. if err != nil || n != 2 {
  141. log.Errorf("Could not read len int from stream: %v\n", err)
  142. pb.closedChan <- true
  143. return
  144. }
  145. n = int(binary.LittleEndian.Uint16(size))
  146. pos := 0
  147. buffer := make([]byte, n)
  148. for n > 0 {
  149. m, err := pb.in.Read(buffer[pos:])
  150. if err != nil {
  151. log.Errorf("Reading into buffer from pipe: %v\n", err)
  152. pb.closedChan <- true
  153. return
  154. }
  155. n -= m
  156. pos += m
  157. }
  158. var message event.IPCMessage
  159. err = json.Unmarshal(buffer, &message)
  160. if err != nil {
  161. log.Errorf("Read error: %v --value: %v", err, message)
  162. continue // signal error?
  163. }
  164. for k, v := range message.Message.Data {
  165. val, _ := base64.StdEncoding.DecodeString(v)
  166. message.Message.Data[k] = string(val)
  167. }
  168. log.Debugf("handleRead read<-: %v\n", message)
  169. pb.read <- message
  170. log.Debugf("handleRead wrote\n")
  171. }
  172. }
  173. func (pb *pipeBridge) Read() (*event.IPCMessage, bool) {
  174. log.Debugf("Read()...\n")
  175. message := <-pb.read
  176. log.Debugf("Read: %v\n", message)
  177. return &message, true
  178. }
  179. func (pb *pipeBridge) Write(message *event.IPCMessage) {
  180. log.Debugf("Write: %v\n", message)
  181. pb.write <- *message
  182. log.Debugf("Wrote\n")
  183. }
  184. func (pb *pipeBridge) Shutdown() {
  185. pb.state = connections.KILLED
  186. pb.closedChan <- true
  187. }