示例#1
0
func (a *AllJoynBridge) processSignals() {

	// work on currently reveived signals only
	// TODO:https://golang.org/doc/effective_go.html#leaky_buffer
	signals := a.signals
	a.signals = make(chan *dbus.Signal, 100)
	close(signals)

	// log.Printf("Processing signals: %d", len(signals))

	for signal := range signals {
		log.Printf("**** Incoming Signal: %+v", signal)

		// get signal signature
		msgId, _ := a.findSignal(signal)

		if msgId == 0 {
			log.Printf("Could not find any matching service for signal: %+v", signal)
			continue
		}

		for _, sessionId := range a.sessions {

			var status C.AJ_Status = C.AJ_OK
			msg := C.Get_AJ_Message()

			status = C.AJ_MarshalSignal_cgo((*C.AJ_Message)(msg), C.uint32_t(msgId), C.uint32_t(sessionId), C.uint8_t(0), C.uint32_t(0))
			log.Printf("**** AJ_MarshalSignal: %d", status)

			// for _, arg := range signal.Body {
			// 	log.Printf("**** ARG: %v", arg)
			// 	signature := dbus.SignatureOf(arg).String()
			// 	sig := C.CString(signature)
			// 	defer C.free(unsafe.Pointer(sig))
			// 	status = C.MarshalArg((*C.AJ_Message)(msg), sig, unsafe.Pointer(&arg))
			// 	log.Printf("**** MarshalArg: (%s, %v) => %d", signature, arg, status)
			// }

			if len(signal.Body) > 0 {

				buf := new(bytes.Buffer)
				buf.Write(make([]byte, (int)(msg.bodyBytes)))
				enc := devicehivealljoyn.NewEncoderAtOffset(buf, (int)(msg.bodyBytes), binary.LittleEndian)
				pad, err := enc.Encode(signal.Body...)

				if err != nil {
					log.Printf("Error encoding result: %s", err)
					continue
				}

				newBuf := buf.Bytes()[(int)(msg.bodyBytes)+pad:]

				status = C.AJ_DeliverMsgPartial((*C.AJ_Message)(msg), C.uint32_t(len(newBuf)))
				log.Printf("**** AJ_DeliverMsgPartial: %d", status)

				if len(newBuf) > 0 {
					status = C.AJ_MarshalRaw((*C.AJ_Message)(msg), unsafe.Pointer(&newBuf[0]), C.size_t(len(newBuf)))
					log.Printf("**** AJ_MarshalRaw: %d", status)
				} else {
					status = C.AJ_MarshalRaw((*C.AJ_Message)(msg), unsafe.Pointer(&newBuf), C.size_t(0))
					log.Printf("**** AJ_MarshalRaw: %d", status)
				}

			}

			status = C.AJ_DeliverMsg((*C.AJ_Message)(msg))
			log.Printf("**** AJ_DeliverMsg: %d", status)

			status = C.AJ_CloseMsg((*C.AJ_Message)(msg))
			log.Printf("**** AJ_CloseMsg: %d", status)
		}

	}
}
示例#2
0
func (a *AllJoynBridge) startAllJoyn(uuid string) *dbus.Error {
	service := a.services[uuid]
	objects := GetAllJoynObjects(service.objects)

	SubscribeToSignals(a.bus, service)

	myMessenger = NewAllJoynMessenger(service.dbusService, a.bus, service.objects)

	// log.Printf("StartAllJoyn: %+v", myMessenger)

	C.AJ_Initialize()
	C.AJ_RegisterObjects((*C.AJ_Object)(objects), nil)
	C.AJ_AboutRegisterPropStoreGetter((C.AJ_AboutPropGetter)(unsafe.Pointer(C.MyAboutPropGetter_cgo)))
	C.AJ_SetMinProtoVersion(10)

	// C.AJ_PrintXML((*C.AJ_Object)(objects))
	connected := false
	var status C.AJ_Status = C.AJ_OK
	busAttachment := C.Get_AJ_BusAttachment()
	msg := C.Get_AJ_Message()
	C.AJ_ClearAuthContext()

	log.Printf("CreateAJ_BusAttachment(): %+v", busAttachment)

	go func() {
		for {
			if !connected {
				busNodeName := C.CString("org.alljoyn.BusNode")
				defer C.free(unsafe.Pointer(busNodeName))
				status = C.AJ_StartService((*C.AJ_BusAttachment)(busAttachment),
					busNodeName,
					60*1000, // TODO: Move connection timeout to config
					C.FALSE,
					C.uint16_t(PORT), // TODO: Move port to config
					C.CString(service.allJoynService),
					C.AJ_NAME_REQ_DO_NOT_QUEUE,
					(*C.AJ_SessionOpts)(C.Get_Session_Opts()))

				if status != C.AJ_OK {
					continue
				}

				log.Printf("StartService returned %d, %+v", status, busAttachment)

				connected = true

				// Start Control Panel by binding a session port
				status = C.AJ_BusBindSessionPort((*C.AJ_BusAttachment)(busAttachment),
					AJ_CP_PORT, (*C.AJ_SessionOpts)(C.Get_Session_Opts()), 0)

				if status != C.AJ_OK {
					log.Printf(("Failed to send bind control panel port message"))
				}

			}

			status = C.AJ_UnmarshalMsg((*C.AJ_BusAttachment)(busAttachment), (*C.AJ_Message)(msg), 100) // TODO: Move unmarshal timeout to config

			if C.AJ_ERR_TIMEOUT == status {
				a.processSignals()
				continue
			}

			log.Printf("AJ_UnmarshalMsg: %+v", status)

			if C.AJ_OK == status {

				msgId := C.Get_AJ_Message_msgId()
				log.Printf("****Got a message, ID: 0x%X", msgId)
				dumpMessage("****Message Detais: ")

				switch {
				case msgId == C.AJ_METHOD_ACCEPT_SESSION:
					{

						var c_port C.uint16_t
						var c_sessionId C.uint32_t

						C.UnmarshalJoinSessionArgs((*C.AJ_Message)(msg), &c_port, &c_sessionId)

						port := int(c_port)
						sessionId := uint32(c_sessionId)

						if port == PORT || port == AJ_CP_PORT {
							status = C.AJ_BusReplyAcceptSession((*C.AJ_Message)(msg), C.TRUE)
							log.Printf("ACCEPT_SESSION: %d at %d port", sessionId, port)
							a.addSession(sessionId)
						} else {
							status = C.AJ_BusReplyAcceptSession((*C.AJ_Message)(msg), C.FALSE)
							log.Printf("REJECT_SESSION: %d at %d port", sessionId, port)
						}
					}

				case msgId == C.AJ_SIGNAL_SESSION_LOST_WITH_REASON:
					{
						var c_sessionId, c_reason C.uint32_t

						C.UnmarshalLostSessionArgs((*C.AJ_Message)(msg), &c_sessionId, &c_reason)

						sessionId := uint32(c_sessionId)
						reason := uint32(c_reason)
						log.Printf("Session lost: %d as of reason %d", sessionId, reason)
						a.removeSession(sessionId)
					}
				case uint32(msgId) == 0x1010003: // Config.GetConfigurations
					// our forwardAllJoyn doesn't support encrypted messages which config service is,
					// so we handle it here manually
					{
						//C.AJ_UnmarshalArgs(msg, "s", &language);
						reply := C.Get_AJ_ReplyMessage()
						C.AJ_MarshalReplyMsg((*C.AJ_Message)(msg), (*C.AJ_Message)(reply))
						C.AJ_MarshalContainer((*C.AJ_Message)(reply), (*C.AJ_Arg)(C.Get_Arg()), C.AJ_ARG_ARRAY)
						C.AJ_MarshalArgs_cgo((*C.AJ_Message)(reply), C.CString("{sv}"), C.CString("DeviceName"), C.CString("s"), C.CString("DeviceHiveVB"))
						C.AJ_MarshalArgs_cgo((*C.AJ_Message)(reply), C.CString("{sv}"), C.CString("DefaultLanguage"), C.CString("s"), C.CString("en"))
						C.AJ_MarshalCloseContainer((*C.AJ_Message)(reply), (*C.AJ_Arg)(C.Get_Arg()))
						C.AJ_DeliverMsg((*C.AJ_Message)(reply))
					}
				case (uint32(msgId) & 0x01000000) != 0:
					{
						myMessenger.forwardAllJoynMessage(uint32(msgId))
					}
				default:

					if (uint32(msgId) & 0xFFFF0000) == 0x00050000 {
						if uint32(msgId) == 0x00050102 {
							log.Printf("Passing About.GetObjectDescription %+v to AllJoyn", msgId)
							status = C.AJ_BusHandleBusMessage((*C.AJ_Message)(msg))
						} else if uint32(msgId) == 0x00050101 {
							log.Printf("Passing About.GetAboutData %+v to AllJoyn", msgId)
							status = C.AJ_BusHandleBusMessage((*C.AJ_Message)(msg))
						} else if uint32(msgId) == 0x00050000 {
							log.Printf("Passing Properties.Get %+v to AllJoyn", msgId)
							status = C.AJ_BusHandleBusMessage((*C.AJ_Message)(msg))
						} else {
							myMessenger.forwardAllJoynMessage(uint32(msgId))
						}
					} else {
						/* Pass to the built-in handlers. */
						log.Printf("Passing msgId %+v to AllJoyn", uint32(msgId))
						status = C.AJ_BusHandleBusMessage((*C.AJ_Message)(msg))
						log.Printf("AllJoyn returned %d", status)
					}
				}

				// Any received packets indicates the link is active, so call to reinforce the bus link state
				C.AJ_NotifyLinkActive()
			}

			/* Messages MUST be discarded to free resources. */
			C.AJ_CloseMsg((*C.AJ_Message)(msg))

			// if status == C.AJ_OK {
			// 	log.Print("***C.AJ_AboutAnnounce***")
			// 	C.AJ_AboutAnnounce((*C.AJ_BusAttachment)(busAttachment))
			// }

			if status == C.AJ_ERR_READ {
				C.AJ_Disconnect((*C.AJ_BusAttachment)(busAttachment))
				log.Print("AllJoyn disconnected, retrying")
				connected = false
				C.AJ_Sleep(1000 * 2) // TODO: Move sleep time to const
			}
		}
	}()
	return nil
}
func (a *AllJoynBridge) processSignals() {

	// work on currently reveived signals only
	// TODO:https://golang.org/doc/effective_go.html#leaky_buffer
	signals := a.signals
	a.signals = make(chan *dbus.Signal, 100)
	close(signals)

	// log.Printf("Processing signals: %d", len(signals))

	for signal := range signals {
		log.Printf("**** Incoming Signal: %+v", signal)

		if a.processNotificationSignal(signal) {
			continue
		}

		// get signal signature
		sigIntrospect, msgId := a.findSignal(signal)

		if msgId == 0 {
			log.Printf("Could not find any matching service for signal: %+v", signal)
			continue
		}
		log.Printf("%v", sigIntrospect)
		if isSessionless(sigIntrospect) {
			log.Printf("SESSIONLESS SIGNAL!")

			var status C.AJ_Status = C.AJ_OK
			msg := C.Get_AJ_Message()

			status = C.AJ_MarshalSignal_cgo(msg, C.uint32_t(msgId), C.uint32_t(0), C.AJ_FLAG_SESSIONLESS, C.uint32_t(0))
			log.Printf("**** AJ_MarshalSignal: %s", status)

			if len(signal.Body) > 0 {

				buf := new(bytes.Buffer)
				buf.Write(make([]byte, (int)(msg.bodyBytes)))
				enc := ajmarshal.NewEncoderAtOffset(buf, (int)(msg.bodyBytes), binary.LittleEndian)
				pad, err := enc.Encode(signal.Body...)

				if err != nil {
					log.Printf("Error encoding result: %s", err)
					continue
				}

				newBuf := buf.Bytes()[(int)(msg.bodyBytes)+pad:]

				if len(newBuf) > 0 {
					status = C.AJ_DeliverMsgPartial((*C.AJ_Message)(msg), C.uint32_t(len(newBuf)))
					log.Printf("**** AJ_DeliverMsgPartial: %s", status)
					status = C.AJ_MarshalRaw((*C.AJ_Message)(msg), unsafe.Pointer(&newBuf[0]), C.size_t(len(newBuf)))
				} else {
					status = C.AJ_MarshalRaw((*C.AJ_Message)(msg), unsafe.Pointer(&newBuf), C.size_t(0))
				}
				log.Printf("**** AJ_MarshalRaw: %s", status)

			}

			status = C.AJ_DeliverMsg((*C.AJ_Message)(msg))
			log.Printf("**** AJ_DeliverMsg: %s", status)

			status = C.AJ_CloseMsg((*C.AJ_Message)(msg))
			log.Printf("**** AJ_CloseMsg: %s", status)

		} else {

			for _, sessionId := range a.sessions {

				var status C.AJ_Status = C.AJ_OK
				msg := C.Get_AJ_Message()

				status = C.AJ_MarshalSignal_cgo(msg, C.uint32_t(msgId), C.uint32_t(sessionId), C.uint8_t(0), C.uint32_t(0))
				log.Printf("**** AJ_MarshalSignal: %s", status)

				if len(signal.Body) > 0 {

					buf := new(bytes.Buffer)
					buf.Write(make([]byte, (int)(msg.bodyBytes)))
					enc := ajmarshal.NewEncoderAtOffset(buf, (int)(msg.bodyBytes), binary.LittleEndian)
					pad, err := enc.Encode(signal.Body...)

					if err != nil {
						log.Printf("Error encoding result: %s", err)
						continue
					}

					newBuf := buf.Bytes()[(int)(msg.bodyBytes)+pad:]

					if len(newBuf) > 0 {
						status = C.AJ_DeliverMsgPartial((*C.AJ_Message)(msg), C.uint32_t(len(newBuf)))
						log.Printf("**** AJ_DeliverMsgPartial: %s", status)
						status = C.AJ_MarshalRaw((*C.AJ_Message)(msg), unsafe.Pointer(&newBuf[0]), C.size_t(len(newBuf)))
					} else {
						status = C.AJ_MarshalRaw((*C.AJ_Message)(msg), unsafe.Pointer(&newBuf), C.size_t(0))
					}
					log.Printf("**** AJ_MarshalRaw: %s", status)

				}

				status = C.AJ_DeliverMsg((*C.AJ_Message)(msg))
				log.Printf("**** AJ_DeliverMsg: %s", status)

				status = C.AJ_CloseMsg((*C.AJ_Message)(msg))
				log.Printf("**** AJ_CloseMsg: %s", status)
			}
		}
	}
}