diff options
Diffstat (limited to 'tools/testing/selftests/android/ion/ipcsocket.c')
-rw-r--r-- | tools/testing/selftests/android/ion/ipcsocket.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/tools/testing/selftests/android/ion/ipcsocket.c b/tools/testing/selftests/android/ion/ipcsocket.c new file mode 100644 index 000000000..7dc521002 --- /dev/null +++ b/tools/testing/selftests/android/ion/ipcsocket.c @@ -0,0 +1,227 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/un.h> +#include <errno.h> + +#include "ipcsocket.h" + + +int opensocket(int *sockfd, const char *name, int connecttype) +{ + int ret, temp = 1; + + if (!name || strlen(name) > MAX_SOCK_NAME_LEN) { + fprintf(stderr, "<%s>: Invalid socket name.\n", __func__); + return -1; + } + + ret = socket(PF_LOCAL, SOCK_STREAM, 0); + if (ret < 0) { + fprintf(stderr, "<%s>: Failed socket: <%s>\n", + __func__, strerror(errno)); + return ret; + } + + *sockfd = ret; + if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&temp, sizeof(int)) < 0) { + fprintf(stderr, "<%s>: Failed setsockopt: <%s>\n", + __func__, strerror(errno)); + goto err; + } + + sprintf(sock_name, "/tmp/%s", name); + + if (connecttype == 1) { + /* This is for Server connection */ + struct sockaddr_un skaddr; + int clientfd; + socklen_t sklen; + + unlink(sock_name); + memset(&skaddr, 0, sizeof(skaddr)); + skaddr.sun_family = AF_LOCAL; + strcpy(skaddr.sun_path, sock_name); + + ret = bind(*sockfd, (struct sockaddr *)&skaddr, + SUN_LEN(&skaddr)); + if (ret < 0) { + fprintf(stderr, "<%s>: Failed bind: <%s>\n", + __func__, strerror(errno)); + goto err; + } + + ret = listen(*sockfd, 5); + if (ret < 0) { + fprintf(stderr, "<%s>: Failed listen: <%s>\n", + __func__, strerror(errno)); + goto err; + } + + memset(&skaddr, 0, sizeof(skaddr)); + sklen = sizeof(skaddr); + + ret = accept(*sockfd, (struct sockaddr *)&skaddr, + (socklen_t *)&sklen); + if (ret < 0) { + fprintf(stderr, "<%s>: Failed accept: <%s>\n", + __func__, strerror(errno)); + goto err; + } + + clientfd = ret; + *sockfd = clientfd; + } else { + /* This is for client connection */ + struct sockaddr_un skaddr; + + memset(&skaddr, 0, sizeof(skaddr)); + skaddr.sun_family = AF_LOCAL; + strcpy(skaddr.sun_path, sock_name); + + ret = connect(*sockfd, (struct sockaddr *)&skaddr, + SUN_LEN(&skaddr)); + if (ret < 0) { + fprintf(stderr, "<%s>: Failed connect: <%s>\n", + __func__, strerror(errno)); + goto err; + } + } + + return 0; + +err: + if (*sockfd) + close(*sockfd); + + return ret; +} + +int sendtosocket(int sockfd, struct socketdata *skdata) +{ + int ret, buffd; + unsigned int len; + char cmsg_b[CMSG_SPACE(sizeof(int))]; + struct cmsghdr *cmsg; + struct msghdr msgh; + struct iovec iov; + struct timeval timeout; + fd_set selFDs; + + if (!skdata) { + fprintf(stderr, "<%s>: socketdata is NULL\n", __func__); + return -1; + } + + FD_ZERO(&selFDs); + FD_SET(0, &selFDs); + FD_SET(sockfd, &selFDs); + timeout.tv_sec = 20; + timeout.tv_usec = 0; + + ret = select(sockfd+1, NULL, &selFDs, NULL, &timeout); + if (ret < 0) { + fprintf(stderr, "<%s>: Failed select: <%s>\n", + __func__, strerror(errno)); + return -1; + } + + if (FD_ISSET(sockfd, &selFDs)) { + buffd = skdata->data; + len = skdata->len; + memset(&msgh, 0, sizeof(msgh)); + msgh.msg_control = &cmsg_b; + msgh.msg_controllen = CMSG_LEN(len); + iov.iov_base = "OK"; + iov.iov_len = 2; + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + cmsg = CMSG_FIRSTHDR(&msgh); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(len); + memcpy(CMSG_DATA(cmsg), &buffd, len); + + ret = sendmsg(sockfd, &msgh, MSG_DONTWAIT); + if (ret < 0) { + fprintf(stderr, "<%s>: Failed sendmsg: <%s>\n", + __func__, strerror(errno)); + return -1; + } + } + + return 0; +} + +int receivefromsocket(int sockfd, struct socketdata *skdata) +{ + int ret, buffd; + unsigned int len = 0; + char cmsg_b[CMSG_SPACE(sizeof(int))]; + struct cmsghdr *cmsg; + struct msghdr msgh; + struct iovec iov; + fd_set recvFDs; + char data[32]; + + if (!skdata) { + fprintf(stderr, "<%s>: socketdata is NULL\n", __func__); + return -1; + } + + FD_ZERO(&recvFDs); + FD_SET(0, &recvFDs); + FD_SET(sockfd, &recvFDs); + + ret = select(sockfd+1, &recvFDs, NULL, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "<%s>: Failed select: <%s>\n", + __func__, strerror(errno)); + return -1; + } + + if (FD_ISSET(sockfd, &recvFDs)) { + len = sizeof(buffd); + memset(&msgh, 0, sizeof(msgh)); + msgh.msg_control = &cmsg_b; + msgh.msg_controllen = CMSG_LEN(len); + iov.iov_base = data; + iov.iov_len = sizeof(data)-1; + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + cmsg = CMSG_FIRSTHDR(&msgh); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(len); + + ret = recvmsg(sockfd, &msgh, MSG_DONTWAIT); + if (ret < 0) { + fprintf(stderr, "<%s>: Failed recvmsg: <%s>\n", + __func__, strerror(errno)); + return -1; + } + + memcpy(&buffd, CMSG_DATA(cmsg), len); + skdata->data = buffd; + skdata->len = len; + } + return 0; +} + +int closesocket(int sockfd, char *name) +{ + char sockname[MAX_SOCK_NAME_LEN]; + + if (sockfd) + close(sockfd); + sprintf(sockname, "/tmp/%s", name); + unlink(sockname); + shutdown(sockfd, 2); + + return 0; +} |