// handle reply from server, calling application client callback.  If there is no reply
// from the daemon on the socket contained in sdRef, the call will block.
DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
    {
    ipc_msg_hdr hdr;
    char *data;
    int rderr;

    if (!sdRef || sdRef->sockfd < 0 || !sdRef->process_reply)
        return kDNSServiceErr_BadReference;

    rderr = read_all(sdRef->sockfd, (void *)&hdr, sizeof(hdr));
    if (rderr < 0) {
		// return NoError on EWOULDBLOCK. This will handle the case
		// where a non-blocking socket is told there is data, but
		// it was a false positive. Can check errno when error
		// code returned is -1
		if ((rderr == -1) && (dnssd_errno() == dnssd_EWOULDBLOCK))
				return kDNSServiceErr_NoError;
	        return kDNSServiceErr_Unknown;
    }
	ConvertHeaderBytes(&hdr);
    if (hdr.version != VERSION)
        return kDNSServiceErr_Incompatible;
    data = malloc(hdr.datalen);
    if (!data) return kDNSServiceErr_NoMemory;
    if (read_all(sdRef->sockfd, data, hdr.datalen) < 0)
        return kDNSServiceErr_Unknown;
    sdRef->process_reply(sdRef, &hdr, data);
    free(data);
    return kDNSServiceErr_NoError;
    }
DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
	(
	DNSServiceFlags  flags,
	uint32_t         interfaceIndex,
	const char      *fullname,
	uint16_t         rrtype,
	uint16_t         rrclass,
	uint16_t         rdlen,
	const void      *rdata
	)
    {
    char *ptr;
    size_t len;
    ipc_msg_hdr *hdr;
    DNSServiceRef tmp;

    len = sizeof(DNSServiceFlags);
    len += sizeof(uint32_t);
    len += strlen(fullname) + 1;
    len += 3 * sizeof(uint16_t);
    len += rdlen;
    tmp = connect_to_server();
    if (!tmp) return(kDNSServiceErr_Unknown);
    hdr = create_hdr(reconfirm_record_request, &len, &ptr, 1);
    if (!hdr) return(kDNSServiceErr_Unknown);

    put_flags(flags, &ptr);
    put_long(interfaceIndex, &ptr);
    put_string(fullname, &ptr);
    put_short(rrtype, &ptr);
    put_short(rrclass, &ptr);
    put_short(rdlen, &ptr);
    put_rdata(rdlen, rdata, &ptr);
	ConvertHeaderBytes(hdr);
    write_all(tmp->sockfd, (char *)hdr, (int) len);
    free(hdr);
    DNSServiceRefDeallocate(tmp);
    return(kDNSServiceErr_NoError);
    }
static DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd)
    {
    ipc_msg_hdr *hdr = msg;
    uint32_t datalen = hdr->datalen;
    dnssd_sockaddr_t caddr, daddr;  // (client and daemon address structs)
    char *const data = (char *)msg + sizeof(ipc_msg_hdr);
    dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
	int ret;
	dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
    DNSServiceErrorType err = kDNSServiceErr_Unknown;

    if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown;

	if (!reuse_sd)
		{
        // setup temporary error socket
        if ((listenfd = socket(AF_DNSSD, SOCK_STREAM, 0)) < 0)
            goto cleanup;
        bzero(&caddr, sizeof(caddr));

#if defined(USE_TCP_LOOPBACK)
			{
			union { uint16_t s; u_char b[2]; } port;
			caddr.sin_family      = AF_INET;
			caddr.sin_port        = 0;
			caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
			ret = bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr));
			if (ret < 0) goto cleanup;
			if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) goto cleanup;
			listen(listenfd, 1);
			port.s = caddr.sin_port;
			data[0] = port.b[0];  // don't switch the byte order, as the
			data[1] = port.b[1];  // daemon expects it in network byte order
			}
#else
			{
			mode_t mask = umask(0);
			caddr.sun_family = AF_LOCAL;
// According to Stevens (section 3.2), there is no portable way to
// determine whether sa_len is defined on a particular platform.
#ifndef NOT_HAVE_SA_LEN
			caddr.sun_len = sizeof(struct sockaddr_un);
#endif
			//syslog(LOG_WARNING, "deliver_request: creating UDS: %s\n", data);
			strcpy(caddr.sun_path, data);
			ret = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
			umask(mask);
			if (ret < 0) goto cleanup;
			listen(listenfd, 1);
			}
#endif
		}

	ConvertHeaderBytes(hdr);
	//syslog(LOG_WARNING, "deliver_request writing %ld bytes\n", datalen + sizeof(ipc_msg_hdr));
	//syslog(LOG_WARNING, "deliver_request name is %s\n", (char *)msg + sizeof(ipc_msg_hdr));
    if (write_all(sdr->sockfd, msg, datalen + sizeof(ipc_msg_hdr)) < 0)
        goto cleanup;
    free(msg);
    msg = NULL;

    if (reuse_sd) errsd = sdr->sockfd;
    else
        {
		//syslog(LOG_WARNING, "deliver_request: accept\n");
        len = sizeof(daddr);
        errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
		//syslog(LOG_WARNING, "deliver_request: accept returned %d\n", errsd);
        if (errsd < 0)  goto cleanup;
        }

    if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0)
        err = kDNSServiceErr_Unknown;
    else
    	err = ntohl(err);

	//syslog(LOG_WARNING, "deliver_request: retrieved error code %d\n", err);

cleanup:
	if (!reuse_sd)
		{
		if (listenfd > 0) dnssd_close(listenfd);
		if (errsd    > 0) dnssd_close(errsd);
#if !defined(USE_TCP_LOOPBACK)
		// syslog(LOG_WARNING, "deliver_request: removing UDS: %s\n", data);
		if (unlink(data) != 0)
			syslog(LOG_WARNING, "WARNING: unlink(\"%s\") failed errno %d (%s)", data, errno, strerror(errno));
		// else syslog(LOG_WARNING, "deliver_request: removed UDS: %s\n", data);
#endif
		}
    if (msg) free(msg);
    return err;
    }