AJ_Status unmarshalTimePropertyValue(TimePropertyValue* timePropertyValue, AJ_Message* message) { AJ_Status status; AJ_Arg outerStructArg, innerStructArg; uint16_t widgetType; status = AJ_UnmarshalContainer(message, &outerStructArg, AJ_ARG_STRUCT); if (status != AJ_OK) { return status; } status = AJ_UnmarshalArgs(message, "q", &widgetType); if (status != AJ_OK) { return status; } if (widgetType != TIME_PROPERTY) { return AJ_ERR_UNEXPECTED; } status = AJ_UnmarshalContainer(message, &innerStructArg, AJ_ARG_STRUCT); if (status != AJ_OK) { return status; } status = AJ_UnmarshalArgs(message, "qqq", &timePropertyValue->hour, &timePropertyValue->minute, &timePropertyValue->second); if (status != AJ_OK) { return status; } status = AJ_UnmarshalCloseContainer(message, &innerStructArg); if (status != AJ_OK) { return status; } return AJ_UnmarshalCloseContainer(message, &outerStructArg); }
/* * An AllJoyn dictionary entry maps cleanly to a JavaScript object property */ static AJ_Status PushDictionaryArg(duk_context* ctx, AJ_Message* msg) { AJ_Arg arg; AJ_Status status = AJ_UnmarshalContainer(msg, &arg, AJ_ARG_ARRAY); if (status == AJ_OK) { int objIndex = duk_push_object(ctx); while (status == AJ_OK) { AJ_Arg entry; status = AJ_UnmarshalContainer(msg, &entry, AJ_ARG_DICT_ENTRY); if (status == AJ_OK) { status = PushArg(ctx, msg); // key if (status == AJ_OK) { status = PushArg(ctx, msg); // value } if (status == AJ_OK) { duk_put_prop(ctx, objIndex); } AJ_UnmarshalCloseContainer(msg, &entry); } } if (status == AJ_ERR_NO_MORE) { status = AJ_OK; } AJ_UnmarshalCloseContainer(msg, &arg); } return status; }
AJ_Status unmarshalDatePropertyValue(DatePropertyValue* datePropertyValue, AJ_Message* message) { AJ_Status status; AJ_Arg outerStructArg, innerStructArg; uint16_t widgetType; status = AJ_UnmarshalContainer(message, &outerStructArg, AJ_ARG_STRUCT); if (status != AJ_OK) { return status; } status = AJ_UnmarshalArgs(message, "q", &widgetType); if (status != AJ_OK) { return status; } if (widgetType != DATE_PROPERTY) { return AJ_ERR_UNEXPECTED; } status = AJ_UnmarshalContainer(message, &innerStructArg, AJ_ARG_STRUCT); if (status != AJ_OK) { return status; } status = AJ_UnmarshalArgs(message, "qqq", &datePropertyValue->mDay, &datePropertyValue->month, &datePropertyValue->fullYear); if (status != AJ_OK) { return status; } status = AJ_UnmarshalCloseContainer(message, &innerStructArg); if (status != AJ_OK) { return status; } return AJ_UnmarshalCloseContainer(message, &outerStructArg); }
uint8_t isControlPanelAnnounce(AJ_Message* msg) { AJ_Status status = AJ_OK; AJ_Arg array1, array2, struct1; uint16_t uint1, uint2; char* buffer; status = AJ_UnmarshalArgs(msg, "q", &uint1); if (status != AJ_OK) { return FALSE; } status = AJ_UnmarshalArgs(msg, "q", &uint2); if (status != AJ_OK) { return FALSE; } status = AJ_UnmarshalContainer(msg, &array1, AJ_ARG_ARRAY); if (status != AJ_OK) { return FALSE; } do { status = AJ_UnmarshalContainer(msg, &struct1, AJ_ARG_STRUCT); if (status != AJ_OK) { return FALSE; } status = AJ_UnmarshalArgs(msg, "o", &buffer); if (status != AJ_OK) { return FALSE; } status = AJ_UnmarshalContainer(msg, &array2, AJ_ARG_ARRAY); if (status != AJ_OK) { return FALSE; } do { if ((status = AJ_UnmarshalArgs(msg, "s", &buffer)) != AJ_OK) { if (status == AJ_ERR_NO_MORE) { break; } else { return FALSE; } } if (strcmp(buffer, "org.alljoyn.ControlPanel.ControlPanel") == 0) { return TRUE; } } while (1); status = AJ_UnmarshalCloseContainer(msg, &array2); if (status != AJ_OK) { break; } status = AJ_UnmarshalCloseContainer(msg, &struct1); if (status != AJ_OK) { break; } } while (1); return FALSE; }
/* * Structs and arrays have the same representation in JavaScript. Ideally an AllJoyn struct would be * represented as a JavaScript object but struct elements are not named in the wire protocol so * there is no way to map them into object properties. */ static AJ_Status PushContainerArg(duk_context* ctx, uint8_t typeId, AJ_Message* msg) { AJ_Arg arg; AJ_Status status = AJ_UnmarshalContainer(msg, &arg, typeId); if (status == AJ_OK) { int elem = 0; int arrayIndex = duk_push_array(ctx); while (status == AJ_OK) { status = PushArg(ctx, msg); if (status == AJ_OK) { duk_put_prop_index(ctx, arrayIndex, elem++); } } if (status == AJ_ERR_NO_MORE) { status = AJ_OK; } AJ_UnmarshalCloseContainer(msg, &arg); } return status; }
static AJ_Status SetWidgetProp(AJ_Message* msg) { AJS_Widget* widget = NULL; AJ_Message reply; AJ_Status status; uint32_t propId; const char* vsig; AJ_InfoPrintf(("SetWidgetProp %s\n", msg->objPath)); status = AJ_UnmarshalPropertyArgs(msg, &propId, &vsig); /* * Two levels of variant because Set always uses a variant and the property type for the widget * is not known until runtime so is specified as a variant type in the property widget interface. */ if (status == AJ_OK) { status = AJ_UnmarshalVariant(msg, &vsig); } if (status == AJ_OK) { status = AJ_UnmarshalVariant(msg, &vsig); } if (status == AJ_OK) { widget = (AJS_Widget*)objectList[OBJ_INDEX(propId)].context; /* * Value is the only property that is writeable. Figure out how to unmarshal it. */ switch (widget->property.wdt.signature[0]) { case 'i': status = AJ_UnmarshalArgs(msg, "i", &widget->property.val.i); break; case 'q': status = AJ_UnmarshalArgs(msg, "q", &widget->property.val.q); break; case 'b': status = AJ_UnmarshalArgs(msg, "b", &widget->property.val.b); break; case 'd': status = AJ_UnmarshalArgs(msg, "d", &widget->property.val.d); break; case 's': status = AJ_UnmarshalArgs(msg, "s", &widget->property.val.s); break; default: { AJ_Arg st; uint16_t propertyType; status = AJ_UnmarshalContainer(msg, &st, AJ_ARG_STRUCT); if (status != AJ_OK) { break; } status = AJ_UnmarshalArgs(msg, "q", &propertyType); if (status != AJ_OK) { break; } /* * For some reason the implementors of the control panel service used 0/1 to * distingsuish between date/time rather than 1/2. Incrementing the property type * fixes this oversight. */ if (++propertyType != widget->property.wdt.propertyType) { status = AJ_ERR_INVALID; break; } if (propertyType == TIME_VALUE_PROPERTY) { status = AJ_UnmarshalArgs(msg, "(qqq)", &widget->property.val.time.hour, &widget->property.val.time.minute, &widget->property.val.time.second); } else { status = AJ_UnmarshalArgs(msg, "(qqq)", &widget->property.val.date.mDay, &widget->property.val.date.month, &widget->property.val.date.fullYear); } /* * Signal that the value has been changed */ AJS_CPS_SignalValueChanged(AJS_GetBusAttachment(), widget); if (status == AJ_OK) { status = AJ_UnmarshalCloseContainer(msg, &st); } } break; } } else { return AJ_ERR_RESOURCES; } /* * Need to make a clone of the message and close the original */ msg = AJS_CloneAndCloseMessage(widget->dukCtx, msg); if (!msg) { return AJ_ERR_RESOURCES; } if (status == AJ_OK) { /* * Call JavaScript to report the value change */ status = AJS_CPS_OnValueChanged(widget); } else { AJ_ErrPrintf(("SetWidgetProp %s\n", AJ_StatusText(status))); } if (status == AJ_OK) { AJ_MarshalReplyMsg(msg, &reply); } else { AJ_MarshalStatusMsg(msg, &reply, status); } AJ_DeliverMsg(&reply); return status; }
AJ_Status AJCFG_ResetConfigurationsHandler(AJ_Message* msg) { AJ_Status status = AJ_OK; AJ_Arg array; AJ_Message reply; char* key; char* language; int8_t langIndex = AJSVC_PROPERTY_STORE_ERROR_LANGUAGE_INDEX; uint8_t numOfDeletedItems = 0; uint8_t errorReply = FALSE; AJ_InfoPrintf(("Handling ResetConfigurations request\n")); status = AJ_UnmarshalArgs(msg, "s", &language); if (status != AJ_OK) { goto Exit; } AJ_InfoPrintf(("Lang=%s\n", language)); errorReply = !AJSVC_IsLanguageSupported(msg, &reply, language, &langIndex); if (!errorReply) { status = AJ_UnmarshalContainer(msg, &array, AJ_ARG_ARRAY); if (status != AJ_OK) { goto Exit; } while (1) { status = AJ_UnmarshalArgs(msg, "s", &key); if (status != AJ_OK) { break; } AJ_InfoPrintf(("Key=%s\n", key)); status = AJSVC_PropertyStore_Reset(key, langIndex); if (status == AJ_OK) { numOfDeletedItems++; } else if (status == AJ_ERR_INVALID) { if (!errorReply) { AJ_MarshalErrorMsg(msg, &reply, AJSVC_ERROR_INVALID_VALUE); errorReply = TRUE; } } else if (status == AJ_ERR_FAILURE) { if (!errorReply) { AJ_MarshalErrorMsg(msg, &reply, AJSVC_ERROR_UPDATE_NOT_ALLOWED); errorReply = TRUE; } } } if (status != AJ_OK && status != AJ_ERR_NO_MORE) { goto Exit; } status = AJ_UnmarshalCloseContainer(msg, &array); if (status != AJ_OK) { goto Exit; } } if (!errorReply) { status = AJ_MarshalReplyMsg(msg, &reply); if (status != AJ_OK) { goto Exit; } } status = AJ_DeliverMsg(&reply); if (status != AJ_OK) { goto Exit; } Exit: if (numOfDeletedItems) { if (errorReply) { AJSVC_PropertyStore_LoadAll(); // Discard partial successful deletions } else { AJSVC_PropertyStore_SaveAll(); AJ_AboutSetShouldAnnounce(); } } return status; }
AJ_Status AJNS_Consumer_NotifySignalHandler(AJ_Message* msg) { AJ_Status status; AJNS_Notification notification; AJNS_NotificationContent content; char appId[UUID_LENGTH * 2 + 1]; AJ_Arg attrbtArray; AJ_Arg customAttributeArray; AJ_Arg notTextArray; AJ_Arg richAudioArray; memset(¬ification, 0, sizeof(AJNS_Notification)); memset(&content, 0, sizeof(AJNS_NotificationContent)); notification.content = &content; AJ_InfoPrintf(("Received notification signal from sender %s\n", msg->sender)); status = AJ_UnmarshalArgs(msg, "q", ¬ification.version); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "i", ¬ification.notificationId); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "q", ¬ification.messageType); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "s", ¬ification.deviceId); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "s", ¬ification.deviceName); if (status != AJ_OK) { goto Exit; } status = AJSVC_UnmarshalAppId(msg, appId, sizeof(appId)); if (status != AJ_OK) { goto Exit; } notification.appId = appId; status = AJ_UnmarshalArgs(msg, "s", ¬ification.appName); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalContainer(msg, &attrbtArray, AJ_ARG_ARRAY); if (status != AJ_OK) { goto Exit; } while (1) { AJ_Arg dictArg; int32_t attrbtKey; const char* variantSig; status = AJ_UnmarshalContainer(msg, &dictArg, AJ_ARG_DICT_ENTRY); if (status == AJ_ERR_NO_MORE) { status = AJ_UnmarshalCloseContainer(msg, &attrbtArray); if (status != AJ_OK) { goto Exit; } else { break; } } else if (status == AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "i", &attrbtKey); if (status != AJ_OK) { goto Exit; } switch (attrbtKey) { case AJNS_RICH_CONTENT_ICON_URL_ATTRIBUTE_KEY: { status = AJ_UnmarshalVariant(msg, &variantSig); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "s", &(notification.content->richIconUrl)); if (status != AJ_OK) { goto Exit; } } break; case AJNS_RICH_CONTENT_ICON_OBJECT_PATH_ATTRIBUTE_KEY: { status = AJ_UnmarshalVariant(msg, &variantSig); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "s", &(notification.content->richIconObjectPath)); if (status != AJ_OK) { goto Exit; } } break; case AJNS_RICH_CONTENT_AUDIO_OBJECT_PATH_ATTRIBUTE_KEY: { status = AJ_UnmarshalVariant(msg, &variantSig); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "s", &(notification.content->richAudioObjectPath)); if (status != AJ_OK) { goto Exit; } } break; case AJNS_CONTROLPANELSERVICE_OBJECT_PATH_ATTRIBUTE_KEY: { status = AJ_UnmarshalVariant(msg, &variantSig); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "s", &(notification.content->controlPanelServiceObjectPath)); if (status != AJ_OK) { goto Exit; } } break; case AJNS_ORIGINAL_SENDER_NAME_ATTRIBUTE_KEY: { status = AJ_UnmarshalVariant(msg, &variantSig); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "s", ¬ification.originalSenderName); if (status != AJ_OK) { goto Exit; } } break; case AJNS_RICH_CONTENT_AUDIO_URL_ATTRIBUTE_KEY: { status = AJ_UnmarshalVariant(msg, &variantSig); if (status != AJ_OK) { goto Exit; } status = AJ_UnmarshalContainer(msg, &richAudioArray, AJ_ARG_ARRAY); if (status != AJ_OK) { goto Exit; } while (1) { AJ_Arg structArg; char* urlLanguage; char* urlText; status = AJ_UnmarshalContainer(msg, &structArg, AJ_ARG_STRUCT); if (status == AJ_ERR_NO_MORE) { status = AJ_UnmarshalCloseContainer(msg, &richAudioArray); if (status != AJ_OK) { goto Exit; } else { break; } } else if (status == AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "ss", &urlLanguage, &urlText); if (status != AJ_OK) { goto Exit; } if (notification.content->numAudioUrls < NUMALLOWEDRICHNOTS) { // if it doesn't fit we just skip richAudiosRecd[notification.content->numAudioUrls].key = urlLanguage; richAudiosRecd[notification.content->numAudioUrls].value = urlText; notification.content->numAudioUrls++; } status = AJ_UnmarshalCloseContainer(msg, &structArg); if (status != AJ_OK) { goto Exit; } } notification.content->richAudioUrls = richAudiosRecd; } break; default: AJ_InfoPrintf(("Unknown argument - skipping\n")); status = AJ_SkipArg(msg); if (status != AJ_OK) { AJ_ErrPrintf(("Error could not skip argument\n")); return status; } } status = AJ_UnmarshalCloseContainer(msg, &dictArg); if (status != AJ_OK) { goto Exit; } } status = AJ_UnmarshalContainer(msg, &customAttributeArray, AJ_ARG_ARRAY); if (status != AJ_OK) { goto Exit; } while (1) { AJ_Arg customAttributeDictArg; char* customKey; char* customVal; status = AJ_UnmarshalContainer(msg, &customAttributeDictArg, AJ_ARG_DICT_ENTRY); if (status == AJ_ERR_NO_MORE) { status = AJ_UnmarshalCloseContainer(msg, &customAttributeArray); if (status != AJ_OK) { goto Exit; } else { break; } } else if (status == AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "ss", &customKey, &customVal); if (status != AJ_OK) { goto Exit; } if (notification.content->numCustomAttributes < NUMALLOWEDCUSTOMATTRIBUTES) { // if it doesn't fit we just skip customAttributesRecd[notification.content->numCustomAttributes].key = customKey; customAttributesRecd[notification.content->numCustomAttributes].value = customVal; notification.content->numCustomAttributes++; } status = AJ_UnmarshalCloseContainer(msg, &customAttributeDictArg); if (status != AJ_OK) { goto Exit; } } notification.content->customAttributes = customAttributesRecd; status = AJ_UnmarshalContainer(msg, ¬TextArray, AJ_ARG_ARRAY); if (status != AJ_OK) { goto Exit; } while (1) { AJ_Arg structArg; char* notificationLanguage; char* notificationText; status = AJ_UnmarshalContainer(msg, &structArg, AJ_ARG_STRUCT); if (status == AJ_ERR_NO_MORE) { status = AJ_UnmarshalCloseContainer(msg, ¬TextArray); if (status != AJ_OK) { goto Exit; } else { break; } } else if (status == AJ_OK) { goto Exit; } status = AJ_UnmarshalArgs(msg, "ss", ¬ificationLanguage, ¬ificationText); if (status != AJ_OK) { goto Exit; } if (notification.content->numTexts < NUMALLOWEDTEXTS) { // if it doesn't fit we just skip textsRecd[notification.content->numTexts].key = notificationLanguage; textsRecd[notification.content->numTexts].value = notificationText; notification.content->numTexts++; } status = AJ_UnmarshalCloseContainer(msg, &structArg); if (status != AJ_OK) { goto Exit; } } notification.content->texts = textsRecd; Exit: if (status != AJ_OK) { AJ_ErrPrintf(("Handle Notification failed: '%s'\n", AJ_StatusText(status))); } else { if (appOnNotify) { status = (*appOnNotify)(¬ification); } } AJ_CloseMsg(msg); return status; }
int AJ_Main() { AJ_Status status; AJ_BusAttachment bus; AJ_Message txMsg; AJ_Message rxMsg; AJ_Arg arg; AJ_Arg array1; AJ_Arg array2; AJ_Arg struct1; AJ_Arg struct2; size_t sz; uint32_t i; uint32_t j; uint32_t k; uint32_t key; uint32_t len; uint32_t u; uint32_t v; int32_t n; int32_t m; uint16_t q; uint16_t r; uint8_t y; char* str; char* sig; void* raw; bus.sock.tx.direction = AJ_IO_BUF_TX; bus.sock.tx.bufSize = sizeof(txBuffer); bus.sock.tx.bufStart = txBuffer; bus.sock.tx.readPtr = bus.sock.tx.bufStart; bus.sock.tx.writePtr = bus.sock.tx.bufStart; bus.sock.tx.send = TxFunc; bus.sock.rx.direction = AJ_IO_BUF_RX; bus.sock.rx.bufSize = sizeof(rxBuffer); bus.sock.rx.bufStart = rxBuffer; bus.sock.rx.readPtr = bus.sock.rx.bufStart; bus.sock.rx.writePtr = bus.sock.rx.bufStart; bus.sock.rx.recv = RxFunc; /* * Set the hook */ #ifndef NDEBUG MutterHook = MsgInit; #else AJ_Printf("mutter only works in DEBUG builds\n"); return -1; #endif for (i = 0; i < ArraySize(testSignature); ++i) { status = AJ_MarshalSignal(&bus, &txMsg, i, "mutter.service", 0, 0, 0); if (status != AJ_OK) { break; } switch (i) { case 0: CHECK(AJ_MarshalContainer(&txMsg, &array1, AJ_ARG_ARRAY)); for (key = 0; key < ArraySize(Fruits); ++key) { AJ_Arg dict; CHECK(AJ_MarshalContainer(&txMsg, &dict, AJ_ARG_DICT_ENTRY)); CHECK(AJ_MarshalArgs(&txMsg, "us", key, Fruits[key])); CHECK(AJ_MarshalCloseContainer(&txMsg, &dict)); } if (status == AJ_OK) { CHECK(AJ_MarshalCloseContainer(&txMsg, &array1)); } break; case 1: CHECK(AJ_MarshalArgs(&txMsg, "u", 11111)); CHECK(AJ_MarshalContainer(&txMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_MarshalArgs(&txMsg, "usu", 22222, "hello", 33333)); CHECK(AJ_MarshalContainer(&txMsg, &struct2, AJ_ARG_STRUCT)); CHECK(AJ_MarshalArgs(&txMsg, "ii", -100, -200)); CHECK(AJ_MarshalCloseContainer(&txMsg, &struct2)); CHECK(AJ_MarshalArgs(&txMsg, "qsq", 4444, "goodbye", 5555)); CHECK(AJ_MarshalCloseContainer(&txMsg, &struct1)); CHECK(AJ_MarshalArgs(&txMsg, "yyy", 1, 2, 3)); break; case 2: CHECK(AJ_MarshalContainer(&txMsg, &array1, AJ_ARG_ARRAY)); for (u = 0; u < ArraySize(Fruits); ++u) { CHECK(AJ_MarshalContainer(&txMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_MarshalArgs(&txMsg, "us", u, Fruits[u])); CHECK(AJ_MarshalArg(&txMsg, AJ_InitArg(&arg, AJ_ARG_BYTE, AJ_ARRAY_FLAG, Data8, u))); CHECK(AJ_MarshalCloseContainer(&txMsg, &struct1)); } if (status == AJ_OK) { CHECK(AJ_MarshalCloseContainer(&txMsg, &array1)); } break; case 3: CHECK(AJ_MarshalContainer(&txMsg, &array1, AJ_ARG_ARRAY)); for (j = 0; j < 3; ++j) { CHECK(AJ_MarshalContainer(&txMsg, &array2, AJ_ARG_ARRAY)); for (k = j; k < ArraySize(Fruits); ++k) { CHECK(AJ_MarshalArgs(&txMsg, "s", Fruits[k])); } CHECK(AJ_MarshalCloseContainer(&txMsg, &array2)); } if (status == AJ_OK) { CHECK(AJ_MarshalCloseContainer(&txMsg, &array1)); } break; case 4: CHECK(AJ_MarshalArgs(&txMsg, "i", 987654321)); CHECK(AJ_MarshalVariant(&txMsg, "a(ii)")); CHECK(AJ_MarshalContainer(&txMsg, &array1, AJ_ARG_ARRAY)); for (j = 0; j < 16; ++j) { CHECK(AJ_MarshalContainer(&txMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_MarshalArgs(&txMsg, "ii", j + 1, (j + 1) * 100)); CHECK(AJ_MarshalCloseContainer(&txMsg, &struct1)); } if (status == AJ_OK) { CHECK(AJ_MarshalCloseContainer(&txMsg, &array1)); } CHECK(AJ_MarshalArgs(&txMsg, "i", 123456789)); break; case 5: CHECK(AJ_MarshalVariant(&txMsg, "(ivi)")); CHECK(AJ_MarshalContainer(&txMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_MarshalArgs(&txMsg, "i", 1212121)); CHECK(AJ_MarshalVariant(&txMsg, "s")); CHECK(AJ_MarshalArgs(&txMsg, "s", "inner variant")); CHECK(AJ_MarshalArgs(&txMsg, "i", 3434343)); CHECK(AJ_MarshalCloseContainer(&txMsg, &struct1)); break; case 6: CHECK(AJ_MarshalVariant(&txMsg, "v")); CHECK(AJ_MarshalVariant(&txMsg, "v")); CHECK(AJ_MarshalVariant(&txMsg, "v")); CHECK(AJ_MarshalVariant(&txMsg, "v")); CHECK(AJ_MarshalVariant(&txMsg, "s")); CHECK(AJ_MarshalArgs(&txMsg, "s", "deep variant")); break; case 7: CHECK(AJ_MarshalContainer(&txMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_MarshalVariant(&txMsg, "i")); CHECK(AJ_MarshalArgs(&txMsg, "i", 1212121)); CHECK(AJ_MarshalVariant(&txMsg, "s")); CHECK(AJ_MarshalArgs(&txMsg, "s", "variant")); CHECK(AJ_MarshalVariant(&txMsg, "ay")); CHECK(AJ_MarshalArg(&txMsg, AJ_InitArg(&arg, AJ_ARG_BYTE, AJ_ARRAY_FLAG, Data8, sizeof(Data8)))); CHECK(AJ_MarshalVariant(&txMsg, "aq")); CHECK(AJ_MarshalArg(&txMsg, AJ_InitArg(&arg, AJ_ARG_UINT16, AJ_ARRAY_FLAG, Data16, sizeof(Data16)))); CHECK(AJ_MarshalCloseContainer(&txMsg, &struct1)); break; case 8: CHECK(AJ_MarshalArgs(&txMsg, "uq", 0xF00F00F0, 0x0707)); len = 5000; CHECK(AJ_DeliverMsgPartial(&txMsg, len + 4)); CHECK(AJ_MarshalRaw(&txMsg, &len, 4)); for (j = 0; j < len; ++j) { uint8_t n = (uint8_t)j; CHECK(AJ_MarshalRaw(&txMsg, &n, 1)); } break; case 9: len = 500; u = len * sizeof(TestStruct); CHECK(AJ_DeliverMsgPartial(&txMsg, u + sizeof(u) + 4)); CHECK(AJ_MarshalRaw(&txMsg, &u, sizeof(u))); /* * Structs are always 8 byte aligned */ u = 0; CHECK(AJ_MarshalRaw(&txMsg, &u, 4)); for (j = 0; j < len; ++j) { TestStruct ts; ts.a = j; ts.b = j + 1; ts.c = j + 2; ts.d = j + 3; CHECK(AJ_MarshalRaw(&txMsg, &ts, sizeof(ts))); } break; case 10: CHECK(AJ_MarshalContainer(&txMsg, &array1, AJ_ARG_ARRAY)); CHECK(AJ_MarshalCloseContainer(&txMsg, &array1)); break; case 11: CHECK(AJ_MarshalArgs(&txMsg, "y", 127)); CHECK(AJ_MarshalContainer(&txMsg, &array1, AJ_ARG_ARRAY)); for (key = 0; key < ArraySize(Colors); ++key) { AJ_Arg dict; CHECK(AJ_MarshalContainer(&txMsg, &dict, AJ_ARG_DICT_ENTRY)); CHECK(AJ_MarshalArgs(&txMsg, "ss", Colors[key], Fruits[key])); CHECK(AJ_MarshalCloseContainer(&txMsg, &dict)); } if (status == AJ_OK) { CHECK(AJ_MarshalCloseContainer(&txMsg, &array1)); } break; case 12: CHECK(AJ_MarshalArgs(&txMsg, "y", 0x11)); CHECK(AJ_MarshalArgs(&txMsg, "y", 0x22)); CHECK(AJ_MarshalArgs(&txMsg, "y", 0x33)); CHECK(AJ_MarshalArgs(&txMsg, "y", 0x44)); CHECK(AJ_MarshalArgs(&txMsg, "y", 0x55)); CHECK(AJ_MarshalContainer(&txMsg, &array1, AJ_ARG_ARRAY)); for (key = 0; key < ArraySize(Colors); ++key) { AJ_Arg dict; CHECK(AJ_MarshalContainer(&txMsg, &dict, AJ_ARG_DICT_ENTRY)); CHECK(AJ_MarshalArgs(&txMsg, "ys", (uint8_t)key, Colors[key])); CHECK(AJ_MarshalCloseContainer(&txMsg, &dict)); } if (status == AJ_OK) { CHECK(AJ_MarshalCloseContainer(&txMsg, &array1)); } break; case 13: CHECK(AJ_MarshalContainer(&txMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_MarshalArgs(&txMsg, "i", 3434343)); CHECK(AJ_MarshalArg(&txMsg, AJ_InitArg(&arg, AJ_ARG_BYTE, AJ_ARRAY_FLAG, Data8, sizeof(Data8)))); CHECK(AJ_MarshalCloseContainer(&txMsg, &struct1)); break; } if (status != AJ_OK) { AJ_Printf("Failed %d\n", i); break; } AJ_Printf("deliver\n"); AJ_DeliverMsg(&txMsg); status = AJ_UnmarshalMsg(&bus, &rxMsg, 0); if (status != AJ_OK) { break; } switch (i) { case 0: CHECK(AJ_UnmarshalContainer(&rxMsg, &array1, AJ_ARG_ARRAY)); while (TRUE) { char* fruit; AJ_Arg dict; CHECK(AJ_UnmarshalContainer(&rxMsg, &dict, AJ_ARG_DICT_ENTRY)); CHECK(AJ_UnmarshalArgs(&rxMsg, "us", &key, &fruit)); AJ_Printf("Unmarshal[%d] = %s\n", key, fruit); CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &dict)); } /* * We expect AJ_ERR_NO_MORE */ if (status == AJ_ERR_NO_MORE) { CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &array1)); } break; case 1: CHECK(AJ_UnmarshalArgs(&rxMsg, "u", &u)); AJ_Printf("Unmarshal %u\n", u); CHECK(AJ_UnmarshalContainer(&rxMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_UnmarshalArgs(&rxMsg, "usu", &u, &str, &v)); AJ_Printf("Unmarshal %u %s %u\n", u, str, v); CHECK(AJ_UnmarshalContainer(&rxMsg, &struct2, AJ_ARG_STRUCT)); CHECK(AJ_UnmarshalArgs(&rxMsg, "ii", &n, &m)); AJ_Printf("Unmarshal %d %d\n", n, m); CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &struct2)); CHECK(AJ_UnmarshalArgs(&rxMsg, "qsq", &q, &str, &r)); AJ_Printf("Unmarshal %u %s %u\n", q, str, r); CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &struct1)); CHECK(AJ_UnmarshalArgs(&rxMsg, "y", &y)); AJ_Printf("Unmarshal %d\n", y); CHECK(AJ_UnmarshalArgs(&rxMsg, "y", &y)); AJ_Printf("Unmarshal %d\n", y); CHECK(AJ_UnmarshalArgs(&rxMsg, "y", &y)); AJ_Printf("Unmarshal %d\n", y); break; case 2: CHECK(AJ_UnmarshalContainer(&rxMsg, &array1, AJ_ARG_ARRAY)); while (status == AJ_OK) { CHECK(AJ_UnmarshalContainer(&rxMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_UnmarshalArgs(&rxMsg, "us", &u, &str)); CHECK(AJ_UnmarshalArg(&rxMsg, &arg)); CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &struct1)); } /* * We expect AJ_ERR_NO_MORE */ if (status == AJ_ERR_NO_MORE) { CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &array1)); } break; case 3: CHECK(AJ_UnmarshalContainer(&rxMsg, &array1, AJ_ARG_ARRAY)); while (status == AJ_OK) { CHECK(AJ_UnmarshalContainer(&rxMsg, &array2, AJ_ARG_ARRAY)); while (status == AJ_OK) { CHECK(AJ_UnmarshalArg(&rxMsg, &arg)); AJ_Printf("Unmarshal %s\n", arg.val.v_string); } /* * We expect AJ_ERR_NO_MORE */ if (status == AJ_ERR_NO_MORE) { CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &array2)); } } /* * We expect AJ_ERR_NO_MORE */ if (status == AJ_ERR_NO_MORE) { CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &array1)); } break; case 4: CHECK(AJ_UnmarshalArgs(&rxMsg, "i", &j)); AJ_Printf("Unmarshal %d\n", j); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalContainer(&rxMsg, &array1, AJ_ARG_ARRAY)); while (status == AJ_OK) { CHECK(AJ_UnmarshalContainer(&rxMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_UnmarshalArgs(&rxMsg, "ii", &j, &k)); AJ_Printf("Unmarshal[%d] %d\n", j, k); CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &struct1)); } /* * We expect AJ_ERR_NO_MORE */ if (status != AJ_ERR_NO_MORE) { break; } CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &array1)); CHECK(AJ_UnmarshalArgs(&rxMsg, "i", &j)); AJ_Printf("Unmarshal %d\n", j); break; case 5: CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalContainer(&rxMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_UnmarshalArgs(&rxMsg, "i", &j)); AJ_Printf("Unmarshal %d\n", j); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalArgs(&rxMsg, "s", &str)); AJ_Printf("Unmarshal %s\n", str); CHECK(AJ_UnmarshalArgs(&rxMsg, "i", &j)); AJ_Printf("Unmarshal %d\n", j); CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &struct1)); break; case 6: CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalArgs(&rxMsg, "s", &str)); AJ_Printf("Unmarshal %s\n", str); break; case 7: CHECK(AJ_UnmarshalContainer(&rxMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalArgs(&rxMsg, "i", &j)); AJ_Printf("Unmarshal %d\n", j); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalArgs(&rxMsg, "s", &str)); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalArg(&rxMsg, &arg)); CHECK(AJ_UnmarshalVariant(&rxMsg, (const char**)&sig)); AJ_Printf("Unmarshal variant %s\n", sig); CHECK(AJ_UnmarshalArg(&rxMsg, &arg)); CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &struct1)); break; case 8: CHECK(AJ_UnmarshalArgs(&rxMsg, "uq", &j, &q)); AJ_Printf("Unmarshal %x\n", j); AJ_Printf("Unmarshal %x\n", q); CHECK(AJ_UnmarshalRaw(&rxMsg, (const void**)&raw, sizeof(len), &sz)); len = *((uint32_t*)raw); AJ_Printf("UnmarshalRaw %d\n", len); for (j = 0; j < len; ++j) { uint8_t v; CHECK(AJ_UnmarshalRaw(&rxMsg, (const void**)&raw, 1, &sz)); v = *((uint8_t*)raw); if (v != (uint8_t)j) { status = AJ_ERR_FAILURE; break; } } break; case 9: CHECK(AJ_UnmarshalRaw(&rxMsg, (const void**)&raw, 4, &sz)); len = *((uint32_t*)raw) / sizeof(TestStruct); /* * Structs are always 8 byte aligned */ CHECK(AJ_UnmarshalRaw(&rxMsg, (const void**)&raw, 4, &sz)); for (j = 0; j < len; ++j) { TestStruct* ts; CHECK(AJ_UnmarshalRaw(&rxMsg, (const void**)&ts, sizeof(TestStruct), &sz)); if ((ts->a != j) || (ts->b != (j + 1)) || (ts->c != (j + 2)) || (ts->d != (j + 3))) { status = AJ_ERR_FAILURE; break; } } break; case 10: CHECK(AJ_UnmarshalContainer(&rxMsg, &array1, AJ_ARG_ARRAY)); status = AJ_UnmarshalArg(&rxMsg, &arg); /* * We expect AJ_ERR_NO_MORE */ if (status == AJ_ERR_NO_MORE) { CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &array1)); } break; case 11: CHECK(AJ_UnmarshalArgs(&rxMsg, "y", &y)); CHECK(AJ_UnmarshalContainer(&rxMsg, &array1, AJ_ARG_ARRAY)); while (TRUE) { AJ_Arg dict; char* fruit; char* color; CHECK(AJ_UnmarshalContainer(&rxMsg, &dict, AJ_ARG_DICT_ENTRY)); CHECK(AJ_UnmarshalArgs(&rxMsg, "ss", &color, &fruit)); AJ_Printf("Unmarshal[%s] = %s\n", color, fruit); CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &dict)); } /* * We expect AJ_ERR_NO_MORE */ if (status == AJ_ERR_NO_MORE) { CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &array1)); } break; case 12: CHECK(AJ_UnmarshalArgs(&rxMsg, "y", &y)); CHECK(AJ_UnmarshalArgs(&rxMsg, "y", &y)); CHECK(AJ_UnmarshalArgs(&rxMsg, "y", &y)); CHECK(AJ_UnmarshalArgs(&rxMsg, "y", &y)); CHECK(AJ_UnmarshalArgs(&rxMsg, "y", &y)); CHECK(AJ_UnmarshalContainer(&rxMsg, &array1, AJ_ARG_ARRAY)); while (TRUE) { AJ_Arg dict; char* color; CHECK(AJ_UnmarshalContainer(&rxMsg, &dict, AJ_ARG_DICT_ENTRY)); CHECK(AJ_UnmarshalArgs(&rxMsg, "ys", &y, &color)); AJ_Printf("Unmarshal[%d] = %s\n", y, color); CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &dict)); } /* * We expect AJ_ERR_NO_MORE */ if (status == AJ_ERR_NO_MORE) { CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &array1)); } break; case 13: CHECK(AJ_UnmarshalContainer(&rxMsg, &struct1, AJ_ARG_STRUCT)); CHECK(AJ_UnmarshalArgs(&rxMsg, "i", &n)); AJ_ASSERT(n == 3434343); CHECK(AJ_UnmarshalArg(&rxMsg, &arg)); for (j = 0; j < arg.len; ++j) { uint8_t val = arg.val.v_byte[j]; AJ_Printf("Unmarhsalled array1[%u] = %u\n", j, val); AJ_ASSERT(val == Data8[j]); } CHECK(AJ_UnmarshalCloseContainer(&rxMsg, &struct1)); break; } if (status != AJ_OK) { AJ_Printf("Failed %d\n", i); break; } AJ_CloseMsg(&rxMsg); AJ_Printf("Passed %d\n", i); } if (status != AJ_OK) { AJ_Printf("Marshal/Unmarshal unit test[%d] failed %d\n", i, status); } return status; }
LampResponseCode LAMP_UnmarshalState(LampStateContainer* state, AJ_Message* msg) { AJ_Arg array1, struct1; AJ_Status status = AJ_UnmarshalContainer(msg, &array1, AJ_ARG_ARRAY); LampResponseCode responseCode = LAMP_OK; AJ_DumpMsg("LAMP_UnmarshalState", msg, TRUE); // initialize memset(state, 0, sizeof(LampStateContainer)); do { char* field; char* sig; status = AJ_UnmarshalContainer(msg, &struct1, AJ_ARG_DICT_ENTRY); if (status != AJ_OK) { break; } status = AJ_UnmarshalArgs(msg, "s", &field); if (status != AJ_OK) { printf("AJ_UnmarshalArgs: %s\n", AJ_StatusText(status)); return LAMP_ERR_MESSAGE; } // Process the field! status = AJ_UnmarshalVariant(msg, (const char**) &sig); if (status != AJ_OK) { AJ_ErrPrintf(("AJ_UnmarshalVariant: %s\n", AJ_StatusText(status))); return LAMP_ERR_MESSAGE; } if (0 == strcmp(field, "OnOff")) { uint32_t onoff; status = AJ_UnmarshalArgs(msg, "b", &onoff); state->state.onOff = onoff ? TRUE : FALSE; state->stateFieldIndicators |= LAMP_STATE_ON_OFF_FIELD_INDICATOR; } else if (0 == strcmp(field, "Hue")) { status = AJ_UnmarshalArgs(msg, "u", &state->state.hue); state->stateFieldIndicators |= LAMP_STATE_HUE_FIELD_INDICATOR; } else if (0 == strcmp(field, "Saturation")) { status = AJ_UnmarshalArgs(msg, "u", &state->state.saturation); state->stateFieldIndicators |= LAMP_STATE_SATURATION_FIELD_INDICATOR; } else if (0 == strcmp(field, "ColorTemp")) { status = AJ_UnmarshalArgs(msg, "u", &state->state.colorTemp); state->stateFieldIndicators |= LAMP_STATE_COLOR_TEMP_FIELD_INDICATOR; } else if (0 == strcmp(field, "Brightness")) { status = AJ_UnmarshalArgs(msg, "u", &state->state.brightness); state->stateFieldIndicators |= LAMP_STATE_BRIGHTNESS_FIELD_INDICATOR; } else { AJ_ErrPrintf(("Unknown field: %s\n", field)); responseCode = LAMP_ERR_MESSAGE; AJ_SkipArg(msg); } status = AJ_UnmarshalCloseContainer(msg, &struct1); // if field invalid, throw the whole thing out and return the error } while (status == AJ_OK && responseCode == LAMP_OK); AJ_UnmarshalCloseContainer(msg, &array1); return responseCode; }
/* * Announcements are processed as follows: * * 1) First check if there is an existing session for the announcement sender. If not create and * initialize an empty session object. A session object has two properties "info" which is a buffer * that holds state information about the session and an array "anno" which is used to accumulate * announcements from the same sender. * 2) Unmarshal the announcement signal and if there is a callback registered for any of the * interfaces add a service object to announcements array. The "interfaces" property on the * service object is an array of all interfaces in the announcement. * 3) If there is already a session with the announcement sender make callbacks now, otherwise send * a JOIN_SESSION method call to join the session with the announcement sender. The callbacks are * reevaluated when the JOIN_SESSION reply is received. */ AJ_Status AJS_AboutAnnouncement(duk_context* ctx, AJ_Message* msg) { AJ_BusAttachment* aj = msg->bus; AJ_Status status; uint16_t version; duk_idx_t anIdx; SessionInfo* sessionInfo; AJ_Arg objList; const char* sender; AJ_InfoPrintf(("AJS_AboutAnnouncement\n")); /* * Ignore our own announcements */ if (strcmp(msg->sender, AJ_GetUniqueName(msg->bus)) == 0) { AJ_InfoPrintf(("Ignoring our own announcement\n")); return AJ_OK; } /* * Push the sender string on the stack to stabilize it. */ sender = duk_push_string(ctx, msg->sender); /* * Announcements are accumulated in a global stash object indexed by peer name */ AJS_GetGlobalStashObject(ctx, "sessions"); sessionInfo = AllocSessionObject(ctx, sender); /* * Get the announcements array */ duk_get_prop_string(ctx, -1, "anno"); anIdx = duk_get_top_index(ctx); /* * Find out if there are JavaScript handlers for this announcement */ AJ_UnmarshalArgs(msg, "qq", &version, &sessionInfo->port); status = AJ_UnmarshalContainer(msg, &objList, AJ_ARG_ARRAY); while (status == AJ_OK) { int ifcCount = 0; uint8_t hasCB = FALSE; AJ_Arg obj; AJ_Arg interfaces; const char* path; status = AJ_UnmarshalContainer(msg, &obj, AJ_ARG_STRUCT); if (status != AJ_OK) { break; } AJ_UnmarshalArgs(msg, "o", &path); /* * Array to accumulate interfaces */ duk_push_array(ctx); status = AJ_UnmarshalContainer(msg, &interfaces, AJ_ARG_ARRAY); while (status == AJ_OK) { /* * Accumulate interfaces checking */ const char* iface; status = AJ_UnmarshalArgs(msg, "s", &iface); if (status == AJ_OK) { duk_push_string(ctx, iface); duk_put_prop_index(ctx, -2, ifcCount++); } /* * We will disard the interface array if no callbacks are registered. */ if (!hasCB && HasServiceCallback(ctx, iface)) { hasCB = TRUE; } } if (hasCB) { AddServiceObject(ctx, sessionInfo, path, sender); /* * Append service object to the announcements array for processing later */ duk_put_prop_index(ctx, anIdx, duk_get_length(ctx, anIdx)); } else { /* discard the interface array */ duk_pop(ctx); } if (status == AJ_ERR_NO_MORE) { status = AJ_UnmarshalCloseContainer(msg, &interfaces); } if (status == AJ_OK) { status = AJ_UnmarshalCloseContainer(msg, &obj); } } if (status == AJ_ERR_NO_MORE) { status = AJ_UnmarshalCloseContainer(msg, &objList); } /* * All done with this message - we need to close it now to free up the output buffer before we * attempt to call AJ_BusJoinSession() below. */ AJ_CloseMsg(msg); /* Pop "anno" and the session object */ duk_pop_2(ctx); if (status != AJ_OK) { goto Exit; } /* * If we already have a session with this peer callback with the new service objects */ if (sessionInfo->sessionId) { AnnouncementCallbacks(ctx, sender, sessionInfo); goto Exit; } /* * If there is a JOIN_SESSION in progress we have nothing more to do */ if (sessionInfo->replySerial != 0) { goto Exit; } /* * If announcements were registered attempt to join the session */ if (sessionInfo->refCount) { status = AJ_BusJoinSession(aj, sender, sessionInfo->port, NULL); if (status == AJ_OK) { sessionInfo->replySerial = aj->serial - 1; } } /* * At this point if we don't have a JOIN_SESSION in progress we must delete the session object */ if (sessionInfo->replySerial == 0) { duk_del_prop_string(ctx, -2, sender); } Exit: /* Pop "sessions" and sender string */ duk_pop_2(ctx); return status; }