コード例 #1
0
ファイル: canopy_ws.go プロジェクト: lonycell/canopy-server
func NewCanopyWebsocketServer(cfg config.Config, outbox jobqueue.Outbox, pigeonServer jobqueue.Server) func(ws *websocket.Conn) {
	// Main websocket server routine.
	// This event loop runs until the websocket connection is broken.
	return func(ws *websocket.Conn) {
		canolog.Websocket("Websocket connection established")

		var cnt int32
		var device datalayer.Device
		var inbox jobqueue.Inbox
		var inboxReciever jobqueue.RecieveHandler
		lastPingTime := time.Now()

		cnt = 0

		// connect to cassandra
		dl := cassandra_datalayer.NewDatalayer(cfg)
		conn, err := dl.Connect("canopy")
		if err != nil {
			canolog.Error("Could not connect to database: ", err)
			return
		}
		defer conn.Close()

		for {
			var in string

			// check for message from client
			ws.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
			err := websocket.Message.Receive(ws, &in)
			if err == nil {
				// success, payload received
				cnt++
				resp := service.ProcessDeviceComm(cfg, conn, device, "", "", in)
				if resp.Device == nil {
					canolog.Error("Error processing device communications: ", resp.Err)
				} else {
					device = resp.Device
					if inbox == nil {
						deviceIdString := device.ID().String()
						inbox, err = pigeonServer.CreateInbox("canopy_ws:" + deviceIdString)
						if err != nil {
							canolog.Error("Error initializing inbox:", err)
							return
						}
						inboxReciever = jobqueue.NewRecieveHandler()
						inbox.SetHandler(inboxReciever)

						err = device.UpdateWSConnected(true)
						if err != nil {
							canolog.Error("Unexpected error: ", err)
						}
					}
				}
			} else if err == io.EOF {
				canolog.Websocket("Websocket connection closed")
				// connection closed
				if inbox != nil {
					if device != nil {
						err = device.UpdateWSConnected(false)
						if err != nil {
							canolog.Error("Unexpected error: ", err)
						}
					}
					inbox.Close()
				}
				return
			} else if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
				// timeout reached, no data for me this time
			} else {
				canolog.Error("Unexpected error: ", err)
			}

			// Periodically send blank message
			if time.Now().After(lastPingTime.Add(30 * time.Second)) {
				err := websocket.Message.Send(ws, "{}")
				if err != nil {
					canolog.Websocket("Websocket connection closed during ping")
					// connection closed
					if inbox != nil {
						if device != nil {
							err = device.UpdateWSConnected(false)
							if err != nil {
								canolog.Error("Unexpected error: ", err)
							}
						}
						inbox.Close()
					}
					return
				}
				canolog.Info("Pinging WS")
				lastPingTime = time.Now()
			}

			if inbox != nil {
				msg, _ := inboxReciever.Recieve(time.Duration(100 * time.Millisecond))
				if msg != nil {
					msgString, err := json.Marshal(msg)

					if err != nil {
						canolog.Error("Unexpected error: ", err)
					}

					canolog.Info("Websocket sending", msgString)
					canolog.Websocket("Websocket sending: ", msgString)
					websocket.Message.Send(ws, msgString)
				}
			}
		}
	}
}