コード例 #1
0
ファイル: communication.c プロジェクト: DBattisti/antidote
/**
 * Runs connection loop over communication layer.
 * This function must run after 'communication_network_start()'operation.
 *
 * @param ctx current context
 */
void communication_connection_loop(Context *ctx)
{
	ContextId id = ctx->id;

	if (get_connection_loop_active(ctx))
		return; // connection loop already running

	if (!communication_is_network_started()) {
		ERROR(" The network layer is not initialized, call communication_network_start() first.");
		return;
	}

	set_connection_loop_active(ctx, 1); // activate loop flag

	DEBUG(" communication:Waiting for data\n");

	// context may become invalid right after wait_for_data_input,
	// so we need so check it every loop, based on ID.

	while ((ctx = context_get_and_lock(id))) {
		if (!get_connection_loop_active(ctx)) {
			context_unlock(ctx);
			break;
		}

		communication_wait_for_data_input(ctx);
		communication_read_input_stream(id);
		context_unlock(ctx);
	}
}
コード例 #2
0
static void event_get_context(void * arg) {
    GetContextArgs * s = (GetContextArgs *)arg;
    Channel * c = s->c;
    Context * ctx = s->ctx;

    if (!is_stream_closed(c)) {
        int err = 0;

        write_stringz(&c->out, "R");
        write_stringz(&c->out, s->token);

        if (ctx->exited) err = ERR_ALREADY_EXITED;
        write_errno(&c->out, err);

        if (err == 0) {
            write_context(&c->out, ctx, s->parent != 0);
            write_stream(&c->out, 0);
        }
        else {
            write_stringz(&c->out, "null");
        }

        write_stream(&c->out, MARKER_EOM);
        flush_stream(&c->out);
    }
    stream_unlock(c);
    context_unlock(ctx);
    loc_free(s);
}
コード例 #3
0
ファイル: context.c プロジェクト: prodigeni/kplugs
/* add a function to a context */
int context_add_function(context_t *cont, function_t *func)
{
	function_t *check_func = NULL;

	context_lock(cont);

	if (func->name != NULL) {
		/* this is a function with a name */
		check_func = LIST_TO_STRUCT(function_t, list, cont->funcs.next);

		/* check that we don't have this function's name already */
		while (check_func != NULL) {
			if (!string_compare(check_func->name, func->name)) {
				context_unlock(cont);
				ERROR(-ERROR_FEXIST);
			}
			check_func = LIST_TO_STRUCT(function_t, list, check_func->list.next);
		}

		/* add the function to the funcs list */
		func->list.next = cont->funcs.next;
		func->list.prev = &cont->funcs;

		if (cont->funcs.next != NULL) {
			cont->funcs.next->prev = &func->list;
		}
		cont->funcs.next = &func->list;

	} else {
		/* this is a anonymous function */

		/* add the function to the anonym list */
		func->list.next = cont->anonym.next;
		func->list.prev = &cont->anonym;

		if (cont->anonym.next != NULL) {
			cont->anonym.next->prev = &func->list;
		}
		cont->anonym.next = &func->list;
	}

	func->cont = cont;

	context_unlock(cont);
	return 0;
}
コード例 #4
0
ファイル: communication.c プロジェクト: DBattisti/antidote
/**
 * Reads APDU from transport layer stream
 *
 * @param id connection context
 */
