Exemple #1
0
int
cf_fault_sink_context_strlist(int sink_id, char *context, cf_dyn_buf *db)
{
	// get the sink
	if (sink_id > cf_fault_sinks_inuse)	return(-1);
	cf_fault_sink *s = &cf_fault_sinks[sink_id];

	// get the severity
	uint i;
	for (i=0;i<CF_FAULT_CONTEXT_UNDEF;i++) {
		if (0 == strcmp(cf_fault_context_strings[i],context))
			break;
	}
	if (i == CF_FAULT_CONTEXT_UNDEF) {
		cf_dyn_buf_append_string(db, context);
		cf_dyn_buf_append_string(db, ":unknown");
		return(0);
	}

	// get the string
	cf_dyn_buf_append_string(db, context);
	cf_dyn_buf_append_char(db, ':');
	cf_dyn_buf_append_string(db, cf_fault_severity_strings[s->limit[i]]);
	return(0);
}
/**
 * Populate dyn buf with endpoints info
 * @param endpoint_list the input list. NULL allowed.
 * @param db the dynamic buffer.
 */
void
as_endpoint_list_info(const as_endpoint_list* endpoint_list, cf_dyn_buf* db)
{
	size_t endpoint_list_size = 0;
	as_endpoint_list_sizeof(endpoint_list, &endpoint_list_size);
	// 4 chars for delimiters, 50 chars for ipv6 ip and port, rounded to 64
	size_t endpoint_list_str_size = 64 * endpoint_list_size;

	char endpoint_list_str[endpoint_list_str_size];
	as_endpoint_list_to_string_match_capabilities(endpoint_list,
			endpoint_list_str, sizeof(endpoint_list_str), AS_ENDPOINT_TLS_MASK,
			0);

	cf_dyn_buf_append_string(db, "endpoint=");
	if (endpoint_list_str[0] != '\0') {
		cf_dyn_buf_append_string(db, endpoint_list_str);
	}
	cf_dyn_buf_append_string(db, ":");

	as_endpoint_list_to_string_match_capabilities(endpoint_list,
			endpoint_list_str, sizeof(endpoint_list_str), AS_ENDPOINT_TLS_MASK,
			AS_ENDPOINT_TLS_MASK);

	cf_dyn_buf_append_string(db, "endpoint-tls=");
	if (endpoint_list_str[0] != '\0') {
		cf_dyn_buf_append_string(db, endpoint_list_str);
	}

}
void
as_namespace_get_bins_info(as_namespace *ns, cf_dyn_buf *db, bool show_ns)
{
	if (show_ns) {
		cf_dyn_buf_append_string(db, ns->name);
		cf_dyn_buf_append_char(db, ':');
	}

	if (ns->single_bin) {
		cf_dyn_buf_append_string(db, "[single-bin]");
	}
	else {
		uint32_t bin_count = cf_vmapx_count(ns->p_bin_name_vmap);

		cf_dyn_buf_append_string(db, "num-bin-names=");
		cf_dyn_buf_append_uint32(db, bin_count);
		cf_dyn_buf_append_string(db, ",bin-names-quota=");
		cf_dyn_buf_append_uint32(db, BIN_NAMES_QUOTA);

		for (uint32_t i = 0; i < bin_count; i++) {
			cf_dyn_buf_append_char(db, ',');
			cf_dyn_buf_append_string(db, as_bin_get_name_from_id(ns, (uint16_t)i));
		}
	}

	if (show_ns) {
		cf_dyn_buf_append_char(db, ';');
	}
}
Exemple #4
0
void
info_append_string_safe(cf_dyn_buf *db, const char *name, const char *value)
{
	cf_dyn_buf_append_string(db, name);
	cf_dyn_buf_append_char(db, '=');
	cf_dyn_buf_append_string(db, value ? value : "null");
	cf_dyn_buf_append_char(db, ';');
}
Exemple #5
0
/*
 * Reading local directory to get specific module item's contents.
 * In future if needed we can change this to reading from smd metadata. 
 */
