void listen_for_connection(int *listener) { int connection, connect_result; connect_result = -1; do { connect_result = wait_for_connection(*listener, &connection); } while(connect_result < 0); pthread_create(&listener_thread, NULL, (void *(*)(void *)) listen_for_connection, listener); handle_rpc(connection); }
static void call_tee(uintptr_t parg32, struct teesmc32_arg *arg32) { u32 ret; u32 funcid; struct smc_param param = { 0 }; if (irqs_disabled()) funcid = TEESMC32_FASTCALL_WITH_ARG; else funcid = TEESMC32_CALL_WITH_ARG; param.a1 = parg32; while (true) { param.a0 = funcid; tee_smc_call(¶m); ret = param.a0; if (ret == TEESMC_RETURN_EBUSY) { /* "Can't happen" */ BUG_ON(1); } else if (TEESMC_RETURN_IS_RPC(ret)) { /* Process the RPC. */ funcid = handle_rpc(¶m); } else { break; } } switch (ret) { case TEESMC_RETURN_UNKNOWN_FUNCTION: arg32->ret = TEEC_ERROR_NOT_IMPLEMENTED; arg32->ret_origin = TEEC_ORIGIN_COMMS; break; case TEESMC_RETURN_OK: /* arg32->ret set by secure world */ break; default: /* Should not happen */ arg32->ret = TEEC_ERROR_COMMUNICATION; arg32->ret_origin = TEEC_ORIGIN_COMMS; break; } }
static void do_listen(struct ovs_cmdl_context *ctx) { struct pstream *pstream; struct jsonrpc **rpcs; size_t n_rpcs, allocated_rpcs; bool done; int error; error = jsonrpc_pstream_open(ctx->argv[1], &pstream, DSCP_DEFAULT); if (error) { ovs_fatal(error, "could not listen on \"%s\"", ctx->argv[1]); } daemonize(); rpcs = NULL; n_rpcs = allocated_rpcs = 0; done = false; for (;;) { struct stream *stream; size_t i; /* Accept new connections. */ error = pstream_accept(pstream, &stream); if (!error) { if (n_rpcs >= allocated_rpcs) { rpcs = x2nrealloc(rpcs, &allocated_rpcs, sizeof *rpcs); } rpcs[n_rpcs++] = jsonrpc_open(stream); } else if (error != EAGAIN) { ovs_fatal(error, "pstream_accept failed"); } /* Service existing connections. */ for (i = 0; i < n_rpcs; ) { struct jsonrpc *rpc = rpcs[i]; struct jsonrpc_msg *msg; jsonrpc_run(rpc); if (!jsonrpc_get_backlog(rpc)) { error = jsonrpc_recv(rpc, &msg); if (!error) { error = handle_rpc(rpc, msg, &done); jsonrpc_msg_destroy(msg); } else if (error == EAGAIN) { error = 0; } } if (!error) { error = jsonrpc_get_status(rpc); } if (error) { jsonrpc_close(rpc); ovs_error(error, "connection closed"); memmove(&rpcs[i], &rpcs[i + 1], (n_rpcs - i - 1) * sizeof *rpcs); n_rpcs--; } else { i++; } } /* Wait for something to do. */ if (done && !n_rpcs) { break; } pstream_wait(pstream); for (i = 0; i < n_rpcs; i++) { struct jsonrpc *rpc = rpcs[i]; jsonrpc_wait(rpc); if (!jsonrpc_get_backlog(rpc)) { jsonrpc_recv_wait(rpc); } } poll_block(); } free(rpcs); pstream_close(pstream); }
static void handle_client_rpc(struct arbiter_thread *abt, struct abt_request *req) { struct rpc_header *hdr; struct client_desc *c; //sanitization if (req->pkt_size <= 0) { AB_MSG("arbiter: NULL packet or recieved failed!\n"); return; } if (req->pkt_size < sizeof(struct rpc_header)) { AB_MSG("arbiter: incomplete packt received.\n"); return; } //retrieve the header hdr = (struct rpc_header *)req->data; if (hdr->abt_magic != ABT_RPC_MAGIC || hdr->msg_len < sizeof(struct rpc_header)) { AB_MSG("arbiter: malformed message received.\n"); return; } //retrive the client information according to the client socket addr c = arbiter_lookup_client(abt, req->client_addr, req->client_addr_len); if (c == NULL ) { AB_MSG("arbiter: unknown client, opcode=%d\n", hdr->opcode); return; } #ifdef _RPC_COUNT static int rpc_count[10] = {0}; rpc_count[hdr->opcode] += 1; printf("RPC count:\n" "pthread_create: %d\n" "pthread_join: %d\n" "malloc: %d\n" "free: %d\n" "create_category: %d\n" "get_label: %d\n" "get_ownership: %d\n" "get_mem_label: %d\n" "calloc: %d\n" "realloc: %d\n", rpc_count[0], rpc_count[1], rpc_count[2], rpc_count[3], rpc_count[4], rpc_count[5], rpc_count[6], rpc_count[7], rpc_count[8], rpc_count[9]); #endif switch(hdr->opcode) { case ABT_CREATE_CAT: { AB_INFO("arbiter: create_cat rpc received. req no=%d.\n", req->pkt_sn); handle_create_cat_rpc(abt, c, req, hdr); break; } case ABT_FORK: { AB_INFO("arbiter: fork rpc received. req no=%d.\n", req->pkt_sn); handle_fork_rpc(abt, c, req, hdr); break; } case ABT_PTHREAD_JOIN: { AB_INFO("arbiter: pthread_join rpc received. req no=%d.\n", req->pkt_sn); handle_pthread_join_rpc(abt, c, req, hdr); break; } case ABT_MALLOC: { AB_INFO("arbiter: malloc rpc received. req no=%d.\n", req->pkt_sn); //the handling routine handle_malloc_rpc(abt, c, req, hdr); break; } case ABT_FREE: { AB_INFO("arbiter: free rpc received. req no=%d.\n", req->pkt_sn); handle_free_rpc(abt, c, req, hdr); break; } case ABT_GET_LABEL: { AB_INFO("arbiter: get_label rpc received. req no=%d.\n", req->pkt_sn); handle_get_label_rpc(abt, c, req, hdr); break; } case ABT_GET_OWNERSHIP: { AB_INFO("arbiter: get_ownership rpc received. req no=%d.\n", req->pkt_sn); handle_get_ownership_rpc(abt, c, req, hdr); break; } case ABT_GET_MEM_LABEL: { AB_INFO("arbiter: get_mem_label rpc received. req no=%d.\n", req->pkt_sn); handle_get_mem_label_rpc(abt, c, req, hdr); break; } case ABT_CALLOC: { AB_INFO("arbiter: calloc rpc received. req no=%d.\n", req->pkt_sn); //the handling routine handle_calloc_rpc(abt, c, req, hdr); break; } case ABT_REALLOC: { AB_INFO("arbiter: realloc rpc received. req no=%d.\n", req->pkt_sn); //the handling routine handle_realloc_rpc(abt, c, req, hdr); break; } case ABT_RPC: { //the handling routine handle_rpc(abt, c, req, hdr); break; } default: AB_MSG("arbiter rpc: Invallid OP code!\n"); } }
static void call_tee(struct tee_tz *ptee, uintptr_t parg32, struct teesmc32_arg *arg32) { u32 ret; u32 funcid; struct smc_param param = { 0 }; if (irqs_disabled()) funcid = TEESMC32_FASTCALL_WITH_ARG; else funcid = TEESMC32_CALL_WITH_ARG; /* * Commented out elements used to visualize the layout dynamic part * of the struct. Note that these fields are not available at all * if num_params == 0. * * params is accessed through the macro TEESMC32_GET_PARAMS */ /* struct teesmc32_param params[num_params]; */ param.a1 = parg32; e_lock_teez(ptee); while (true) { param.a0 = funcid; tee_smc_call(¶m); ret = param.a0; if (ret == TEESMC_RETURN_EBUSY) { /* * Since secure world returned busy, release the * lock we had when entering this function and wait * for "something to happen" (something else to * exit from secure world and needed resources may * have become available). */ e_lock_wait_completion_teez(ptee); } else if (TEESMC_RETURN_IS_RPC(ret)) { /* Process the RPC. */ e_unlock_teez(ptee); funcid = handle_rpc(ptee, ¶m); e_lock_teez(ptee); } else { break; } } e_unlock_teez(ptee); switch (ret) { case TEESMC_RETURN_UNKNOWN_FUNCTION: break; case TEESMC_RETURN_OK: /* arg32->ret set by secure world */ break; default: /* Should not happen */ arg32->ret = TEEC_ERROR_COMMUNICATION; arg32->ret_origin = TEEC_ORIGIN_COMMS; break; } }