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