diff --git a/examples/socket_grid.cc b/examples/socket_grid.cc new file mode 100644 index 00000000..9b79a43a --- /dev/null +++ b/examples/socket_grid.cc @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int sock; +static const char *sock_path_fmt = "/tmp/GridUnixSocket.%d"; +static char sock_path[256]; + +class UnixSockets { +public: + static void Open(int rank) + { + int errnum; + + sock = socket(AF_UNIX, SOCK_DGRAM, 0); assert(sock>0); + printf("allocated socket %d\n",sock); + + struct sockaddr_un sa_un = { 0 }; + sa_un.sun_family = AF_UNIX; + snprintf(sa_un.sun_path, sizeof(sa_un.sun_path),sock_path_fmt,rank); + unlink(sa_un.sun_path); + if (bind(sock, (struct sockaddr *)&sa_un, sizeof(sa_un))) { + perror("bind failure"); + exit(EXIT_FAILURE); + } + printf("bound socket %d to %s\n",sock,sa_un.sun_path); + } + + static int RecvFileDescriptor(void) + { + int n; + int fd; + char buf[1]; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + char cms[CMSG_SPACE(sizeof(int))]; + + iov.iov_base = buf; + iov.iov_len = 1; + + memset(&msg, 0, sizeof msg); + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = (caddr_t)cms; + msg.msg_controllen = sizeof cms; + + if((n=recvmsg(sock, &msg, 0)) < 0) { + perror("recvmsg failed"); + return -1; + } + if(n == 0){ + perror("recvmsg returned 0"); + return -1; + } + cmsg = CMSG_FIRSTHDR(&msg); + memmove(&fd, CMSG_DATA(cmsg), sizeof(int)); + printf("received fd %d from socket %d\n",fd,sock); + return fd; + } + + static void SendFileDescriptor(int fildes,int xmit_to_rank) + { + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg = NULL; + char ctrl[CMSG_SPACE(sizeof(int))]; + char data = ' '; + + memset(&msg, 0, sizeof(struct msghdr)); + memset(ctrl, 0, CMSG_SPACE(sizeof(int))); + iov.iov_base = &data; + iov.iov_len = sizeof(data); + + sprintf(sock_path,sock_path_fmt,xmit_to_rank); + printf("sending FD %d over socket %d to rank %d AF_UNIX path %s\n",fildes,sock,xmit_to_rank,sock_path);fflush(stdout); + + struct sockaddr_un sa_un = { 0 }; + sa_un.sun_family = AF_UNIX; + snprintf(sa_un.sun_path, sizeof(sa_un.sun_path),sock_path_fmt,xmit_to_rank); + + msg.msg_name = (void *)&sa_un; + msg.msg_namelen = sizeof(sa_un); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_controllen = CMSG_SPACE(sizeof(int)); + msg.msg_control = ctrl; + + 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)) = fildes; + + if ( sendmsg(sock, &msg, 0) == -1 ) perror("sendmsg failed"); + }; +}; + +int main(int argc, char **argv) +{ + int me = fork()?0:1; + + UnixSockets::Open(me); + + // need MPI barrier + sleep(10); + const char * message = "Hello, World\n"; + if( me ) { + int fd = open("foo",O_RDWR|O_CREAT,0666); + if ( fd < 0 ) { + perror("failed to open file"); + exit(EXIT_FAILURE); + } + // rank 1 sends ot rank 0 + UnixSockets::SendFileDescriptor(fd,0); + close(fd); + } else { + // rank 0 sends receives frmo rank 1 + int fd = UnixSockets::RecvFileDescriptor(); + write(fd,(const void *)message,strlen(message)); + close(fd); + } +}