28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/param.h>
34 #include <arpa/inet.h>
35 #include <netinet/in.h>
40 #include <tqapplication.h>
42 #include <tqcstring.h>
43 #include <tqstrlist.h>
44 #include <tqstringlist.h>
46 #include <tqdatetime.h>
49 #include <tqguardedptr.h>
60 #include "kresolver.h"
61 #include "kresolver_p.h"
62 #include "tdesocketaddress.h"
66 TQMutex getXXbyYYmutex;
74 using namespace KNetwork::Internal;
79 class KNetwork::KResolverEntryPrivate:
public TQShared
86 TQCString encodedName;
88 inline KResolverEntryPrivate() :
89 socktype(0), protocol(0)
101 const TQString& canonName,
const TQCString& encodedName) :
102 d(new KResolverEntryPrivate)
105 d->socktype = socktype;
107 d->canonName = canonName;
113 int protocol,
const TQString& canonName,
114 const TQCString& encodedName) :
115 d(new KResolverEntryPrivate)
118 d->socktype = socktype;
120 d->canonName = canonName;
150 return d ? d->addr.length() : 0;
156 return d ? d->addr.family() : AF_UNSPEC;
162 return d ? d->canonName : TQString::null;
168 return d ? d->encodedName : TQCString();
174 return d ? d->socktype : 0;
180 return d ? d->protocol : 0;
200 class KNetwork::KResolverResultsPrivate
203 TQString node, service;
204 int errorcode, syserror;
206 KResolverResultsPrivate() :
207 errorcode(0), syserror(0)
213 : d(new KResolverResultsPrivate)
219 : TQValueList<
KResolverEntry>(other), d(new KResolverResultsPrivate)
241 TQValueList<KResolverEntry>::operator =(other);
261 d->errorcode = errorcode;
262 d->syserror = systemerror;
279 const TQString& service)
282 d->service = service;
285 void KResolverResults::virtual_hook(
int,
void* )
292 TQStringList *KResolver::idnDomains = 0;
297 : TQObject(parent, name), d(new KResolverPrivate(this))
303 TQObject *parent,
const char *name)
304 : TQObject(parent, name), d(new KResolverPrivate(this, nodename, servicename))
336 return d->status > 0 && d->status < Success;
342 return d->input.node;
348 return d->input.service;
357 d->input.node = nodename;
359 d->results.setAddress(nodename, d->input.service);
369 d->input.service = service;
371 d->results.setAddress(d->input.node, service);
385 return d->input.flags;
391 int oldflags = d->input.flags;
394 d->input.flags =
flags;
405 d->input.familyMask = families;
415 d->input.socktype = type;
431 d->input.protocolName = name;
432 if (protonum == 0 && name != 0L && *name !=
'\0')
438 d->input.protocol = protonum;
449 if (d->input.node.isEmpty() && d->input.service.isEmpty())
451 d->status = KResolver::Success;
455 KResolverManager::manager()->enqueue(
this, 0L);
469 TQMutexLocker locker(&d->mutex);
486 while (!msec || t.elapsed() < msec)
491 KResolverManager::manager()->notifyWaiters.wait(&d->mutex, msec - t.elapsed());
493 KResolverManager::manager()->notifyWaiters.wait(&d->mutex);
514 KResolverManager::manager()->dequeue(
this);
527 r.
setAddress(d->input.node, d->input.service);
528 r.
setError(d->errorcode, d->syserror);
534 if (
static_cast<int>(e->type()) == KResolverManager::ResolutionCompleted)
543 void KResolver::emitFinished()
546 d->status = KResolver::Success;
548 TQGuardedPtr<TQObject> p =
this;
552 if (p && d->deleteWhenDone)
559 static const char *
const messages[] =
561 I18N_NOOP(
"no error"),
562 I18N_NOOP(
"requested family not supported for this host name"),
563 I18N_NOOP(
"temporary failure in name resolution"),
564 I18N_NOOP(
"non-recoverable failure in name resolution"),
565 I18N_NOOP(
"invalid flags"),
566 I18N_NOOP(
"memory allocation failure"),
567 I18N_NOOP(
"name or service not known"),
568 I18N_NOOP(
"requested family not supported"),
569 I18N_NOOP(
"requested service not supported for this socket type"),
570 I18N_NOOP(
"requested socket type not supported"),
571 I18N_NOOP(
"unknown error"),
572 I18N_NOOP2(
"1: the i18n'ed system error code, from errno",
577 if (errorcode == Canceled)
578 return i18n(
"request was canceled");
580 if (errorcode > 0 || errorcode < SystemError)
581 return TQString::null;
583 TQString msg = i18n(messages[-errorcode]);
584 if (errorcode == SystemError)
585 msg.arg(TQString::fromLocal8Bit(strerror(syserror)));
594 KResolver qres(host, service, tqApp,
"synchronous KResolver");
603 const TQString& host,
const TQString& service,
604 int flags,
int families)
610 qres->d->deleteWhenDone =
true;
611 return qres->
start();
616 struct protoent *pe = 0L;
617 #ifndef HAVE_GETPROTOBYNAME_R
618 TQMutexLocker locker(&getXXbyYYmutex);
620 pe = getprotobynumber(protonum);
624 struct protoent protobuf;
625 struct protoent_data pdata;
626 ::memset(&pdata, 0,
sizeof pdata);
628 if (getprotobynumber_r(protonum, &protobuf, &pdata) == 0)
634 size_t buflen = 1024;
635 struct protoent protobuf;
639 buf =
new char[buflen];
641 if ((pe = getprotobynumber_r(protonum, &protobuf, buf, buflen)) && (errno == ERANGE))
643 if (getprotobynumber_r(protonum, &protobuf, buf, buflen, &pe) == ERANGE)
661 lst.append(pe->p_name);
662 for (
char **p = pe->p_aliases; *p; p++)
666 #ifdef HAVE_GETPROTOBYNAME_R
677 struct protoent *pe = 0L;
678 #ifndef HAVE_GETPROTOBYNAME_R
679 TQMutexLocker locker(&getXXbyYYmutex);
681 pe = getprotobyname(protoname);
685 struct protoent protobuf;
686 struct protoent_data pdata;
687 ::memset(&pdata, 0,
sizeof pdata);
689 if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
695 size_t buflen = 1024;
696 struct protoent protobuf;
700 buf =
new char[buflen];
702 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
704 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
722 lst.append(pe->p_name);
723 for (
char **p = pe->p_aliases; *p; p++)
727 #ifdef HAVE_GETPROTOBYNAME_R
738 struct protoent *pe = 0L;
739 #ifndef HAVE_GETPROTOBYNAME_R
740 TQMutexLocker locker(&getXXbyYYmutex);
742 pe = getprotobyname(protoname);
746 struct protoent protobuf;
747 struct protoent_data pdata;
748 ::memset(&pdata, 0,
sizeof pdata);
750 if (getprotobyname_r(protoname, &protobuf, &pdata) == 0)
756 size_t buflen = 1024;
757 struct protoent protobuf;
761 buf =
new char[buflen];
763 if ((pe = getprotobyname_r(protoname, &protobuf, buf, buflen)) && (errno == ERANGE))
765 if (getprotobyname_r(protoname, &protobuf, buf, buflen, &pe) == ERANGE)
782 protonum = pe->p_proto;
784 #ifdef HAVE_GETPROTOBYNAME_R
795 struct servent *se = 0L;
796 #ifndef HAVE_GETSERVBYNAME_R
797 TQMutexLocker locker(&getXXbyYYmutex);
799 se = getservbyname(servname, protoname);
803 struct servent servbuf;
804 struct servent_data sdata;
805 ::memset(&sdata, 0,
sizeof sdata);
806 if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0)
812 size_t buflen = 1024;
813 struct servent servbuf;
817 buf =
new char[buflen];
819 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
821 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
838 servport = ntohs(se->s_port);
840 #ifdef HAVE_GETSERVBYNAME_R
851 struct servent *se = 0L;
852 #ifndef HAVE_GETSERVBYNAME_R
853 TQMutexLocker locker(&getXXbyYYmutex);
855 se = getservbyname(servname, protoname);
859 struct servent servbuf;
860 struct servent_data sdata;
861 ::memset(&sdata, 0,
sizeof sdata);
862 if (getservbyname_r(servname, protoname, &servbuf, &sdata) == 0)
868 size_t buflen = 1024;
869 struct servent servbuf;
873 buf =
new char[buflen];
875 if ((se = getservbyname_r(servname, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
877 if (getservbyname_r(servname, protoname, &servbuf, buf, buflen, &se) == ERANGE)
895 lst.append(se->s_name);
896 for (
char **p = se->s_aliases; *p; p++)
900 #ifdef HAVE_GETSERVBYNAME_R
911 struct servent *se = 0L;
912 #ifndef HAVE_GETSERVBYPORT_R
913 TQMutexLocker locker(&getXXbyYYmutex);
915 se = getservbyport(port, protoname);
919 struct servent servbuf;
920 struct servent_data sdata;
921 ::memset(&sdata, 0,
sizeof sdata);
922 if (getservbyport_r(port, protoname, &servbuf, &sdata) == 0)
928 size_t buflen = 1024;
929 struct servent servbuf;
933 buf =
new char[buflen];
935 if ((se = getservbyport_r(port, protoname, &servbuf, buf, buflen)) && (errno == ERANGE))
937 if (getservbyport_r(port, protoname, &servbuf, buf, buflen, &se) == ERANGE)
955 lst.append(se->s_name);
956 for (
char **p = se->s_aliases; *p; p++)
960 #ifdef HAVE_GETSERVBYPORT_R
974 #ifdef MAXHOSTNAMELEN
975 len = MAXHOSTNAMELEN;
984 if (gethostname(name.data(), len - 1) == 0)
988 name[len - 1] =
'\0';
993 if (errno == ENAMETOOLONG || errno == EINVAL)
1003 return TQString::fromLatin1(
"localhost");
1005 if (name.find(
'.') == -1)
1012 return TQString::fromLatin1(
"localhost");
1014 return results.first().canonicalName();
1022 static TQStringList splitLabels(
const TQString& unicodeDomain);
1023 static TQCString ToASCII(
const TQString& label);
1024 static TQString ToUnicode(
const TQString& label);
1026 static TQStringList *KResolver_initIdnDomains()
1028 const char *kde_use_idn = getenv(
"TDE_USE_IDN");
1030 kde_use_idn =
"ac:at:br:cat:ch:cl:cn:de:dk:fi:gr:hu:info:io:is:jp:kr:li:lt:museum:org:no:se:sh:th:tm:tw:vn";
1031 return new TQStringList(TQStringList::split(
':', TQString::fromLatin1(kde_use_idn).lower()));
1038 idnDomains = KResolver_initIdnDomains();
1046 TQStringList input = splitLabels(unicodeDomain);
1049 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
1050 return input.join(
".").lower().latin1();
1056 TQStringList::Iterator it = input.begin();
1057 const TQStringList::Iterator end = input.end();
1058 for ( ; it != end; ++it)
1060 TQCString cs = ToASCII(*it);
1065 if (!retval.isEmpty())
1081 if (asciiDomain.isEmpty())
1084 idnDomains = KResolver_initIdnDomains();
1094 TQStringList input = splitLabels(asciiDomain);
1097 if (input.count() && !idnDomains->contains(input[input.count()-1].lower()))
1098 return asciiDomain.lower();
1104 TQStringList::Iterator it;
1105 const TQStringList::Iterator end = input.end();
1106 for (it = input.begin(); it != end; ++it)
1108 TQString label = ToUnicode(*it).lower();
1111 if (!retval.isEmpty())
1124 void KResolver::virtual_hook(
int,
void* )
1136 static TQStringList splitLabels(
const TQString& unicodeDomain)
1143 static const unsigned int separators[] = { 0x002E, 0x3002, 0xFF0E, 0xFF61 };
1148 for (i = 0; i < unicodeDomain.length(); i++)
1150 unsigned int c = unicodeDomain[i].unicode();
1152 if (c == separators[0] ||
1153 c == separators[1] ||
1154 c == separators[2] ||
1158 lst << unicodeDomain.mid(start, i - start);
1162 if ((
long)i >= start)
1164 lst << unicodeDomain.mid(start, i - start);
1169 static TQCString ToASCII(
const TQString& label)
1175 if (
label.length() > 64)
1178 if (
label.length() == 0)
1180 return TQCString(
"");
1185 TQ_UINT32* ucs4 =
new TQ_UINT32[
label.length() + 1];
1188 for (i = 0; i <
label.length(); i++)
1189 ucs4[i] = (
unsigned long)
label[i].unicode();
1192 if (idna_to_ascii_4i(ucs4,
label.length(), buf, 0) == IDNA_SUCCESS)
1199 return label.latin1();
1203 static TQString ToUnicode(
const TQString& label)
1209 TQ_UINT32 *ucs4_input, *ucs4_output;
1212 ucs4_input =
new TQ_UINT32[
label.length() + 1];
1213 for (uint i = 0; i <
label.length(); i++)
1214 ucs4_input[i] = (
unsigned long)
label[i].unicode();
1217 ucs4_output =
new TQ_UINT32[outlen =
label.length()];
1219 idna_to_unicode_44i(ucs4_input,
label.length(),
1220 ucs4_output, &outlen,
1223 if (outlen >
label.length())
1226 delete [] ucs4_output;
1227 ucs4_output =
new TQ_UINT32[outlen];
1229 idna_to_unicode_44i(ucs4_input,
label.length(),
1230 ucs4_output, &outlen,
1236 result.setLength(outlen);
1237 for (uint i = 0; i < outlen; i++)
1238 result[i] = (
unsigned int)ucs4_output[i];
1240 delete [] ucs4_input;
1241 delete [] ucs4_output;
1249 #include "kresolver.moc"
int protocol() const
Retrieves the protocol associated with this entry.
KResolverEntry()
Default constructor.
TQ_UINT16 length() const
Retrieves the length of the socket address structure.
~KResolverEntry()
Destructor.
int socketType() const
Retrieves the socket type associated with this entry.
TQCString encodedName() const
Retrieves the encoded domain name associated with this entry, if there is any.
TDESocketAddress address() const
Retrieves the socket address associated with this entry.
int family() const
Retrieves the family associated with this socket address.
TQString canonicalName() const
Retrieves the canonical name associated with this entry, if there is any.
KResolverEntry & operator=(const KResolverEntry &other)
Assignment operator.
Name and service resolution results.
KResolverResults()
Default constructor.
virtual ~KResolverResults()
Destructor.
void setAddress(const TQString &host, const TQString &service)
Sets the new nodename and service name.
int systemError() const
Retrieves the system error code, if any.
int error() const
Retrieves the error code associated with this resolution.
TQString nodeName() const
The nodename to which the resolution was performed.
KResolverResults & operator=(const KResolverResults &other)
Assignment operator.
TQString serviceName() const
The service name to which the resolution was performed.
void setError(int errorcode, int systemerror=0)
Sets the error codes.
Name and service resolution class.
KResolver(TQObject *=0L, const char *=0L)
Default constructor.
void cancel(bool emitSignal=true)
Cancels a running request.
KResolverResults results() const
Retrieves the results of this resolution.
TQString nodeName() const
The nodename to which the resolution was/is to be performed.
static TQString domainToUnicode(const TQCString &asciiDomain)
Does the inverse of domainToAscii and return an Unicode domain name from the given ACE-encoded domain...
int status() const
Retrieve the current status of this object.
static TQStrList protocolName(int protonum)
Resolves a protocol number to its names.
TQString errorString() const
Returns the textual representation of the error in this object.
int error() const
Retrieve the error code in this object.
void setProtocol(int protonum, const char *name=0L)
Sets the protocol we want.
static KResolverResults resolve(const TQString &host, const TQString &service, int flags=0, int families=KResolver::InternetFamily)
Resolve the nodename and service name synchronously.
static TQCString domainToAscii(const TQString &unicodeDomain)
Returns the domain name in an ASCII Compatible Encoding form, suitable for DNS lookups.
virtual bool event(TQEvent *)
Handles events.
bool isRunning() const
Returns true if this object is currently running.
int systemError() const
Retrieve the associated system error code in this object.
void finished(KResolverResults results)
This signal is emitted whenever the resolution is finished, one way or another (success or failure).
void setFamily(int families)
Sets the allowed socket families.
static int servicePort(const char *servname, const char *protoname)
Resolves a service name to its port number.
int flags() const
Retrieves the flags set for the resolution.
static int protocolNumber(const char *protoname)
Resolves a protocol name to its number.
void setServiceName(const TQString &service)
Sets the service name to be resolved.
virtual ~KResolver()
Destructor.
bool wait(int msec=0)
Waits for a request to finish resolving.
static bool resolveAsync(TQObject *userObj, const char *userSlot, const TQString &host, const TQString &service, int flags=0, int families=KResolver::InternetFamily)
Start an asynchronous name resolution.
void setNodeName(const TQString &nodename)
Sets the nodename for the resolution.
int setFlags(int flags)
Sets the flags.
void setSocketType(int type)
Sets the socket type we want.
TQString serviceName() const
The service name to which the resolution was/is to be performed.
static TQString normalizeDomain(const TQString &domain)
Normalise a domain name.
bool start()
Starts the name resolution asynchronously.
void setAddress(const TQString &node, const TQString &service)
Sets both the host and the service names.
static TQString localHostName()
Returns this machine's local hostname.
A generic socket address.
A namespace to store all networking-related (socket) classes.
TQString label(StdAccel id)
Returns a localized label for user-visible display.