-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathmhttp.c
More file actions
150 lines (131 loc) · 4.32 KB
/
mhttp.c
File metadata and controls
150 lines (131 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include "mdnsd.h"
#include "sdtxt.h"
// conflict!
void con(char *name, int type, void *arg)
{
printf("conflicting name detected %s for type %d\n",name,type);
exit(1);
}
// quit
int _shutdown = 0;
mdnsd _d;
int _zzz[2];
void done(int sig)
{
_shutdown = 1;
mdnsd_shutdown(_d);
write(_zzz[1]," ",1);
}
// create multicast 224.0.0.251:5353 socket
int msock()
{
int s, flag = 1, ittl = 255;
struct sockaddr_in in;
struct ip_mreq mc;
char ttl = 255;
bzero(&in, sizeof(in));
in.sin_family = AF_INET;
in.sin_port = htons(5353);
in.sin_addr.s_addr = 0;
if((s = socket(AF_INET,SOCK_DGRAM,0)) < 0) return 0;
#ifdef SO_REUSEPORT
setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (char*)&flag, sizeof(flag));
#endif
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag));
if(bind(s,(struct sockaddr*)&in,sizeof(in))) { close(s); return 0; }
mc.imr_multiaddr.s_addr = inet_addr("224.0.0.251");
mc.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc, sizeof(mc));
setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ittl, sizeof(ittl));
flag = fcntl(s, F_GETFL, 0);
flag |= O_NONBLOCK;
fcntl(s, F_SETFL, flag);
return s;
}
int main(int argc, char *argv[])
{
mdnsd d;
mdnsdr r;
struct message m;
struct in_addr ip;
unsigned short int port;
struct timeval *tv;
int bsize, ssize = sizeof(struct sockaddr_in);
unsigned char buf[MAX_PACKET_LEN];
struct sockaddr_in from, to;
fd_set fds;
int s;
unsigned char *packet, hlocal[256], nlocal[256];
int len = 0;
xht h;
if(argc < 4) { printf("usage: mhttp 'unique name' 12.34.56.78 80 '/optionalpath'\n"); return; }
ip.s_addr = inet_addr(argv[2]);
port = atoi(argv[3]);
printf("Announcing .local site named '%s' to %s:%d and extra path '%s'\n",argv[1],inet_ntoa(ip),port,argv[4]);
signal(SIGINT,done);
signal(SIGHUP,done);
signal(SIGQUIT,done);
signal(SIGTERM,done);
pipe(_zzz);
_d = d = mdnsd_new(QCLASS_IN,1000);
if((s = msock()) == 0) { printf("can't create socket: %s\n",strerror(errno)); return 1; }
sprintf(hlocal,"%s._http._tcp.local.",argv[1]);
sprintf(nlocal,"http-%s.local.",argv[1]);
r = mdnsd_shared(d,"_http._tcp.local.",QTYPE_PTR,120);
mdnsd_set_host(d,r,hlocal);
r = mdnsd_unique(d,hlocal,QTYPE_SRV,600,con,0);
mdnsd_set_srv(d,r,0,0,port,nlocal);
r = mdnsd_unique(d,nlocal,QTYPE_A,600,con,0);
mdnsd_set_raw(d,r,(unsigned char *)&ip,4);
r = mdnsd_unique(d,hlocal,QTYPE_TXT,600,con,0);
h = xht_new(11);
if(argc == 5 && argv[4] && strlen(argv[4]) > 0) xht_set(h,"path",argv[4]);
packet = sd2txt(h, &len);
xht_free(h);
mdnsd_set_raw(d,r,packet,len);
free(packet);
while(1)
{
tv = mdnsd_sleep(d);
FD_ZERO(&fds);
FD_SET(_zzz[0],&fds);
FD_SET(s,&fds);
select(s+1,&fds,0,0,tv);
// only used when we wake-up from a signal, shutting down
if(FD_ISSET(_zzz[0],&fds)) read(_zzz[0],buf,MAX_PACKET_LEN);
if(FD_ISSET(s,&fds))
{
while((bsize = recvfrom(s,buf,MAX_PACKET_LEN,0,(struct sockaddr*)&from,&ssize)) > 0)
{
bzero(&m,sizeof(struct message));
message_parse(&m,buf);
mdnsd_in(d,&m,(unsigned long int)from.sin_addr.s_addr,from.sin_port);
}
if(bsize < 0 && errno != EAGAIN) { printf("can't read from socket %d: %s\n",errno,strerror(errno)); return 1; }
}
while(mdnsd_out(d,&m,(long unsigned int*)&ip.s_addr,&port))
{
bzero(&to, sizeof(to));
to.sin_family = AF_INET;
to.sin_port = port;
to.sin_addr.s_addr = ip.s_addr;
if(sendto(s,message_packet(&m),message_packet_len(&m),0,(struct sockaddr *)&to,sizeof(struct sockaddr_in)) != message_packet_len(&m)) { printf("can't write to socket: %s\n",strerror(errno)); return 1; }
}
if(_shutdown) break;
}
mdnsd_shutdown(d);
mdnsd_free(d);
return 0;
}