#include "ipc_msg.h"
|
#include <string.h>
|
#include <stdlib.h>
|
|
/**
|
* @brief 发送目标文件描述符
|
* @param fd 传递信息的 UNIX 域 文件描述符
|
* @param fd_to_send 待发送的文件描述符
|
*/
|
int send_fd_args_sendmsg(int fd, int fd_to_send, pid_t pid, void **ppdata, int len)
|
{
|
struct iovec iov[1];
|
struct msghdr msg;
|
int control_len = 0;
|
int ret = 0;
|
memfd_data_st memfd_data;
|
struct cmsghdr cm; /* 这是辅助数据头部结构体,文件描述符就是通过这个结构体以及后面的数据部分发送的 */
|
|
control_len = CMSG_SPACE(sizeof(memfd_data_st) + len);
|
char * recv_buf = (char *)malloc(control_len);
|
|
if(NULL != recv_buf)
|
{
|
return -1;
|
}
|
|
iov[0].iov_base = recv_buf;
|
iov[0].iov_len = 1;
|
msg.msg_name = NULL;
|
msg.msg_namelen = 0;
|
msg.msg_iov = iov;
|
msg.msg_iovlen = 1;
|
|
memfd_data.memfd = fd_to_send;
|
memfd_data.pid = pid;
|
memfd_data.data = *ppdata;
|
memfd_data.len = len;
|
|
|
cm.cmsg_len = control_len; /* 辅助数据的字节数,包扩头部和真正的数据 */
|
cm.cmsg_level = SOL_SOCKET; /* 表示原始协议级别,与 setsockopt 的 level 参数相同 */
|
cm.cmsg_type = SCM_RIGHTS; /* 控制信息类型,SCM_RIGHTS 表示传送的内容是访问权 */
|
*(memfd_data_st*)CMSG_DATA(&cm) = memfd_data;/* 设置真正数据部分为我们想发送的文件描述符 */
|
msg.msg_control = &cm; /* 设置辅助数据 */
|
msg.msg_controllen = control_len;
|
|
ret = sendmsg(fd, &msg, 0);
|
free(recv_buf);
|
return ret;
|
}
|
|
/**
|
* @brief 发送目标文件描述符
|
* @param fd 传递信息的 UNIX 域 文件描述符
|
* @param fd_to_send 待发送的文件描述符
|
*/
|
int send_fd_sendmsg(int fd, memfd_data_st** ppmemfd_data)
|
{
|
memfd_data_st *ptr_memfd_data = *ppmemfd_data;
|
return send_fd_args_sendmsg(fd, ptr_memfd_data->memfd, ptr_memfd_data->pid, &ptr_memfd_data->data, ptr_memfd_data->len);
|
}
|
|
/**
|
* @brief 接受文件描述符
|
* @param fd 传递信息的 UNIX 域 文件描述符
|
*/
|
int recv_fd_recvmsg(int fd, memfd_data_st** ppmemfd_data)
|
{
|
struct iovec iov[1];
|
struct msghdr msg;
|
char recv_buf[MAX_LEN];
|
int ret = -1;
|
int control_len = 0;
|
struct cmsghdr cm;
|
|
iov[0].iov_base = recv_buf;
|
iov[0].iov_len = 1;
|
msg.msg_name = NULL;
|
msg.msg_namelen = 0;
|
msg.msg_iov = iov;
|
msg.msg_iovlen = 1;
|
|
control_len = CMSG_SPACE(sizeof(memfd_data_st) + MAX_LEN);
|
|
msg.msg_control = &cm;
|
msg.msg_controllen = control_len;
|
|
ret = recvmsg(fd, &msg, 0);
|
if(ret < 0)
|
{
|
ret = -1;
|
}
|
|
int off = offsetof(memfd_data_st, len);
|
int len = *(int*)((char *)CMSG_DATA(&cm) + off);
|
control_len = CMSG_SPACE(sizeof(memfd_data_st) + len);
|
*ppmemfd_data = (memfd_data_st *)malloc(control_len);
|
if(*ppmemfd_data == NULL)
|
{
|
return -1;
|
}
|
memset(*ppmemfd_data, 0, control_len);
|
memcpy(*ppmemfd_data, CMSG_DATA(&cm), control_len);
|
return ret;
|
}
|