Beispiel #1
0
mDNSexport int embedded_mDNSInit() {
	mStatus err;
	if (mDNSIsInitialized != 0) {
		return 0;
	}

	mDNSPlatformMemZero( &mDNSStorage, sizeof(mDNSStorage));
	mDNSPlatformMemZero( &platformSupport, sizeof(platformSupport));

//	mDNSStorage.AutoTargetServices = 1;

	err = mDNS_Init(
		&mDNSStorage,
		&platformSupport,
		rrcachestorage,
		RR_CACHE_SIZE,
		mDNS_Init_AdvertiseLocalAddresses,
		mDNS_Init_NoInitCallback,
		mDNS_Init_NoInitCallbackContext
	);
	if (err)
		return err;

#ifdef WIN32
	platformSupport.reportStatusFunc = embedded_mDNSInit_ReportStatus;
	err = SetupInterfaceList( &mDNSStorage );
	if (err)
		return err;
	err = uDNS_SetupDNSConfig( &mDNSStorage );
#endif

	if (err == 0) {
		mDNSIsInitialized = 1;
	}
	return err;
}
mDNSexport int main(int argc, char **argv)
{
    mStatus status;
    sigset_t signals;

    if (argc < 3) goto usage;

    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
                       mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
                       mDNS_Init_DontAdvertiseLocalAddresses,
                       mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
    if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); }

    mDNSPosixListenForSignalInEventLoop(SIGINT);
    mDNSPosixListenForSignalInEventLoop(SIGTERM);

    if (!strcmp(argv[1], "-"))
    {
        domainname proxyhostname;
        AuthRecord proxyrecord;
        if (argc < 5) goto usage;
        proxyhostname.c[0] = 0;
        AppendLiteralLabelString(&proxyhostname, argv[2]);
        AppendLiteralLabelString(&proxyhostname, "local");
        RegisterNoSuchService(&mDNSStorage, &proxyrecord, &proxyhostname, argv[3], argv[4], "local.");
    }
    else
    {
        ProxyHost proxyhost;
        ServiceRecordSet proxyservice;

        proxyhost.ip.NotAnInteger = inet_addr(argv[1]);
        if (proxyhost.ip.NotAnInteger == INADDR_NONE)   // INADDR_NONE is 0xFFFFFFFF
        {
            struct hostent *h = gethostbyname(argv[1]);
            if (h) proxyhost.ip.NotAnInteger = *(long*)h->h_addr;
        }
        if (proxyhost.ip.NotAnInteger == INADDR_NONE)   // INADDR_NONE is 0xFFFFFFFF
        {
            fprintf(stderr, "%s is not valid host address\n", argv[1]);
            return(-1);
        }

        MakeDomainLabelFromLiteralString(&proxyhost.hostlabel, argv[2]);

        mDNS_RegisterProxyHost(&mDNSStorage, &proxyhost);

        if (argc >=6)
            RegisterService(&mDNSStorage, &proxyservice, argv[3], argv[4], "local.",
                            proxyhost.RR_A.resrec.name, atoi(argv[5]), argc-6, &argv[6]);
    }

    do
    {
        struct timeval timeout = { 0x3FFFFFFF, 0 };     // wait until SIGINT or SIGTERM
        mDNSBool gotSomething;
        mDNSPosixRunEventLoopOnce(&mDNSStorage, &timeout, &signals, &gotSomething);
    }
    while ( !( sigismember( &signals, SIGINT) || sigismember( &signals, SIGTERM)));

    mDNS_Close(&mDNSStorage);

    return(0);

