11397 |
11402 |
11398 reinitialize |
11403 reinitialize |
11399 "clear the protocol cache, when the system has been restarted" |
11404 "clear the protocol cache, when the system has been restarted" |
11400 |
11405 |
11401 ProtocolCache := nil. |
11406 ProtocolCache := nil. |
|
11407 ! ! |
|
11408 |
|
11409 !UnixOperatingSystem::SocketHandle class methodsFor:'queries'! |
|
11410 |
|
11411 getAddressInfo:hostName serviceName:serviceName domain:domainArg type:typeArg protocol:protoArg flags:flags |
|
11412 "answer an Array of socket addresses for serviceName on hostName |
|
11413 Domain, type, protocol may be nil or specify a hint for the socket |
|
11414 addresses to be returned." |
|
11415 |
|
11416 |error errorString result domain type proto| |
|
11417 |
|
11418 domain := self domainCodeOf:domainArg. |
|
11419 type := self socketTypeCodeOf:typeArg. |
|
11420 proto := self protocolCodeOf:protoArg. |
|
11421 |
|
11422 %{ /* STACK:32000 */ |
|
11423 /* #undef NI_NUMERICHOST */ /* undef to test gethost...() path */ |
|
11424 |
|
11425 |
|
11426 #if !defined(NO_SOCKET) |
|
11427 char *__hostName, *__serviceName; |
|
11428 int ret, cnt = 0; |
|
11429 |
|
11430 if (hostName == nil) { |
|
11431 __hostName = 0; |
|
11432 } else if (__isString(hostName) || __isSymbol(hostName)) { |
|
11433 __hostName = __stringVal(hostName); |
|
11434 } else { |
|
11435 error = @symbol(badArgument1); |
|
11436 goto err; |
|
11437 } |
|
11438 if (serviceName == nil) { |
|
11439 __serviceName = 0; |
|
11440 } else if (__isString(serviceName) || __isSymbol(serviceName)) { |
|
11441 __serviceName = __stringVal(serviceName); |
|
11442 } else { |
|
11443 error = @symbol(badArgument2); |
|
11444 goto err; |
|
11445 } |
|
11446 if (__hostName == 0 && __serviceName == 0) { |
|
11447 error = @symbol(badArgument); |
|
11448 goto err; |
|
11449 } |
|
11450 |
|
11451 { |
|
11452 # if defined(AI_NUMERICHOST) |
|
11453 struct addrinfo hints; |
|
11454 struct addrinfo *info = 0, *infop; |
|
11455 |
|
11456 memset(&hints, 0, sizeof(hints)); |
|
11457 if (__isSmallInteger(domain)) |
|
11458 hints.ai_family = __intVal(domain); |
|
11459 if (__isSmallInteger(type)) |
|
11460 hints.ai_socktype = __intVal(type); |
|
11461 if (__isSmallInteger(proto)) |
|
11462 hints.ai_protocol = __intVal(proto); |
|
11463 |
|
11464 do { |
|
11465 __BEGIN_INTERRUPTABLE__ |
|
11466 ret = getaddrinfo(__hostName, __serviceName, &hints, &info); |
|
11467 __END_INTERRUPTABLE__ |
|
11468 } while (ret == EAI_SYSTEM && errno == EINTR); |
|
11469 if (ret != 0) { |
|
11470 switch (ret) { |
|
11471 case EAI_FAMILY: |
|
11472 error = @symbol(badProtocol); |
|
11473 break; |
|
11474 case EAI_SOCKTYPE: |
|
11475 error = @symbol(badSocketType); |
|
11476 break; |
|
11477 case EAI_BADFLAGS: |
|
11478 error = @symbol(badFlags); |
|
11479 break; |
|
11480 case EAI_NONAME: |
|
11481 error = @symbol(unknownHost); |
|
11482 break; |
|
11483 case EAI_SERVICE: |
|
11484 error = @symbol(unknownService); |
|
11485 break; |
|
11486 case EAI_ADDRFAMILY : |
|
11487 error = @symbol(unknownHostForProtocol); |
|
11488 break; |
|
11489 case EAI_NODATA: |
|
11490 error = @symbol(noAddress); |
|
11491 break; |
|
11492 case EAI_MEMORY: |
|
11493 error = @symbol(allocationFailure); |
|
11494 break; |
|
11495 case EAI_FAIL: |
|
11496 error = @symbol(permanentFailure); |
|
11497 break; |
|
11498 case EAI_AGAIN: |
|
11499 error = @symbol(tryAgain); |
|
11500 break; |
|
11501 case EAI_SYSTEM: |
|
11502 error = @symbol(systemError); |
|
11503 break; |
|
11504 default: |
|
11505 error = @symbol(unknownError); |
|
11506 } |
|
11507 errorString = __MKSTRING(gai_strerror(ret)); |
|
11508 goto err; |
|
11509 } |
|
11510 for (cnt=0, infop=info; infop; infop=infop->ai_next) |
|
11511 cnt++; |
|
11512 |
|
11513 result = __ARRAY_NEW_INT(cnt); |
|
11514 if (result == nil) { |
|
11515 error = @symbol(allocationFailure); |
|
11516 goto err; |
|
11517 } |
|
11518 for (infop=info, cnt=0; infop; infop=infop->ai_next, cnt++) { |
|
11519 OBJ o, resp; |
|
11520 |
|
11521 resp = __ARRAY_NEW_INT(6); |
|
11522 if (resp == nil) { |
|
11523 error = @symbol(allocationFailure); |
|
11524 goto err; |
|
11525 } |
|
11526 |
|
11527 __ArrayInstPtr(result)->a_element[cnt] = resp; |
|
11528 __STORE(result, resp); |
|
11529 __ArrayInstPtr(resp)->a_element[0] = __MKSMALLINT(infop->ai_flags); |
|
11530 __ArrayInstPtr(resp)->a_element[1] = __MKSMALLINT(infop->ai_family); |
|
11531 __ArrayInstPtr(resp)->a_element[2] = __MKSMALLINT(infop->ai_socktype); |
|
11532 __ArrayInstPtr(resp)->a_element[3] = __MKSMALLINT(infop->ai_protocol); |
|
11533 o = __BYTEARRAY_NEW_INT(infop->ai_addrlen); |
|
11534 if (o == nil) { |
|
11535 error = @symbol(allocationFailure); |
|
11536 goto err; |
|
11537 } |
|
11538 memcpy(__byteArrayVal(o), infop->ai_addr, infop->ai_addrlen); |
|
11539 __ArrayInstPtr(resp)->a_element[4] = o; |
|
11540 __STORE(resp, o); |
|
11541 if (infop->ai_canonname) { |
|
11542 o = __MKSTRING(infop->ai_canonname); |
|
11543 if (o == nil) { |
|
11544 error = @symbol(allocationFailure); |
|
11545 goto err; |
|
11546 } |
|
11547 __ArrayInstPtr(resp)->a_element[5] = o; |
|
11548 __STORE(resp, o); |
|
11549 } |
|
11550 } |
|
11551 |
|
11552 err: |
|
11553 if (info) freeaddrinfo(info); |
|
11554 |
|
11555 # else /* ! AI_NUMERICHOST =============================================================*/ |
|
11556 |
|
11557 struct hostent *hp; |
|
11558 char **addrpp; |
|
11559 int port = 0; |
|
11560 int i; |
|
11561 |
|
11562 /* |
|
11563 * Use gethostByName() |
|
11564 */ |
|
11565 |
|
11566 if (__serviceName) { |
|
11567 struct servent *sp; |
|
11568 char *__proto = 0; |
|
11569 |
|
11570 if (__isString(protoArg) || __isSymbol(protoArg)) |
|
11571 __proto = __stringVal(protoArg); |
|
11572 |
|
11573 sp = getservbyname(__serviceName, __proto); |
|
11574 if (sp == NULL) { |
|
11575 errorString = @symbol(unknownService); |
|
11576 error = __mkSmallInteger(-3); |
|
11577 goto err; |
|
11578 } |
|
11579 port = sp->s_port; |
|
11580 } |
|
11581 |
|
11582 if (__hostName) { |
|
11583 # ifdef USE_H_ERRNO |
|
11584 do { |
|
11585 /* __BEGIN_INTERRUPTABLE__ is dangerous, because gethostbyname |
|
11586 * uses a static data area |
|
11587 */ |
|
11588 __BEGIN_INTERRUPTABLE__ |
|
11589 hp = gethostbyname(__hostName); |
|
11590 __END_INTERRUPTABLE__ |
|
11591 } while ((hp == NULL) |
|
11592 && ( |
|
11593 (h_errno == TRY_AGAIN) |
|
11594 || errno == EINTR |
|
11595 # ifdef IRIX5_3 |
|
11596 || (errno == ECONNREFUSED) |
|
11597 # endif |
|
11598 ) |
|
11599 ); |
|
11600 if (hp == 0) { |
|
11601 switch (h_errno) { |
|
11602 case HOST_NOT_FOUND: |
|
11603 error = @symbol(unknownHost); |
|
11604 break; |
|
11605 case NO_ADDRESS: |
|
11606 error = @symbol(noAddress); |
|
11607 break; |
|
11608 case NO_RECOVERY: |
|
11609 error = @symbol(permanentFailure); |
|
11610 break; |
|
11611 case TRY_AGAIN: |
|
11612 error = @symbol(tryAgain); |
|
11613 break; |
|
11614 default: |
|
11615 error = @symbol(unknownError); |
|
11616 } |
|
11617 errorString = __MKSTRING(hstrerror(h_errno)); |
|
11618 goto err; |
|
11619 } |
|
11620 # else /* !USE_H_ERRNO */ |
|
11621 hp = gethostbyname(__hostName); |
|
11622 if (hp == 0) { |
|
11623 errorString = @symbol(unknownHost); |
|
11624 error = __mkSmallInteger(-1); |
|
11625 goto err; |
|
11626 } |
|
11627 # endif /* !USE_H_ERRNO*/ |
|
11628 |
|
11629 if (__isSmallInteger(domain) && hp->h_addrtype != __smallIntegerVal(domain)) { |
|
11630 errorString = @symbol(unknownHost); |
|
11631 error = __mkSmallInteger(-2); |
|
11632 goto err; |
|
11633 } |
|
11634 |
|
11635 for (cnt = 0, addrpp = hp->h_addr_list; *addrpp; addrpp++) |
|
11636 cnt++; |
|
11637 addrpp = hp->h_addr_list; |
|
11638 } else { |
|
11639 cnt = 1; |
|
11640 } |
|
11641 |
|
11642 result = __ARRAY_NEW_INT(cnt); |
|
11643 if (result == nil) { |
|
11644 error = @symbol(allocationFailure); |
|
11645 goto err; |
|
11646 } |
|
11647 |
|
11648 for (i = 0; i < cnt; i++) { |
|
11649 OBJ o, resp; |
|
11650 struct sockaddr_in *sa; |
|
11651 |
|
11652 resp = __ARRAY_NEW_INT(6); |
|
11653 if (resp == nil) { |
|
11654 error = @symbol(allocationFailure); |
|
11655 goto err; |
|
11656 } |
|
11657 |
|
11658 __ArrayInstPtr(result)->a_element[i] = resp; |
|
11659 __STORE(result, resp); |
|
11660 __ArrayInstPtr(resp)->a_element[0] = __mkSmallInteger(0); |
|
11661 __ArrayInstPtr(resp)->a_element[2] = type; |
|
11662 __ArrayInstPtr(resp)->a_element[3] = proto; |
|
11663 o = __BYTEARRAY_NEW_INT(sizeof(*sa)); |
|
11664 if (o == nil) { |
|
11665 error = @symbol(allocationFailure); |
|
11666 goto err; |
|
11667 } |
|
11668 __ArrayInstPtr(resp)->a_element[4] = o; |
|
11669 __STORE(resp, o); |
|
11670 sa = (struct sockaddr_in *)__byteArrayVal(o); |
|
11671 sa->sin_port = port; |
|
11672 |
|
11673 if (__hostName) { |
|
11674 sa->sin_family = hp->h_addrtype; |
|
11675 memcpy(&sa->sin_addr, *addrpp, hp->h_length); |
|
11676 __ArrayInstPtr(resp)->a_element[1] = __mkSmallInteger(hp->h_addrtype); |
|
11677 if (hp->h_name) { |
|
11678 o = __MKSTRING(hp->h_name); |
|
11679 if (o == nil) { |
|
11680 error = @symbol(allocationFailure); |
|
11681 goto err; |
|
11682 } |
|
11683 __ArrayInstPtr(resp)->a_element[5] = o; |
|
11684 __STORE(resp, o); |
|
11685 } |
|
11686 addrpp++; |
|
11687 } else{ |
|
11688 __ArrayInstPtr(resp)->a_element[1] = domain; |
|
11689 } |
|
11690 } |
|
11691 |
|
11692 err:; |
|
11693 # endif /* ! AI_NUMERICHOST */ |
|
11694 } |
|
11695 #else /* ! HAS_SOCKET */ |
|
11696 error = @symbol(notImplemented); |
|
11697 #endif |
|
11698 %}. |
|
11699 error notNil ifTrue:[ |
|
11700 NameLookupError raiseWith:error errorString:errorString. |
|
11701 ]. |
|
11702 1 to:result size do:[:i | |
|
11703 |entry dom info| |
|
11704 |
|
11705 info := SocketAddressInfo new. |
|
11706 entry := result at:i. |
|
11707 info flags:(entry at:1). |
|
11708 info domain:(dom := self domainSymbolOf:(entry at:2)). |
|
11709 info type:(self socketTypeSymbolOf:(entry at:3)). |
|
11710 info protocol:(self protocolSymbolOf:(entry at:4)). |
|
11711 info socketAddress:((SocketAddress newDomain:dom) fromBytes:(entry at:5)). |
|
11712 info canonicalName:(entry at:6). |
|
11713 result at:i put:info |
|
11714 ]. |
|
11715 ^ result |
|
11716 |
|
11717 " |
|
11718 self getAddressInfo:'localhost' serviceName:nil |
|
11719 domain:nil type:nil protocol:nil flags:nil |
|
11720 self getAddressInfo:'localhost' serviceName:nil |
|
11721 domain:#inet type:#stream protocol:nil flags:nil |
|
11722 self getAddressInfo:'localhost' serviceName:nil |
|
11723 domain:#inet type:#stream protocol:#tcp flags:nil |
|
11724 self getAddressInfo:'blurb.exept.de' serviceName:nil |
|
11725 domain:#inet type:nil protocol:nil flags:nil |
|
11726 self getAddressInfo:'1.2.3.4' serviceName:'bla' |
|
11727 domain:#inet type:nil protocol:nil flags:nil |
|
11728 self getAddressInfo:'localhost' serviceName:'echo' |
|
11729 domain:#inet type:nil protocol:nil flags:nil |
|
11730 self getAddressInfo:nil serviceName:'echo' |
|
11731 domain:#inet type:nil protocol:nil flags:nil |
|
11732 self getAddressInfo:nil serviceName:nil |
|
11733 domain:#inet type:nil protocol:nil flags:nil |
|
11734 " |
|
11735 ! |
|
11736 |
|
11737 getNameInfo:socketAddress wantHostName:wantHostName wantServiceName:wantServiceName datagram:useDatagram flags:flags |
|
11738 "answer an Array containing the hostName and serviceName |
|
11739 in socketAddress. SocketType may be one " |
|
11740 |
|
11741 |error errorString hostName serviceName| |
|
11742 |
|
11743 %{ /* STACK:32000 */ |
|
11744 |
|
11745 /* #undef NI_NUMERICHOST */ /* undef to test gethost...() path */ |
|
11746 |
|
11747 #if !defined(NO_SOCKET) |
|
11748 |
|
11749 # ifndef NI_MAXHOST |
|
11750 # define NI_MAXHOST 256 |
|
11751 # define NI_MAXSERV 64 |
|
11752 # endif |
|
11753 |
|
11754 char host[NI_MAXHOST]; |
|
11755 char service[NI_MAXSERV]; |
|
11756 char *hp = 0, *sp = 0; |
|
11757 int hsz = 0, ssz = 0; |
|
11758 int ret, __flags; |
|
11759 |
|
11760 if (wantHostName == true) { |
|
11761 hp = host; |
|
11762 hsz = sizeof(host); |
|
11763 } |
|
11764 if (wantServiceName == true) { |
|
11765 sp = service; |
|
11766 ssz = sizeof(service); |
|
11767 } |
|
11768 if (hp == 0 && sp == 0) { |
|
11769 error = @symbol(badArgument); |
|
11770 goto err; |
|
11771 } |
|
11772 if (!__isNonNilObject(socketAddress) || |
|
11773 (__intVal(__ClassInstPtr(__qClass(socketAddress))->c_flags) & ARRAYMASK) != BYTEARRAY) { |
|
11774 DBGPRINTF(("SOCKET: bad socket address")); |
|
11775 error = @symbol(badArgument1); |
|
11776 goto err; |
|
11777 } |
|
11778 if (!__isSmallInteger(flags)) { |
|
11779 error = @symbol(badArgument5); |
|
11780 goto err; |
|
11781 } |
|
11782 __flags = __intVal(flags); |
|
11783 |
|
11784 #if defined(NI_NUMERICHOST) |
|
11785 if (useDatagram == true) { |
|
11786 __flags |= NI_DGRAM; |
|
11787 } |
|
11788 |
|
11789 { |
|
11790 __BEGIN_INTERRUPTABLE__ |
|
11791 ret = getnameinfo((struct sockaddr *)__byteArrayVal(socketAddress), |
|
11792 __byteArraySize(socketAddress), |
|
11793 hp, hsz, sp, ssz, __flags); |
|
11794 __END_INTERRUPTABLE__ |
|
11795 } while (ret == EAI_SYSTEM && errno == EINTR); |
|
11796 if (ret != 0) { |
|
11797 switch (ret) { |
|
11798 case EAI_FAMILY: |
|
11799 error = @symbol(badProtocol); |
|
11800 break; |
|
11801 case EAI_SOCKTYPE: |
|
11802 error = @symbol(badSocketType); |
|
11803 break; |
|
11804 case EAI_BADFLAGS: |
|
11805 error = @symbol(badFlags); |
|
11806 break; |
|
11807 case EAI_NONAME: |
|
11808 error = @symbol(unknownHost); |
|
11809 break; |
|
11810 case EAI_SERVICE: |
|
11811 error = @symbol(unknownService); |
|
11812 break; |
|
11813 case EAI_ADDRFAMILY : |
|
11814 error = @symbol(unknownHostForProtocol); |
|
11815 break; |
|
11816 case EAI_NODATA: |
|
11817 error = @symbol(noAddress); |
|
11818 break; |
|
11819 case EAI_MEMORY: |
|
11820 error = @symbol(allocationFailure); |
|
11821 break; |
|
11822 case EAI_FAIL: |
|
11823 error = @symbol(permanentFailure); |
|
11824 break; |
|
11825 case EAI_AGAIN: |
|
11826 error = @symbol(tryAgain); |
|
11827 break; |
|
11828 case EAI_SYSTEM: |
|
11829 error = @symbol(systemError); |
|
11830 break; |
|
11831 default: |
|
11832 error = @symbol(unknownError); |
|
11833 } |
|
11834 errorString = __MKSTRING(gai_strerror(ret)); |
|
11835 goto err; |
|
11836 } |
|
11837 # else /* ! NI_NUMERICHOST */ |
|
11838 /* |
|
11839 * Do it using gethostbyaddr() |
|
11840 */ |
|
11841 |
|
11842 struct sockaddr_in *sa; |
|
11843 if (__byteArraySize(socketAddress) < sizeof(*sa)) { |
|
11844 error = @symbol(badArgument1); |
|
11845 goto err; |
|
11846 } |
|
11847 sa = (struct sockaddr_in *)__byteArrayVal(socketAddress); |
|
11848 |
|
11849 if (sp) { |
|
11850 struct servent *servp; |
|
11851 char *__proto = 0; |
|
11852 |
|
11853 __proto = (useDatagram == true ? "udp" : "tcp"); |
|
11854 |
|
11855 servp = getservbyport(sa->sin_port, __proto); |
|
11856 if (servp) { |
|
11857 sp = servp->s_name; |
|
11858 } |
|
11859 } |
|
11860 if (hp) { |
|
11861 struct hostent *hostp; |
|
11862 # ifdef USE_H_ERRNO |
|
11863 do { |
|
11864 /* __BEGIN_INTERRUPTABLE__ is dangerous, because gethostbyname |
|
11865 * uses a static data area |
|
11866 */ |
|
11867 hostp = gethostbyaddr((char *)&sa->sin_addr, sizeof(sa->sin_addr), AF_INET); |
|
11868 } while ((hp == NULL) |
|
11869 && ((h_errno == TRY_AGAIN) |
|
11870 || errno == EINTR |
|
11871 # ifdef IRIX5_3 |
|
11872 || (errno == ECONNREFUSED) |
|
11873 # endif |
|
11874 ) |
|
11875 ); |
|
11876 if (hp == 0) { |
|
11877 switch (h_errno) { |
|
11878 case HOST_NOT_FOUND: |
|
11879 error = @symbol(unknownHost); |
|
11880 break; |
|
11881 case NO_ADDRESS: |
|
11882 error = @symbol(noAddress); |
|
11883 break; |
|
11884 case NO_RECOVERY: |
|
11885 error = @symbol(permanentFailure); |
|
11886 break; |
|
11887 case TRY_AGAIN: |
|
11888 error = @symbol(tryAgain); |
|
11889 break; |
|
11890 default: |
|
11891 error = @symbol(unknownError); |
|
11892 } |
|
11893 errorString = __MKSTRING(hstrerror(h_errno)); |
|
11894 goto err; |
|
11895 } |
|
11896 # else /* !USE_H_ERRNO */ |
|
11897 hostp = gethostbyaddr(sa->sin_addr, sizeof(sa->sin_addr), AF_INET); |
|
11898 if (hostp == 0) { |
|
11899 errorString = @symbol(unknownHost); |
|
11900 error = __mkSmallInteger(-1); |
|
11901 goto err; |
|
11902 } |
|
11903 # endif /* !USE_H_ERRNO*/ |
|
11904 hp = hostp->h_name; |
|
11905 } |
|
11906 # endif /* ! NI_NUMERICHOST */ |
|
11907 |
|
11908 if (hp) |
|
11909 hostName = __MKSTRING(hp); |
|
11910 if (sp) |
|
11911 serviceName = __MKSTRING(sp); |
|
11912 |
|
11913 err:; |
|
11914 #else |
|
11915 error = @symbol(notImplemented); |
|
11916 #endif |
|
11917 %}. |
|
11918 error notNil ifTrue:[ |
|
11919 NameLookupError raiseWith:error errorString:errorString. |
|
11920 ^ nil |
|
11921 ]. |
|
11922 |
|
11923 ^ Array with:hostName with:serviceName |
|
11924 |
|
11925 " |
|
11926 self getNameInfo: |
|
11927 (self getAddressInfo:'localhost' serviceName:'echo' |
|
11928 domain:#inet type:#stream protocol:nil flags:nil) first socketAddress |
|
11929 wantHostName:true wantServiceName:true datagram:false flags:0 |
|
11930 " |
11402 ! ! |
11931 ! ! |
11403 |
11932 |
11404 !UnixOperatingSystem::SocketHandle methodsFor:'accepting'! |
11933 !UnixOperatingSystem::SocketHandle methodsFor:'accepting'! |
11405 |
11934 |
11406 acceptWithPeerAddressBuffer:peerOrNil |
11935 acceptWithPeerAddressBuffer:peerOrNil |