int __conman_util_block_write(int fd, const void * const buffer, size_t len) { int towrite; int ret; char *buf; if (len == 0) { return OK; } buf = (char *)buffer; towrite = len; do { ret = write(fd, buf + len - towrite, towrite); if (ret < 0) { conman_dbg("write failed %d\n", errno); return ERROR; } towrite -= ret; } while (towrite > 0); return OK; }
int conman_client_get_connection_status(struct conman_client_s *client, struct conman_status_s *status) { sq_queue_t qevents; int ret; if (!status) { return ERROR; } ret = conman_send_req(client->sd, CONMAN_MSG_GET_CONNECTION_STATUS, NULL, 0); if (ret != OK) { conman_dbg("conman_send_req failed\n"); return ERROR; } sq_init(&qevents); ret = conman_wait_for_response(client, false, &qevents); if (ret != OK) { conman_dbg("conman communication failed\n"); ret = ERROR; goto out; } if (client->respval != CONMAN_RESP_OK) { ret = ERROR; goto out; } DEBUGASSERT(sizeof(*status) == client->payloadlen); memcpy(status, client->payload, sizeof(*status)); free(client->payload); client->payload = NULL; ret = OK; out: handle_queued_events(client, &qevents); return ret; }
int conman_client_set_connections_config(struct conman_client_s *client, const char *config) { conman_dbg("%s\n", config); return do_command_no_payload(client, CONMAN_MSG_SET_CONNECTIONS_CONFIG, config, strlen(config) + 1); }
int __conman_cc3000_request_connection(struct conman_s *conman, enum conman_connection_type_e type) { (void)conman; (void)type; conman_dbg("no WiFi configs available\n"); return ERROR; }
int conman_client_request_connection(struct conman_client_s *client, enum conman_connection_type_e type, uint32_t *connid) { sq_queue_t qevents; int ret; ret = conman_send_req(client->sd, CONMAN_MSG_CREATE_CONNECTION, &type, sizeof(type)); if (ret != OK) { conman_dbg("conman_send_req failed\n"); return ERROR; } sq_init(&qevents); ret = conman_wait_for_response(client, false, &qevents); if (ret != OK) { conman_dbg("conman communication failed\n"); ret = ERROR; goto out; } if (client->respval != CONMAN_RESP_OK) { ret = ERROR; goto out; } DEBUGASSERT(sizeof(*connid) == client->payloadlen); memcpy(connid, client->payload, sizeof(*connid)); free(client->payload); client->payload = NULL; ret = OK; out: handle_queued_events(client, &qevents); return ret; }
static int do_command_no_payload(struct conman_client_s *client, uint8_t type, const void *buf, size_t buflen) { sq_queue_t qevents; int ret; ret = conman_send_req(client->sd, type, buf, buflen); if (ret != OK) { conman_dbg("conman_send_req failed\n"); return ERROR; } sq_init(&qevents); ret = conman_wait_for_response(client, false, &qevents); if (ret != OK) { conman_dbg("conman communication failed\n"); ret = ERROR; goto out; } if (client->respval != CONMAN_RESP_OK) { ret = ERROR; goto out; } DEBUGASSERT(client->payload == NULL); ret = OK; out: handle_queued_events(client, &qevents); return ret; }
void __conman_send_boardcast_event(struct conman_s *conman, enum conman_msgs_ids type, const void *payload, size_t payloadlen) { struct conman_sd_entry_s *client; struct conman_resp_hdr hdr = {}; int send_count = 0; int ret; hdr.head.id = type; hdr.head.len = payloadlen; hdr.respval = CONMAN_RESP_EVENT; for (client = (struct conman_sd_entry_s *)sq_peek(&conman->server.sds); client != NULL; client = (struct conman_sd_entry_s *)sq_next(&client->entry)) { if (!client->events_enabled) { continue; } ret = __conman_util_block_write(client->sd, &hdr, sizeof(hdr)); if (ret < 0) { continue; } ret = __conman_util_block_write(client->sd, payload, hdr.head.len); if (ret < 0) { continue; } send_count++; } conman_dbg("send boardcast event (type=%d) to %d clients.\n", type, send_count); }
int __conman_util_block_read(int fd, void *buffer, size_t len) { int toread; int ret; char *buf; buf = (char *)buffer; toread = len; do { ret = read(fd, buf + len - toread, toread); if (ret < 0) { conman_dbg("read failed %d\n", errno); return ERROR; } toread -= ret; } while (toread > 0); return OK; }
int conman_client_send_sms(struct conman_client_s *client, const char *phonenumber, const char *message) { struct conman_msg_send_sms_s sms = {}; size_t receiverlen = strlen(phonenumber); size_t messagelen = strlen(message); struct iovec bufs[3]; sq_queue_t qevents; int ret; sms.message_len = messagelen + 1; sms.receiver_len = receiverlen + 1; if (sms.message_len != messagelen + 1) { conman_dbg("Too long message\n"); return ERROR; } if (sms.receiver_len != receiverlen + 1) { conman_dbg("Too long phone-number\n"); return ERROR; } bufs[0].iov_base = &sms; bufs[0].iov_len = sizeof(sms); bufs[1].iov_base = (void *)phonenumber; bufs[1].iov_len = receiverlen + 1; bufs[2].iov_base = (void *)message; bufs[2].iov_len = messagelen + 1; ret = conman_send_reqv(client->sd, CONMAN_MSG_SEND_SMS, bufs, 3); if (ret != OK) { conman_dbg("conman_send_reqv failed\n"); return ERROR; } sq_init(&qevents); ret = conman_wait_for_response(client, false, &qevents); if (ret != OK) { conman_dbg("conman communication failed\n"); ret = ERROR; goto out; } DEBUGASSERT(client->payload == NULL); if (client->respval != CONMAN_RESP_OK) { ret = ERROR; goto out; } ret = OK; out: handle_queued_events(client, &qevents); return ret; }
int conman_client_init_events(struct conman_client_s *client, conman_event_callback_fn_t event_callback, void *event_priv) { struct sockaddr_un myaddr; socklen_t addrlen; int ret; memset(client, 0, sizeof(*client)); client->event_callback = event_callback; client->event_priv = event_priv; /* Create a new Unix domain socket */ client->sd = socket(PF_LOCAL, SOCK_STREAM, 0); if (client->sd < 0) { conman_dbg("socket failed: %d\n", errno); return ERROR; } /* Connect the socket to the server */ addrlen = strlen(CONFIG_CONMAN_LISTEN_SOCKET_ADDR); if (addrlen > UNIX_PATH_MAX - 1) { addrlen = UNIX_PATH_MAX - 1; } myaddr.sun_family = AF_LOCAL; strncpy(myaddr.sun_path, CONFIG_CONMAN_LISTEN_SOCKET_ADDR, addrlen); myaddr.sun_path[addrlen] = '\0'; conman_dbg("Connecting to %s\n", CONFIG_CONMAN_LISTEN_SOCKET_ADDR); addrlen += sizeof(sa_family_t) + 1; ret = connect(client->sd, (struct sockaddr *)&myaddr, addrlen); if (ret < 0) { conman_dbg("connect failed: %d\n", errno); goto errout_with_socket; } conman_dbg("Connected\n"); if (event_callback) { /* Enable events. */ if (conman_client_enable_events(client) < 0) { conman_dbg("conman_client_enable_events failed\n"); goto errout_with_socket; } } return OK; errout_with_socket: close(client->sd); return ERROR; }
static int conman_client_enable_events(struct conman_client_s *client) { conman_dbg("\n"); return do_command_no_payload(client, CONMAN_MSG_ENABLE_EVENTS, NULL, 0); }
int conman_main(int argc, char **argv) { struct conman_s *conman = &g_conman; int ubmodem_max_pfds = 0; int client_max_pfds = 0; struct pollfd *pfds; int ret; int maxfds = 0; int i; __conman_config_init(conman); ret = __conman_server_initialize(conman, &client_max_pfds); if (ret != OK) { conman_dbg("__conman_server_initialize failed"); return EXIT_FAILURE; } maxfds += client_max_pfds; /* client fds */ ret = __conman_ubmodem_initialize(conman, &ubmodem_max_pfds); if (ret != OK) { conman_dbg("__conman_ubmodem_initialize failed\n"); return EXIT_FAILURE; } maxfds += ubmodem_max_pfds; /* modem fds */ maxfds += __conman_cc3000_get_max_pollfds(conman); /* wifi fds */ pfds = calloc(maxfds, sizeof(*pfds)); if (!pfds) { conman_dbg("ubmodemd_daemon: Out-of-memory, tried to allocate %d.\n", maxfds * sizeof(*pfds)); return EXIT_FAILURE; } while (true) { int ubmodem_pos_fds, ubmodem_num_fds; int cc3000_pos_fds, cc3000_num_fds; int client_pos_fds, client_num_fds; int nfds; int timeout; nfds = 0; timeout = INT_MAX; /* Setup pollfd for listening socket */ pfds[nfds].fd = conman->listensd; pfds[nfds].events = POLLIN; nfds++; /* Setup pollfds for clients and get timeout for timers. */ client_pos_fds = nfds; __conman_server_setup_pollfds(conman, pfds, maxfds, &nfds, &timeout); client_num_fds = nfds - client_pos_fds; /* Setup pollfds for modem and get timeout for timers. */ ubmodem_pos_fds = nfds; __conman_ubmodem_setup_pollfds(conman, pfds, maxfds, &nfds, &timeout); ubmodem_num_fds = nfds - ubmodem_pos_fds; /* Setup pollfds for cc3000 and get timeout for timers. */ cc3000_pos_fds = nfds; __conman_cc3000_setup_pollfds(conman, pfds, maxfds, &nfds, &timeout); cc3000_num_fds = nfds - cc3000_pos_fds; ret = poll(pfds, nfds, timeout == INT_MAX ? -1 : timeout); if (ret < 0) { conman_dbg("poll failed %d\n", errno); break; } if (ret == 0) { conman_dbg("poll() timed out\n"); __conman_ubmodem_poll_timedout(conman); continue; } for (i = 0; i < nfds && ret > 0; i++) { if (pfds[i].revents) { ret--; conman_dbg("poll index: %d, fd: %d, " "events: 0x%02x, revents: 0x%02x\n", i, pfds[i].fd, pfds[i].events, pfds[i].revents); } if (pfds[i].revents && pfds[i].fd == conman->listensd) { __conman_server_handle_pollin(conman, &pfds[i]); } else if (pfds[i].revents && client_num_fds > 0 && i >= client_pos_fds && i < (client_pos_fds + client_num_fds)) { __conman_ctl_handle_pollin(conman, &pfds[i]); } else if (pfds[i].revents && cc3000_num_fds > 0 && i >= cc3000_pos_fds && i < (cc3000_pos_fds + cc3000_num_fds)) { __conman_cc3000_handle_pollfds(conman, &pfds[i]); } else if (ubmodem_pos_fds == i && ubmodem_num_fds > 0) { int j; for (j = 1; j < ubmodem_num_fds; j++) { if (pfds[i + j].revents) { ret--; } } __conman_ubmodem_handle_pollfds(conman, &pfds[i], ubmodem_num_fds); i += ubmodem_num_fds - 1; } } } /* Reached only on poll() error */ free(pfds); return EXIT_FAILURE; }