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;
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,
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);
623 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API 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];
640 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobynumber_r which returns struct *protoent or NULL 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);
684 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API 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];
701 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL 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);
745 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API 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];
762 # ifdef USE_SOLARIS // Solaris uses a 4 argument getprotobyname_r which returns struct *protoent or NULL 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);
802 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API 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];
818 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL 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);
858 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API 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];
874 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyname_r which returns struct *servent or NULL 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);
918 # ifdef USE_OPENBSD // OpenBSD uses an HP/IBM/DEC API 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];
934 # ifdef USE_SOLARIS // Solaris uses a 5 argument getservbyport_r which returns struct *servent or NULL 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)
1010 if (results.isEmpty())
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" A generic socket address.
KResolverResults & operator=(const KResolverResults &other)
Assignment operator.
KResolverEntry & operator=(const KResolverEntry &other)
Assignment operator.
TDESocketAddress address() const
Retrieves the socket address associated with this entry.
static TQString domainToUnicode(const TQCString &asciiDomain)
Does the inverse of domainToAscii and return an Unicode domain name from the given ACE-encoded domain...
int systemError() const
Retrieve the associated system error code in this object.
int flags() const
Retrieves the flags set for the resolution.
KResolverResults results() const
Retrieves the results of this resolution.
int protocol() const
Retrieves the protocol associated with this entry.
virtual ~KResolverResults()
Destructor.
void setFamily(int families)
Sets the allowed socket families.
TQString nodeName() const
The nodename to which the resolution was/is to be performed.
Name and service resolution class.
void setProtocol(int protonum, const char *name=0L)
Sets the protocol we want.
TQString serviceName() const
The service name to which the resolution was performed.
TQString canonicalName() const
Retrieves the canonical name associated with this entry, if there is any.
Name and service resolution results.
virtual bool event(TQEvent *)
Handles events.
A namespace to store all networking-related (socket) classes.
void setServiceName(const TQString &service)
Sets the service name to be resolved.
bool wait(int msec=0)
Waits for a request to finish resolving.
int systemError() const
Retrieves the system error code, if any.
int status() const
Retrieve the current status of this object.
int error() const
Retrieve the error code in this object.
TQCString encodedName() const
Retrieves the encoded domain name associated with this entry, if there is any.
int socketType() const
Retrieves the socket type associated with this entry.
~KResolverEntry()
Destructor.
static TQString normalizeDomain(const TQString &domain)
Normalise a domain name.
TQString serviceName() const
The service name to which the resolution was/is to be performed.
static TQString localHostName()
Returns this machine's local hostname.
void setAddress(const TQString &node, const TQString &service)
Sets both the host and the service names.
TQString nodeName() const
The nodename to which the resolution was performed.
void setAddress(const TQString &host, const TQString &service)
Sets the new nodename and service name.
TQString errorString() const
Returns the textual representation of the error in this object.
void finished(KResolverResults results)
This signal is emitted whenever the resolution is finished, one way or another (success or failure)...
int family() const
Retrieves the family associated with this socket address.
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.
TQ_UINT16 length() const
Retrieves the length of the socket address structure.
static int servicePort(const char *servname, const char *protoname)
Resolves a service name to its port number.
void setNodeName(const TQString &nodename)
Sets the nodename for the resolution.
KResolverEntry()
Default constructor.
KResolverResults()
Default constructor.
bool isRunning() const
Returns true if this object is currently running.
void setSocketType(int type)
Sets the socket type we want.
virtual ~KResolver()
Destructor.
int error() const
Retrieves the error code associated with this resolution.
static TQCString domainToAscii(const TQString &unicodeDomain)
Returns the domain name in an ASCII Compatible Encoding form, suitable for DNS lookups.
void setError(int errorcode, int systemerror=0)
Sets the error codes.
void cancel(bool emitSignal=true)
Cancels a running request.
int setFlags(int flags)
Sets the flags.
KResolver(TQObject *=0L, const char *=0L)
Default constructor.
static int protocolNumber(const char *protoname)
Resolves a protocol name to its number.
bool start()
Starts the name resolution asynchronously.
static TQStrList protocolName(int protonum)
Resolves a protocol number to its names.
static KResolverResults resolve(const TQString &host, const TQString &service, int flags=0, int families=KResolver::InternetFamily)
Resolve the nodename and service name synchronously.