Re-write ustcomm parts of UST v2
[ust.git] / libustcomm / ustcomm.c
index 567c5d113f9785bc7b2f3cd09eb89809c48f03ef..50038cba157cdc964a553c718a22a6e38b6217c6 100644 (file)
@@ -25,6 +25,7 @@
 #include <sys/un.h>
 #include <unistd.h>
 #include <poll.h>
+#include <sys/epoll.h>
 #include <sys/stat.h>
 
 #include <stdio.h>
@@ -35,9 +36,6 @@
 #include "ustcomm.h"
 #include "usterr.h"
 #include "share.h"
-#include "multipoll.h"
-
-#define UNIX_PATH_MAX 108
 
 static int mkdir_p(const char *path, mode_t mode)
 {
@@ -91,430 +89,450 @@ static int mkdir_p(const char *path, mode_t mode)
        return retval;
 }
 
-static int signal_process(pid_t pid)
+static struct sockaddr_un * create_sock_addr(const char *name,
+                                            size_t *sock_addr_size)
 {
-       return 0;
-}
+       struct sockaddr_un * addr;
+       size_t alloc_size;
 
-void ustcomm_init_connection(struct ustcomm_connection *conn)
-{
-       conn->recv_buf = NULL;
-       conn->recv_buf_size = 0;
-       conn->recv_buf_alloc = 0;
-}
+       alloc_size = (size_t) (((struct sockaddr_un *) 0)->sun_path) +
+               strlen(name) + 1;
 
-int pid_is_online(pid_t pid) {
-       return 1;
-}
+       addr = malloc(alloc_size);
+       if (addr < 0) {
+               ERR("allocating addr failed");
+               return NULL;
+       }
 
-/* Send a message
- *
- * @fd: file descriptor to send to
- * @msg: a null-terminated string containing the message to send
- *
- * Return value:
- * -1: error
- * 0: connection closed
- * 1: success
- */
+       addr->sun_family = AF_UNIX;
+       strcpy(addr->sun_path, name);
+
+       *sock_addr_size = alloc_size;
+
+       return addr;
+}
 
-static int send_message_fd(int fd, const char *msg)
+struct ustcomm_sock * ustcomm_init_sock(int fd, int epoll_fd,
+                                       struct list_head *list)
 {
-       int result;
+       struct epoll_event ev;
+       struct ustcomm_sock *sock;
 
-       /* Send including the final \0 */
-       result = patient_send(fd, msg, strlen(msg)+1, MSG_NOSIGNAL);
-       if(result == -1) {
-               if(errno != EPIPE)
-                       PERROR("send");
-               return -1;
+       sock = malloc(sizeof(struct ustcomm_sock));
+       if (!sock) {
+               perror("malloc: couldn't allocate ustcomm_sock");
+               return NULL;
        }
-       else if(result == 0) {
-               return 0;
+
+       ev.events = EPOLLIN;
+       ev.data.ptr = sock;
+       sock->fd = fd;
+
+       if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock->fd, &ev) == -1) {
+               perror("epoll_ctl: failed to add socket\n");
+               free(sock);
+               return NULL;
        }
 
-       DBG("sent message \"%s\"", msg);
-       return 1;
+       sock->epoll_fd = epoll_fd;
+       if (list) {
+               list_add(&sock->list, list);
+       } else {
+               INIT_LIST_HEAD(&sock->list);
+       }
+
+       return sock;
 }
 
-/* Called by an app to ask the consumer daemon to connect to it. */
+void ustcomm_del_sock(struct ustcomm_sock *sock, int keep_in_epoll)
+{
+       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");
+               }
+       }
+       close(sock->fd);
+       free(sock);
+}
 