void communication_read_input_stream(ContextId id)
{
	Context *ctx = context_get_and_lock(id);
	if (ctx != NULL) {
		communication_process_input_data(ctx, communication_get_apdu_stream(ctx));
		context_unlock(ctx);
	}
}
コード例 #5
0
ファイル: context.c プロジェクト: prodigeni/kplugs
/* copy the last exception to inside or outside memory */
int context_get_last_exception(context_t *cont, exception_t *excep)
{
	int ret;

	context_lock(cont);

	if (!cont->last_exception.had_exception) {
		context_unlock(cont);

		ERROR(-ERROR_PARAM);
	}

	ret = safe_memory_copy(excep, &cont->last_exception, sizeof(exception_t), ADDR_UNDEF, ADDR_INSIDE, 0, 0);

	cont->last_exception.had_exception = 0;

	context_unlock(cont);

	return ret;
}
コード例 #6
0
ファイル: context.c プロジェクト: prodigeni/kplugs
/* find an anonymous function by address */
void *context_find_anonymous(context_t *cont, byte *ptr)
{
	function_t *func;

	context_lock(cont);

	func = LIST_TO_STRUCT(function_t, list, cont->anonym.next);
	while (func != NULL) {
		if (func->func_code == ptr) {
			function_get(func);

			context_unlock(cont);
			return func;
		}
		func = LIST_TO_STRUCT(function_t, list, func->list.next);
	}

	context_unlock(cont);

	return NULL;
}
コード例 #7
0
ファイル: context.c プロジェクト: prodigeni/kplugs
/* find a function by name */
void *context_find_function(context_t *cont, byte *name)
{
	function_t *func;

	context_lock(cont);

	func = LIST_TO_STRUCT(function_t, list, cont->funcs.next);
	while (func != NULL) {
		if (!string_compare(func->name, (char *)name)) {
			function_get(func);

			context_unlock(cont);
			return func;
		}
		func = LIST_TO_STRUCT(function_t, list, func->list.next);
	}

	context_unlock(cont);

	return NULL;
}
コード例 #8
0
ファイル: context.c プロジェクト: prodigeni/kplugs
/* remove and delete a function from the context */
void context_free_function(function_t *func)
{
	context_t *cont = func->cont;

	context_lock(cont);

	if (NULL == func->list.prev && NULL == func->list.next) {
		/* This is a race condition! The function was already removed from the context... */
		context_unlock(cont);
		return;
	}

	func->list.prev->next = func->list.next;
	if (func->list.next != NULL) {
		func->list.next->prev = func->list.prev;
	}

	func->list.prev = NULL;
	func->list.next = NULL;

	function_put(func);

	context_unlock(cont);
}
コード例 #9
0
ファイル: context.c プロジェクト: prodigeni/kplugs
/* create a reply */
void context_create_reply(context_t *cont, word val, exception_t *excep)
{
	context_lock(cont);

	if (NULL != excep) {
		memory_copy(&cont->last_exception, excep, sizeof(exception_t));
	}

	memory_set(&cont->cmd, 0, sizeof(kplugs_command_t));
	cont->cmd.val1 = val;
	cont->cmd.type = KPLUGS_REPLY;
	cont->has_answer = 1;

	context_unlock(cont);
}
コード例 #10
0
ファイル: communication.c プロジェクト: DBattisti/antidote
/**
 * Destroys a connection context,
 * see topic 8.1 of IEEE 11071-20601 documentation
 *
 * @param id context id
 * @param addr transport address (informative)
 */
void communication_transport_disconnect_indication(ContextId id, const char *addr)
{
	Context *ctx = context_get_and_lock(id);

	if (!ctx)
		return;

	communication_fire_transport_disconnect_evt(ctx);

	if (disconnection_listener)
		disconnection_listener(ctx, addr);

	context_unlock(ctx);

	context_remove(id);
}
コード例 #11
0
static void event_terminate(void * x) {
    TerminateArgs * args = (TerminateArgs *)x;
    Context * ctx = args->ctx;
    TCFBroadcastGroup * bcg = args->bcg;
    LINK * qp = ctx->children.next;
    while (qp != &ctx->children) {
        Context * c = cldl2ctxp(qp);
        if (c->intercepted) send_event_context_resumed(&bcg->out, c);
        c->pending_intercept = 0;
        c->pending_signals |= 1 << SIGKILL;
        qp = qp->next;
    }
    if (ctx->intercepted) send_event_context_resumed(&bcg->out, ctx);
    ctx->pending_intercept = 0;
    ctx->pending_signals |= 1 << SIGKILL;
    context_unlock(ctx);
    loc_free(args);
}
コード例 #12
0
ファイル: context.c プロジェクト: prodigeni/kplugs
/* copy the reply back to the user */
int context_get_reply(context_t *cont, char *buf, word length)
{
	word copy;

	context_lock(cont);

	/* return an answer if there is one */
	if (cont->has_answer) {
		copy = (length > sizeof(kplugs_command_t)) ? sizeof(kplugs_command_t) : length;
		memory_copy(buf, &cont->cmd, copy);
		cont->has_answer = 0;
	} else {
		copy = 0;
	}

	context_unlock(cont);

	return (int)copy;
}
コード例 #13
0
ファイル: trans.c プロジェクト: DBattisti/antidote
/**
 * Called by any transcoding plug-in when a device connects
 *
 * @param plugin the transcoding plugin
 * @param lladdr low-level address of device (opaque at this level)
 * @param spec MDS attributes, at the very least must contain specialization
 * @param assoc_info association information in 11073 format
 * @param config device configuration in 11073 format
 * @return 0 if error, >0 if ok
 */
