X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=libustcomm%2Fustcomm.c;h=e401c4256e6666292a3ea6b9f5dddd948d811b64;hb=304f67a5f2d2eaaa7407c09b2ac7d6e049bccf1f;hp=50038cba157cdc964a553c718a22a6e38b6217c6;hpb=4723ca096d740ff93da400df304c9902e9834e5f;p=ust.git diff --git a/libustcomm/ustcomm.c b/libustcomm/ustcomm.c index 50038cb..e401c42 100644 --- a/libustcomm/ustcomm.c +++ b/libustcomm/ustcomm.c @@ -113,7 +113,7 @@ static struct sockaddr_un * create_sock_addr(const char *name, } struct ustcomm_sock * ustcomm_init_sock(int fd, int epoll_fd, - struct list_head *list) + struct cds_list_head *list) { struct epoll_event ev; struct ustcomm_sock *sock; @@ -136,9 +136,9 @@ struct ustcomm_sock * ustcomm_init_sock(int fd, int epoll_fd, sock->epoll_fd = epoll_fd; if (list) { - list_add(&sock->list, list); + cds_list_add(&sock->list, list); } else { - INIT_LIST_HEAD(&sock->list); + CDS_INIT_LIST_HEAD(&sock->list); } return sock; @@ -146,7 +146,7 @@ struct ustcomm_sock * ustcomm_init_sock(int fd, int epoll_fd, void ustcomm_del_sock(struct ustcomm_sock *sock, int keep_in_epoll) { - list_del(&sock->list); + cds_list_del(&sock->list); if (!keep_in_epoll) { if (epoll_ctl(sock->epoll_fd, EPOLL_CTL_DEL, sock->fd, NULL) == -1) { PERROR("epoll_ctl: failed to delete socket"); @@ -277,58 +277,58 @@ del_sock: ustcomm_del_sock(sock, keep_socket_file); } +int ustcomm_recv_alloc(int sock, + struct ustcomm_header *header, + char **data) { + int result; + struct ustcomm_header peek_header; + struct iovec iov[2]; + struct msghdr msg; -/* Called by an app to ask the consumer daemon to connect to it. */ + /* Just to make the caller fail hard */ + *data = NULL; -int ustcomm_request_consumer(pid_t pid, const char *channel) -{ - int result, daemon_fd; - int retval = 0; - char *msg=NULL; - char *explicit_daemon_socket_path, *daemon_path; - - explicit_daemon_socket_path = getenv("UST_DAEMON_SOCKET"); - if (explicit_daemon_socket_path) { - /* user specified explicitly a socket path */ - result = asprintf(&daemon_path, "%s", explicit_daemon_socket_path); - } else { - /* just use the default path */ - result = asprintf(&daemon_path, "%s/ustd", SOCK_DIR); - } - if (result < 0) { - ERR("string overflow allocating socket name"); - return -1; + result = recv(sock, &peek_header, sizeof(peek_header), + MSG_PEEK | MSG_WAITALL); + if (result <= 0) { + if(errno == ECONNRESET) { + return 0; + } else if (errno == EINTR) { + return -1; + } else if (result < 0) { + PERROR("recv"); + return -1; + } + return 0; } - if (asprintf(&msg, "collect %d %s", pid, channel) < 0) { - ERR("ustcomm_request_consumer : asprintf failed (collect %d/%s)", - pid, channel); - retval = -1; - goto free_daemon_path; - } + memset(&msg, 0, sizeof(msg)); - result = ustcomm_connect_path(daemon_path, &daemon_fd); - if (result < 0) { - WARN("ustcomm_connect_path failed, daemon_path: %s", - daemon_path); - retval = -1; - goto del_string; + iov[0].iov_base = (char *)header; + iov[0].iov_len = sizeof(struct ustcomm_header); + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + if (peek_header.size) { + *data = zmalloc(peek_header.size); + if (!*data) { + return -ENOMEM; + } + + iov[1].iov_base = *data; + iov[1].iov_len = peek_header.size; + + msg.msg_iovlen++; } - result = ustcomm_send_request(daemon_fd, msg, NULL); + result = recvmsg(sock, &msg, MSG_WAITALL); if (result < 0) { - WARN("ustcomm_send_request failed, daemon path: %s", - daemon_path); - retval = -1; + free(*data); + PERROR("recvmsg failed"); } - close(daemon_fd); -del_string: - free(msg); -free_daemon_path: - free(daemon_path); - - return retval; + return result; } /* returns 1 to indicate a message was received @@ -337,10 +337,9 @@ free_daemon_path: */ int ustcomm_recv_fd(int sock, struct ustcomm_header *header, - char **data, int *fd) + char *data, int *fd) { int result; - int retval; struct ustcomm_header peek_header; struct iovec iov[2]; struct msghdr msg; @@ -369,16 +368,14 @@ int ustcomm_recv_fd(int sock, msg.msg_iov = iov; msg.msg_iovlen = 1; - if (peek_header.size) { - if (peek_header.size < 0 || peek_header.size > 100) { - WARN("big peek header! %d", peek_header.size); - } - *data = malloc(peek_header.size); - if (!*data) { - ERR("failed to allocate space for message"); + if (peek_header.size && data) { + if (peek_header.size < 0 || + peek_header.size > USTCOMM_DATA_SIZE) { + ERR("big peek header! %ld", peek_header.size); + return 0; } - iov[1].iov_base = (char *)*data; + iov[1].iov_base = data; iov[1].iov_len = peek_header.size; msg.msg_iovlen++; @@ -389,22 +386,12 @@ int ustcomm_recv_fd(int sock, msg.msg_controllen = sizeof(buf); } - result = recvmsg(sock, &msg, - MSG_WAITALL); - + result = recvmsg(sock, &msg, MSG_WAITALL); if (result <= 0) { - if(errno == ECONNRESET) { - retval = 0; - } else if (errno == EINTR) { - retval = -1; - } else if (result < 0) { - PERROR("recv"); - retval = -1; - } else { - retval = 0; + if (result < 0) { + PERROR("recvmsg failed"); } - free(*data); - return retval; + return result; } if (fd && peek_header.fd_included) { @@ -429,19 +416,12 @@ int ustcomm_recv_fd(int sock, int ustcomm_recv(int sock, struct ustcomm_header *header, - char **data) + char *data) { return ustcomm_recv_fd(sock, header, data, NULL); } -int recv_message_conn(int sock, char **msg) -{ - struct ustcomm_header header; - - return ustcomm_recv(sock, &header, msg); -} - int ustcomm_send_fd(int sock, const struct ustcomm_header *header, const char *data, @@ -461,7 +441,7 @@ int ustcomm_send_fd(int sock, msg.msg_iov = iov; msg.msg_iovlen = 1; - if (header->size) { + if (header->size && data) { iov[1].iov_base = (char *)data; iov[1].iov_len = header->size; @@ -494,68 +474,20 @@ int ustcomm_send(int sock, return ustcomm_send_fd(sock, header, data, NULL); } -int ustcomm_send_reply(char *msg, int sock) +int ustcomm_req(int sock, + const struct ustcomm_header *req_header, + const char *req_data, + struct ustcomm_header *res_header, + char *res_data) { int result; - struct ustcomm_header header; - - memset(&header, 0, sizeof(header)); - header.size = strlen(msg) + 1; - - result = ustcomm_send(sock, &header, msg); - if(result < 0) { - ERR("error in ustcomm_send"); - return result; - } - - return 0; -} - -int ustcomm_send_req(int sock, - const struct ustcomm_header *req_header, - const char *data, - char **response) -{ - int result; - struct ustcomm_header res_header; - - result = ustcomm_send(sock, req_header, data); + result = ustcomm_send(sock, req_header, req_data); if ( result <= 0) { return result; } - if (!response) { - return 1; - } - - return ustcomm_recv(sock, - &res_header, - response); - -} - -/* - * Return value: - * 0: Success, but no reply because recv() returned 0 - * 1: Success - * -1: Error - * - * On error, the error message is printed, except on - * ECONNRESET, which is normal when the application dies. - */ - -int ustcomm_send_request(int sock, const char *req, char **reply) -{ - struct ustcomm_header req_header; - - req_header.size = strlen(req) + 1; - - return ustcomm_send_req(sock, - &req_header, - req, - reply); - + return ustcomm_recv(sock, res_header, res_data); } /* Return value: @@ -601,6 +533,21 @@ close_sock: return -1; } +/* Returns the current users socket directory, must be freed */ +char *ustcomm_user_sock_dir(void) +{ + int result; + char *sock_dir = NULL; + + result = asprintf(&sock_dir, "%s%s", USER_SOCK_DIR, + cuserid(NULL)); + if (result < 0) { + ERR("string overflow allocating directory name"); + return NULL; + } + + return sock_dir; +} /* Open a connection to a traceable app. * @@ -613,141 +560,297 @@ int ustcomm_connect_app(pid_t pid, int *app_fd) { int result; int retval = 0; - char *name; + char *dir_name, *sock_name; + + dir_name = ustcomm_user_sock_dir(); + if (!dir_name) + return -ENOMEM; - result = asprintf(&name, "%s/%d", SOCK_DIR, pid); + result = asprintf(&sock_name, "%s/%d", dir_name, pid); if (result < 0) { ERR("failed to allocate socket name"); - return -1; + retval = -1; + goto free_dir_name; } - result = ustcomm_connect_path(name, app_fd); + result = ustcomm_connect_path(sock_name, app_fd); if (result < 0) { ERR("failed to connect to app"); retval = -1; + goto free_sock_name; } - free(name); +free_sock_name: + free(sock_name); +free_dir_name: + free(dir_name); return retval; } -int ensure_dir_exists(const char *dir) +int ensure_dir_exists(const char *dir, mode_t mode) { struct stat st; int result; - if(!strcmp(dir, "")) + if (!strcmp(dir, "")) return -1; result = stat(dir, &st); - if(result == -1 && errno != ENOENT) { + if (result < 0 && errno != ENOENT) { return -1; - } - else if(result == -1) { + } else if (result < 0) { /* ENOENT */ int result; - /* mkdir mode to 0777 */ - result = mkdir_p(dir, S_IRWXU | S_IRWXG | S_IRWXO); + result = mkdir_p(dir, mode); if(result != 0) { ERR("executing in recursive creation of directory %s", dir); return -1; } + } else { + if (st.st_mode != mode) { + result = chmod(dir, mode); + if (result < 0) { + ERR("couldn't set directory mode on %s", dir); + return -1; + } + } } return 0; } -/* Used by the daemon to initialize its server so applications - * can connect to it. - */ +char * ustcomm_print_data(char *data_field, int field_size, + int *offset, const char *format, ...) +{ + va_list args; + int count, limit; + char *ptr = USTCOMM_POISON_PTR; + limit = field_size - *offset; + va_start(args, format); + count = vsnprintf(&data_field[*offset], limit, format, args); + va_end(args); -static const char *find_tok(const char *str) + if (count < limit && count > -1) { + ptr = NULL + *offset; + *offset = *offset + count + 1; + } + + return ptr; +} + +char * ustcomm_restore_ptr(char *ptr, char *data_field, int data_field_size) { - while(*str == ' ') { - str++; + if ((unsigned long)ptr > data_field_size || + ptr == USTCOMM_POISON_PTR) { + return NULL; + } + + return data_field + (long)ptr; +} + +int ustcomm_pack_single_field(struct ustcomm_header *header, + struct ustcomm_single_field *single_field, + const char *string) +{ + int offset = 0; + + single_field->field = ustcomm_print_data(single_field->data, + sizeof(single_field->data), + &offset, + string); - if(*str == 0) - return NULL; + if (single_field->field == USTCOMM_POISON_PTR) { + return -ENOMEM; } - return str; + header->size = COMPUTE_MSG_SIZE(single_field, offset); + + return 0; } -static const char *find_sep(const char *str) +int ustcomm_unpack_single_field(struct ustcomm_single_field *single_field) { - while(*str != ' ') { - str++; + single_field->field = ustcomm_restore_ptr(single_field->field, + single_field->data, + sizeof(single_field->data)); + if (!single_field->field) { + return -EINVAL; + } - if(*str == 0) - break; + return 0; +} + +int ustcomm_pack_channel_info(struct ustcomm_header *header, + struct ustcomm_channel_info *ch_inf, + const char *trace, + const char *channel) +{ + int offset = 0; + + ch_inf->trace = ustcomm_print_data(ch_inf->data, + sizeof(ch_inf->data), + &offset, + trace); + + if (ch_inf->trace == USTCOMM_POISON_PTR) { + return -ENOMEM; } - return str; + ch_inf->channel = ustcomm_print_data(ch_inf->data, + sizeof(ch_inf->data), + &offset, + channel); + + if (ch_inf->channel == USTCOMM_POISON_PTR) { + return -ENOMEM; + } + + header->size = COMPUTE_MSG_SIZE(ch_inf, offset); + + return 0; } -int nth_token_is(const char *str, const char *token, int tok_no) + +int ustcomm_unpack_channel_info(struct ustcomm_channel_info *ch_inf) { - int i; - const char *start; - const char *end; + ch_inf->trace = ustcomm_restore_ptr(ch_inf->trace, + ch_inf->data, + sizeof(ch_inf->data)); + if (!ch_inf->trace) { + return -EINVAL; + } - for(i=0; i<=tok_no; i++) { - str = find_tok(str); - if(str == NULL) - return -1; + ch_inf->channel = ustcomm_restore_ptr(ch_inf->channel, + ch_inf->data, + sizeof(ch_inf->data)); + if (!ch_inf->channel) { + return -EINVAL; + } - start = str; + return 0; +} - str = find_sep(str); - if(str == NULL) - return -1; +int ustcomm_pack_buffer_info(struct ustcomm_header *header, + struct ustcomm_buffer_info *buf_inf, + const char *trace, + const char *channel, + int channel_cpu) +{ + int offset = 0; + + buf_inf->trace = ustcomm_print_data(buf_inf->data, + sizeof(buf_inf->data), + &offset, + trace); - end = str; + if (buf_inf->trace == USTCOMM_POISON_PTR) { + return -ENOMEM; } - if(end-start != strlen(token)) - return 0; + buf_inf->channel = ustcomm_print_data(buf_inf->data, + sizeof(buf_inf->data), + &offset, + channel); - if(strncmp(start, token, end-start)) - return 0; + if (buf_inf->channel == USTCOMM_POISON_PTR) { + return -ENOMEM; + } - return 1; + buf_inf->ch_cpu = channel_cpu; + + header->size = COMPUTE_MSG_SIZE(buf_inf, offset); + + return 0; +} + + +int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info *buf_inf) +{ + buf_inf->trace = ustcomm_restore_ptr(buf_inf->trace, + buf_inf->data, + sizeof(buf_inf->data)); + if (!buf_inf->trace) { + return -EINVAL; + } + + buf_inf->channel = ustcomm_restore_ptr(buf_inf->channel, + buf_inf->data, + sizeof(buf_inf->data)); + if (!buf_inf->channel) { + return -EINVAL; + } + + return 0; } -char *nth_token(const char *str, int tok_no) +int ustcomm_pack_marker_info(struct ustcomm_header *header, + struct ustcomm_marker_info *marker_inf, + const char *trace, + const char *channel, + const char *marker) { - static char *retval = NULL; - int i; - const char *start; - const char *end; + int offset = 0; + + marker_inf->trace = ustcomm_print_data(marker_inf->data, + sizeof(marker_inf->data), + &offset, + trace); - for(i=0; i<=tok_no; i++) { - str = find_tok(str); - if(str == NULL) - return NULL; + if (marker_inf->trace == USTCOMM_POISON_PTR) { + return -ENOMEM; + } - start = str; - str = find_sep(str); - if(str == NULL) - return NULL; + marker_inf->channel = ustcomm_print_data(marker_inf->data, + sizeof(marker_inf->data), + &offset, + channel); - end = str; + if (marker_inf->channel == USTCOMM_POISON_PTR) { + return -ENOMEM; } - if(retval) { - free(retval); - retval = NULL; + + marker_inf->marker = ustcomm_print_data(marker_inf->data, + sizeof(marker_inf->data), + &offset, + marker); + + if (marker_inf->marker == USTCOMM_POISON_PTR) { + return -ENOMEM; } - if (asprintf(&retval, "%.*s", (int)(end-start), start) < 0) { - ERR("nth_token : asprintf failed (%.*s)", - (int)(end-start), start); - return NULL; + header->size = COMPUTE_MSG_SIZE(marker_inf, offset); + + return 0; +} + +int ustcomm_unpack_marker_info(struct ustcomm_marker_info *marker_inf) +{ + marker_inf->trace = ustcomm_restore_ptr(marker_inf->trace, + marker_inf->data, + sizeof(marker_inf->data)); + if (!marker_inf->trace) { + return -EINVAL; } - return retval; + marker_inf->channel = ustcomm_restore_ptr(marker_inf->channel, + marker_inf->data, + sizeof(marker_inf->data)); + if (!marker_inf->channel) { + return -EINVAL; + } + + marker_inf->marker = ustcomm_restore_ptr(marker_inf->marker, + marker_inf->data, + sizeof(marker_inf->data)); + if (!marker_inf->marker) { + return -EINVAL; + } + + return 0; } +