--- a/UnixOperatingSystem.st Wed Aug 18 10:44:40 2010 +0200
+++ b/UnixOperatingSystem.st Wed Aug 18 20:33:20 2010 +0200
@@ -11252,7 +11252,7 @@
!UnixOperatingSystem::SocketHandle class methodsFor:'queries'!
-getAddressInfo:hostName serviceName:serviceNameArg domain:domainArg type:typeArg protocol:protoArg flags:flags
+XXgetAddressInfo:hostName serviceName:serviceNameArg domain:domainArg type:typeArg protocol:protoArg flags:flags
"answer an Array of socket addresses for serviceName on hostName
Domain, type, protocol may be nil or specify a hint for the socket
addresses to be returned."
@@ -11626,6 +11626,76 @@
"
!
+getAddressInfo:hostName serviceName:serviceNameArg domain:domainArg type:typeArg protocol:protoArg flags:flags
+ "answer an Array of socket addresses for serviceName on hostName
+ Domain, type, protocol may be nil or specify a hint for the socket
+ addresses to be returned."
+
+ |result domain type proto serviceName|
+
+ domain := OperatingSystem domainCodeOf:domainArg.
+ type := OperatingSystem socketTypeCodeOf:typeArg.
+ proto := self protocolCodeOf:protoArg.
+ serviceNameArg notNil ifTrue:[
+ serviceName := serviceNameArg printString. "convert integer port numbers"
+ ].
+
+ result := self primGetAddressInfo:hostName serviceName:serviceName domainCode:domain socketTypeCode:type protocolCode:proto flags:flags.
+ result isArray ifFalse:[
+ |request|
+ request := SocketAddressInfo new
+ domain:domainArg;
+ type:typeArg;
+ protocol:protoArg;
+ canonicalName:hostName;
+ serviceName:serviceName.
+ ^ (HostNameLookupError new
+ parameter:result;
+ messageText:' - ', (result printString);
+ request:request) raiseRequest.
+ ].
+ 1 to:result size do:[:i |
+ |entry dom info|
+
+ entry := result at:i.
+
+ info := SocketAddressInfo new.
+ info
+ flags:(entry at:1);
+ domain:(dom := OperatingSystem domainSymbolOf:(entry at:2));
+ type:(OperatingSystem socketTypeSymbolOf:(entry at:3));
+ protocol:(self protocolSymbolOf:(entry at:4));
+ socketAddress:((SocketAddress newDomain:dom) fromBytes:(entry at:5));
+ canonicalName:(entry at:6).
+
+ result at:i put:info.
+ ].
+ ^ result
+
+ "
+ self getAddressInfo:'localhost' serviceName:nil
+ domain:nil type:nil protocol:nil flags:nil
+ self getAddressInfo:'localhost' serviceName:nil
+ domain:#inet type:#stream protocol:nil flags:nil
+ self getAddressInfo:'localhost' serviceName:nil
+ domain:#inet type:#stream protocol:#tcp flags:nil
+ self getAddressInfo:'blurb.exept.de' serviceName:nil
+ domain:#inet type:nil protocol:nil flags:nil
+ self getAddressInfo:'1.2.3.4' serviceName:'bla'
+ domain:#inet type:nil protocol:nil flags:nil
+ self getAddressInfo:'localhost' serviceName:'echo'
+ domain:#inet type:nil protocol:nil flags:nil
+ self getAddressInfo:nil serviceName:'echo'
+ domain:#inet type:nil protocol:nil flags:nil
+ self getAddressInfo:nil serviceName:nil
+ domain:#inet type:nil protocol:nil flags:nil
+ self getAddressInfo:'www.google.de' serviceName:nil
+ domain:nil type:nil protocol:nil flags:nil
+ self getAddressInfo:'smc1' serviceName:nil
+ domain:nil type:nil protocol:nil flags:nil
+ "
+!
+
getNameInfo:socketAddress wantHostName:wantHostName wantServiceName:wantServiceName datagram:useDatagram flags:flags
"answer an Array containing the hostName and serviceName
in socketAddress.
@@ -11857,6 +11927,327 @@
domain:#inet type:#stream protocol:nil flags:nil) first socketAddress
wantHostName:true wantServiceName:true datagram:false flags:0
"
+!
+
+primGetAddressInfo:hostName serviceName:serviceName domainCode:domain socketTypeCode:type protocolCode:proto flags:flags
+ "answer an Array of socket addresses for serviceName on hostName
+ Domain, type, protocol may be nil or specify a hint for the socket
+ addresses to be returned."
+
+ |error errorString result|
+
+%{ /* UNLIMITEDSTACK */ /* Don't know whether DNS, NIS, LDAP or whatever is consulted */
+#undef xxAI_NUMERICHOST /* remove xx to test gethost...() path */
+
+
+#if !defined(NO_SOCKET)
+ char *__hostName, *__serviceName;
+ int ret, cnt = 0;
+
+ if (hostName == nil) {
+ __hostName = 0;
+ } else if (__isStringLike(hostName)) {
+ __hostName = __stringVal(hostName);
+ } else {
+ error = @symbol(badArgument1);
+ goto err;
+ }
+ if (serviceName == nil) {
+ __serviceName = 0;
+ } else if (__isStringLike(serviceName)) {
+ __serviceName = __stringVal(serviceName);
+ } else {
+ error = @symbol(badArgument2);
+ goto err;
+ }
+ if (__hostName == 0 && __serviceName == 0) {
+ error = @symbol(badArgument);
+ goto err;
+ }
+
+{
+# if defined(AI_NUMERICHOST)
+ /*
+ * Use getaddrinfo()
+ */
+ struct addrinfo hints;
+ struct addrinfo *info = NULL, *infop;
+
+ memset(&hints, 0, sizeof(hints));
+ if (__isSmallInteger(domain))
+ hints.ai_family = __intVal(domain);
+ if (__isSmallInteger(type))
+ hints.ai_socktype = __intVal(type);
+ if (__isSmallInteger(proto))
+ hints.ai_protocol = __intVal(proto);
+
+ do {
+ if (hostName == nil) {
+ __hostName = 0;
+ } else if (__isStringLike(hostName)) {
+ __hostName = __stringVal(hostName);
+ }
+ if (serviceName == nil) {
+ __serviceName = 0;
+ } else if (__isStringLike(serviceName)) {
+ __serviceName = __stringVal(serviceName);
+ }
+
+// __BEGIN_INTERRUPTABLE__
+ ret = getaddrinfo(__hostName, __serviceName, &hints, &info);
+// __END_INTERRUPTABLE__
+ } while (ret == EAI_SYSTEM && errno == EINTR);
+ if (ret != 0) {
+ switch (ret) {
+ case EAI_FAMILY:
+ error = @symbol(badProtocol);
+ break;
+ case EAI_SOCKTYPE:
+ error = @symbol(badSocketType);
+ break;
+ case EAI_BADFLAGS:
+ error = @symbol(badFlags);
+ break;
+ case EAI_NONAME:
+ error = @symbol(unknownHost);
+ break;
+ case EAI_SERVICE:
+ error = @symbol(unknownService);
+ break;
+#ifdef EAI_ADDRFAMILY
+ case EAI_ADDRFAMILY :
+ error = @symbol(unknownHostForProtocol);
+ break;
+#endif
+#ifdef EAI_NODATA
+ case EAI_NODATA:
+ error = @symbol(noAddress);
+ break;
+#endif
+ case EAI_MEMORY:
+ error = @symbol(allocationFailure);
+ break;
+ case EAI_FAIL:
+ error = @symbol(permanentFailure);
+ break;
+ case EAI_AGAIN:
+ error = @symbol(tryAgain);
+ break;
+ case EAI_SYSTEM:
+ error = @symbol(systemError);
+ break;
+ default:
+ error = @symbol(unknownError);
+ }
+ errorString = __MKSTRING(gai_strerror(ret));
+ goto err;
+ }
+ for (cnt=0, infop=info; infop; infop=infop->ai_next)
+ cnt++;
+
+ result = __ARRAY_NEW_INT(cnt);
+ if (result == nil) {
+ error = @symbol(allocationFailure);
+ goto err;
+ }
+ for (infop=info, cnt=0; infop; infop=infop->ai_next, cnt++) {
+ OBJ o, resp;
+
+ resp = __ARRAY_NEW_INT(6);
+ if (resp == nil) {
+ error = @symbol(allocationFailure);
+ goto err;
+ }
+
+ __ArrayInstPtr(result)->a_element[cnt] = resp; __STORE(result, resp);
+
+ __ArrayInstPtr(resp)->a_element[0] = __mkSmallInteger(infop->ai_flags);
+ __ArrayInstPtr(resp)->a_element[1] = __mkSmallInteger(infop->ai_family);
+ __ArrayInstPtr(resp)->a_element[2] = __mkSmallInteger(infop->ai_socktype);
+ __ArrayInstPtr(resp)->a_element[3] = __mkSmallInteger(infop->ai_protocol);
+
+ __PROTECT__(resp);
+ o = __BYTEARRAY_NEW_INT(infop->ai_addrlen);
+ __UNPROTECT__(resp);
+ if (o == nil) {
+ error = @symbol(allocationFailure);
+ goto err;
+ }
+ memcpy(__byteArrayVal(o), infop->ai_addr, infop->ai_addrlen);
+ __ArrayInstPtr(resp)->a_element[4] = o; __STORE(resp, o);
+
+ if (infop->ai_canonname) {
+ __PROTECT__(resp);
+ o = __MKSTRING(infop->ai_canonname);
+ __UNPROTECT__(resp);
+ if (o == nil) {
+ error = @symbol(allocationFailure);
+ goto err;
+ }
+ __ArrayInstPtr(resp)->a_element[5] = o; __STORE(resp, o);
+ }
+ }
+
+err:
+ if (info) freeaddrinfo(info);
+
+# else /* ! AI_NUMERICHOST =============================================================*/
+
+ /*
+ * Use getservbyname() / gethostByName()
+ */
+ struct hostent *hp;
+ char **addrpp;
+ int port = 0;
+ int i;
+
+ if (__serviceName) {
+ struct servent *sp;
+ char *__proto = 0;
+
+ if (__isStringLike(protoArg))
+ __proto = __stringVal(protoArg);
+
+ sp = getservbyname(__serviceName, __proto);
+ if (sp == NULL) {
+ errorString = @symbol(unknownService);
+ error = __mkSmallInteger(-3);
+ goto err;
+ }
+ port = sp->s_port;
+ }
+
+ if (__hostName) {
+# ifdef USE_H_ERRNO
+ do {
+ if (hostName == nil) {
+ __hostName = 0;
+ } else if (__isStringLike(hostName)) {
+ __hostName = __stringVal(hostName);
+ }
+ /* __BEGIN_INTERRUPTABLE__ is dangerous, because gethostbyname
+ * uses a static data area
+ */
+ __BEGIN_INTERRUPTABLE__
+ hp = gethostbyname(__hostName);
+ __END_INTERRUPTABLE__
+ } while ((hp == NULL)
+ && (
+ (h_errno == TRY_AGAIN)
+ || errno == EINTR
+# ifdef IRIX5_3
+ || (errno == ECONNREFUSED)
+# endif
+ )
+ );
+ if (hp == 0) {
+ switch (h_errno) {
+ case HOST_NOT_FOUND:
+ errorString = @symbol(unknownHost);
+ break;
+ case NO_ADDRESS:
+ errorString = @symbol(noAddress);
+ break;
+ case NO_RECOVERY:
+ errorString = @symbol(permanentFailure);
+ break;
+ case TRY_AGAIN:
+ errorString = @symbol(tryAgain);
+ break;
+ default:
+ errorString = @symbol(unknownError);
+ break;
+ }
+ error = __mkSmallInteger(h_errno);
+ goto err;
+ }
+# else /* !USE_H_ERRNO */
+ hp = gethostbyname(__hostName);
+ if (hp == 0) {
+ errorString = @symbol(unknownHost);
+ error = __mkSmallInteger(-1);
+ goto err;
+ }
+# endif /* !USE_H_ERRNO*/
+
+ if (__isSmallInteger(domain) && hp->h_addrtype != __smallIntegerVal(domain)) {
+ errorString = @symbol(unknownHost);
+ error = __mkSmallInteger(-2);
+ goto err;
+ }
+
+ for (cnt = 0, addrpp = hp->h_addr_list; *addrpp; addrpp++)
+ cnt++;
+ addrpp = hp->h_addr_list;
+ } else {
+ cnt = 1;
+ }
+
+ result = __ARRAY_NEW_INT(cnt);
+ if (result == nil) {
+ error = @symbol(allocationFailure);
+ goto err;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ OBJ o, resp;
+ struct sockaddr_in *sa;
+
+ resp = __ARRAY_NEW_INT(6);
+ if (resp == nil) {
+ error = @symbol(allocationFailure);
+ goto err;
+ }
+
+ __ArrayInstPtr(result)->a_element[i] = resp; __STORE(result, resp);
+ __ArrayInstPtr(resp)->a_element[0] = __mkSmallInteger(0);
+ __ArrayInstPtr(resp)->a_element[2] = type; __STORE(result, type);
+ __ArrayInstPtr(resp)->a_element[3] = proto; __STORE(result, proto);
+ __PROTECT__(resp);
+ o = __BYTEARRAY_NEW_INT(sizeof(*sa));
+ __UNPROTECT__(resp);
+ if (o == nil) {
+ error = @symbol(allocationFailure);
+ goto err;
+ }
+ __ArrayInstPtr(resp)->a_element[4] = o; __STORE(resp, o);
+ sa = (struct sockaddr_in *)__byteArrayVal(o);
+ sa->sin_port = port;
+
+ if (__hostName) {
+ sa->sin_family = hp->h_addrtype;
+ memcpy(&sa->sin_addr, *addrpp, hp->h_length);
+ __ArrayInstPtr(resp)->a_element[1] = __mkSmallInteger(hp->h_addrtype);
+ if (hp->h_name) {
+ __PROTECT__(resp);
+ o = __MKSTRING(hp->h_name);
+ __UNPROTECT__(resp);
+ if (o == nil) {
+ error = @symbol(allocationFailure);
+ goto err;
+ }
+ __ArrayInstPtr(resp)->a_element[5] = o; __STORE(resp, o);
+ }
+ addrpp++;
+ } else{
+ __ArrayInstPtr(resp)->a_element[1] = domain; __STORE(resp, domain);
+ }
+ }
+
+err:;
+# endif /* ! AI_NUMERICHOST */
+}
+#else /* ! HAS_SOCKET */
+ error = @symbol(notImplemented);
+#endif
+%}.
+ error notNil ifTrue:[
+ errorString notNil ifTrue:[
+ ^ errorString.
+ ].
+ ^ error.
+ ].
+ ^ result.
! !
!UnixOperatingSystem::SocketHandle methodsFor:'accepting'!
@@ -12700,11 +13091,11 @@
!UnixOperatingSystem class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.276 2010-07-27 09:08:07 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.277 2010-08-18 18:33:20 stefan Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.276 2010-07-27 09:08:07 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.277 2010-08-18 18:33:20 stefan Exp $'
! !
UnixOperatingSystem initialize!