int trans_connected(TransPlugin *plugin,
			char *lladdr,
			AttributeList spec,
			PhdAssociationInformation assoc_info,
			ConfigReport config)
{
	// create context, if any
	ContextId context = trans_context_get(lladdr, plugin);

	if (!context.plugin) {
		DEBUG("Transcoding: context not found for %s", lladdr);
		return 0;
	}

	communication_transport_connect_indication(context, lladdr);

	Context *ctx = context_get_and_lock(context);
	if (!ctx) {
		DEBUG("Transcoding: context struct not found");
		return 0;
	}

	association_accept_data_protocol_20601_in(ctx, assoc_info, 1);
	del_phdassociationinformation(&assoc_info);

	// following call deletes config_report (if necessary)
	configuring_perform_configuration_in(ctx, config, NULL, 1);

	int i;
	for (i = 0; i < spec.count; i++) {
		AVA_Type *attribute = &spec.value[i];
		mds_set_attribute(ctx->mds, attribute);
	}

	context_unlock(ctx);

	del_attributelist(&spec);

	return 1;
}
コード例 #14
0
ファイル: trans.c プロジェクト: DBattisti/antidote
/**
 * Called by any transcoding plug-in when measurement data is received
 *
 * @param plugin the transcoding plugin
 * @param lladdr low-level address of device (opaque at this level)
 * @param report Measurement data in 11073 format
 * @return 0 if error, >0 if ok
 */
