mDNSlocal void DNSSECProbeCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
    if (!AddRecord)
        return;

    mDNS_Lock(m);
    if ((m->timenow - question->StopTime) >= 0)
    {
        mDNS_Unlock(m);
        LogDNSSEC("DNSSECProbeCallback: Question %##s (%s) timed out", question->qname.c, DNSTypeName(question->qtype));
        mDNS_StopQuery(m, question);
        return;
    }
    mDNS_Unlock(m);

    // Wait till we get the DNSSEC results. If we get a negative response e.g., no DNS servers, the
    // question will be restarted by the core and we should have the DNSSEC results eventually.
    if (AddRecord != QC_dnssec)
    {
        LogDNSSEC("DNSSECProbeCallback: Question %##s (%s)", question->qname.c, DNSTypeName(question->qtype), RRDisplayString(m, answer));
        return;
    }

    LogDNSSEC("DNSSECProbeCallback: Question %##s (%s), DNSSEC status %s", question->qname.c, DNSTypeName(question->qtype),
            DNSSECStatusName(question->ValidationStatus));

    mDNS_StopQuery(m, question);
}
mDNSlocal void tcpConnectionCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err)
	{
	mStatus     status  = mStatus_NoError;
	tcpLNTInfo *tcpInfo = (tcpLNTInfo *)context;
	mDNSBool    closed  = mDNSfalse;
	long        n       = 0;
	long        nsent   = 0;

	if (tcpInfo == mDNSNULL) { LogInfo("tcpConnectionCallback: no tcpInfo context"); status = mStatus_Invalid; goto exit; }

	// The handlers below expect to be called with the lock held
	mDNS_Lock(tcpInfo->m);
	
	if (err) { LogInfo("tcpConnectionCallback: received error"); goto exit; }

	if (ConnectionEstablished)		// connection is established - send the message
		{
		LogInfo("tcpConnectionCallback: connection established, sending message");
		nsent = mDNSPlatformWriteTCP(sock, (char *)tcpInfo->Request, tcpInfo->requestLen);
		if (nsent != (long)tcpInfo->requestLen) { LogMsg("tcpConnectionCallback: error writing"); status = mStatus_UnknownErr; goto exit; }
		}
	else
		{
		n = mDNSPlatformReadTCP(sock, (char *)tcpInfo->Reply + tcpInfo->nread, tcpInfo->replyLen - tcpInfo->nread, &closed);
		LogInfo("tcpConnectionCallback: mDNSPlatformReadTCP read %d bytes", n);

		if      (n < 0)  { LogInfo("tcpConnectionCallback - read returned %d", n);                           status = mStatus_ConnFailed; goto exit; }
		else if (closed) { LogInfo("tcpConnectionCallback: socket closed by remote end %d", tcpInfo->nread); status = mStatus_ConnFailed; goto exit; }

		tcpInfo->nread += n;
		LogInfo("tcpConnectionCallback tcpInfo->nread %d", tcpInfo->nread);
		if (tcpInfo->nread > LNT_MAXBUFSIZE)
			{
			LogInfo("result truncated...");
			tcpInfo->nread = LNT_MAXBUFSIZE;
			}

		switch (tcpInfo->op)
			{
			case LNTDiscoveryOp:     handleLNTDeviceDescriptionResponse (tcpInfo); break;
			case LNTExternalAddrOp:  handleLNTGetExternalAddressResponse(tcpInfo); break;
			case LNTPortMapOp:       handleLNTPortMappingResponse       (tcpInfo); break;
			case LNTPortMapDeleteOp: status = mStatus_ConfigChanged;               break;
			default: LogMsg("tcpConnectionCallback: bad tcp operation! %d", tcpInfo->op); status = mStatus_Invalid; break;
			}
		}
exit:
	if (err || status)
		{
		mDNS   *m = tcpInfo->m;
		switch (tcpInfo->op)
			{
			case LNTDiscoveryOp:     if (m->UPnPSOAPAddressString == mDNSNULL)
										mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "failure", "SOAP Address", "");
									 if (m->UPnPSOAPURL == mDNSNULL)
										mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "failure", "SOAP path", "");
									 if (m->UPnPSOAPAddressString && m->UPnPSOAPURL)
										mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "success", "success", "");
									 break;
			case LNTExternalAddrOp:	 mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest", mDNSIPv4AddressIsZero(m->ExternalAddress) ? "failure" : "success", mDNSIPv4AddressIsZero(m->ExternalAddress) ? "failure" : "success", "");
									 break;
			case LNTPortMapOp:       if (tcpInfo->parentNATInfo)	
										mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", (tcpInfo->parentNATInfo->Result) ? "failure" : "success", 
											(tcpInfo->parentNATInfo->Result) ? "failure" : "success", "Result: %d", tcpInfo->parentNATInfo->Result);
									 break;
			case LNTPortMapDeleteOp: break;
			default:				 break;
			}

		mDNSPlatformTCPCloseConnection(tcpInfo->sock);
		tcpInfo->sock = mDNSNULL;
		if (tcpInfo->Request) { mDNSPlatformMemFree(tcpInfo->Request); tcpInfo->Request = mDNSNULL; }
		if (tcpInfo->Reply  ) { mDNSPlatformMemFree(tcpInfo->Reply);   tcpInfo->Reply   = mDNSNULL; }
		}

	if (tcpInfo) mDNS_Unlock(tcpInfo->m);

	if (status == mStatus_ConfigChanged) DisposeInfoFromUnmapList(tcpInfo->m, tcpInfo);
	}