int udf_cask_info_get(char *name, char * params, cf_dyn_buf * out) {

	int                 resp                = 0;
	char                filename[128]       = {0};
	int                 filename_len        = sizeof(filename);
	uint8_t *           content             = NULL;
	size_t              content_len         = 0;
	unsigned char       content_gen[256]    = {0};
	uint8_t             udf_type            = AS_UDF_TYPE_LUA;

	cf_debug(AS_INFO, "UDF CASK INFO GET");

	// get (required) script filename
	if ( as_info_parameter_get(params, "filename", filename, &filename_len) ) {
		cf_info(AS_INFO, "invalid or missing filename");
		cf_dyn_buf_append_string(out, "error=invalid_filename");
		return 0;
	}

	mod_lua_rdlock(&mod_lua);
	// read the script from filesystem
	resp = file_read(filename, &content, &content_len, content_gen);
	mod_lua_unlock(&mod_lua);
	if ( resp ) {
		switch ( resp ) {
			case 1 : {
				cf_dyn_buf_append_string(out, "error=not_found");
				break;
			}
			case 2 : {
				cf_dyn_buf_append_string(out, "error=empty");
				break;
			}
			default : {
				cf_dyn_buf_append_string(out, "error=unknown_error");
				break; // complier complains without a break;
			}
		}
	}
	else {
		// put back the result
		cf_dyn_buf_append_string(out, "gen=");
		cf_dyn_buf_append_string(out, (char *) content_gen);
		cf_dyn_buf_append_string(out, ";type=");
		cf_dyn_buf_append_string(out, as_udf_type_name[udf_type]);
		cf_dyn_buf_append_string(out, ";content=");
		cf_dyn_buf_append_buf(out, content, content_len);
		cf_dyn_buf_append_string(out, ";");
	}

	if ( content ) {
		cf_free(content);
		content = NULL;
	}

	return 0;
}
Exemple #6
0
static inline void
append_indexed_name(cf_dyn_buf *db, const char *name, uint32_t ix,
		const char *attr)
{
	cf_dyn_buf_append_string(db, name);
	cf_dyn_buf_append_char(db, '[');
	cf_dyn_buf_append_uint32(db, ix);
	cf_dyn_buf_append_char(db, ']');

	if (attr) {
		cf_dyn_buf_append_char(db, '.');
		cf_dyn_buf_append_string(db, attr);
	}

	cf_dyn_buf_append_char(db, '=');
}
Exemple #7
0
int
cf_fault_sink_context_all_strlist(int sink_id, cf_dyn_buf *db)
{
	// get the sink
	if (sink_id > cf_fault_sinks_inuse)	return(-1);
	cf_fault_sink *s = &cf_fault_sinks[sink_id];

	for (uint i=0; i<CF_FAULT_CONTEXT_UNDEF; i++) {
		cf_dyn_buf_append_string(db, cf_fault_context_strings[i]);
		cf_dyn_buf_append_char(db, ':');
		cf_dyn_buf_append_string(db, cf_fault_severity_strings[s->limit[i]]);
		cf_dyn_buf_append_char(db, ';');
	}
	cf_dyn_buf_chomp(db);
	return(0);
}
//------------------------------------------------
// Append a linear histogram "snapshot" to db.
//
void
linear_hist_get_info(linear_hist *h, cf_dyn_buf *db)
{
	pthread_mutex_lock(&h->info_lock);
	cf_dyn_buf_append_string(db, h->info_snapshot);
	pthread_mutex_unlock(&h->info_lock);
}
Exemple #9
0
void
info_append_indexed_string(cf_dyn_buf *db, const char *name, uint32_t ix,
		const char *attr, const char *value)
{
	append_indexed_name(db, name, ix, attr);
	cf_dyn_buf_append_string(db, value);
	cf_dyn_buf_append_char(db, ';');
}
Exemple #10
0
void
info_append_uint64_x(cf_dyn_buf *db, const char *name, uint64_t value)
{
	cf_dyn_buf_append_string(db, name);
	cf_dyn_buf_append_char(db, '=');
	cf_dyn_buf_append_uint64_x(db, value);
	cf_dyn_buf_append_char(db, ';');
}
Exemple #11
0
void
info_append_int(cf_dyn_buf *db, const char *name, int value)
{
	cf_dyn_buf_append_string(db, name);
	cf_dyn_buf_append_char(db, '=');
	cf_dyn_buf_append_int(db, value);
	cf_dyn_buf_append_char(db, ';');
}
Exemple #12
0
void
info_append_bool(cf_dyn_buf *db, const char *name, bool value)
{
	cf_dyn_buf_append_string(db, name);
	cf_dyn_buf_append_char(db, '=');
	cf_dyn_buf_append_bool(db, value);
	cf_dyn_buf_append_char(db, ';');
}
Exemple #13
0
int udf_cask_info_remove(char *name, char * params, cf_dyn_buf * out) {

	char    filename[128]   = {0};
	int     filename_len    = sizeof(filename);
	char file_path[1024]	= {0};
	struct stat buf;

	cf_debug(AS_INFO, "UDF CASK INFO REMOVE");

	// get (required) script filename
	if ( as_info_parameter_get(params, "filename", filename, &filename_len) ) {
		cf_info(AS_UDF, "invalid or missing filename");
		cf_dyn_buf_append_string(out, "error=invalid_filename");
	}

	// now check if such a file-name exists :
	if (!g_config.mod_lua.user_path)
	{
		return -1;
	}

	snprintf(file_path, 1024, "%s/%s", g_config.mod_lua.user_path, filename);

	cf_debug(AS_INFO, " Lua file removal full-path is : %s \n", file_path);

	if (stat(file_path, &buf) != 0) {
		cf_info(AS_UDF, "failed to read file from : %s, error : %s", file_path, cf_strerror(errno));
		cf_dyn_buf_append_string(out, "error=file_not_found");
		return -1;
	}

	as_smd_delete_metadata(udf_smd_module_name, filename);

	// this is what an error would look like
	//    cf_dyn_buf_append_string(out, "error=");
	//    cf_dyn_buf_append_int(out, resp);

	cf_dyn_buf_append_string(out, "ok");

	cf_info(AS_UDF, "UDF module '%s' (%s) removed", filename, file_path);

	return 0;
}
Exemple #14
0
int
cf_fault_sink_strlist(cf_dyn_buf *db)
{
	for (int i = 0; i < cf_fault_sinks_inuse; i++) {
		cf_dyn_buf_append_int(db, i);
		cf_dyn_buf_append_char(db, ':');
		cf_dyn_buf_append_string(db,cf_fault_sinks[i].path);
		cf_dyn_buf_append_char(db, ';');
	}
	cf_dyn_buf_chomp(db);
	return(0);
}
Exemple #15
0
void
info_append_format(cf_dyn_buf *db, const char *name, const char *form, ...)
{
	va_list va;
	va_start(va, form);

	cf_dyn_buf_append_string(db, name);
	cf_dyn_buf_append_char(db, '=');
	cf_dyn_buf_append_format_va(db, form, va);
	cf_dyn_buf_append_char(db, ';');

	va_end(va);
}
int udf_cask_info_remove(char *name, char * params, cf_dyn_buf * out) {

	char    filename[128]   = {0};
	int     filename_len    = sizeof(filename);

	cf_debug(AS_INFO, "UDF CASK INFO REMOVE");

	// get (required) script filename
	if ( as_info_parameter_get(params, "filename", filename, &filename_len) ) {
		cf_info(AS_UDF, "invalid or missing filename");
		cf_dyn_buf_append_string(out, "error=invalid_filename");
	}

	as_smd_delete_metadata(udf_smd_module_name, filename);

	// this is what an error would look like
	//    cf_dyn_buf_append_string(out, "error=");
	//    cf_dyn_buf_append_int(out, resp);

	cf_dyn_buf_append_string(out, "ok");

	return 0;
}
Exemple #17
0
static int file_read(char * filename, uint8_t ** content, size_t * content_len, unsigned char * hash) {

	char    filepath[256]   = {0};
	FILE *  file            = NULL;
	char    line[1024]      = {0};
	size_t  line_len        = sizeof(line);

	file_resolve(filepath, filename, NULL);

	cf_dyn_buf_define(buf);

	file = fopen(filepath, "r");
	if ( file ) {

		while( fgets(line, line_len, file) != NULL ) {
			cf_dyn_buf_append_string(&buf, line);
		}

		fclose(file);
		file = NULL;

		if ( buf.used_sz > 0 ) {

			char *src = cf_dyn_buf_strdup(&buf);

			file_generation(filepath, (uint8_t *)src, buf.used_sz, hash);

			uint32_t src_len = (uint32_t)buf.used_sz;
			uint32_t out_size = cf_b64_encoded_len(src_len);

			*content = (uint8_t *)cf_malloc(out_size);
			*content_len = out_size;

			cf_b64_encode((const uint8_t*)src, src_len, (char*)(*content));

			cf_free(src);
			src = NULL;

			return 0;
		}

		*content = NULL;
		*content_len = 0;
		return 2;
	}

	*content = NULL;
	*content_len = 0;
	return 1;
}
void as_namespace_get_set_info(as_namespace *ns, const char *set_name, cf_dyn_buf *db)
{
	as_set *p_set;

	if (set_name) {
		if (cf_vmapx_get_by_name(ns->p_sets_vmap, set_name, (void**)&p_set) == CF_VMAPX_OK) {
			append_set_props(p_set, db);
		}

		return;
	}

	for (uint32_t idx = 0; idx < cf_vmapx_count(ns->p_sets_vmap); idx++) {
		if (cf_vmapx_get_by_index(ns->p_sets_vmap, idx, (void**)&p_set) == CF_VMAPX_OK) {
			cf_dyn_buf_append_string(db, "ns_name=");
			cf_dyn_buf_append_string(db, ns->name);
			cf_dyn_buf_append_char(db, ':');
			cf_dyn_buf_append_string(db, "set_name=");
			cf_dyn_buf_append_string(db, p_set->name);
			cf_dyn_buf_append_char(db, ':');
			append_set_props(p_set, db);
		}
	}
}
Exemple #19
0
/*
 *  Clear out the Lua cache.
 */