int trans_event_report_var(TransPlugin *plugin,
			char *lladdr,
			ScanReportInfoVar report)
{
	// passing plugin = NULL indirectly blocks creation
	ContextId context = trans_context_get(lladdr, NULL);

	if (!context.plugin) {
		DEBUG("Transcoded %s no context for evt report (var)", lladdr);
		return 0;
	}
	Context *ctx = context_get_and_lock(context);
	if (!ctx) {
		DEBUG("Transcoding: context struct not found");
		return 0;
	}

	mds_event_report_dynamic_data_update_var(ctx, &report);
	context_unlock(ctx);
	del_scanreportinfovar(&report);
	return 1;
}
コード例 #15
0
static void safe_memory_get(void * parm) {
    MemoryCommandArgs * args = (MemoryCommandArgs *)parm;
    Channel * c = args->c;
    Context * ctx = args->ctx;

    if (!is_channel_closed(c)) {
        Trap trap;
        if (set_trap(&trap)) {
            OutputStream * out = &args->c->out;
            char * token = args->token;
            ContextAddress addr0 = args->addr;
            ContextAddress addr = args->addr;
            unsigned long size = args->size;
            unsigned long pos = 0;
            char buf[BUF_SIZE];
            int err = 0;
            MemoryErrorInfo err_info;
            JsonWriteBinaryState state;

            memset(&err_info, 0, sizeof(err_info));
            if (ctx->exiting || ctx->exited) err = ERR_ALREADY_EXITED;

            write_stringz(out, "R");
            write_stringz(out, token);

            json_write_binary_start(&state, out, size);
            while (pos < size) {
                int rd = size - pos;
                if (rd > BUF_SIZE) rd = BUF_SIZE;
                /* TODO: word size, mode */
                memset(buf, 0, rd);
                if (err == 0) {
                    if (context_read_mem(ctx, addr, buf, rd) < 0) {
                        err = errno;
#if ENABLE_ExtendedMemoryErrorReports
                        context_get_mem_error_info(&err_info);
#endif
                    }
                    else {
                        addr += rd;
                    }
                }
                json_write_binary_data(&state, buf, rd);
                pos += rd;
            }
            json_write_binary_end(&state);
            write_stream(out, 0);

            write_errno(out, err);
            if (err == 0) {
                write_stringz(out, "null");
            }
            else {
                write_ranges(out, addr0, (int)(addr - addr0), BYTE_CANNOT_READ, &err_info);
            }
            write_stream(out, MARKER_EOM);
            clear_trap(&trap);
        }
        else {
            trace(LOG_ALWAYS, "Exception in Memory.get: %s", errno_to_str(trap.error));
            channel_close(c);
        }
    }
    channel_unlock(c);
    context_unlock(ctx);
    loc_free(args);
}
コード例 #16
0
static void event_pid_exited(pid_t pid, int status, int signal) {
    Context * ctx;

    ctx = context_find_from_pid(pid, 1);
    if (ctx == NULL) {
        ctx = find_pending(pid);
        if (ctx == NULL) {
            trace(LOG_EVENTS, "event: ctx not found, pid %d, exit status %d, term signal %d", pid, status, signal);
        }
        else {
            assert(ctx->ref_count == 0);
            ctx->ref_count = 1;
            if (EXT(ctx)->attach_callback != NULL) {
                if (status == 0) status = EINVAL;
                EXT(ctx)->attach_callback(status, ctx, EXT(ctx)->attach_data);
            }
            assert(list_is_empty(&ctx->children));
            assert(ctx->parent == NULL);
            ctx->exited = 1;
            context_unlock(ctx);
        }
    }
    else {
        /* Note: ctx->exiting should be 1 here. However, PTRACE_EVENT_EXIT can be lost by PTRACE because of racing
         * between PTRACE_CONT (or PTRACE_SYSCALL) and SIGTRAP/PTRACE_EVENT_EXIT. So, ctx->exiting can be 0.
         */
        if (EXT(ctx->parent)->pid == pid) ctx = ctx->parent;
        assert(EXT(ctx)->attach_callback == NULL);
        if (ctx->exited) {
            trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d unexpected, stopped %d, exited %d",
                ctx, pid, status, ctx->stopped, ctx->exited);
        }
        else {
            trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d, term signal %d", ctx, pid, status, signal);
            ctx->exiting = 1;
            if (ctx->stopped) send_context_started_event(ctx);
            if (!list_is_empty(&ctx->children)) {
                LINK * l = ctx->children.next;
                while (l != &ctx->children) {
                    Context * c = cldl2ctxp(l);
                    l = l->next;
                    assert(c->parent == ctx);
                    if (!c->exited) {
                        c->exiting = 1;
                        if (c->stopped) send_context_started_event(c);
                        release_error_report(EXT(c)->regs_error);
                        loc_free(EXT(c)->regs);
                        EXT(c)->regs_error = NULL;
                        EXT(c)->regs = NULL;
                        send_context_exited_event(c);
                    }
                }
            }
            release_error_report(EXT(ctx)->regs_error);
            loc_free(EXT(ctx)->regs);
            EXT(ctx)->regs_error = NULL;
            EXT(ctx)->regs = NULL;
            send_context_exited_event(ctx);
        }
    }
}
コード例 #17
0
static void safe_memory_fill(void * parm) {
    MemoryCommandArgs * args = (MemoryCommandArgs *)parm;
    Channel * c = args->c;
    Context * ctx = args->ctx;

    if (!is_channel_closed(c)) {
        Trap trap;
        if (set_trap(&trap)) {
            InputStream * inp = &c->inp;
            OutputStream * out = &c->out;
            char * token = args->token;
            ContextAddress addr0 = args->addr;
            ContextAddress addr = args->addr;
            unsigned long size = args->size;
            MemoryErrorInfo err_info;
            MemoryFillBuffer buf;
            char * tmp = NULL;
            int err = 0;

            memset(&err_info, 0, sizeof(err_info));
            if (ctx->exiting || ctx->exited) err = ERR_ALREADY_EXITED;

            memset(&buf, 0, sizeof(buf));
            buf.buf = (char *)tmp_alloc(buf.max = BUF_SIZE);

            if (err) json_skip_object(inp);
            else json_read_array(inp, read_memory_fill_array_cb, &buf);
            json_test_char(inp, MARKER_EOA);
            json_test_char(inp, MARKER_EOM);

            while (err == 0 && buf.pos < size && buf.pos <= buf.max / 2) {
                if (buf.pos == 0) {
                    buf.buf[buf.pos++] = 0;
                }
                else {
                    memcpy(buf.buf + buf.pos, buf.buf, buf.pos);
                    buf.pos *= 2;
                }
            }

            while (err == 0 && addr < addr0 + size) {
                /* Note: context_write_mem() modifies buffer contents */
                unsigned wr = (unsigned)(addr0 + size - addr);
                if (tmp == NULL) tmp = (char *)tmp_alloc(buf.pos);
                if (wr > buf.pos) wr = buf.pos;
                /* TODO: word size, mode */
                memcpy(tmp, buf.buf, wr);
                if (context_write_mem(ctx, addr, tmp, wr) < 0) {
                    err = errno;
#if ENABLE_ExtendedMemoryErrorReports
                    context_get_mem_error_info(&err_info);
#endif
                }
                else {
                    addr += wr;
                }
            }

            send_event_memory_changed(ctx, addr0, size);

            write_stringz(out, "R");
            write_stringz(out, token);
            write_errno(out, err);
            if (err == 0) {
                write_stringz(out, "null");
            }
            else {
                write_ranges(out, addr0, (int)(addr - addr0), BYTE_CANNOT_WRITE, &err_info);
            }
            write_stream(out, MARKER_EOM);
            clear_trap(&trap);
        }
        else {
            trace(LOG_ALWAYS, "Exception in Memory.fill: %s", errno_to_str(trap.error));
            channel_close(c);
        }
    }
    channel_unlock(c);
    context_unlock(ctx);
    loc_free(args);
}
コード例 #18
0
static void safe_memory_set(void * parm) {
    MemoryCommandArgs * args = (MemoryCommandArgs *)parm;
    Channel * c = args->c;
    Context * ctx = args->ctx;

    if (!is_channel_closed(c)) {
        Trap trap;
        if (set_trap(&trap)) {
            InputStream * inp = &c->inp;
            OutputStream * out = &c->out;
            char * token = args->token;
            ContextAddress addr0 = args->addr;
            ContextAddress addr = args->addr;
            unsigned long size = 0;
            char buf[BUF_SIZE];
            int err = 0;
            MemoryErrorInfo err_info;
            JsonReadBinaryState state;

            memset(&err_info, 0, sizeof(err_info));
            if (ctx->exiting || ctx->exited) err = ERR_ALREADY_EXITED;

            json_read_binary_start(&state, inp);
            for (;;) {
                int rd = json_read_binary_data(&state, buf, sizeof(buf));
                if (rd == 0) break;
                if (err == 0) {
                    /* TODO: word size, mode */
                    if (context_write_mem(ctx, addr, buf, rd) < 0) {
                        err = errno;
#if ENABLE_ExtendedMemoryErrorReports
                        context_get_mem_error_info(&err_info);
#endif
                    }
                    else {
                        addr += rd;
                    }
                }
                size += rd;
            }
            json_read_binary_end(&state);
            json_test_char(inp, MARKER_EOA);
            json_test_char(inp, MARKER_EOM);

            send_event_memory_changed(ctx, addr0, size);

            write_stringz(out, "R");
            write_stringz(out, token);
            write_errno(out, err);
            if (err == 0) {
                write_stringz(out, "null");
            }
            else {
                write_ranges(out, addr0, (int)(addr - addr0), BYTE_CANNOT_WRITE, &err_info);
            }
            write_stream(out, MARKER_EOM);
            clear_trap(&trap);
        }
        else {
            trace(LOG_ALWAYS, "Exception in Memory.set: %s", errno_to_str(trap.error));
            channel_close(c);
        }
    }
    channel_unlock(c);
    context_unlock(ctx);
    loc_free(args);
}