4 #include <sys/socket.h>
5 #include <netinet/in.h>
13 typedef struct stream_opts
15 int proto; /* always TCP */
22 #define c(sv) ((stream_t)((sv)->classinfo))
24 static int stream_opt(service_t sv, char *opt)
28 if (strncmp(opt, "port=", 5) == 0) {
32 port = strtoul(opt+5, &ep, 10);
34 c(sv)->port = htons(port);
37 se = getservbyname(opt+5, protos);
39 c(sv)->port = se->s_port;
43 if (strncmp(opt, "backlog=", 8) == 0) {
45 c(sv)->backlog = strtoul(opt+8, &ep, 10);
52 static void stream_register(service_t sv)
54 /* create a socket and bind it */
55 stream_t s = sv->classinfo;
56 struct sockaddr_in addr;
59 if (s->sock >=0 || s->port <= 0)
61 s->sock = socket(AF_INET, SOCK_STREAM, s->proto);
65 setsockopt(s->sock, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));
67 memset(&addr, 0, sizeof(addr));
68 addr.sin_family = AF_INET;
69 addr.sin_port = s->port;
70 if (bind(s->sock, (struct sockaddr *)&addr, sizeof(addr))) {
76 if (listen(s->sock, s->backlog)<0) {
84 static void stream_unregister(service_t sv)
86 stream_t s = sv->classinfo;
92 static void stream_check(service_t sv)
94 stream_t s = sv->classinfo;
97 if (readyon(s->sock)) {
99 env[0] = "METAD_REASON=connect";
100 env[1] = "METAD_ARG=";
102 if (new_proc(sv, env) == -1)
103 if (s->newsock >= 0) {
112 static int stream_prefork(service_t sv)
115 stream_t s = sv->classinfo;
119 s->newsock = accept(s->sock, NULL, 0);
122 /* disable NDELAY which might be inherited */
123 f = fcntl(s->newsock, F_GETFL, 0);
125 fcntl(s->newsock, F_SETFL, f);
129 static void stream_init(service_t to)
131 /* set up defaults */
133 n = (stream_t)malloc(sizeof(struct stream_opts));
135 n->proto = IPPROTO_TCP;
144 static void stream_copy(service_t from, service_t to)
148 c(to)->sock = c(from)->sock;
152 static void stream_freestate(service_t sv)
154 stream_t s = sv->classinfo;
160 static void stream_newparent(service_t sv, proc_t p)
162 if (c(sv)->newsock >= 0) {
163 close(c(sv)->newsock);
168 static void stream_newchild(service_t sv)
171 if (c(sv)->newsock < 0)
173 dup2(c(sv)->newsock, 0);
174 dup2(c(sv)->newsock, 1);
175 if (c(sv)->newsock > 1)
176 close(c(sv)->newsock);
180 static void stream_send(service_t sv)
182 send_byte(2); /*stream */
183 send_int(c(sv)->proto);
184 send_int(ntohs(c(sv)->port));
185 send_int(c(sv)->backlog);
186 send_int(c(sv)->sock>=0);
189 struct class stream_class = {
191 .c_process_opt = stream_opt,
192 .register_service= stream_register,
193 .c_check_service= stream_check,
194 .init_state = stream_init,
195 .copy_state = stream_copy,
196 .free_state = stream_freestate,
197 .send_class = stream_send,
198 .disable_service= stream_unregister,
199 .new_parent = stream_newparent,
200 .new_child = stream_newchild,
201 .prefork = stream_prefork,