Ejemplo n.º 1
0
func (m *AllJoynMessenger) forwardAllJoynMessage(msgId uint32) (err error) {
	log.Printf("****forwardAllJoynMessage****")
	msg := C.Get_AJ_Message()
	reply := C.Get_AJ_ReplyMessage()

	var data uintptr
	var actual C.size_t

	b := make([]byte, 0)
	signature := C.GoString(C.Get_AJ_Message_signature())
	bodyLen := C.Get_AJ_Message_bodyLen()
	for i := 0; i < int(bodyLen); i++ {
		status := C.AJ_UnmarshalRaw((*C.AJ_Message)(msg), (*unsafe.Pointer)(unsafe.Pointer(&data)), C.size_t(1), (*C.size_t)(unsafe.Pointer(&actual)))
		if status == C.AJ_OK {
			b = append(b, C.GoBytes(unsafe.Pointer(data), C.int(actual))...)
			// log.Printf("Reading RAW message, status = %d, actual = %d", status, actual)
		} else {
			log.Printf("Error while reading message body, status = %d", status)
			break
		}
	}
	s, err := dbus.ParseSignature(signature)

	if err != nil {
		log.Printf("Error parsing signature: %s", err)
		return err
	}

	d := dbus.NewDecoder(bytes.NewReader(b), binary.LittleEndian)
	res, err := d.Decode(s)

	if err != nil {
		log.Printf("Error decoding message [%+v] : %s", b, err)
		return err
	}

	//log.Printf("Received application alljoyn message, signature: %s, bytes: %+v, decoded: %+v", signature, b, res)

	objPath := C.GoString(C.Get_AJ_Message_objPath())
	member := C.GoString(C.Get_AJ_Message_member())
	destination := C.GoString(C.Get_AJ_Message_destination())
	iface := C.GoString(C.Get_AJ_Message_iface())

	log.Printf("****Message [objPath, member, iface, destination]: %s, %s, %s, %s", objPath, member, iface, destination)

	for _, service := range m.binding {
		if service.allJoynPath == objPath {
			log.Printf("Found matching dbus service: %+v", service)
			C.AJ_MarshalReplyMsg((*C.AJ_Message)(msg), (*C.AJ_Message)(reply))
			m.callRemoteMethod((*C.AJ_Message)(reply), service.dbusPath, iface+"."+member, res)
			C.AJ_DeliverMsg((*C.AJ_Message)(reply))
			break
		}
	}
	return nil
}
Ejemplo n.º 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
}