228 lines
4.7 KiB
C
228 lines
4.7 KiB
C
|
#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;
|
||
|
}
|