Blob


1 #include <u.h>
2 #define NOPLAN9DEFINES
3 #include <libc.h>
5 #include <sys/socket.h>
6 #include <netinet/in.h>
7 #include <sys/un.h>
9 #undef sun
10 #define sun sockun
11 extern int _p9dialparse(char*, char**, char**, u32int*, int*);
13 static int
14 getfd(char *dir)
15 {
16 int fd;
18 if(strncmp(dir, "/dev/fd/", 8) != 0)
19 return -1;
20 fd = strtol(dir+8, &dir, 0);
21 if(*dir != 0)
22 return -1;
23 return fd;
24 }
26 static void
27 putfd(char *dir, int fd)
28 {
29 snprint(dir, NETPATHLEN, "/dev/fd/%d", fd);
30 }
32 #undef unix
34 int
35 p9announce(char *addr, char *dir)
36 {
37 int proto;
38 char *buf, *unix;
39 char *net;
40 u32int host;
41 int port, s;
42 int n, sn;
43 struct sockaddr_in sa;
44 struct sockaddr_un sun;
46 buf = strdup(addr);
47 if(buf == nil)
48 return -1;
50 if(_p9dialparse(buf, &net, &unix, &host, &port) < 0){
51 free(buf);
52 return -1;
53 }
54 if(strcmp(net, "tcp") == 0)
55 proto = SOCK_STREAM;
56 else if(strcmp(net, "udp") == 0)
57 proto = SOCK_DGRAM;
58 else if(strcmp(net, "unix") == 0)
59 goto Unix;
60 else{
61 werrstr("can only handle tcp, udp, and unix: not %s", net);
62 free(buf);
63 return -1;
64 }
65 free(buf);
67 memset(&sa, 0, sizeof sa);
68 memmove(&sa.sin_addr, &host, 4);
69 sa.sin_family = AF_INET;
70 sa.sin_port = htons(port);
71 if((s = socket(AF_INET, proto, 0)) < 0)
72 return -1;
73 sn = sizeof n;
74 if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&n, &sn) >= 0
75 && n == SOCK_STREAM){
76 n = 1;
77 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
78 }
79 if(bind(s, (struct sockaddr*)&sa, sizeof sa) < 0){
80 close(s);
81 return -1;
82 }
83 if(proto == SOCK_STREAM){
84 listen(s, 8);
85 putfd(dir, s);
86 print("announce dir: %s\n", dir);
87 }
88 return s;
90 Unix:
91 memset(&sun, 0, sizeof sun);
92 sun.sun_family = AF_UNIX;
93 strcpy(sun.sun_path, unix);
94 if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
95 return -1;
96 sn = sizeof sun;
97 if(bind(s, (struct sockaddr*)&sun, sizeof sun) < 0){
98 close(s);
99 return -1;
101 listen(s, 8);
102 putfd(dir, s);
103 return s;
106 int
107 p9listen(char *dir, char *newdir)
109 int fd;
111 if((fd = getfd(dir)) < 0){
112 werrstr("bad 'directory' in listen: %s", dir);
113 return -1;
116 print("accept %d", fd);
117 if((fd = accept(fd, nil, nil)) < 0)
118 return -1;
119 print(" -> %d\n", fd);
121 putfd(newdir, fd);
122 print("listen dir: %s\n", newdir);
123 return fd;
126 int
127 p9accept(int cfd, char *dir)
129 int fd;
131 if((fd = getfd(dir)) < 0){
132 werrstr("bad 'directory' in accept");
133 return -1;
135 /* need to dup because the listen fd will be closed */
136 return dup(fd);