// 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; }