/* * Init function */ errval_t arrakis_rpc_client_init(struct arrakis_rpc_client *rpc, struct arrakis_binding *binding) { errval_t _err; // Setup state of RPC client object rpc->b = binding; rpc->reply_present = false; rpc->rpc_in_progress = false; rpc->async_error = SYS_ERR_OK; waitset_init(&(rpc->rpc_waitset)); flounder_support_waitset_chanstate_init(&(rpc->dummy_chanstate)); rpc->vtbl = arrakis_rpc_vtbl; binding->st = rpc; // Change waitset on binding _err = ((binding->change_waitset)(binding, &(rpc->rpc_waitset))); if (err_is_fail(_err)) { waitset_destroy(&(rpc->rpc_waitset)); return(err_push(_err, FLOUNDER_ERR_CHANGE_WAITSET)); } // Set RX handlers on binding object for RPCs (binding->rx_vtbl).spawn_arrakis_domain_response = arrakis_spawn_arrakis_domain__rpc_rx_handler; // Set error handler on binding object binding->error_handler = arrakis_rpc_client_error; return(SYS_ERR_OK); }
/* * Init function */ errval_t usb_manager_rpc_client_init(struct usb_manager_rpc_client *rpc, struct usb_manager_binding *binding) { errval_t _err; // Setup state of RPC client object rpc->b = binding; rpc->reply_present = false; rpc->rpc_in_progress = false; rpc->async_error = SYS_ERR_OK; waitset_init(&(rpc->rpc_waitset)); flounder_support_waitset_chanstate_init(&(rpc->dummy_chanstate)); rpc->vtbl = usb_manager_rpc_vtbl; binding->st = rpc; // Change waitset on binding _err = ((binding->change_waitset)(binding, &(rpc->rpc_waitset))); if (err_is_fail(_err)) { waitset_destroy(&(rpc->rpc_waitset)); return(err_push(_err, FLOUNDER_ERR_CHANGE_WAITSET)); } // Set RX handlers on binding object for RPCs (binding->rx_vtbl).connect_response = usb_manager_connect__rpc_rx_handler; (binding->rx_vtbl).device_disconnect_notify_response = usb_manager_device_disconnect_notify__rpc_rx_handler; (binding->rx_vtbl).request_read_response = usb_manager_request_read__rpc_rx_handler; (binding->rx_vtbl).request_write_response = usb_manager_request_write__rpc_rx_handler; (binding->rx_vtbl).request_response = usb_manager_request__rpc_rx_handler; (binding->rx_vtbl).transfer_setup_response = usb_manager_transfer_setup__rpc_rx_handler; (binding->rx_vtbl).transfer_unsetup_response = usb_manager_transfer_unsetup__rpc_rx_handler; (binding->rx_vtbl).transfer_start_response = usb_manager_transfer_start__rpc_rx_handler; (binding->rx_vtbl).transfer_stop_response = usb_manager_transfer_stop__rpc_rx_handler; (binding->rx_vtbl).transfer_status_response = usb_manager_transfer_status__rpc_rx_handler; (binding->rx_vtbl).transfer_state_response = usb_manager_transfer_state__rpc_rx_handler; (binding->rx_vtbl).transfer_clear_stall_response = usb_manager_transfer_clear_stall__rpc_rx_handler; (binding->rx_vtbl).transfer_done_notify_response = usb_manager_transfer_done_notify__rpc_rx_handler; (binding->rx_vtbl).device_get_speed_response = usb_manager_device_get_speed__rpc_rx_handler; (binding->rx_vtbl).device_get_state_response = usb_manager_device_get_state__rpc_rx_handler; (binding->rx_vtbl).device_suspend_response = usb_manager_device_suspend__rpc_rx_handler; (binding->rx_vtbl).device_resume_response = usb_manager_device_resume__rpc_rx_handler; (binding->rx_vtbl).device_powersave_response = usb_manager_device_powersave__rpc_rx_handler; // Set error handler on binding object binding->error_handler = usb_manager_rpc_client_error; return(SYS_ERR_OK); }
/* * Init function */ errval_t acpi_rpc_client_init(struct acpi_rpc_client *rpc, struct acpi_binding *binding) { errval_t _err; // Setup state of RPC client object rpc->b = binding; rpc->reply_present = false; rpc->rpc_in_progress = false; rpc->async_error = SYS_ERR_OK; waitset_init(&(rpc->rpc_waitset)); flounder_support_waitset_chanstate_init(&(rpc->dummy_chanstate)); rpc->vtbl = acpi_rpc_vtbl; binding->st = rpc; // Change waitset on binding _err = ((binding->change_waitset)(binding, &(rpc->rpc_waitset))); if (err_is_fail(_err)) { waitset_destroy(&(rpc->rpc_waitset)); return(err_push(_err, FLOUNDER_ERR_CHANGE_WAITSET)); } // Set RX handlers on binding object for RPCs (binding->rx_vtbl).get_pcie_confspace_response = acpi_get_pcie_confspace__rpc_rx_handler; (binding->rx_vtbl).read_irq_table_response = acpi_read_irq_table__rpc_rx_handler; (binding->rx_vtbl).set_device_irq_response = acpi_set_device_irq__rpc_rx_handler; (binding->rx_vtbl).enable_and_route_interrupt_response = acpi_enable_and_route_interrupt__rpc_rx_handler; (binding->rx_vtbl).reset_response = acpi_reset__rpc_rx_handler; (binding->rx_vtbl).sleep_response = acpi_sleep__rpc_rx_handler; (binding->rx_vtbl).get_vbe_bios_cap_response = acpi_get_vbe_bios_cap__rpc_rx_handler; (binding->rx_vtbl).mm_alloc_range_proxy_response = acpi_mm_alloc_range_proxy__rpc_rx_handler; (binding->rx_vtbl).mm_realloc_range_proxy_response = acpi_mm_realloc_range_proxy__rpc_rx_handler; (binding->rx_vtbl).mm_free_proxy_response = acpi_mm_free_proxy__rpc_rx_handler; // Set error handler on binding object binding->error_handler = acpi_rpc_client_error; return(SYS_ERR_OK); }
ssize_t recv(int sockfd, void *buf, size_t len, int flags) { struct fdtab_entry *e = fdtab_get(sockfd); switch(e->type) { case FDTAB_TYPE_UNIX_SOCKET: { struct _unix_socket *us = e->handle; // XXX: Don't support flags assert(flags == 0); thread_mutex_lock(&us->mutex); if(us->passive || us->u.active.mode != _UNIX_SOCKET_MODE_CONNECTED) { errno = ENOTCONN; thread_mutex_unlock(&us->mutex); return -1; } if(us->recv_buf_valid == 0) { // No more data if(us->nonblocking) { errno = EAGAIN; thread_mutex_unlock(&us->mutex); return -1; } else { struct waitset ws; errval_t err; waitset_init(&ws); err = us->u.active.binding->change_waitset (us->u.active.binding, &ws); if(err_is_fail(err)) { USER_PANIC_ERR(err, "change_waitset"); } while(us->recv_buf_valid == 0) { err = event_dispatch(&ws); if(err_is_fail(err)) { USER_PANIC_ERR(err, "waitset_destroy"); } } // XXX: Assume it was on the default waitset err = us->u.active.binding->change_waitset (us->u.active.binding, get_default_waitset()); if(err_is_fail(err)) { USER_PANIC_ERR(err, "change_waitset"); } err = waitset_destroy(&ws); if(err_is_fail(err)) { USER_PANIC_ERR(err, "waitset_destroy"); } } } size_t recved = 0; while(recved < len && us->recv_list != NULL) { struct _unix_socket_recv *usr = us->recv_list; size_t consume = MIN(len - recved, usr->size - usr->consumed); memcpy(buf + recved, &usr->msg[usr->consumed], consume); usr->consumed += consume; us->recv_buf_valid -= consume; recved += consume; if(usr->consumed == usr->size) { us->recv_list = usr->next; if(us->recv_list == NULL) { us->recv_list_end = NULL; } free(usr->msg); free(usr); } else { assert(recved == len); } } thread_mutex_unlock(&us->mutex); return recved; } case FDTAB_TYPE_LWIP_SOCKET: lwip_mutex_lock(); ssize_t ret = lwip_recv(e->fd, buf, len, flags); lwip_mutex_unlock(); return ret; case FDTAB_TYPE_AVAILABLE: errno = EBADF; return -1; default: errno = ENOTSOCK; return -1; } }
ssize_t send(int sockfd, const void *buf, size_t len, int flags) { struct fdtab_entry *e = fdtab_get(sockfd); switch(e->type) { case FDTAB_TYPE_UNIX_SOCKET: { struct _unix_socket *us = e->handle; // XXX: Don't support flags assert(flags == 0); thread_mutex_lock(&us->mutex); if(us->passive || us->u.active.mode != _UNIX_SOCKET_MODE_CONNECTED) { errno = ENOTCONN; thread_mutex_unlock(&us->mutex); return -1; } if(us->send_buf != NULL) { if(us->nonblocking) { errno = EAGAIN; thread_mutex_unlock(&us->mutex); return -1; } else { assert(!"NYI"); } } // Bleh. Gotta copy here. I can't just wait until the // message is fully sent, as that might block // indefinitely. us->send_buf = malloc(len); memcpy(us->send_buf, buf, len); struct event_closure ec = { .handler = unixsock_sent, .arg = us, }; errval_t err = us->u.active.binding->tx_vtbl. send(us->u.active.binding, ec, us->send_buf, len); if(err_is_fail(err)) { USER_PANIC_ERR(err, "unixsock->send"); thread_mutex_unlock(&us->mutex); return -1; } // Wait until all data sent if blocking if(!us->nonblocking) { struct waitset ws; waitset_init(&ws); err = us->u.active.binding->change_waitset (us->u.active.binding, &ws); if(err_is_fail(err)) { USER_PANIC_ERR(err, "change_waitset"); } while(us->send_buf != NULL) { err = event_dispatch(&ws); if(err_is_fail(err)) { USER_PANIC_ERR(err, "waitset_destroy"); } } // XXX: Assume it was on the default waitset err = us->u.active.binding->change_waitset (us->u.active.binding, get_default_waitset()); if(err_is_fail(err)) { USER_PANIC_ERR(err, "change_waitset"); } err = waitset_destroy(&ws); if(err_is_fail(err)) { USER_PANIC_ERR(err, "waitset_destroy"); } } // XXX: We send all or nothing thread_mutex_unlock(&us->mutex); return len; } case FDTAB_TYPE_LWIP_SOCKET: lwip_mutex_lock(); ssize_t ret = lwip_send(e->fd, buf, len, flags); lwip_mutex_unlock(); return ret; case FDTAB_TYPE_AVAILABLE: errno = EBADF; return -1; default: errno = ENOTSOCK; return -1; } }