main.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. package main
  2. import (
  3. "context"
  4. "flag"
  5. "log"
  6. "math/rand"
  7. "net/http"
  8. "sync"
  9. // "github.com/improbable-eng/grpc-web/go/grpcweb"
  10. _ "net/http/pprof"
  11. pb "git.capella.pro/thepaint/protos"
  12. "google.golang.org/protobuf/proto"
  13. "encoding/base64"
  14. "encoding/json"
  15. "github.com/gorilla/websocket"
  16. "github.com/pion/webrtc/v3"
  17. "github.com/sirupsen/logrus"
  18. )
  19. var (
  20. tls = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP")
  21. certFile = flag.String("cert_file", "", "The TLS cert file")
  22. keyFile = flag.String("key_file", "", "The TLS key file")
  23. jsonDBFile = flag.String("json_db_file", "", "A json file containing a list of features")
  24. port = flag.Int("port", 8080, "The server port")
  25. )
  26. var upgrader = websocket.Upgrader{
  27. CheckOrigin: func(r *http.Request) bool { return true },
  28. }
  29. type server struct {
  30. pb.UnimplementedPaintClientServer
  31. // savedFeatures []*pb.Feature // read-only after initialized
  32. //
  33. // mu sync.Mutex // protects routeNotes
  34. // routeNotes map[string][]*pb.RouteNote
  35. }
  36. func main() {
  37. http.HandleFunc("/ws", websocketHandler)
  38. logrus.Fatal(http.ListenAndServe(":8081", nil))
  39. }
  40. func (s *server) Paint(ctx context.Context, request *pb.PaintRequest) (*pb.PaintReply, error) {
  41. panic("implement me")
  42. }
  43. func (s *server) Monitor(sub *pb.MonitorSub, monitorServer pb.PaintClient_MonitorServer) error {
  44. // for k := 0; k < 4; k++ {
  45. // points := []*pb.MonitorPoint{}
  46. // for i := 64*k; i < 64*(k+1); i++ {
  47. // for j := 0; j < 256; j++ {
  48. // points = append(points, &pb.MonitorPoint{
  49. // Point: &pb.BPoint{
  50. // X: int32(i),
  51. // Y: int32(j),
  52. // },
  53. // Color: &pb.BColor{
  54. // Rgba: uint32(rand.Intn(256)) | uint32(rand.Intn(256))<<8 | uint32(rand.Intn(256))<<16 | 255<<24,
  55. // },
  56. // })
  57. // }
  58. // }
  59. //
  60. // monitorServer.Send(&pb.MonitorReply{
  61. // Points: points,
  62. // // BytesPoints: b.Bytes(),
  63. // })
  64. // }
  65. points := Getp(0, 0)
  66. monitorServer.Send(&pb.MonitorReply{
  67. Points: points,
  68. // BytesPoints: b.Bytes(),
  69. })
  70. return nil
  71. }
  72. func Getp(ii int, jj int) []*pb.MonitorPoint {
  73. points := []*pb.MonitorPoint{}
  74. for i := ii * 32; i < 32*(1+ii); i++ {
  75. for j := jj * 32; j < 32*(1+jj); j++ {
  76. points = append(points, &pb.MonitorPoint{
  77. Point: &pb.BPoint{
  78. X: int32(i),
  79. Y: int32(j),
  80. },
  81. Color: &pb.BColor{
  82. Rgba: uint32(rand.Intn(256)) | uint32(rand.Intn(256))<<8 | uint32(rand.Intn(256))<<16 | 255<<24,
  83. },
  84. })
  85. }
  86. }
  87. return points
  88. }
  89. func Encode(obj interface{}) string {
  90. b, err := json.Marshal(obj)
  91. if err != nil {
  92. panic(err)
  93. }
  94. return base64.StdEncoding.EncodeToString(b)
  95. }
  96. // Handle incoming websockets
  97. func websocketHandler(w http.ResponseWriter, r *http.Request) {
  98. // Upgrade HTTP request to Websocket
  99. unsafeConn, err := upgrader.Upgrade(w, r, nil)
  100. if err != nil {
  101. log.Print("upgrade:", err)
  102. return
  103. }
  104. c := &threadSafeWriter{unsafeConn, sync.Mutex{}}
  105. logrus.Info("NEW GRPC")
  106. // Configure and create a new PeerConnection.
  107. config := webrtc.Configuration{
  108. ICEServers: []webrtc.ICEServer{
  109. {
  110. URLs: []string{"stun:melvans.com:3478"},
  111. Username: "b84e4232f84505e3c3967184df374f2cdaa954f1",
  112. Credential: "afc39ae0591c132292f73a87f6f3725311fbafa0",
  113. // URLs: []string{"stun:stun.l.google.com:19302"},
  114. },
  115. },
  116. }
  117. pc, err := webrtc.NewPeerConnection(config)
  118. if err != nil {
  119. logrus.Error(err)
  120. }
  121. // Create DataChannel.
  122. sendChannel, err := pc.CreateDataChannel("data", nil)
  123. if err != nil {
  124. logrus.Error(err)
  125. }
  126. sendChannel.OnClose(func() {
  127. logrus.Println("sendChannel has closed")
  128. })
  129. sendChannel.OnOpen(func() {
  130. logrus.Println("sendChannel has opened")
  131. for i := 0; i < 8; i++ {
  132. for j := 0; j < 8; j++ {
  133. data := &pb.MonitorReply{
  134. Points: Getp(i, j),
  135. }
  136. md, err := proto.Marshal(data)
  137. if err != nil {
  138. logrus.Error(err)
  139. continue
  140. }
  141. err = sendChannel.Send(md)
  142. if err != nil {
  143. logrus.Error(err)
  144. continue
  145. }
  146. }
  147. }
  148. })
  149. sendChannel.OnMessage(func(msg webrtc.DataChannelMessage) {
  150. logrus.Println(string(msg.Data))
  151. })
  152. // Create offer
  153. offer, err := pc.CreateOffer(nil)
  154. if err != nil {
  155. logrus.Error(err)
  156. }
  157. if err := pc.SetLocalDescription(offer); err != nil {
  158. logrus.Error(err)
  159. }
  160. // Add handlers for setting up the connection.
  161. pc.OnICEConnectionStateChange(func(state webrtc.ICEConnectionState) {
  162. logrus.Println(state)
  163. })
  164. // connectionString := make(chan bool)
  165. // Trickle ICE. Emit server candidate to client
  166. pc.OnICECandidate(func(i *webrtc.ICECandidate) {
  167. if i == nil {
  168. return
  169. }
  170. data := &pb.RTCData{
  171. Event: string(pc.LocalDescription().Type.String()),
  172. Data: string(pc.LocalDescription().SDP),
  173. }
  174. logrus.WithField("data", data).Info("data to client")
  175. md, _ := proto.Marshal(data)
  176. w, _ := unsafeConn.NextWriter(websocket.BinaryMessage)
  177. w.Write(md)
  178. w.Close()
  179. })
  180. for {
  181. _, raw, err := c.ReadMessage()
  182. data := &pb.RTCData{}
  183. if err != nil {
  184. logrus.Error(err)
  185. return
  186. } else if err := proto.Unmarshal(raw, data); err != nil {
  187. logrus.WithField("data", string(raw)).Error(err)
  188. return
  189. }
  190. logrus.WithField("data", data).Info("data from client")
  191. switch data.Event {
  192. case "candidate":
  193. candidate := webrtc.ICECandidateInit{}
  194. if err := json.Unmarshal([]byte(data.Data), &candidate); err != nil {
  195. logrus.Error(err)
  196. return
  197. }
  198. if err := pc.AddICECandidate(candidate); err != nil {
  199. logrus.Error(err)
  200. return
  201. }
  202. case "answer":
  203. answer := webrtc.SessionDescription{
  204. Type: webrtc.NewSDPType(data.Event),
  205. SDP: data.Data,
  206. }
  207. if err := pc.SetRemoteDescription(answer); err != nil {
  208. logrus.Error(err)
  209. return
  210. }
  211. }
  212. }
  213. }
  214. type threadSafeWriter struct {
  215. *websocket.Conn
  216. sync.Mutex
  217. }
  218. func (t *threadSafeWriter) WriteJSON(v interface{}) error {
  219. t.Lock()
  220. defer t.Unlock()
  221. return t.Conn.WriteJSON(v)
  222. }