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 extern int _p9dialparse(char*, char**, char**, u32int*, int*);
11 static int
12 getfd(char *dir)
13 {
14 int fd;
16 if(strncmp(dir, "/dev/fd/", 8) != 0)
17 return -1;
18 fd = strtol(dir+8, &dir, 0);
19 if(*dir != 0)
20 return -1;
21 return fd;
22 }
24 static void
25 putfd(char *dir, int fd)
26 {
27 snprint(dir, NETPATHLEN, "/dev/fd/%d", fd);
28 }
30 #undef unix
32 int
33 p9announce(char *addr, char *dir)
34 {
35 int proto;
36 char *buf, *unix;
37 char *net;
38 u32int host;
39 int port, s;
40 int n, sn;
41 struct sockaddr_in sa;
42 struct sockaddr_un sun;
44 buf = strdup(addr);
45 if(buf == nil)
46 return -1;
48 if(_p9dialparse(buf, &net, &unix, &host, &port) < 0){
49 free(buf);
50 return -1;
51 }
52 if(strcmp(net, "tcp") == 0)
53 proto = SOCK_STREAM;
54 else if(strcmp(net, "udp") == 0)
55 proto = SOCK_DGRAM;
56 else if(strcmp(net, "unix") == 0)
57 goto Unix;
58 else{
59 werrstr("can only handle tcp, udp, and unix: not %s", net);
60 free(buf);
61 return -1;
62 }
63 free(buf);
65 memset(&sa, 0, sizeof sa);
66 memmove(&sa.sin_addr, &host, 4);
67 sa.sin_family = AF_INET;
68 sa.sin_port = htons(port);
69 if((s = socket(AF_INET, proto, 0)) < 0)
70 return -1;
71 sn = sizeof n;
72 if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&n, &sn) >= 0
73 && n == SOCK_STREAM){
74 n = 1;
75 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
76 }
77 if(bind(s, (struct sockaddr*)&sa, sizeof sa) < 0){
78 close(s);
79 return -1;
80 }
81 if(proto == SOCK_STREAM){
82 listen(s, 8);
83 putfd(dir, s);
84 print("announce dir: %s\n", dir);
85 }
86 return s;
88 Unix:
89 memset(&sun, 0, sizeof sun);
90 sun.sun_family = AF_UNIX;
91 sun.sun_len = sizeof sun;
92 strcpy(sun.sun_path, unix);
93 if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
94 return -1;
95 sn = sizeof sun;
96 if(bind(s, (struct sockaddr*)&sun, sizeof sun) < 0){
97 close(s);
98 return -1;
99 }
100 listen(s, 8);
101 putfd(dir, s);
102 return s;
105 int
106 p9listen(char *dir, char *newdir)
108 int fd;
110 if((fd = getfd(dir)) < 0){
111 werrstr("bad 'directory' in listen: %s", dir);
112 return -1;
115 print("accept %d", fd);
116 if((fd = accept(fd, nil, nil)) < 0)
117 return -1;
118 print(" -> %d\n", fd);
120 putfd(newdir, fd);
121 print("listen dir: %s\n", newdir);
122 return fd;
125 int
126 p9accept(int cfd, char *dir)
128 int fd;
130 if((fd = getfd(dir)) < 0){
131 werrstr("bad 'directory' in accept");
132 return -1;
134 /* need to dup because the listen fd will be closed */
135 return dup(fd);