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