-int ustcomm_request_consumer(pid_t pid, const char *channel)
+struct ustcomm_sock * ustcomm_init_named_socket(const char *name,
+                                               int epoll_fd)
 {
-       char path[UNIX_PATH_MAX];
        int result;
-       char *msg=NULL;
-       int retval = 0;
-       struct ustcomm_connection conn;
-       char *explicit_daemon_socket_path;
+       int fd;
+       size_t sock_addr_size;
+       struct sockaddr_un * addr;
+       struct ustcomm_sock *sock;
 
-       explicit_daemon_socket_path = getenv("UST_DAEMON_SOCKET");
-       if(explicit_daemon_socket_path) {
-               /* user specified explicitly a socket path */
-               result = snprintf(path, UNIX_PATH_MAX, "%s", explicit_daemon_socket_path);
-       }
-       else {
-               /* just use the default path */
-               result = snprintf(path, UNIX_PATH_MAX, "%s/ustd", SOCK_DIR);
+       fd = socket(PF_UNIX, SOCK_STREAM, 0);
+       if(fd == -1) {
+               PERROR("socket");
+               return NULL;
        }
 
-       if(result >= UNIX_PATH_MAX) {
-               ERR("string overflow allocating socket name");
-               return -1;
+       addr = create_sock_addr(name, &sock_addr_size);
+       if (addr == NULL) {
+               ERR("allocating addr, UST thread bailing");
+               goto close_sock;
        }
 
-       if (asprintf(&msg, "collect %d %s", pid, channel) < 0) {
-               ERR("ustcomm_request_consumer : asprintf failed (collect %d/%s)",
-                   pid, channel);
-               return -1;
+       result = access(name, F_OK);
+       if(result == 0) {
+               /* file exists */
+               result = unlink(name);
+               if(result == -1) {
+                       PERROR("unlink of socket file");
+                       goto free_addr;
+               }
+               DBG("socket already exists; overwriting");
        }
 
-       /* don't signal it because it's the daemon */
-       result = ustcomm_connect_path(path, &conn, -1);
+       result = bind(fd, (struct sockaddr *)addr, sock_addr_size);
        if(result == -1) {
-               WARN("ustcomm_connect_path failed");
-               retval = -1;
-               goto del_string;
+               PERROR("bind");
+               goto free_addr;
        }
 
-       result = ustcomm_send_request(&conn, msg, NULL);
+       result = listen(fd, 1);
        if(result == -1) {
-               WARN("ustcomm_send_request failed");
-               retval = -1;
-               goto disconnect;
+               PERROR("listen");
+               goto free_addr;
        }
 
-       disconnect:
-       ustcomm_disconnect(&conn);
-       del_string:
-       free(msg);
+       sock = ustcomm_init_sock(fd, epoll_fd,
+                                NULL);
+       if (!sock) {
+               ERR("failed to create ustcomm_sock");
+               goto free_addr;
+       }
 
-       return retval;
-}
+       free(addr);
 
-/* returns 1 to indicate a message was received
- * returns 0 to indicate no message was received (end of stream)
- * returns -1 to indicate an error
- */
+       return sock;
 
-#define RECV_INCREMENT 1000
-#define RECV_INITIAL_BUF_SIZE 10
+free_addr:
+       free(addr);
+close_sock:
+       close(fd);
 
-static int recv_message_fd(int fd, char **recv_buf, int *recv_buf_size, int *recv_buf_alloc, char **msg)
+       return NULL;
+}
+
+void ustcomm_del_named_sock(struct ustcomm_sock *sock,
+                           int keep_socket_file)
 {
-       int result;
+       int result, fd;
+       struct stat st;
+       struct sockaddr dummy;
+       struct sockaddr_un *sockaddr = NULL;
+       int alloc_size;
 
-       /* 1. Check if there is a message in the buf */
-       /* 2. If not, do:
-           2.1 receive chunk and put it in buffer
-          2.2 process full message if there is one
-          -- while no message arrived
-       */
+       fd = sock->fd;
 
-       for(;;) {
-               int i;
-               int nulfound = 0;
+       if(!keep_socket_file) {
 
-               /* Search for full message in buffer */
-               for(i=0; i<*recv_buf_size; i++) {
-                       if((*recv_buf)[i] == '\0') {
-                               nulfound = 1;
-                               break;
-                       }
+               /* Get the socket name */
+               alloc_size = sizeof(dummy);
+               if (getsockname(fd, &dummy, (socklen_t *)&alloc_size) < 0) {
+                       PERROR("getsockname failed");
+                       goto del_sock;
                }
 
-               /* Process found message */
-               if(nulfound == 1) {
-                       char *newbuf;
-
-                       if(i == 0) {
-                               /* problem */
-                               WARN("received empty message");
-                       }
-                       *msg = strndup(*recv_buf, i);
-
-                       /* Remove processed message from buffer */
-                       newbuf = (char *) malloc(*recv_buf_size - (i+1));
-                       memcpy(newbuf, *recv_buf + (i+1), *recv_buf_size - (i+1));
-                       free(*recv_buf);
-                       *recv_buf = newbuf;
-                       *recv_buf_size -= (i+1);
-                       *recv_buf_alloc -= (i+1);
-
-                       return 1;
+               sockaddr = zmalloc(alloc_size);
+               if (!sockaddr) {
+                       ERR("failed to allocate sockaddr");
+                       goto del_sock;
                }
 
-               /* Receive a chunk from the fd */
-               if(*recv_buf_alloc - *recv_buf_size < RECV_INCREMENT) {
-                       *recv_buf_alloc += RECV_INCREMENT - (*recv_buf_alloc - *recv_buf_size);
-                       *recv_buf = (char *) realloc(*recv_buf, *recv_buf_alloc);
+               if (getsockname(fd, sockaddr, (socklen_t *)&alloc_size) < 0) {
+                       PERROR("getsockname failed");
+                       goto free_sockaddr;
                }
 
-               result = recv(fd, *recv_buf+*recv_buf_size, RECV_INCREMENT, 0);
-               if(result == -1) {
-                       if(errno == ECONNRESET) {
-                               *recv_buf_size = 0;
-                               return 0;
-                       }
-                       else if(errno == EINTR) {
-                               return -1;
-                       }
-                       else {
-                               PERROR("recv");
-                               return -1;
-                       }
+               /* Destroy socket */
+               result = stat(sockaddr->sun_path, &st);
+               if(result < 0) {
+                       PERROR("stat (%s)", sockaddr->sun_path);
+                       goto free_sockaddr;
                }
-               if(result == 0) {
-                       return 0;
+
+               /* Paranoid check before deleting. */
+               result = S_ISSOCK(st.st_mode);
+               if(!result) {
+                       ERR("The socket we are about to delete is not a socket.");
+                       goto free_sockaddr;
                }
-               *recv_buf_size += result;
 
-               /* Go back to the beginning to check if there is a full message in the buffer */
+               result = unlink(sockaddr->sun_path);
+               if(result < 0) {
+                       PERROR("unlink");
+               }
        }
 
-       DBG("received message \"%s\"", *recv_buf);
-
-       return 1;
+free_sockaddr:
+       free(sockaddr);
 
+del_sock:
+       ustcomm_del_sock(sock, keep_socket_file);
 }
 
-static int recv_message_conn(struct ustcomm_connection *conn, char **msg)
-{
-       return recv_message_fd(conn->fd, &conn->recv_buf, &conn->recv_buf_size, &conn->recv_buf_alloc, msg);
-}
 
-int ustcomm_send_reply(struct ustcomm_server *server, char *msg, struct ustcomm_source *src)
+/* Called by an app to ask the consumer daemon to connect to it. */
+
+int ustcomm_request_consumer(pid_t pid, const char *channel)
 {
-       int result;
+       int result, daemon_fd;
+       int retval = 0;
+       char *msg=NULL;
+       char *explicit_daemon_socket_path, *daemon_path;
 
-       result = send_message_fd(src->fd, msg);
-       if(result < 0) {
-               ERR("error in send_message_fd");
+       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;
        }
 
-       return 0;
-} 
-
-/* Called after a fork. */
+       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;
+       }
 
-int ustcomm_close_all_connections(struct ustcomm_server *server)
-{
-       struct ustcomm_connection *conn;
-       struct ustcomm_connection *deletable_conn = NULL;
+       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;
+       }
 
-       list_for_each_entry(conn, &server->connections, list) {
-               free(deletable_conn);
-               deletable_conn = conn;
-               ustcomm_close_app(conn);
-               list_del(&conn->list);
+       result = ustcomm_send_request(daemon_fd, msg, NULL);
+       if (result < 0) {
+               WARN("ustcomm_send_request failed, daemon path: %s",
+                    daemon_path);
+               retval = -1;
        }
 
-       return 0;
+       close(daemon_fd);
+del_string:
+       free(msg);
+free_daemon_path:
+       free(daemon_path);
+
+       return retval;
 }
 
-/* @timeout: max blocking time in milliseconds, -1 means infinity
- *
- * returns 1 to indicate a message was received
- * returns 0 to indicate no message was received
+/* returns 1 to indicate a message was received
+ * returns 0 to indicate no message was received (end of stream)
  * returns -1 to indicate an error
  */
-
-int ustcomm_recv_message(struct ustcomm_server *server, char **msg, struct ustcomm_source *src, int timeout)
+int ustcomm_recv_fd(int sock,
+                   struct ustcomm_header *header,
+                   char **data, int *fd)
 {
-       struct pollfd *fds;
-       struct ustcomm_connection **conn_table;
-       struct ustcomm_connection *conn;
        int result;
        int retval;
-
-       for(;;) {
-               int idx = 0;
-               int n_fds = 1;
-
-               list_for_each_entry(conn, &server->connections, list) {
-                       n_fds++;
-               }
-
-               fds = (struct pollfd *) zmalloc(n_fds * sizeof(struct pollfd));
-               if(fds == NULL) {
-                       ERR("zmalloc returned NULL");
+       struct ustcomm_header peek_header;
+       struct iovec iov[2];
+       struct msghdr msg;
+       struct cmsghdr *cmsg;
+       char buf[CMSG_SPACE(sizeof(int))];
+
+       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;
+       }
 
-               conn_table = (struct ustcomm_connection **) zmalloc(n_fds * sizeof(struct ustcomm_connection *));
-               if(conn_table == NULL) {
-                       ERR("zmalloc returned NULL");
-                       retval = -1;
-                       goto free_fds_return;
-               }
+       memset(&msg, 0, sizeof(msg));
 
-               /* special idx 0 is for listening socket */
-               fds[idx].fd = server->listen_fd;
-               fds[idx].events = POLLIN;
-               idx++;
+       iov[0].iov_base = (char *)header;
+       iov[0].iov_len = sizeof(struct ustcomm_header);
 
-               list_for_each_entry(conn, &server->connections, list) {
-                       fds[idx].fd = conn->fd;
-                       fds[idx].events = POLLIN;
-                       conn_table[idx] = conn;
-                       idx++;
-               }
+       msg.msg_iov = iov;
+       msg.msg_iovlen = 1;
 
-               result = poll(fds, n_fds, timeout);
-               if(result == -1 && errno == EINTR) {
-                       /* That's ok. ustd receives signals to notify it must shutdown. */
-                       retval = -1;
-                       goto free_conn_table_return;
+       if (peek_header.size) {
+               if (peek_header.size < 0 || peek_header.size > 100) {
+                       WARN("big peek header! %d", peek_header.size);
                }
-               else if(result == -1) {
-                       PERROR("poll");
-                       retval = -1;
-                       goto free_conn_table_return;
-               }
-               else if(result == 0) {
-                       retval = 0;
-                       goto free_conn_table_return;
+               *data = malloc(peek_header.size);
+               if (!*data) {
+                       ERR("failed to allocate space for message");
                }
 
-               if(fds[0].revents) {
-                       struct ustcomm_connection *newconn;
-                       int newfd;
+               iov[1].iov_base = (char *)*data;
+               iov[1].iov_len = peek_header.size;
 
-                       result = newfd = accept(server->listen_fd, NULL, NULL);
-                       if(result == -1) {
-                               PERROR("accept");
-                               retval = -1;
-                               goto free_conn_table_return;
-                       }
+               msg.msg_iovlen++;
+       }
 
-                       newconn = (struct ustcomm_connection *) zmalloc(sizeof(struct ustcomm_connection));
-                       if(newconn == NULL) {
-                               ERR("zmalloc returned NULL");
-                               return -1;
-                       }
+       if (fd && peek_header.fd_included) {
+               msg.msg_control = buf;
+               msg.msg_controllen = sizeof(buf);
+       }
 
-                       ustcomm_init_connection(newconn);
-                       newconn->fd = newfd;
+       result = recvmsg(sock, &msg,
+                        MSG_WAITALL);
 
-                       list_add(&newconn->list, &server->connections);
+       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;
                }
-
-               for(idx=1; idx<n_fds; idx++) {
-                       if(fds[idx].revents) {
-                               retval = recv_message_conn(conn_table[idx], msg);
-                               if(src)
-                                       src->fd = fds[idx].fd;
-
-                               if(retval == 0) {
-                                       /* connection finished */
-                                       list_for_each_entry(conn, &server->connections, list) {
-                                               if(conn->fd == fds[idx].fd) {
-                                                       ustcomm_close_app(conn);
-                                                       list_del(&conn->list);
-                                                       free(conn);
-                                                       break;
-                                               }
-                                       }
-                               }
-                               else {
-                                       goto free_conn_table_return;
-                               }
+               free(*data);
+               return retval;
+       }
+
+       if (fd && peek_header.fd_included) {
+               cmsg = CMSG_FIRSTHDR(&msg);
+               result = 0;
+               while (cmsg != NULL) {
+                       if (cmsg->cmsg_level == SOL_SOCKET
+                           && cmsg->cmsg_type  == SCM_RIGHTS) {
+                               *fd = *(int *) CMSG_DATA(cmsg);
+                               result = 1;
+                               break;
                        }
+                       cmsg = CMSG_NXTHDR(&msg, cmsg);
+               }
+               if (!result) {
+                       ERR("Failed to receive file descriptor\n");
                }
-
-               free(fds);
-               free(conn_table);
        }
 
-free_conn_table_return:
-       free(conn_table);
-free_fds_return:
-       free(fds);
-       return retval;
+       return 1;
 }
 
-int ustcomm_ustd_recv_message(struct ustcomm_ustd *ustd, char **msg, struct ustcomm_source *src, int timeout)
+int ustcomm_recv(int sock,
+                struct ustcomm_header *header,
+                char **data)
 {
-       return ustcomm_recv_message(&ustd->server, msg, src, timeout);
+       return ustcomm_recv_fd(sock, header, data, NULL);
 }
 
-int ustcomm_app_recv_message(struct ustcomm_app *app, char **msg, struct ustcomm_source *src, int timeout)
+
+int recv_message_conn(int sock, char **msg)
 {
-       return ustcomm_recv_message(&app->server, msg, src, timeout);
-}
+       struct ustcomm_header header;
 
-/* This removes src from the list of active connections of app.
- */
+       return ustcomm_recv(sock, &header, msg);
+}
 
-int ustcomm_app_detach_client(struct ustcomm_app *app, struct ustcomm_source *src)
+int ustcomm_send_fd(int sock,
+                   const struct ustcomm_header *header,
+                   const char *data,
+                   int *fd)
 {
-       struct ustcomm_server *server = (struct ustcomm_server *)app;
-       struct ustcomm_connection *conn;
+       struct iovec iov[2];
+       struct msghdr msg;
+       int result;
+       struct cmsghdr *cmsg;
+       char buf[CMSG_SPACE(sizeof(int))];
+
+       memset(&msg, 0, sizeof(msg));
+
+       iov[0].iov_base = (char *)header;
+       iov[0].iov_len = sizeof(struct ustcomm_header);
+
+       msg.msg_iov = iov;
+       msg.msg_iovlen = 1;
+
+       if (header->size) {
+               iov[1].iov_base = (char *)data;
+               iov[1].iov_len = header->size;
+
+               msg.msg_iovlen++;
 
-       list_for_each_entry(conn, &server->connections, list) {
-               if(conn->fd == src->fd) {
-                       list_del(&conn->list);
-                       goto found;
-               }
        }
 
-       return -1;
-found:
-       return src->fd;
+       if (fd && header->fd_included) {
+               msg.msg_control = buf;
+               msg.msg_controllen = sizeof(buf);
+               cmsg = CMSG_FIRSTHDR(&msg);
+               cmsg->cmsg_level = SOL_SOCKET;
+               cmsg->cmsg_type = SCM_RIGHTS;
+               cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+               *(int *) CMSG_DATA(cmsg) = *fd;
+               msg.msg_controllen = cmsg->cmsg_len;
+       }
+
+       result = sendmsg(sock, &msg, MSG_NOSIGNAL);
+       if (result < 0 && errno != EPIPE) {
+               PERROR("sendmsg failed");
+       }
+       return result;
 }
 
-static int init_named_socket(const char *name, char **path_out)
+int ustcomm_send(int sock,
+                const struct ustcomm_header *header,
+                const char *data)
 {
-       int result;
-       int fd;
+       return ustcomm_send_fd(sock, header, data, NULL);
+}
 
-       struct sockaddr_un addr;
-       
-       result = fd = socket(PF_UNIX, SOCK_STREAM, 0);
-       if(result == -1) {
-               PERROR("socket");
-               return -1;
-       }
+int ustcomm_send_reply(char *msg, int sock)
+{
+       int result;
+       struct ustcomm_header header;
 
-       addr.sun_family = AF_UNIX;
+       memset(&header, 0, sizeof(header));
 
-       strncpy(addr.sun_path, name, UNIX_PATH_MAX);
-       addr.sun_path[UNIX_PATH_MAX-1] = '\0';
+       header.size = strlen(msg) + 1;
 
-       result = access(name, F_OK);
-       if(result == 0) {
-               /* file exists */
-               result = unlink(name);
-               if(result == -1) {
-                       PERROR("unlink of socket file");
-                       goto close_sock;
-               }
-               DBG("socket already exists; overwriting");
+       result = ustcomm_send(sock, &header, msg);
+       if(result < 0) {
+               ERR("error in ustcomm_send");
+               return result;
        }
 
-       result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
-       if(result == -1) {
-               PERROR("bind");
-               goto close_sock;
-       }
+       return 0;
+}
 
-       result = listen(fd, 1);
-       if(result == -1) {
-               PERROR("listen");
-               goto close_sock;
-       }
+int ustcomm_send_req(int sock,
+                    const struct ustcomm_header *req_header,
+                    const char *data,
+                    char **response)
+{
+       int result;
+       struct ustcomm_header res_header;
 
-       if(path_out) {
-               *path_out = strdup(addr.sun_path);
+       result = ustcomm_send(sock, req_header, data);
+       if ( result <= 0) {
+               return result;
        }
 
-       return fd;
+       if (!response) {
+               return 1;
+       }
 
-       close_sock:
-       close(fd);
+       return ustcomm_recv(sock,
+                           &res_header,
+                           response);
 
-       return -1;
 }
 
 /*
@@ -527,27 +545,17 @@ static int init_named_socket(const char *name, char **path_out)
  * ECONNRESET, which is normal when the application dies.
  */
 
-int ustcomm_send_request(struct ustcomm_connection *conn, const char *req, char **reply)
+int ustcomm_send_request(int sock, const char *req, char **reply)
 {
-       int result;
+       struct ustcomm_header req_header;
 
-       /* Send including the final \0 */
-       result = send_message_fd(conn->fd, req);
-       if(result != 1)
-               return result;
+       req_header.size = strlen(req) + 1;
 
-       if(!reply)
-               return 1;
+       return ustcomm_send_req(sock,
+                               &req_header,
+                               req,
+                               reply);
 
-       result = recv_message_conn(conn, reply);
-       if(result == -1) {
-               return -1;
-       }
-       else if(result == 0) {
-               return 0;
-       }
-       
-       return 1;
 }
 
 /* Return value:
@@ -555,52 +563,45 @@ int ustcomm_send_request(struct ustcomm_connection *conn, const char *req, char
  * -1: error
  */
 
-int ustcomm_connect_path(const char *path, struct ustcomm_connection *conn, pid_t signalpid)
+int ustcomm_connect_path(const char *name, int *connection_fd)
 {
-       int fd;
-       int result;
-       struct sockaddr_un addr;
+       int result, fd;
+       size_t sock_addr_size;
+       struct sockaddr_un *addr;
 
-       ustcomm_init_connection(conn);
-
-       result = fd = socket(PF_UNIX, SOCK_STREAM, 0);
-       if(result == -1) {
+       fd = socket(PF_UNIX, SOCK_STREAM, 0);
+       if(fd == -1) {
                PERROR("socket");
                return -1;
        }
 
-       addr.sun_family = AF_UNIX;
-
-       result = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s", path);
-       if(result >= UNIX_PATH_MAX) {
-               ERR("string overflow allocating socket name");
-               return -1;
-       }
-
-       if(signalpid >= 0) {
-               result = signal_process(signalpid);
-               if(result == -1) {
-                       ERR("could not signal process");
-                       return -1;
-               }
+       addr = create_sock_addr(name, &sock_addr_size);
+       if (addr == NULL) {
+               ERR("allocating addr failed");
+               goto close_sock;
        }
 
-       result = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
+       result = connect(fd, (struct sockaddr *)addr, sock_addr_size);
        if(result == -1) {
-               PERROR("connect (path=%s)", path);
-               return -1;
+               PERROR("connect (path=%s)", name);
+               goto free_sock_addr;
        }
 
-       conn->fd = fd;
+       *connection_fd = fd;
+
+       free(addr);
 
        return 0;
-}
 
-int ustcomm_disconnect(struct ustcomm_connection *conn)
-{
-       return close(conn->fd);
+free_sock_addr:
+       free(addr);
+close_sock:
+       close(fd);
+
+       return -1;
 }
 
+
 /* Open a connection to a traceable app.
  *
  * Return value:
@@ -608,35 +609,30 @@ int ustcomm_disconnect(struct ustcomm_connection *conn)
  * -1: error
  */
 
-int ustcomm_connect_app(pid_t pid, struct ustcomm_connection *conn)
+int ustcomm_connect_app(pid_t pid, int *app_fd)
 {
        int result;
-       char path[UNIX_PATH_MAX];
-
+       int retval = 0;
+       char *name;
 
-       result = snprintf(path, UNIX_PATH_MAX, "%s/%d", SOCK_DIR, pid);
-       if(result >= UNIX_PATH_MAX) {
-               ERR("string overflow allocating socket name");
+       result = asprintf(&name, "%s/%d", SOCK_DIR, pid);
+       if (result < 0) {
+               ERR("failed to allocate socket name");
                return -1;
        }
 
-       return ustcomm_connect_path(path, conn, pid);
-}
-
-/* Close a connection to a traceable app. It frees the
- * resources. It however does not free the
- * ustcomm_connection itself.
- */
+       result = ustcomm_connect_path(name, app_fd);
+       if (result < 0) {
+               ERR("failed to connect to app");
+               retval = -1;
+       }
 
-int ustcomm_close_app(struct ustcomm_connection *conn)
-{
-       close(conn->fd);
-       free(conn->recv_buf);
+       free(name);
 
-       return 0;
+       return retval;
 }
 
-static int ensure_dir_exists(const char *dir)
+int ensure_dir_exists(const char *dir)
 {
        struct stat st;
        int result;
@@ -663,139 +659,10 @@ static int ensure_dir_exists(const char *dir)
        return 0;
 }
 
-/* Called by an application to initialize its server so daemons can
- * connect to it.
- */
-
-int ustcomm_init_app(pid_t pid, struct ustcomm_app *handle)
-{
-       int result;
-       char *name;
-
-       result = asprintf(&name, "%s/%d", SOCK_DIR, (int)pid);
-       if(result >= UNIX_PATH_MAX) {
-               ERR("string overflow allocating socket name");
-               return -1;
-       }
-
-       result = ensure_dir_exists(SOCK_DIR);
-       if(result == -1) {
-               ERR("Unable to create socket directory %s", SOCK_DIR);
-               return -1;
-       }
-
-       handle->server.listen_fd = init_named_socket(name, &(handle->server.socketpath));
-       if(handle->server.listen_fd < 0) {
-               ERR("Error initializing named socket (%s). Check that directory exists and that it is writable.", name);
-               goto free_name;
-       }
-       free(name);
-
-       INIT_LIST_HEAD(&handle->server.connections);
-
-       return 0;
-
-free_name:
-       free(name);
-       return -1;
-}
-
 /* Used by the daemon to initialize its server so applications
  * can connect to it.
  */
 
-int ustcomm_init_ustd(struct ustcomm_ustd *handle, const char *sock_path)
-{
-       char *name;
-       int retval = 0;
-
-       if(sock_path) {
-               if (asprintf(&name, "%s", sock_path) < 0) {
-                       ERR("ustcomm_init_ustd : asprintf failed (sock_path %s)",
-                           sock_path);
-                       return -1;
-               }
-       }
-       else {
-               int result;
-
-               /* Only check if socket dir exists if we are using the default directory */
-               result = ensure_dir_exists(SOCK_DIR);
-               if(result == -1) {
-                       ERR("Unable to create socket directory %s", SOCK_DIR);
-                       return -1;
-               }
-
-               if (asprintf(&name, "%s/%s", SOCK_DIR, "ustd") < 0) {
-                       ERR("ustcomm_init_ustd : asprintf failed (%s/ustd)",
-                           SOCK_DIR);
-                       return -1;
-               }
-       }
-
-       handle->server.listen_fd = init_named_socket(name, &handle->server.socketpath);
-       if(handle->server.listen_fd < 0) {
-               ERR("error initializing named socket at %s", name);
-               retval = -1;
-               goto free_name;
-       }
-
-       INIT_LIST_HEAD(&handle->server.connections);
-
-free_name:
-       free(name);
-
-       return retval;
-}
-
-static void ustcomm_fini_server(struct ustcomm_server *server, int keep_socket_file)
-{
-       int result;
-       struct stat st;
-
-       if(!keep_socket_file) {
-               /* Destroy socket */
-               result = stat(server->socketpath, &st);
-               if(result == -1) {
-                       PERROR("stat (%s)", server->socketpath);
-                       return;
-               }
-
-               /* Paranoid check before deleting. */
-               result = S_ISSOCK(st.st_mode);
-               if(!result) {
-                       ERR("The socket we are about to delete is not a socket.");
-                       return;
-               }
-
-               result = unlink(server->socketpath);
-               if(result == -1) {
-                       PERROR("unlink");
-               }
-       }
-
-       free(server->socketpath);
-
-       result = close(server->listen_fd);
-       if(result == -1) {
-               PERROR("close");
-               return;
-       }
-}
-
-/* Free a traceable application server */
-
-void ustcomm_fini_app(struct ustcomm_app *handle, int keep_socket_file)
-{
-       ustcomm_fini_server(&handle->server, keep_socket_file);
-}
-
-/* Free a ustd server */
-
-void ustcomm_fini_ustd(struct ustcomm_ustd *handle)
-{
-       ustcomm_fini_server(&handle->server, 0);
-}
 
 static const char *find_tok(const char *str)
 {
@@ -884,89 +751,3 @@ char *nth_token(const char *str, int tok_no)
 
        return retval;
 }
-
-/* Callback from multipoll.
- * Receive a new connection on the listening socket.
- */
-
-static int process_mp_incoming_conn(void *priv, int fd, short events)
-{
-       struct ustcomm_connection *newconn;
-       struct ustcomm_server *server = (struct ustcomm_server *) priv;
-       int newfd;
-       int result;
-
-       result = newfd = accept(server->listen_fd, NULL, NULL);
-       if(result == -1) {
-               PERROR("accept");
-               return -1;
-       }
-
-       newconn = (struct ustcomm_connection *) zmalloc(sizeof(struct ustcomm_connection));
-       if(newconn == NULL) {
-               ERR("zmalloc returned NULL");
-               return -1;
-       }
-
-       ustcomm_init_connection(newconn);
-       newconn->fd = newfd;
-
-       list_add(&newconn->list, &server->connections);
-
-       return 0;
-}
-
-/* Callback from multipoll.
- * Receive a message on an existing connection.
- */
-
-static int process_mp_conn_msg(void *priv, int fd, short revents)
-{
-       struct ustcomm_multipoll_conn_info *mpinfo = (struct ustcomm_multipoll_conn_info *) priv;
-       int result;
-       char *msg;
-       struct ustcomm_source src;
-
-       if(revents) {
-               src.fd = fd;
-
-               result = recv_message_conn(mpinfo->conn, &msg);
-               if(result == -1) {
-                       ERR("error in recv_message_conn");
-               }
-
-               else if(result == 0) {
-                       /* connection finished */
-                       ustcomm_close_app(mpinfo->conn);
-                       list_del(&mpinfo->conn->list);
-                       free(mpinfo->conn);
-               }
-               else {
-                       mpinfo->cb(msg, &src);
-                       free(msg);
-               }
-       }
-
-       return 0;
-}
-
-int free_ustcomm_client_poll(void *data)
-{
-       free(data);
-       return 0;
-}
-
-void ustcomm_mp_add_app_clients(struct mpentries *ent, struct ustcomm_app *app, int (*cb)(char *recvbuf, struct ustcomm_source *src))
-{
-       struct ustcomm_connection *conn;
-
-       /* add listener socket */
-       multipoll_add(ent, app->server.listen_fd, POLLIN, process_mp_incoming_conn, &app->server, NULL);
-
-       list_for_each_entry(conn, &app->server.connections, list) {
-               struct ustcomm_multipoll_conn_info *mpinfo = (struct ustcomm_multipoll_conn_info *) zmalloc(sizeof(struct ustcomm_multipoll_conn_info));
-               mpinfo->conn = conn;
-               mpinfo->cb = cb;
-               multipoll_add(ent, conn->fd, POLLIN, process_mp_conn_msg, mpinfo, free_ustcomm_client_poll);
-       }
-}
This page took 0.034982 seconds and 4 git commands to generate.