usage:
    fprintf(stderr, "%s ip hostlabel [srvname srvtype port txt [txt ...]]\n", argv[0]);
    fprintf(stderr, "ip        Real IP address (or valid host name) of the host where the service actually resides\n");
    fprintf(stderr, "hostlabel First label of the dot-local host name to create for this host, e.g. \"foo\" for \"foo.local.\"\n");
    fprintf(stderr, "srvname   Descriptive name of service, e.g. \"Stuart's Ink Jet Printer\"\n");
    fprintf(stderr, "srvtype   IANA service type, e.g. \"_ipp._tcp\" or \"_ssh._tcp\", etc.\n");
    fprintf(stderr, "port      Port number where the service resides (1-65535)\n");
    fprintf(stderr, "txt       Additional name/value pairs specified in service definition, e.g. \"pdl=application/postscript\"\n");
    fprintf(stderr, "e.g. %s 169.254.12.34 thehost                                (just create a dot-local host name)\n", argv[0]);
    fprintf(stderr, "or   %s 169.254.12.34 thehost \"My Printer\" _printer._tcp. 515 rp=lpt1 pdl=application/postscript\n", argv[0]);
    fprintf(stderr, "or   %s -             thehost \"My Printer\" _printer._tcp.           (assertion of non-existence)\n", argv[0]);
    return(-1);
}
Beispiel #3
0
mDNSexport int main(int argc, char **argv)
{
    const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
    int this_arg = 1;
    mStatus status;
    struct in_addr s4;
#if HAVE_IPV6
    struct in6_addr s6;
#endif
    char buffer[256];
    DNSQuestion q;

    if (argc < 2) goto usage;

    // Since this is a special command-line tool, we want LogMsg() errors to go to stderr, not syslog
    mDNS_DebugMode = mDNStrue;

    // Initialise the mDNS core.
    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
                       gRRCache, RR_CACHE_SIZE,
                       mDNS_Init_DontAdvertiseLocalAddresses,
                       mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
    if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); }

    signal(SIGINT, HandleSIG);  // SIGINT is what you get for a Ctrl-C
    signal(SIGTERM, HandleSIG);

    while (this_arg < argc)
    {
        char *arg = argv[this_arg++];
        if (this_arg > 2) printf("\n");

        lastid = id = zeroID;
        hostaddr = target = zeroAddr;
        hostname[0] = hardware[0] = software[0] = 0;
        NumAddr = NumAAAA = NumHINFO = 0;

        if (inet_pton(AF_INET, arg, &s4) == 1)
        {
            mDNSu8 *p = (mDNSu8 *)&s4;
            // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
            mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]);
            printf("%s\n", buffer);
            target.type = mDNSAddrType_IPv4;
            target.ip.v4.NotAnInteger = s4.s_addr;
            DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback);
            if (StopNow == 2) break;
        }
#if HAVE_IPV6
        else if (inet_pton(AF_INET6, arg, &s6) == 1)
        {
            int i;
            mDNSu8 *p = (mDNSu8 *)&s6;
            for (i = 0; i < 16; i++)
            {
                static const char hexValues[] = "0123456789ABCDEF";
                buffer[i * 4    ] = hexValues[p[15-i] & 0x0F];
                buffer[i * 4 + 1] = '.';
                buffer[i * 4 + 2] = hexValues[p[15-i] >> 4];
                buffer[i * 4 + 3] = '.';
            }
            mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
            target.type = mDNSAddrType_IPv6;
            mDNSPlatformMemCopy(&target.ip.v6, &s6, sizeof(target.ip.v6));
            DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback);
            if (StopNow == 2) break;
        }