int udf_cask_info_clear_cache(char *name, char * params, cf_dyn_buf * out)
{
	cf_debug(AS_INFO, "UDF CASK INFO CLEAR CACHE");

	mod_lua_wrlock(&mod_lua);

	as_module_event e = {
		.type = AS_MODULE_EVENT_CLEAR_CACHE
	};
	as_module_update(&mod_lua, &e);

	mod_lua_unlock(&mod_lua);

	cf_dyn_buf_append_string(out, "ok");

	return 0;
}
Exemple #20
0
/*
 * UDF SMD get metadata items callback.
 */
static int udf_cask_get_metadata_cb(char *module, as_smd_item_list_t *items, void *udata)
{
	udf_get_data_t *p_get_data = (udf_get_data_t *) udata;
	cf_dyn_buf *out = p_get_data->db;

	unsigned char   hash[SHA_DIGEST_LENGTH];
	// hex string to be returned to the client
	unsigned char   sha1_hex_buff[CF_SHA_HEX_BUFF_LEN];
	// Currently just return directly for LUA
	uint8_t udf_type = AS_UDF_TYPE_LUA;

	for (int index = 0; index < items->num_items; index++) {
		as_smd_item_t *item = items->item[index];
		cf_debug(AS_UDF, "UDF metadata item[%d]:  module \"%s\" ; key \"%s\" ; value \"%s\" ; generation %u ; timestamp %lu",
				 index, item->module_name, item->key, item->value, item->generation, item->timestamp);
		cf_dyn_buf_append_string(out, "filename=");
		cf_dyn_buf_append_buf(out, (uint8_t *)item->key, strlen(item->key));
		cf_dyn_buf_append_string(out, ",");
		SHA1((uint8_t *)item->value, strlen(item->value), hash);

		// Convert to a hexadecimal string
		cf_convert_sha1_to_hex(hash, sha1_hex_buff);
		cf_dyn_buf_append_string(out, "hash=");
		cf_dyn_buf_append_buf(out, sha1_hex_buff, CF_SHA_HEX_BUFF_LEN);
		cf_dyn_buf_append_string(out, ",type=");
		cf_dyn_buf_append_string(out, as_udf_type_name[udf_type]);
		cf_dyn_buf_append_string(out, ";");
	}

	pthread_mutex_lock(p_get_data->mt);

	p_get_data->done = true;
	int retval = pthread_cond_signal(p_get_data->cv);
	if (retval) {
		cf_warning(AS_UDF, "pthread_cond_signal failed (rv %d)", retval);
	}

	pthread_mutex_unlock(p_get_data->mt);

	return retval;
}
int udf_cask_info_list(char *name, cf_dyn_buf * out) {

	DIR 		  * dir	             = NULL;
	bool 		    not_empty        = false;
	struct dirent * entry            = NULL;
	int 		    count 	         = 0;
	uint8_t       * content          = NULL;
	size_t          content_len      = 0;
	unsigned char   content_gen[256] = {0};
	unsigned char   hash[SHA_DIGEST_LENGTH];
	// hex string to be returned to the client
	unsigned char   sha1_hex_buff[CF_SHA_HEX_BUFF_LEN];

	cf_debug(AS_INFO, "UDF CASK INFO LIST");

	// Currently just return directly for LUA
	uint8_t 		udf_type 	    = AS_UDF_TYPE_LUA;
	dir = opendir(g_config.mod_lua.user_path);
	if ( dir == 0 ) {
		cf_warning(AS_UDF, "could not open udf directory %s: %s", g_config.mod_lua.user_path, cf_strerror(errno));
		return -1;
	}

	while ( (entry = readdir(dir)) && entry->d_name ) {

		char * name = entry->d_name;
		size_t len = strlen(name);

		// if ( len < 4 ) continue;

		if ( name[0] == '.' ) continue;

		if ( not_empty ) {
			cf_dyn_buf_append_char(out, ';');
		}
		else {
			not_empty = true;
		}

		cf_dyn_buf_append_string(out, "filename=");
		cf_dyn_buf_append_buf(out, (uint8_t *) name, len);
		cf_dyn_buf_append_string(out, ",");
		mod_lua_rdlock(&mod_lua);
		if (file_read(name, &content, &content_len, content_gen) != 0) {
			cf_info(AS_UDF, "UDF-list : file not readable");
			cf_dyn_buf_append_string(out, "error=file_not_readable");
			mod_lua_unlock(&mod_lua);
			return 0;
		}
		mod_lua_unlock(&mod_lua);
		SHA1(content, content_len, hash);
		// Convert to a hexadecimal string
		cf_convert_sha1_to_hex(hash, sha1_hex_buff);
		cf_dyn_buf_append_string(out, "hash=");
		cf_dyn_buf_append_buf(out, sha1_hex_buff, CF_SHA_HEX_BUFF_LEN);
		cf_dyn_buf_append_string(out, ",type=");
		cf_dyn_buf_append_string(out, as_udf_type_name[udf_type]);
		count ++;
	}
	if (not_empty)
	{
		cf_dyn_buf_append_string(out, ";");
	}

	closedir(dir);

	return 0;
}
void
as_namespace_get_hist_info(as_namespace *ns, char *set_name, char *hist_name,
		cf_dyn_buf *db, bool show_ns)
{
	if (show_ns) {
		cf_dyn_buf_append_string(db, ns->name);
		cf_dyn_buf_append_char(db, ':');
	}

	if (set_name == NULL || set_name[0] == 0) {
		if (strcmp(hist_name, "ttl") == 0) {
			cf_dyn_buf_append_string(db, "ttl=");
			linear_histogram_get_info(ns->ttl_hist, db);
			cf_dyn_buf_append_char(db, ';');
		} else if (strcmp(hist_name, "evict") == 0) {
			cf_dyn_buf_append_string(db, "evict=");
			linear_histogram_get_info(ns->evict_hist, db);
			cf_dyn_buf_append_char(db, ';');
		} else if (strcmp(hist_name, "evictc") == 0) {
			cf_dyn_buf_append_string(db, "evictc=");
			linear_histogram_get_info(ns->evict_coarse_hist, db);
			cf_dyn_buf_append_char(db, ';');
		} else if (strcmp(hist_name, "objsz") == 0) {
			if (ns->storage_type == AS_STORAGE_ENGINE_SSD) {
				cf_dyn_buf_append_string(db, "objsz=");
				linear_histogram_get_info(ns->obj_size_hist, db);
				cf_dyn_buf_append_char(db, ';');
			} else {
				cf_dyn_buf_append_string(db, "hist-not-applicable");
			}
		} else {
			cf_dyn_buf_append_string(db, "error-unknown-hist-name");
		}
	} else {
		uint16_t set_id = as_namespace_get_set_id(ns, set_name);
		if (set_id != INVALID_SET_ID) {
			if (strcmp(hist_name, "ttl") == 0) {
				if (ns->set_ttl_hists[set_id]) {
					cf_dyn_buf_append_string(db, "ttl=");
					linear_histogram_get_info(ns->set_ttl_hists[set_id], db);
					cf_dyn_buf_append_char(db, ';');
				} else {
					cf_dyn_buf_append_string(db, "hist-unavailable");
				}
			} else if (strcmp(hist_name, "objsz") == 0) {
				if (ns->storage_type == AS_STORAGE_ENGINE_SSD) {
					if (ns->set_obj_size_hists[set_id]) {
						cf_dyn_buf_append_string(db, "objsz=");
						linear_histogram_get_info(ns->set_obj_size_hists[set_id], db);
						cf_dyn_buf_append_char(db, ';');
					} else {
						cf_dyn_buf_append_string(db, "hist-unavailable");
					}
				} else {
					cf_dyn_buf_append_string(db, "hist-not-applicable");
				}
			} else {
				cf_dyn_buf_append_string(db, "error-unknown-hist-name");
			}
		} else {
			cf_dyn_buf_append_string(db, "error-unknown-set-name");
		}
	}
}
static void
append_set_props(as_set *p_set, cf_dyn_buf *db)
{
	cf_dyn_buf_append_string(db, "n_objects=");
	cf_dyn_buf_append_uint64(db, cf_atomic64_get(p_set->num_elements));
	cf_dyn_buf_append_char(db, ':');
	cf_dyn_buf_append_string(db, "n-bytes-memory=");
	cf_dyn_buf_append_uint64(db, cf_atomic64_get(p_set->n_bytes_memory));
	cf_dyn_buf_append_char(db, ':');
	cf_dyn_buf_append_string(db, "stop-writes-count=");
	cf_dyn_buf_append_uint64(db, cf_atomic64_get(p_set->stop_writes_count));
	cf_dyn_buf_append_char(db, ':');
	cf_dyn_buf_append_string(db, "set-enable-xdr=");
	if (cf_atomic32_get(p_set->enable_xdr) == AS_SET_ENABLE_XDR_TRUE) {
		cf_dyn_buf_append_string(db, "true");
	}
	else if (cf_atomic32_get(p_set->enable_xdr) == AS_SET_ENABLE_XDR_FALSE) {
		cf_dyn_buf_append_string(db, "false");
	}
	else if (cf_atomic32_get(p_set->enable_xdr) == AS_SET_ENABLE_XDR_DEFAULT) {
		cf_dyn_buf_append_string(db, "use-default");
	}
	else {
		cf_dyn_buf_append_uint32(db, cf_atomic32_get(p_set->enable_xdr));
	}
	cf_dyn_buf_append_char(db, ':');
	cf_dyn_buf_append_string(db, "disable-eviction=");
	if (IS_SET_EVICTION_DISABLED(p_set)) {
		cf_dyn_buf_append_string(db, "true");
	}
	else {
		cf_dyn_buf_append_string(db, "false");
	}
	cf_dyn_buf_append_char(db, ':');
	cf_dyn_buf_append_string(db, "set-delete=");
	if (IS_SET_DELETED(p_set)) {
		cf_dyn_buf_append_string(db, "true");
	}
	else {
		cf_dyn_buf_append_string(db, "false");
	}
	cf_dyn_buf_append_char(db, ';');
}
Exemple #24
0
int udf_cask_info_put(char *name, char * params, cf_dyn_buf * out) {

	cf_debug(AS_INFO, "UDF CASK INFO PUT");

	int					rc 					= 0;
	char                filename[128]       = {0};
	int                 filename_len        = sizeof(filename);
	// Content_len from the client and its expected size
	char                content_len[32]     = {0};
	int 		        clen		        = sizeof(content_len);
	// Udf content from the client and its expected length
	char	 		    *udf_content        = NULL;
	int 		        udf_content_len    = 0;
	// Udf type from the client and its expected size
	char 		         type[8]            = {0};
	int 		         type_len 	        = sizeof(type);

	// get (required) script filename
	char *tmp_char;

	if ( as_info_parameter_get(params, "filename", filename, &filename_len)
			|| !(tmp_char = strchr(filename, '.'))               // No extension in filename
			|| tmp_char == filename                              // '.' at the begining of filename
			|| strlen (tmp_char) <= 1) {                         // '.' in filename, but no extnsion e.g. "abc."
		cf_info(AS_INFO, "invalid or missing filename");
		cf_dyn_buf_append_string(out, "error=invalid_filename");
		return 0;
	}

	if ( as_info_parameter_get(params, "content-len", content_len, &(clen)) ) {
		cf_info(AS_INFO, "invalid or missing content-len");
		cf_dyn_buf_append_string(out, "error=invalid_content_len");
		return 0;
	}

	if ( as_info_parameter_get(params, "udf-type", type, &type_len) ) {
		// Replace with DEFAULT IS LUA
		strcpy(type, as_udf_type_name[0]);
	}

	// check type field
	if (-1 == udf_type_getid(type)) {
		cf_info(AS_INFO, "invalid or missing udf-type : %s not valid", type);
		cf_dyn_buf_append_string(out, "error=invalid_udf_type");
		return 0;
	}

	// get b64 encoded script
	udf_content_len = atoi(content_len) + 1;
	udf_content = (char *) cf_malloc(udf_content_len);

	if ( udf_content == NULL ) {
		cf_info(AS_UDF, "internal allocation error");
		cf_dyn_buf_append_string(out, "error=internal_error");
		// As memory is not allocated.
		// It should not continue.
		return 0;
	}

	// cf_info(AS_UDF, "content_len = %s", content_len);
	// cf_info(AS_UDF, "udf_content_len = %d", udf_content_len);


	// get (required) script content - base64 encoded here.
	if ( as_info_parameter_get(params, "content", udf_content, &(udf_content_len)) ) {
		cf_info(AS_UDF, "invalid content");
		cf_dyn_buf_append_string(out, "error=invalid_content");
		cf_free(udf_content);
		return 0;
	}

	// base 64 decode it
	uint32_t encoded_len = strlen(udf_content);
	uint32_t decoded_len = cf_b64_decoded_buf_size(encoded_len) + 1;
	
	// Don't allow UDF file size > 1MB 
	if ( decoded_len > MAX_UDF_CONTENT_LENGTH) {
		cf_info(AS_INFO, "lua file size:%d > 1MB", decoded_len);
		cf_dyn_buf_append_string(out, "error=invalid_udf_content_len, lua file size > 1MB");
		return 0;
	}

	char * decoded_str = cf_malloc(decoded_len);

	if ( ! cf_b64_validate_and_decode(udf_content, encoded_len, (uint8_t*)decoded_str, &decoded_len) ) {
		cf_info(AS_UDF, "invalid base64 content %s", filename);
		cf_dyn_buf_append_string(out, "error=invalid_base64_content");
		cf_free(decoded_str);
		return 0;
	}

	decoded_str[decoded_len] = '\0';

	as_module_error err;
	rc = as_module_validate(&mod_lua, NULL, filename, decoded_str, decoded_len, &err);

	cf_free(decoded_str);
	decoded_str = NULL;
	decoded_len = 0;

	if ( rc ) {
		cf_warning(AS_UDF, "udf-put: compile error: [%s:%d] %s", err.file, err.line, err.message);
		cf_dyn_buf_append_string(out, "error=compile_error");
		cf_dyn_buf_append_string(out, ";file=");
		cf_dyn_buf_append_string(out, err.file);
		cf_dyn_buf_append_string(out, ";line=");
		cf_dyn_buf_append_uint32(out, err.line);

		uint32_t message_len = strlen(err.message);
		uint32_t enc_message_len = cf_b64_encoded_len(message_len);
		char enc_message[enc_message_len];

		cf_b64_encode((const uint8_t*)err.message, message_len, enc_message);

		cf_dyn_buf_append_string(out, ";message=");
		cf_dyn_buf_append_buf(out, (uint8_t *)enc_message, enc_message_len);

		cf_free(udf_content);
		return 0;
	}

	// Create an empty JSON object
	json_t *udf_obj = 0;
	if (!(udf_obj = json_object())) {
		cf_warning(AS_UDF, "failed to create JSON array for receiving UDF");
		if (udf_content) cf_free(udf_content);
		return -1;
	}
	int e = 0;
	e += json_object_set_new(udf_obj, "content64", json_string(udf_content));
	e += json_object_set_new(udf_obj, "type", json_string(type));
	e += json_object_set_new(udf_obj, "name", json_string(filename));
	if (e) {
		cf_warning(AS_UDF, "could not encode UDF object, error %d", e);
		json_decref(udf_obj);
		if (udf_content) cf_free(udf_content);
		return(-1);
	}
	// make it into a string, yet another buffer copy
	char *udf_obj_str = json_dumps(udf_obj, 0/*flags*/);
	json_decref(udf_obj);
	udf_obj = 0;

	cf_debug(AS_UDF, "created json object %s", udf_obj_str);

	// how do I know whether to call create or add?
	e = as_smd_set_metadata(udf_smd_module_name, filename, udf_obj_str);
	if (e) {
		cf_warning(AS_UDF, "could not add UDF metadata, error %d", e);
		cf_free(udf_obj_str);
		if (udf_content) cf_free(udf_content);
		return(-1);
	}

	cf_info(AS_UDF, "UDF module '%s' (%s/%s) registered", filename, g_config.mod_lua.user_path, filename);

	// free the metadata
	cf_free(udf_obj_str);
	udf_obj_str = 0;

	if (udf_content) cf_free(udf_content);

	return 0;
}