int main(int argc, char *argv[]) { mdnsd d; struct message m; unsigned long int 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; if(argc != 3) { printf("usage: mquery 12 _http._tcp.local.\n"); return; } d = mdnsd_new(1,1000); if((s = msock()) == 0) { printf("can't create socket: %s\n",strerror(errno)); return 1; } mdnsd_query(d,argv[2],atoi(argv[1]),ans,0); while(1) { tv = mdnsd_sleep(d); FD_ZERO(&fds); FD_SET(s,&fds); select(s+1,&fds,0,0,tv); 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,&ip,&port)) { bzero(&to, sizeof(to)); to.sin_family = AF_INET; to.sin_port = port; to.sin_addr.s_addr = ip; 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; } } } mdnsd_shutdown(d); mdnsd_free(d); return 0; }
void* ScanThread::Entry() { mdnsd d; struct message m; unsigned long int ip; unsigned short int port; struct timeval *tv; fd_set fds; SOCKET s; bool exit = false; d = mdnsd_new(1,1000); if((s = msock()) < 0) { p->err.Printf(_("Can't create socket: %s\n"), strerror(errno)); exit = true; } // register query(w,t) at mdnsd d, submit our address for callback ans() mdnsd_query(d, w.char_str(), t, ans, this); #ifdef __WXGTK__ // this signal is generated when we pop up a file dialog wwith wxGTK // we need to block it here cause it interrupts the select() call sigset_t newsigs; sigset_t oldsigs; sigemptyset(&newsigs); sigemptyset(&oldsigs); sigaddset(&newsigs, SIGRTMIN-1); #endif while(!TestDestroy() && !exit) { tv = mdnsd_sleep(d); long msecs = tv->tv_sec == 0 ? 100 : tv->tv_sec*1000; // so that the while loop beneath gets executed once wxLogDebug(wxT("wxServDisc %p: scanthread waiting for data, timeout %i seconds"), p, tv->tv_sec); // we split the one select() call into several ones every 100ms // to be able to catch TestDestroy()... int datatoread = 0; while(msecs > 0 && !TestDestroy() && !datatoread) { // the select call leaves tv undefined, so re-set tv->tv_sec = 0; tv->tv_usec = 100000; // 100 ms FD_ZERO(&fds); FD_SET(s,&fds); #ifdef __WXGTK__ sigprocmask(SIG_BLOCK, &newsigs, &oldsigs); #endif datatoread = select(s+1,&fds,0,0,tv); // returns 0 if timeout expired #ifdef __WXGTK__ sigprocmask(SIG_SETMASK, &oldsigs, NULL); #endif if(!datatoread) // this is a timeout msecs-=100; if(datatoread == -1) break; } wxLogDebug(wxT("wxServDisc %p: scanthread woke up, reason: incoming data(%i), timeout(%i), error(%i), deletion(%i)"), p, datatoread>0, msecs<=0, datatoread==-1, TestDestroy() ); // receive if(FD_ISSET(s,&fds)) { while(recvm(&m, s, &ip, &port) > 0) mdnsd_in(d, &m, ip, port); } // send while(mdnsd_out(d,&m,&ip,&port)) if(!sendm(&m, s, ip, port)) { exit = true; break; } } mdnsd_shutdown(d); mdnsd_free(d); return NULL; }