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) } } }
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) } } } }