Beispiel #1
0
// Do a request/task asynchronously
func (service *Service) doAsync(task Task) <-chan Task {
	ch := make(chan Task, 1)

	go func() {
		defer func() { ch <- task }()

		log.Tracef("REST: sending: %+v", task.request)
		task.response, task.err = service.client.Do(task.request)
		if task.err != nil {
			log.Warnf("REST: failed to do %s %s request (error: %s)",
				task.request.Method, task.request.URL, task.err)
			return
		}
		log.Tracef("REST: got %s %s response: %+v",
			task.request.Method, task.request.URL, task.response)

		// read body
		defer task.response.Body.Close()
		task.body, task.err = ioutil.ReadAll(task.response.Body)
		if task.err != nil {
			log.Warnf("REST: failed to read %s %s response body (error: %s)",
				task.request.Method, task.request.URL, task.err)
			return
		}

		log.Debugf("REST: got %s %s body: %s",
			task.request.Method, task.request.URL, string(task.body))
	}()

	return ch
}
// GetServerInfo() function gets the main server's information.
func (service *Service) GetServerInfo(timeout time.Duration) (info *core.ServerInfo, err error) {
	log.Tracef("REST: getting server info...")

	task, err := service.prepareGetServerInfo()
	if err != nil {
		log.Warnf("REST: failed to prepare /info task (error: %s)", err)
		return
	}

	select {
	case <-time.After(timeout):
		log.Warnf("REST: failed to wait %s for /info task", timeout)
		err = fmt.Errorf("timed out")

	case task = <-service.doAsync(task):
		info = &core.ServerInfo{}
		err = service.processGetServerInfo(task, info)
		if err != nil {
			log.Warnf("REST: failed to process /info task (error: %s)", err)
			return
		}
	}

	return
}
Beispiel #3
0
// NewService creates new service.
func NewService(baseUrl, accessKey string) (service *Service, err error) {
	log.Tracef("REST: creating service (url:%q)", baseUrl)
	service = &Service{accessKey: accessKey}

	// remove trailing slashes from URL
	for len(baseUrl) > 1 && strings.HasSuffix(baseUrl, "/") {
		baseUrl = baseUrl[0 : len(baseUrl)-1]
	}

	// parse URL
	service.baseUrl, err = url.Parse(baseUrl)
	if err != nil {
		log.Warnf("REST: failed to parse URL (error: %s)", err)
		return
	}

	// initialize HTTP client
	service.client = &http.Client{}
	// TODO: client.Transport
	// TODO: client.CookieJar
	// TODO: client.Timeout

	service.commandListeners = make(map[string]*core.CommandListener)
	service.notificationListeners = make(map[string]*core.NotificationListener)
	return
}
// GetNetwork() function get the network data.
func (service *Service) GetNetwork(networkId uint64, timeout time.Duration) (network *core.Network, err error) {
	log.Tracef("REST: getting network %d...", networkId)

	task, err := service.prepareGetNetwork(networkId)
	if err != nil {
		log.Warnf("REST: failed to prepare /network/get task (error: %s)", err)
		return
	}

	select {
	case <-time.After(timeout):
		log.Warnf("REST: failed to wait %s for /network/get task", timeout)
		err = fmt.Errorf("timed out")

	case task = <-service.doAsync(task):
		network = &core.Network{Id: networkId}
		err = service.processGetNetwork(task, network)
		if err != nil {
			log.Warnf("REST: failed to process /network/get task (error: %s)", err)
			return
		}
	}

	return
}
Beispiel #5
0
// TX thread
func (service *Service) doTX() {
	for {
		select {
		case task, ok := <-service.tx:
			if !ok || task == nil {
				log.Infof("WS: TX thread stopped")
				service.conn.Close() // TODO: send Close frame?
				return
			}

			body, err := task.Format()
			if err != nil {
				log.Warnf("WS: failed to format message (error: %s)", err)
				continue // TODO: return?
			}

			log.Tracef("WS: sending message: %s", string(body))
			err = service.conn.WriteMessage(websocket.TextMessage, body)
			if err != nil {
				log.Warnf("WS: failed to send message (error: %s)", err)
				continue // TODO: return?
			}

			//			case <-service.pingTimer.C:
			//			if err := c.write(websocket.PingMessage, []byte{}); err != nil {
			//				log.Warnf("WS: could not write ping message (error: %s)", err)
			//				return
			//			}
		}
	}
}
// GetNotification() function get the notification data.
func (service *Service) GetNotification(device *core.Device, notificationId uint64, timeout time.Duration) (notification *core.Notification, err error) {
	log.Tracef("REST: getting notification %q/%d...", device.Id, notificationId)

	task, err := service.prepareGetNotification(device, notificationId)
	if err != nil {
		log.Warnf("REST: failed to prepare /notification/get task (error: %s)", err)
		return
	}

	select {
	case <-time.After(timeout):
		log.Warnf("REST: failed to wait %s for /notification/get task", timeout)
		err = fmt.Errorf("timed out")

	case task = <-service.doAsync(task):
		notification = &core.Notification{Id: notificationId}
		err = service.processGetNotification(task, notification)
		if err != nil {
			log.Warnf("REST: failed to process /notification/get task (error: %s)", err)
			return
		}
	}

	return
}
Beispiel #7
0
// GetDevice() function get the device data.
func (service *Service) GetDevice(deviceId, deviceKey string, timeout time.Duration) (device *core.Device, err error) {
	log.Tracef("REST: getting device %q...", deviceId)

	task, err := service.prepareGetDevice(deviceId, deviceKey)
	if err != nil {
		log.Warnf("REST: failed to prepare /device/get task (error: %s)", err)
		return
	}

	select {
	case <-time.After(timeout):
		log.Warnf("REST: failed to wait %s for /device/get task", timeout)
		err = fmt.Errorf("timed out")

	case task = <-service.doAsync(task):
		device = &core.Device{Id: deviceId, Key: deviceKey}
		err = service.processGetDevice(task, device)
		if err != nil {
			log.Warnf("REST: failed to process /device/get task (error: %s)", err)
			return
		}
	}

	return
}
Beispiel #8
0
// export main + introspectable DBus objects
func exportDBusObject(bus *dbus.Conn, w *DBusWrapper) {
	bus.Export(w, ComDevicehiveCloudPath, ComDevicehiveCloudIface)

	// main service interface
	serviceInterface := introspect.Interface{
		Name:    ComDevicehiveCloudIface,
		Methods: introspect.Methods(w),
		Signals: []introspect.Signal{
			{
				Name: "CommandReceived",
				Args: []introspect.Arg{
					{"id", "t", "in"},
					{"name", "s", "in"},
					{"parameters", "s", "in"}, // JSON string
				},
			},
		},
	}

	// main service node
	n := &introspect.Node{
		Name: ComDevicehiveCloudPath,
		Interfaces: []introspect.Interface{
			introspect.IntrospectData,
			prop.IntrospectData,
			serviceInterface},
	}
	n_obj := introspect.NewIntrospectable(n)
	log.Tracef("%q introspectable: %s", ComDevicehiveCloudPath, n_obj)
	bus.Export(n_obj, ComDevicehiveCloudPath, "org.freedesktop.DBus.Introspectable")

	// root node
	root := &introspect.Node{
		Children: []introspect.Node{
			{Name: ComDevicehiveCloudPath},
		},
	}
	root_obj := introspect.NewIntrospectable(root)
	log.Tracef("%q introspectable: %s", "/", root_obj)
	bus.Export(root_obj, "/", "org.freedesktop.DBus.Introspectable")
}
Beispiel #9
0
// NewService creates new Websocket /device service.
func NewService(baseUrl, accessKey string) (service *Service, err error) {
	log.Tracef("WS: creating service (url:%q)", baseUrl)
	service = &Service{accessKey: accessKey}

	// remove trailing slashes from URL
	for len(baseUrl) > 1 && strings.HasSuffix(baseUrl, "/") {
		baseUrl = baseUrl[0 : len(baseUrl)-1]
	}

	// parse URL
	service.baseUrl, err = url.Parse(baseUrl)
	if err != nil {
		log.Warnf("WS: failed to parse URL (error: %s)", err)
		service = nil
		return
	}

	// connect to /device endpoint
	ws_url := fmt.Sprintf("%s/device", service.baseUrl)
	headers := http.Header{}
	headers.Add("Origin", "http://localhost/")
	if len(service.accessKey) != 0 {
		headers.Add("Authorization", "Bearer "+service.accessKey)
	}
	service.conn, _, err = websocket.DefaultDialer.Dial(ws_url, headers)
	if err != nil {
		log.Warnf("WS: failed to dial (error: %s)", err)
		service = nil
		return
	}

	// set of active tasks
	service.tasks = make(map[uint64]*Task)

	// command listeners
	service.commandListeners = make(map[string]*core.CommandListener)

	// create TX channel
	service.tx = make(chan *Task)

	// and start RX/TX threads
	go service.doRX()
	go service.doTX()

	return
}
Beispiel #10
0
// RX thread
func (service *Service) doRX() {
	for {
		_, body, err := service.conn.ReadMessage()
		if err != nil {
			log.Warnf("WS: failed to receive message (error: %s)", err)
			return
		}
		log.Tracef("WS: received message: %s", string(body))

		// parse JSON
		var msg map[string]interface{}
		err = json.Unmarshal(body, &msg)
		if err != nil {
			log.Warnf("WS: failed to parse JSON (error: %s), ignored", err)
			continue
		}

		// log.Tracef("WS: parsed JSON %+v", msg)
		if v, ok := msg["requestId"]; ok {
			id := safeUint64(v)
			task := service.takeTask(id)
			if task != nil {
				task.dataRecved = msg
				task.done <- task
				continue
			}
		}

		if v, ok := msg["action"]; ok {
			action := safeString(v)
			service.handleAction(action, msg)
			continue
		}

		log.Warnf("WS: unexpected message: %s, ignored", string(body))
	}
}
// InsertNetwork() function inserts the network.
func (service *Service) InsertNetwork(network *core.Network, timeout time.Duration) (err error) {
	log.Tracef("REST: inserting network %q...", network.Name)

	task, err := service.prepareInsertNetwork(network)
	if err != nil {
		log.Warnf("REST: failed to prepare /network/insert task (error: %s)", err)
		return
	}

	select {
	case <-time.After(timeout):
		log.Warnf("REST: failed to wait %s for /network/insert task", timeout)
		err = fmt.Errorf("timed out")

	case task = <-service.doAsync(task):
		err = service.processInsertNetwork(task, network)
		if err != nil {
			log.Warnf("REST: failed to process /network/insert task (error: %s)", err)
			return
		}
	}

	return
}
Beispiel #12
0
// GetDeviceList() function get the device list.
func (service *Service) GetDeviceList(take, skip int, timeout time.Duration) (devices []core.Device, err error) {
	log.Tracef("REST: getting device list (take:%d, skip:%d)...", take, skip)

	task, err := service.prepareGetDeviceList(take, skip)
	if err != nil {
		log.Warnf("REST: failed to prepare /device/list task (error: %s)", err)
		return
	}

	select {
	case <-time.After(timeout):
		log.Warnf("REST: failed to wait %s for /device/list task", timeout)
		err = fmt.Errorf("timed out")

	case task = <-service.doAsync(task):
		devices, err = service.processGetDeviceList(task)
		if err != nil {
			log.Warnf("REST: failed to process /device/list task (error: %s)", err)
			return
		}
	}

	return
}
// GetNotification() function poll the notifications.
func (service *Service) PollNotifications(device *core.Device, timestamp, names, waitTimeout string, timeout time.Duration) (notifications []core.Notification, err error) {
	log.Tracef("REST: polling notifications %q...", device.Id)

	task, err := service.preparePollNotification(device, timestamp, names, waitTimeout)
	if err != nil {
		log.Warnf("REST: failed to prepare /notification/poll task (error: %s)", err)
		return
	}

	select {
	case <-time.After(timeout):
		log.Warnf("REST: failed to wait %s for /notification/poll task", timeout)
		err = fmt.Errorf("timed out")

	case task = <-service.doAsync(task):
		notifications, err = service.processPollNotification(task)
		if err != nil {
			log.Warnf("REST: failed to process /notification/poll task (error: %s)", err)
			return
		}
	}

	return
}
// InsertNotification() function inserts the device notification.
func (service *Service) InsertNotification(device *core.Device, notification *core.Notification, timeout time.Duration) (err error) {
	log.Tracef("REST: inserting notification %q to %q...", notification.Name, device.Id)

	task, err := service.prepareInsertNotification(device, notification)
	if err != nil {
		log.Warnf("REST: failed to prepare /notification/insert task (error: %s)", err)
		return
	}

	select {
	case <-time.After(timeout):
		log.Warnf("REST: failed to wait %s for /notification/insert task", timeout)
		err = fmt.Errorf("timed out")

	case task = <-service.doAsync(task):
		err = service.processInsertNotification(task, notification)
		if err != nil {
			log.Warnf("REST: failed to process /notification/insert task (error: %s)", err)
			return
		}
	}

	return
}
// RegisterDevice() function registers the device.
func (service *Service) RegisterDevice(device *core.Device, timeout time.Duration) (err error) {
	log.Tracef("REST: registering device %q...", device.Id)

	task, err := service.prepareRegisterDevice(device)
	if err != nil {
		log.Warnf("REST: failed to prepare /device/register task (error: %s)", err)
		return
	}

	select {
	case <-time.After(timeout):
		log.Warnf("REST: failed to wait %s for /device/register task", timeout)
		err = fmt.Errorf("timed out")

	case task = <-service.doAsync(task):
		err = service.processRegisterDevice(task)
		if err != nil {
			log.Warnf("REST: failed to process /device/register task (error: %s)", err)
			return
		}
	}

	return
}