Some socket connectors UNIX<->TCP and UNIX<->PIPE.
[nethome.git] / src / unixtcp.c
diff --git a/src/unixtcp.c b/src/unixtcp.c
new file mode 100644 (file)
index 0000000..f728f53
--- /dev/null
@@ -0,0 +1,139 @@
+/* $Id$ */
+
+FIXME: Check and tidy it up first!
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <string.h>
+
+
+int main(int argc,char **argv)
+{
+int fdunix,fdtcp,fdtcplisten;
+struct sockaddr_un sockaddr_unix;
+struct sockaddr_in sockaddr_tcp;
+const char *pathnameunix,*nametcp;
+struct pollfd pollfds[2];
+int fdi,fdo;
+socklen_t sockaddr_tcp_len;
+int setsockopt_SO_REUSEADDR_on;
+
+       if (argc!=3) {
+               fprintf(stderr,"%s: <pathname UNIX socket> <name TCP>\n",argv[0]);
+               exit(EXIT_FAILURE);
+               }
+       pathnameunix=argv[1];
+       nametcp=argv[2];
+
+       if (-1==(fdunix=socket(PF_UNIX,SOCK_STREAM,0))) {
+               fprintf(stderr,"socket(PF_UNIX,SOCK_STREAM,0)=%d: %m\n",fdunix);
+               exit(EXIT_FAILURE);
+               }
+       memset(&sockaddr_unix,0,sizeof(sockaddr_unix));
+       sockaddr_unix.sun_family=AF_UNIX;
+       strncpy(sockaddr_unix.sun_path,pathnameunix,sizeof(sockaddr_unix.sun_path));
+       if (connect(fdunix,(const struct sockaddr *)&sockaddr_unix,sizeof(sockaddr_unix))) {
+               fprintf(stderr,"connect(UNIX socket,\"%s\"): %m\n",pathnameunix);
+               exit(EXIT_FAILURE);
+               }
+
+       if (-1==(fdtcplisten=socket(PF_INET,SOCK_STREAM,0))) {
+               fprintf(stderr,"socket(PF_INET,SOCK_STREAM,0)=%d: %m\n",fdtcplisten);
+               exit(EXIT_FAILURE);
+               }
+       setsockopt_SO_REUSEADDR_on=1;
+       if (setsockopt(fdtcplisten,SOL_SOCKET,SO_REUSEADDR,&setsockopt_SO_REUSEADDR_on,sizeof(setsockopt_SO_REUSEADDR_on))) {
+               fprintf(stderr,"setsockopt(TCP socket,SOL_SOCKET,SO_REUSEADDR,&1,sizeof(1)): %m\n");
+               exit(EXIT_FAILURE);
+               }
+       memset(&sockaddr_tcp,0,sizeof(sockaddr_tcp));
+       sockaddr_tcp.sin_family=AF_INET;
+       sockaddr_tcp.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
+       sockaddr_tcp.sin_port=htons(atoi(nametcp));
+       if (bind(fdtcplisten,(const struct sockaddr *)&sockaddr_tcp,sizeof(sockaddr_tcp))) {
+               fprintf(stderr,"bind(TCP socket,127.0.0.1:%s): %m\n",nametcp);
+               exit(EXIT_FAILURE);
+               }
+       if (listen(fdtcplisten,1)) {
+               fprintf(stderr,"listen(TCP socket,1): %m\n");
+               exit(EXIT_FAILURE);
+               }
+       sockaddr_tcp_len=sizeof(sockaddr_tcp);
+       fprintf(stderr,"accept... ");
+       if (-1==(fdtcp=accept(fdtcplisten,(struct sockaddr *)&sockaddr_tcp,&sockaddr_tcp_len))) {
+               fprintf(stderr,"accept(TCP socket): %m\n");
+               exit(EXIT_FAILURE);
+               }
+       fprintf(stderr,"done\n");
+       if (close(fdtcplisten)) {
+               fprintf(stderr,"close(TCP listen socket): %m\n");
+               exit(EXIT_FAILURE);
+               }
+
+       for (;;) {
+               pollfds[0].fd=fdunix;
+               pollfds[0].events=POLLIN;
+               pollfds[1].fd=fdtcp;
+               pollfds[1].events=POLLIN;
+               if (0>=poll(pollfds,sizeof(pollfds)/sizeof(*pollfds),-1)) {
+                       fprintf(stderr,"poll(UNIX socket,PIPE socket): %m\n");
+                       exit(EXIT_FAILURE);
+                       }
+               if (pollfds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) {
+                       fprintf(stderr,"poll(UNIX socket): revents=0x%X\n",(unsigned)pollfds[0].revents);
+                       exit(EXIT_FAILURE);
+                       }
+               if (pollfds[1].revents & (POLLERR|POLLHUP|POLLNVAL)) {
+                       fprintf(stderr,"poll(PIPE socket): revents=0x%X\n",(unsigned)pollfds[1].revents);
+                       exit(EXIT_FAILURE);
+                       }
+               for (fdi=0;fdi<sizeof(pollfds)/sizeof(*pollfds);fdi++) {
+                       for (;;) {
+                               ssize_t got;
+                               char buf[0x1000];
+
+                               if (fcntl(pollfds[fdi].fd,F_SETFL,O_NONBLOCK)) {
+                                       fprintf(stderr,"fcntl(%s socket,F_SETFL,O_NONBLOCK): %m\n",
+                                                       (fdi==0 ? "UNIX" : (fdi==1 ? "PIPE" : "<UNKNOWN>")));
+                                       exit(EXIT_FAILURE);
+                                       }
+                               got=read(pollfds[fdi].fd,buf,sizeof(buf));
+                               if (got<0) {
+                                       if (errno==EAGAIN)
+                                               break;
+                                       fprintf(stderr,"read(%s socket): %m\n",
+                                                       (fdi==0 ? "UNIX" : (fdi==1 ? "PIPE" : "<UNKNOWN>")));
+                                       exit(EXIT_FAILURE);
+                                       }
+                               if (got==0)
+                                       exit(EXIT_SUCCESS);
+                               for (fdo=0;fdo<sizeof(pollfds)/sizeof(*pollfds);fdo++) {
+                                       if (fdi==fdo)
+                                               continue;
+                                       if (fcntl(pollfds[fdo].fd,F_SETFL,0 /* !O_NONBLOCK */)) {
+                                               fprintf(stderr,"fcntl(%s socket,F_SETFL,0 /* !O_NONBLOCK */): %m\n",
+                                                               (fdi==0 ? "UNIX" : (fdi==1 ? "PIPE" : "<UNKNOWN>")));
+                                               exit(EXIT_FAILURE);
+                                               }
+                                       if (got!=write(pollfds[fdo].fd,buf,got)) {
+                                               fprintf(stderr,"write(%s socket,%ld): %m\n",
+                                                               (fdo==0 ? "UNIX" : (fdo==1 ? "PIPE" : "<UNKNOWN>")),
+                                                               (long)got);
+                                               exit(EXIT_FAILURE);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       return EXIT_SUCCESS;
+}