/** * Handles incoming data on a client connection. * @param socket_server Socket server * @param conn Client connection */ static void handle_connection(struct lwpb_transport_socket_server *socket_server, struct lwpb_socket_server_conn *conn) { void *res_buf; size_t res_len; ssize_t len; size_t used; struct protocol_header_info info; lwpb_err_t ret; used = conn->pos - conn->buf; len = recv(conn->socket, conn->pos, conn->len - used, 0); if (len <= 0) { close_connection(socket_server, conn); return; } conn->pos += len; used = conn->pos - conn->buf; LWPB_DEBUG("Client(%d) received %d bytes", conn->index, len); // Try to decode the request ret = parse_request(conn->buf, used, &info, socket_server->server->service_list); if (ret != PARSE_ERR_OK) return; LWPB_DEBUG("Client(%d) received request header", conn->index); LWPB_DEBUG("type = %d, service = %p, method = %p, header_len = %d, msg_len = %d", info.msg_type, info.service_desc, info.method_desc, info.header_len, info.msg_len); if (!info.service_desc) { // TODO unknown service } if (!info.method_desc) { // TODO unknown method } // Allocate response buffer ret = lwpb_transport_alloc_buf(&socket_server->super, &res_buf, &res_len); if (ret != LWPB_ERR_OK) { // TODO handle memory error } ret = socket_server->server->call_handler( socket_server->server, info.method_desc, info.method_desc->req_desc,conn->buf + info.header_len, info.msg_len, info.method_desc->res_desc, res_buf, &res_len, socket_server->server->arg); // Send response back to server send_response(conn->socket, info.method_desc, res_buf, res_len); lwpb_transport_free_buf(&socket_server->super, res_buf); }
/** * Closes the socket client. * @param transport Transport handle */ void lwpb_transport_socket_client_close(lwpb_transport_t transport) { struct lwpb_transport_socket_client *socket_client = (struct lwpb_transport_socket_client *) transport; int i; if (socket_client->socket == -1) return; // Free receive buffer lwpb_transport_free_buf(transport, socket_client->buf); // Close socket close(socket_client->socket); socket_client->socket == -1; }
/** * This method is called from the client to start an RPC call. * @param transport Transport implementation * @param client Client * @param method_desc Method descriptor * @return Returns LWPB_ERR_OK if successful. */ static lwpb_err_t transport_call(lwpb_transport_t transport, struct lwpb_client *client, const struct lwpb_method_desc *method_desc) { struct lwpb_transport_socket_client *socket_client = (struct lwpb_transport_socket_client *) transport; lwpb_err_t ret = LWPB_ERR_OK; void *req_buf = NULL; size_t req_len; // Only continue if connected to server if (socket_client->socket == -1) { client->done_handler(client, method_desc, LWPB_RPC_NOT_CONNECTED, client->arg); goto out; } // Allocate a buffer for the request message ret = lwpb_transport_alloc_buf(transport, &req_buf, &req_len); if (ret != LWPB_ERR_OK) goto out; // Encode the request message ret = client->request_handler(client, method_desc, method_desc->req_desc, req_buf, &req_len, client->arg); if (ret != LWPB_ERR_OK) goto out; socket_client->last_method = method_desc; // Send the request to the server // TODO check result send_request(socket_client->socket, method_desc, req_buf, req_len); out: // Free allocated requiest message buffer if (req_buf) lwpb_transport_free_buf(transport, req_buf); return ret; }
/** * This method is called from the client to start an RPC call. * @param transport Transport implementation * @param client Client * @param method_desc Method descriptor * @return Returns LWPB_ERR_OK if successful. */ static lwpb_err_t transport_call(lwpb_transport_t transport, struct lwpb_client *client, const struct lwpb_method_desc *method_desc) { struct lwpb_transport_socket_server *socket_server = (struct lwpb_transport_socket_server *) transport; lwpb_err_t ret = LWPB_ERR_OK; void *req_buf = NULL; size_t req_len; void *res_buf = NULL; size_t res_len; // Allocate a buffer for the request message ret = lwpb_transport_alloc_buf(transport, &req_buf, &req_len); if (ret != LWPB_ERR_OK) goto out; // Allocate a buffer for the response message ret = lwpb_transport_alloc_buf(transport, &res_buf, &res_len); if (ret != LWPB_ERR_OK) goto out; // Encode the request message ret = client->request_handler(client, method_desc, method_desc->req_desc, req_buf, &req_len, client->arg); if (ret != LWPB_ERR_OK) goto out; // We need a registered server to continue if (!socket_server->server) { client->done_handler(client, method_desc, LWPB_RPC_NOT_CONNECTED, client->arg); goto out; } // Process the call on the server ret = socket_server->server->call_handler(socket_server->server, method_desc, method_desc->req_desc, req_buf, req_len, method_desc->res_desc, res_buf, &res_len, socket_server->server->arg); if (ret != LWPB_ERR_OK) { client->done_handler(client, method_desc, LWPB_RPC_FAILED, client->arg); goto out; } // Process the response in the client ret = client->response_handler(client, method_desc, method_desc->res_desc, res_buf, res_len, client->arg); client->done_handler(client, method_desc, LWPB_RPC_OK, client->arg); out: // Free allocated message buffers if (req_buf) lwpb_transport_free_buf(transport, req_buf); if (res_buf) lwpb_transport_free_buf(transport, res_buf); return ret; }