/* Load from a dynamic library */ static int corto_load_fromDl(corto_dl dl, char *fileName, int argc, char *argv[]) { int (*proc)(int argc, char* argv[]); corto_debug("loader: invoke cortomain of '%s' with %d arguments", fileName, argc); /* Lookup main function */ proc = (int(*)(int,char*[]))corto_dlProc(dl, "cortomain"); if (proc) { /* Call main */ if (proc(argc, argv)) { if (!corto_lasterr()) { corto_seterr("cortomain failed"); } goto error; } } else { corto_string ___ (*build)(void); /* Lookup build function */ build = (corto_string ___ (*)(void))corto_dlProc(dl, "corto_getBuild"); if (build) { corto_seterr("library '%s' linked with corto but does not have a cortomain", fileName); goto error; } } /* Add library to libraries list */ corto_mutexLock (&corto_adminLock); if (!libraries) { libraries = corto_ll_new(); } corto_ll_insert(libraries, dl); corto_mutexUnlock (&corto_adminLock); corto_debug("loader: loaded '%s'", fileName); return 0; error: return -1; }
static corto_dl corto_load_validLibrary(corto_string fileName, corto_string *build_out) { corto_dl result = NULL; corto_string ___ (*build)(void); corto_string ___ (*library)(void); if (build_out) { *build_out = NULL; } if (!(result = corto_dlOpen(fileName))) { corto_seterr("%s", corto_dlError()); goto error; } /* Lookup build function */ build = (corto_string ___ (*)(void))corto_dlProc(result, "corto_getBuild"); library = (corto_string ___ (*)(void))corto_dlProc(result, "corto_getLibrary"); /* Validate version */ if (build && strcmp(build(), corto_getBuild())) { corto_seterr( "corto: library '%s' links with conflicting corto library\n" " links with: '%s' (%s)\n" " current: '%s' (%s)\n", fileName, library ? library() : "???", build(), corto_getLibrary(), corto_getBuild()); /* Library is linked with different Corto version */ if (build_out) { *build_out = corto_strdup(build()); } goto error; } else if (build) { corto_debug( "loader: '%s' links with correct corto library\n build: '%s'\n library: '%s'\n", fileName, build(), library()); } else { corto_trace("loader: found '%s' which doesn't link with corto", fileName); } /* If no build function is available, the library is not linked with * Corto, and probably represents a --nocorto package */ return result; error: if (result) corto_dlClose(result); return NULL; }
static void mqtt_onLog(struct mosquitto *mosq, void *obj, int level, const char *str) { corto_debug("%s", str); }
static void mqtt_onMessage( struct mosquitto *client, void *data, const struct mosquitto_message *msg) { corto_id nameBuffer; char *name = nameBuffer; corto_object o = NULL; mqtt_Connector this = data; corto_bool isDelete = FALSE; /* If the payload has been serialized as a corto string, the typename is * potentially prefixed to the value */ char *valueStr = strchr(msg->payload, '{'); /* mqtt is the owner of this thread. This ensures that all subsequent create * update / delete actions are performed with the right owner. Ownership * ensures to not trigger on own updates, and to only forward data from * other connectors (or the application). */ corto_object prevOwner = corto_setOwner(this); /* Remove topic from name, so that name is relative to mount point. */ strcpy(name, msg->topic); if (this->topic) { name += strlen(this->topic) + 1; } char *lastElem = strrchr(name, '/'); if (lastElem && !strcmp(lastElem, "/_d")) { *lastElem = '\0'; isDelete = TRUE; } corto_debug("mqtt: %s: received '%s'", msg->topic, msg->payload); /* If object doesn't yet exist in the store, create it */ if (!(o = corto_lookup(corto_mount(this)->mount, name)) && !isDelete) { corto_id buffer; corto_debug("mqtt: creating new object for '%s'", name); /* If the mount has been configured with a fixed type, use that type to * create a new object. Otherwise, look for type in payload. */ if (corto_observer(this)->type) { strcpy(buffer, corto_observer(this)->type); } else { char *typeStr = strchr(msg->payload, '{'); memcpy(buffer, msg->payload, typeStr - (char*)msg->payload); buffer[typeStr - (char*)msg->payload] = '\0'; } /* Resolve type. If type wasn't yet loaded in corto, corto_resolve will * do a lookup on the package repository. If it doesn't exist there * either throw an error. Currently, the MQTT connector does not align * types. */ corto_type type = corto_resolve(NULL, buffer); if (!type) { corto_error("mqtt: type '%s' not found", buffer); goto error; } corto_debug("mqtt: creating '%s' with type '%s'", name, buffer); /* Create a new object under the mountpoint. The name is derived from * the MQTT topic name. */ o = corto_declareChild(corto_mount(this)->mount, name, type); if (!o) { corto_error("mqtt: failed to create object '%s'", name); goto error; } } else { corto_debug("mqtt: found '%s' for '%s'", corto_fullpath(NULL, o), name); } /* Only continue updating object when it is owned by mqtt */ if (o && corto_owned(o)) { if (isDelete) { if (corto_delete(o)) { corto_error("mqtt: failed to delete '%s': %s", name, corto_lasterr()); } corto_release(o); } else { /* Start updating object (takes a writelock) */ if (!corto_updateBegin(o)) { /* Serialize value from JSON string */ if (corto_fromcontent(o, "text/json", valueStr)) { corto_error("mqtt: failed to deserialize for %s: %s (%s)\n", name, corto_lasterr(), msg->payload); /* If deserialization fails, cancel the update. No notification * will be sent. */ corto_updateCancel(o); goto error; } /* Successful update. Send notification and unlock object */ if (corto_updateEnd(o)) { corto_error("mqtt: failed to update '%s': %s", name, corto_lasterr()); goto error; } } else { /* For some reason, couldn't start updating object */ corto_error("mqtt: failed to start updating '%s': %s", name, corto_lasterr()); goto error; } } } else if (o) { corto_debug("mqtt: '%s' not owned by me (%s, defined = %d), ignoring", corto_fullpath(NULL, o), corto_ownerof(o) ? corto_fullpath(NULL, o) : "local", corto_checkState(o, CORTO_DEFINED)); } error: /* Restore previous owner */ corto_setOwner(prevOwner); }