#endif
        else
        {
            if (strlen(arg) >= sizeof(hostname))
int rend_private_init(char *user) {
    mStatus status;
    mDNSBool result;

    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
                       mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
                       mDNS_Init_AdvertiseLocalAddresses,
                       mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
    
    if (status != mStatus_NoError) {
        DPRINTF(E_FATAL,L_REND,"mDNS Error %d\n",status);
        return(-1);
    }

    if(os_drop_privs(user))
        return -1;

    signal(SIGINT,  HandleSigInt);      // SIGINT is what you get for a Ctrl-C
    signal(SIGQUIT, HandleSigQuit);     // SIGQUIT is what you get for a Ctrl-\ (indeed)
    signal(SIGHUP,  SIG_IGN);           // SIGHUP might happen from a request to reload the daap server

    while (!gStopNow) {
        int nfds = 1;
        fd_set readfds;
        struct timeval timeout;
        int result;
        
        // 1. Set up the fd_set as usual here.
        // This example client has no file descriptors of its own,
        // but a real application would call FD_SET to add them to the set here
        FD_ZERO(&readfds);
        FD_SET(rend_pipe_to[RD_SIDE],&readfds);
        
        // 2. Set up the timeout.
        // This example client has no other work it needs to be doing,
        // so we set an effectively infinite timeout
        timeout.tv_sec = 0x3FFFFFFF;
        timeout.tv_usec = 0;
        
        // 3. Give the mDNSPosix layer a chance to add its information to the fd_set and timeout
        mDNSPosixGetFDSet(&mDNSStorage, &nfds, &readfds, &timeout);
        
        // 4. Call select as normal
        DPRINTF(E_SPAM,L_REND,"select(%d, %d.%06d)\n", nfds, 
                timeout.tv_sec, timeout.tv_usec);
        
        result = select(nfds, &readfds, NULL, NULL, &timeout);
        
        if (result < 0) {
            if (errno != EINTR) gStopNow = mDNStrue;
            DPRINTF(E_WARN,L_REND,"select() returned %d errno %d\n", result, errno);
        } else {
            // 5. Call mDNSPosixProcessFDSet to let the mDNSPosix layer do its work
            mDNSPosixProcessFDSet(&mDNSStorage, &readfds);
            
            // 6. This example client has no other work it needs to be doing,
            // but a real client would do its work here
            // ... (do work) ...
            if(FD_ISSET(rend_pipe_to[RD_SIDE],&readfds)) {
                rend_callback();
            }
        }
    }
    
    DPRINTF(E_DBG,L_REND,"Exiting\n");
    
    DeregisterOurServices();
    mDNS_Close(&mDNSStorage);
    
    if (status == mStatus_NoError) {
        result = 0;
    } else {
        result = 2;
    }
    DPRINTF(E_DBG,L_REND, "Finished with status %ld, result %d\n", 
            status, result);

    exit(result);
}
Beispiel #5
0
int main(int argc, char **argv)
{
    mStatus status;
    int     result;

    // Parse our command line arguments.  This won't come back if there's an error.
    
    ParseArguments(argc, argv);

    // If we're told to run as a daemon, then do that straight away.
    // Note that we don't treat the inability to create our PID 
    // file as an error.  Also note that we assign getpid to a long 
    // because printf has no format specified for pid_t.
    
    if (gDaemon) {
        if (gMDNSPlatformPosixVerboseLevel > 0) {
            fprintf(stderr, "%s: Starting in daemon mode\n", gProgramName);
        }
        daemon(0,0);
        {
            FILE *fp;
            int  junk;
            
            fp = fopen(gPIDFile, "w");
            if (fp != NULL) {
                fprintf(fp, "%ld\n", (long) getpid());
                junk = fclose(fp);
                assert(junk == 0);
            }
        }
    } else {
        if (gMDNSPlatformPosixVerboseLevel > 0) {
            fprintf(stderr, "%s: Starting in foreground mode, PID %ld\n", gProgramName, (long) getpid());
        }
    }

    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
    	mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
    	mDNS_Init_AdvertiseLocalAddresses,
    	mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
    if (status != mStatus_NoError) return(2);

	status = RegisterOurServices();
    if (status != mStatus_NoError) return(2);
    
    signal(SIGHUP,  HandleSigHup);      // SIGHUP has to be sent by kill -HUP <pid>
    signal(SIGINT,  HandleSigInt);      // SIGINT is what you get for a Ctrl-C
    signal(SIGQUIT, HandleSigQuit);     // SIGQUIT is what you get for a Ctrl-\ (indeed)
    signal(SIGUSR1, HandleSigUsr1);     // SIGUSR1 has to be sent by kill -USR1 <pid>

	while (!gStopNow)
		{
		int nfds = 0;
		fd_set readfds;
		struct timeval timeout;
		int result;
		
		// 1. Set up the fd_set as usual here.
		// This example client has no file descriptors of its own,
		// but a real application would call FD_SET to add them to the set here
		FD_ZERO(&readfds);
		
		// 2. Set up the timeout.
		// This example client has no other work it needs to be doing,
		// so we set an effectively infinite timeout
		timeout.tv_sec = 0x3FFFFFFF;
		timeout.tv_usec = 0;
		
		// 3. Give the mDNSPosix layer a chance to add its information to the fd_set and timeout
		mDNSPosixGetFDSet(&mDNSStorage, &nfds, &readfds, &timeout);
		
		// 4. Call select as normal
		verbosedebugf("select(%d, %d.%06d)", nfds, timeout.tv_sec, timeout.tv_usec);
		result = select(nfds, &readfds, NULL, NULL, &timeout);
		
		if (result < 0)
			{
			verbosedebugf("select() returned %d errno %d", result, errno);
			if (errno != EINTR) gStopNow = mDNStrue;
			else
				{
				if (gReceivedSigUsr1)
					{
					gReceivedSigUsr1 = mDNSfalse;
					gMDNSPlatformPosixVerboseLevel += 1;
					if (gMDNSPlatformPosixVerboseLevel > 2)
						gMDNSPlatformPosixVerboseLevel = 0;
					if ( gMDNSPlatformPosixVerboseLevel > 0 )
						fprintf(stderr, "\nVerbose level %d\n", gMDNSPlatformPosixVerboseLevel);
					}
				if (gReceivedSigHup)
					{
					if (gMDNSPlatformPosixVerboseLevel > 0)
						fprintf(stderr, "\nSIGHUP\n");
					gReceivedSigHup = mDNSfalse;
					DeregisterOurServices();
					status = mDNSPlatformPosixRefreshInterfaceList(&mDNSStorage);
					if (status != mStatus_NoError) break;
					status = RegisterOurServices();
					if (status != mStatus_NoError) break;
					}
				}
			}
		else
			{
			// 5. Call mDNSPosixProcessFDSet to let the mDNSPosix layer do its work
			mDNSPosixProcessFDSet(&mDNSStorage, &readfds);
			
			// 6. This example client has no other work it needs to be doing,
			// but a real client would do its work here
			// ... (do work) ...
			}
		}

	debugf("Exiting");
    
	DeregisterOurServices();
	mDNS_Close(&mDNSStorage);

    if (status == mStatus_NoError) {
        result = 0;
    } else {
        result = 2;
    }
    if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) {
        fprintf(stderr, "%s: Finished with status %ld, result %d\n", gProgramName, status, result);
    }
    
    return result;
}
Beispiel #6
0
int main(void)
    // The program's main entry point.  The program does a trivial 
    // mDNS query, looking for mDNS service & device in the local domain.
{
    	int     result;
    	mStatus     status;
    	DNSQuestion question;
    	domainname  type;
    	domainname  domain;
	char DeviceName[64];

    	// Initialise the mDNS core.
	status = mDNS_Init(&mDNSStorage, &PlatformStorage,
    	gRRCache, RR_CACHE_SIZE,
    	mDNS_Init_DontAdvertiseLocalAddresses,
    	mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);

    if (status == mStatus_NoError) {
#if 1 /* Query service type */
        // Construct and start the query.
        MakeDomainNameFromDNSNameString(&type, gServiceType);
        MakeDomainNameFromDNSNameString(&domain, gServiceDomain);

        status = mDNS_StartBrowse(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, mDNSfalse, BrowseCallback, NULL);
    
	//return;
        // Run the platform main event loop. 
        // The BrowseCallback routine is responsible for printing 
        // any results that we find.
        
        if (status == mStatus_NoError) {
            	fprintf(stderr, "* Query: %s\n", gServiceType);
        	EventLoop(&mDNSStorage);
            	mDNS_StopQuery(&mDNSStorage, &question);
                //Parse all service type and query detail
                //fprintf(stderr, "===== Parse all service type and query detail...\n");
                callback = 0;
                event = 0;
		StopNow = 0;
	}
	return 0;
#endif

#if 0 /* Query device name */
		Service_tmp = Service_list;
		while(Service_tmp!=NULL) {
			printf("\n======= Queried Service: %s.%s\n", Service_tmp->service, Service_tmp->type);
			sprintf(Query_type, "%s.%s", Service_tmp->service, Service_tmp->type);
			//Device_found = Service_tmp->sup_device;
			gServiceType = Query_type;
			MakeDomainNameFromDNSNameString(&type, gServiceType);
			status = mDNS_StartBrowse(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, mDNSfalse, QueryCallback, NULL);
			if (status == mStatus_NoError) {
		                EventLoop(&mDNSStorage);
        		        mDNS_StopQuery(&mDNSStorage, &question);
			}
                        callback = 0;
                        event = 0;
                        StopNow = 0;
                        Service_tmp = Service_tmp->next;
                }
		printf("===============\n\n");
#endif

#if 0 /* Query IP of device */
		DeviceIP_cur = Device_list;
		printf("%d,%d,%d  ", callback, event, StopNow);
		printf("QUERY DEVICE: %s/%s\n", Device_cur->name, Device_cur->IPv4Addr);
		char *cc = Device_cur->IPv4Addr;
		int x =0;
		for(; x<16; x++) {
			printf("%",*cc);
			cc++;
		}
		printf("\n");
		//if(DeviceIP_cur->IPv4Addr == NULL)
		if(!strcmp(DeviceIP_cur->IPv4Addr, ""))
			printf("    DeviceIP_cur->IPv4Addr == NULL\n");

		while(DeviceIP_cur && (!strcmp(DeviceIP_cur->IPv4Addr, ""))) {
			memset(DeviceName, 0, 64);
			strcpy(DeviceName, DeviceIP_cur->name);
			HostnameParse(DeviceName);
			gServiceType = DeviceName;
        		printf("Query IP of %s\n", gServiceType);
		        // Construct and start the query.
		       	MakeDomainNameFromDNSNameString(&type, gServiceType);
		        status = mDNS_GetAddrInfo(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, mDNSfalse, IPInfoCallback, NULL);
		        if (status == mStatus_NoError) {
		       	        EventLoop(&mDNSStorage);
                		mDNS_StopQuery(&mDNSStorage, &question);
		        }
			else {
				printf("Error= %ld\n", status);
			}
			DeviceIP_cur = DeviceIP_cur->next;
        	               callback = 0;
                        event = 0;
                       	StopNow = 0;
		}

		printf("===============\n");
#endif
int nvram_size, i = 0;
char *nvram_info;
char device_name_ascii[256], service_type_list[512];
struct mDNS_service_handler *handler;

nvram_size = device_count*64 + service_count*4;
nvram_info = malloc(nvram_size);
memset(nvram_info, 0, nvram_size);
printf("nvram_size= %d\n", nvram_size);

    	//Print all info
    	Service_tmp = Service_list;
    	while(Service_tmp!=NULL) {
		printf("\n=== %s.%s ===\n", Service_tmp->service, Service_tmp->type);
		Service_tmp = Service_tmp->next;
    	}

printf("\n===== Print device ========\n");
        Device_tmp = Device_list;
        while(Device_tmp!=NULL) {
                //printf("    %s:%s->", Device_tmp->name, Device_tmp->IPv4Addr);
		memset(device_name_ascii, 0, 256);
		char_to_ascii(device_name_ascii, Device_tmp->name);
		strcat(nvram_info, "<");
		sprintf(nvram_info, "%s%s>%s>", nvram_info, Device_tmp->IPv4Addr, device_name_ascii);
printf("    %s\n", nvram_info);
		Sup_service_tmp = Device_tmp->sup_service;
		memset(service_type_list, 0, 512);
		while(Sup_service_tmp!=NULL) {
			for(handler = &service_handler[0], i=0; handler->service; handler++, i++) {
				if(strstr(Sup_service_tmp->name, handler->service)) {
					sprintf(service_type_list, "%s#%d", service_type_list, i);
					break;
				}	
			}

			printf("%s ", Sup_service_tmp->name);
			Sup_service_tmp = Sup_service_tmp->next;
		}
		printf("\n");
		printf("Service_type= %s\n", service_type_list);
		sprintf(nvram_info, "%s%s", nvram_info, service_type_list);
printf("-> %s\n", nvram_info);
                Device_tmp = Device_tmp->next;
        }
	printf("\n==> %s\n", nvram_info);

	free(nvram_info);
	mDNS_Close(&mDNSStorage);
    }//Endof Initialise the mDNS core.
    
    if (status == mStatus_NoError) {
        result = 0;
    } else {
        result = 2;
    }
    if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) {
        fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result);
    }

    return 0;
}
int main()
	{
	mStatus err;
	Boolean DoneSetup = false;
	void *tempmem;

	SIOUXSettings.asktosaveonclose = false;
	SIOUXSettings.userwindowtitle  = "\pMulticast DNS Searcher";
	SIOUXSettings.rows             = 40;
	SIOUXSettings.columns          = 132;

	printf("Multicast DNS Searcher\n\n");
	printf("This software reports errors using MacsBug breaks,\n");
	printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
	printf("******************************************************************************\n");

	err = InitOpenTransport();
	if (err) { debugf("InitOpenTransport failed %d", err); return(err); }

	err = mDNS_Init(&mDNSStorage, &PlatformSupportStorage, rrcachestorage, RR_CACHE_SIZE,
		mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
	if (err) return(err);

	// Make sure OT has a large enough memory pool for us to draw from at OTNotifier (interrupt) time
	tempmem = OTAllocMem(0x10000);
	if (tempmem) OTFreeMem(tempmem);
	else printf("**** Warning: OTAllocMem couldn't pre-allocate 64K for us.\n");

	services.serviceinfolist.fHead = NULL;
	services.headerPrinted         = false;
	services.lostRecords           = false;

	while (!YieldSomeTime(35))
		{
#if MDNS_ONLYSYSTEMTASK
		// For debugging, use "#define MDNS_ONLYSYSTEMTASK 1" and call mDNSPlatformIdle() periodically.
		// For shipping code, don't define MDNS_ONLYSYSTEMTASK, and you don't need to call mDNSPlatformIdle()
		extern void mDNSPlatformIdle(mDNS *const m);
		mDNSPlatformIdle(&mDNSStorage);	// Only needed for debugging version
#endif
		if (mDNSStorage.mDNSPlatformStatus == mStatus_NoError && !DoneSetup)
			{
			domainname srvtype, srvdom;
			DoneSetup = true;
			printf("\nSending mDNS service lookup queries and waiting for responses...\n\n");
			MakeDomainNameFromDNSNameString(&srvtype, "_http._tcp.");
			MakeDomainNameFromDNSNameString(&srvdom, "local.");
			err = mDNS_StartBrowse(&mDNSStorage, &browsequestion, &srvtype, &srvdom, mDNSInterface_Any, mDNSfalse, FoundInstance, &services);
			if (err) break;
			err = mDNS_GetDomains(&mDNSStorage, &domainquestion, mDNS_DomainTypeBrowse, NULL, mDNSInterface_Any, FoundDomain, &services);
			if (err) break;
			}

		if (services.serviceinfolist.fHead)
			PrintServiceInfo(&services);

		if (services.lostRecords)
			{
			services.lostRecords = false;
			printf("**** Warning: Out of memory: Records have been missed.\n");
			}
		}

	mDNS_StopBrowse(&mDNSStorage, &browsequestion);
	mDNS_Close(&mDNSStorage);
	return(0);
	}
int main()
	{
	mStatus err;
	Boolean DoneSetup = false;
	mDNSs32 nextAvail, nextBusy;

	SIOUXSettings.asktosaveonclose = false;
	SIOUXSettings.userwindowtitle = "\pMulticast DNS Responder";

	printf("Multicast DNS Responder\n\n");
	printf("This software reports errors using MacsBug breaks,\n");
	printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
	printf("******************************************************************************\n");

	err = InitOpenTransport();
	if (err) { debugf("InitOpenTransport failed %d", err); return(err); }

	err = mDNS_Init(&m, &p, mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
		mDNS_Init_AdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
	if (err) return(err);

	while (!YieldSomeTime(35))
		{
#if MDNS_ONLYSYSTEMTASK
		// For debugging, use "#define MDNS_ONLYSYSTEMTASK 1" and call mDNSPlatformIdle() periodically.
		// For shipping code, don't define MDNS_ONLYSYSTEMTASK, and you don't need to call mDNSPlatformIdle()
		extern void mDNSPlatformIdle(mDNS *const m);
		mDNSPlatformIdle(&m);	// Only needed for debugging version
#endif
		if (m.mDNSPlatformStatus == mStatus_NoError && !DoneSetup)
			{
			DoneSetup = true;
			printf("\nListening for mDNS queries...\n");
			mDNSResponderTestSetup(&m);
			mDNSResponderSetAvail(&m, &availRec1, &p1);
			availRec2Active = false;
			nextAvail = mDNS_TimeNow(&m) + mDNSPlatformOneSecond * 10;
			nextBusy  = mDNS_TimeNow(&m) + mDNSPlatformOneSecond * 15;
			}

		if (DoneSetup)
			{
			// We check availRec2.RecordType because we don't want to re-register this record
			// if the previous mDNS_Deregister() has not yet completed
			if (mDNS_TimeNow(&m) - nextAvail > 0 && !availRec2Active)
				{
				printf("Setting Two now available\n");
				availRec2Active = true;
				mDNSResponderSetAvail(&m, &availRec2, &p2);
				nextAvail = nextBusy + mDNSPlatformOneSecond * 10;
				}
			else if (mDNS_TimeNow(&m) - nextBusy > 0)
				{
				printf("Setting Two now busy\n");
				mDNS_Deregister(&m, &availRec2);
				nextBusy = nextAvail + mDNSPlatformOneSecond * 5;
				}
			}
		}
	
	if (p1.RR_SRV.resrec.RecordType) mDNS_DeregisterService(&m, &p1);
	if (p2.RR_SRV.resrec.RecordType) mDNS_DeregisterService(&m, &p2);
	if (availRec1.resrec.RecordType) mDNS_Deregister(&m, &availRec1);
	if (availRec2Active)             mDNS_Deregister(&m, &availRec2);

	mDNS_Close(&m);
	
	return(0);
	}