Socket.st
changeset 1282 7e4ffdfd19f6
parent 1280 b973855bfe74
child 1299 d8bd042eba6a
equal deleted inserted replaced
1281:6df4f8f211e3 1282:7e4ffdfd19f6
  1266 
  1266 
  1267     |newSock|
  1267     |newSock|
  1268 
  1268 
  1269     newSock := self newTCP.
  1269     newSock := self newTCP.
  1270     newSock notNil ifTrue:[
  1270     newSock notNil ifTrue:[
  1271 	(newSock bindTo:(self portOfService:aService) address:nil) ifFalse:[
  1271         (newSock bindTo:(self portOfService:aService) address:nil) ifFalse:[
  1272 	    ^ nil
  1272             ^ nil
  1273 	]
  1273         ]
  1274     ].
  1274     ].
  1275     ^ newSock
  1275     ^ newSock
  1276 "
       
  1277 same as:
       
  1278     ^ (self new) for:nil port:aPort
       
  1279 "
       
  1280 !
  1276 !
  1281 
  1277 
  1282 newUDP
  1278 newUDP
  1283     "create a UDP socket - no binding or other setup is done,
  1279     "create a UDP socket - no binding or other setup is done,
  1284      neither connect nor connect-wait is done."
  1280      neither connect nor connect-wait is done."
  1550 
  1546 
  1551 connectTo:service on:host
  1547 connectTo:service on:host
  1552     "standard & easy client setup: 
  1548     "standard & easy client setup: 
  1553         create new client tcp socket, bind and connect; 
  1549         create new client tcp socket, bind and connect; 
  1554         return the socket.
  1550         return the socket.
  1555      The thread block (interruptable), until the connection is 
  1551      The thread block (interruptable), until the connection is established."
  1556      established."
  1552 
  1557 
  1553     ^ self newTCPclientToHost:host port:(self portOfService:service).
  1558     <resource:#obsolete>
       
  1559 
       
  1560     self obsoleteMethodWarning:'use newTCP: / connect'.
       
  1561 
       
  1562     ^ (self new) for:host port:(self portOfService:service).
       
  1563 
  1554 
  1564     "
  1555     "
  1565      Socket connectTo:9995 on:'clam'
  1556      Socket connectTo:9995 on:'clam'
  1566      Socket connectTo:4711 on:'exept'
  1557      Socket connectTo:4711 on:'exept'
  1567      Socket connectTo:'finger' on:'clam'
  1558      Socket connectTo:'finger' on:'clam'
  1568      Socket connectTo:'ftp' on:'exept'
  1559      Socket connectTo:'ftp' on:'exept'
  1569      Socket connectTo:'nntp' on:(OperatingSystem getEnvironment:'NNTPSERVER')
  1560      Socket connectTo:'nntp' on:(OperatingSystem getEnvironment:'NNTPSERVER')
  1570     "
  1561     "
  1571 !
  1562 !
  1572 
  1563 
  1573 provide:service
  1564 provide:aService
  1574     "standard & easy server setup: 
  1565     "standard & easy server setup: 
  1575      create a new TCP server socket providing a service."
  1566      create a new TCP server socket providing a service."
  1576 
  1567 
  1577     <resource:#obsolete>
  1568     <resource:#obsolete>
  1578 
  1569 
  1579     |newSock|
  1570     |newSock|
  1580 
  1571 
  1581     self obsoleteMethodWarning:'use newTCP: / listen'.
  1572     self obsoleteMethodWarning:'use newTCPserverAtPort: / listen'.
  1582 
  1573 
  1583     newSock := (self new) for:nil port:(self portOfService:service).
  1574     newSock := self newTCPserverAtPort:(self portOfService:aService).
  1584     newSock notNil ifTrue:[
  1575     newSock notNil ifTrue:[
  1585         newSock listenFor:5.
  1576         newSock listenFor:5.
  1586     ].
  1577     ].
  1587     ^ newSock
  1578     ^ newSock
  1588 
  1579 
  1944     int n;
  1935     int n;
  1945     char *cp;
  1936     char *cp;
  1946     int flags = 0;
  1937     int flags = 0;
  1947 
  1938 
  1948     if (fp != nil) {
  1939     if (fp != nil) {
  1949 	sock = fileno(__FILEVal(fp));
  1940         sock = fileno(__FILEVal(fp));
  1950 
  1941 
  1951 	oClass = __Class(aDataBuffer);
  1942         oClass = __Class(aDataBuffer);
  1952 	switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  1943         switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  1953 	    case BYTEARRAY:
  1944             case BYTEARRAY:
  1954 	    case WORDARRAY:
  1945             case WORDARRAY:
  1955 	    case SWORDARRAY:
  1946             case SWORDARRAY:
  1956 	    case LONGARRAY:
  1947             case LONGARRAY:
  1957 	    case SLONGARRAY:
  1948             case SLONGARRAY:
  1958 	    case FLOATARRAY:
  1949             case FLOATARRAY:
  1959 	    case DOUBLEARRAY:
  1950             case DOUBLEARRAY:
  1960 		break;
  1951                 break;
  1961 	    default:
  1952             default:
  1962 		goto bad;
  1953                 goto bad;
  1963 	}
  1954         }
  1964 
  1955 
  1965 	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  1956         nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  1966 	nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
  1957         nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
  1967 	objSize = _Size(aDataBuffer) - nInstBytes;
  1958         objSize = _Size(aDataBuffer) - nInstBytes;
  1968 	cp = (char *)__InstPtr(aDataBuffer) + nInstBytes;
  1959         cp = (char *)__InstPtr(aDataBuffer) + nInstBytes;
  1969 	if (__isSmallInteger(startIndex)) {
  1960         if (__isSmallInteger(startIndex)) {
  1970 	    cp += __intVal(startIndex);
  1961             cp += __intVal(startIndex);
  1971 	    objSize -= __intVal(startIndex);
  1962             objSize -= __intVal(startIndex);
  1972 	}
  1963         }
  1973 	if (__isSmallInteger(nBytes)) {
  1964         if (__isSmallInteger(nBytes)) {
  1974 	    if (__intVal(nBytes) < objSize) {
  1965             if (__intVal(nBytes) < objSize) {
  1975 		objSize = __intVal(nBytes);
  1966                 objSize = __intVal(nBytes);
  1976 	    }
  1967             }
  1977 	}
  1968         }
  1978 
  1969 
  1979 	__BEGIN_INTERRUPTABLE__
  1970         __BEGIN_INTERRUPTABLE__
  1980 	do {
  1971         do {
  1981 	    n = recv(sock, cp, objSize, flags);
  1972             n = recv(sock, cp, objSize, flags);
  1982 	} while ((n < 0) && (errno == EINTR));
  1973         } while ((n < 0) && (errno == EINTR));
  1983 	__END_INTERRUPTABLE__
  1974         __END_INTERRUPTABLE__
  1984 
  1975 
  1985 	if (n < 0) {
  1976         if (n < 0) {
  1986 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
  1977             __INST(lastErrorNumber) = __MKSMALLINT(errno);
  1987 	}
  1978         }
  1988 	nReceived = __MKSMALLINT(n);
  1979         nReceived = __MKSMALLINT(n);
  1989     }
  1980     }
  1990 #endif
  1981 #endif
  1991 bad: ;
  1982 bad: ;
  1992 %}.
  1983 %}.
  1993     nReceived notNil ifTrue:[
  1984     nReceived notNil ifTrue:[
  1994 	nReceived < 0 ifTrue:[
  1985         nReceived < 0 ifTrue:[
  1995 	    'Socket [warning]: ' infoPrint.
  1986             'Socket [warning]: ' infoPrint.
  1996 	    (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR.
  1987             (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR.
  1997 	].
  1988         ].
  1998 	^ nReceived
  1989         ^ nReceived
  1999     ].
  1990     ].
  2000     "
  1991     "
  2001      arrive here if you try to receive into an invalid buffer
  1992      arrive here if you try to receive into an invalid buffer (i.e. not ByteArray-like)
  2002      (i.e. not ByteArray-like), 
       
  2003      or if the addressBuffer is nonNil AND not a ByteArray/String 
       
  2004      or if the addressBuffer is nonNil AND too small.
       
  2005     "
  1993     "
  2006     self primitiveFailed
  1994     self primitiveFailed
  2007 !
  1995 !
  2008 
  1996 
  2009 receiveFrom:anAddressBuffer buffer:aDataBuffer
  1997 receiveFrom:anAddressBuffer buffer:aDataBuffer
  2017 
  2005 
  2018     ^ self receiveFrom:anAddressBuffer buffer:aDataBuffer start:1 for:(aDataBuffer size)
  2006     ^ self receiveFrom:anAddressBuffer buffer:aDataBuffer start:1 for:(aDataBuffer size)
  2019 !
  2007 !
  2020 
  2008 
  2021 receiveFrom:anAddressBuffer buffer:aDataBuffer start:startIndex for:nBytes
  2009 receiveFrom:anAddressBuffer buffer:aDataBuffer start:startIndex for:nBytes
  2022     "receive datagramm data - put address of originating host into
  2010     "receive datagramm data 
  2023      anAddressBuffer, data into aBuffer. For ST-80 compatibility,
  2011      - put address of originating host into anAddressBuffer, data into aBuffer. 
  2024      the addressBuffer may be a non-ByteArray; then, it must understand
  2012      For backward compatibility, the addressBuffer may be a non-SocketAddress; 
  2025      the addressBytes-message (i.e. be a SocketAddress instance).
  2013      then, it must be a byteArray with appropriate size for the addressBytes.
       
  2014 
  2026      Return the number of bytes received, or a negative number on error.
  2015      Return the number of bytes received, or a negative number on error.
  2027      On error, the unix error code is left in the lastErrorNumber
  2016      On error, the unix error code is left in the lastErrorNumber
  2028      instance variable.
  2017      instance variable.
  2029      The thread blocks until data arrives - you may want to wait before
  2018      The thread blocks until data arrives - you may want to wait before
  2030      receiving, using #readWait or #readWaitWithTimeout:."
  2019      receiving, using #readWait or #readWaitWithTimeout:."
  2031 
  2020 
  2032     |addrBytes addrLen nReceived addrPort|
  2021     |domainClass addr addrLen nReceived|
  2033 
  2022 
  2034     addrBytes := ByteArray new:100.
  2023     domainClass := self class socketAddressClassForDomain:domain.
       
  2024     domainClass isNil ifTrue:[
       
  2025         ^ self error:'invalid (unsupported) domain'.
       
  2026     ].
       
  2027     (anAddressBuffer isKindOf:SocketAddress) ifTrue:[
       
  2028         anAddressBuffer class == domainClass ifFalse:[
       
  2029             ^ self error:'addressBuffer class mismatch (domain)'.
       
  2030         ].
       
  2031         addr := anAddressBuffer.
       
  2032     ] ifFalse:[
       
  2033         anAddressBuffer notNil ifTrue:[
       
  2034             addr := domainClass new.
       
  2035         ].
       
  2036     ].
       
  2037 
  2035 %{
  2038 %{
  2036 #ifndef NO_SOCKET
  2039 #ifndef NO_SOCKET
  2037     OBJ oClass, myDomain;
  2040     OBJ oClass, myDomain;
  2038     OBJ fp = __INST(filePointer);
  2041     OBJ fp = __INST(filePointer);
  2039     int nInstVars, nInstBytes, objSize;
  2042     int nInstVars, nInstBytes, objSize;
  2043     int n, offs, sIdx;
  2046     int n, offs, sIdx;
  2044     char *cp;
  2047     char *cp;
  2045     int flags = 0;
  2048     int flags = 0;
  2046 
  2049 
  2047     if (fp != nil) {
  2050     if (fp != nil) {
  2048 	sock = fileno(__FILEVal(fp));
  2051         sock = fileno(__FILEVal(fp));
  2049 
  2052 
  2050 	oClass = __Class(aDataBuffer);
  2053         oClass = __Class(aDataBuffer);
  2051 	offs = 0;
  2054         offs = 0;
  2052 	sIdx = 0;
  2055         sIdx = 0;
  2053 	if (__isSmallInteger(startIndex)) {
  2056         if (__isSmallInteger(startIndex)) {
  2054 	    sIdx = __intVal(startIndex) - 1;
  2057             sIdx = __intVal(startIndex) - 1;
  2055 	}
  2058         }
  2056 	switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  2059         switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  2057 	    case BYTEARRAY:
  2060             case BYTEARRAY:
  2058 		offs = sIdx;
  2061                 offs = sIdx;
  2059 		break;
  2062                 break;
  2060 	    case WORDARRAY:
  2063             case WORDARRAY:
  2061 	    case SWORDARRAY:
  2064             case SWORDARRAY:
  2062 		offs = sIdx * 2;
  2065                 offs = sIdx * 2;
  2063 		break;
  2066                 break;
  2064 	    case LONGARRAY:
  2067             case LONGARRAY:
  2065 	    case SLONGARRAY:
  2068             case SLONGARRAY:
  2066 		offs = sIdx * 4;
  2069                 offs = sIdx * 4;
  2067 		break;
  2070                 break;
  2068 	    case LONGLONGARRAY:
  2071             case LONGLONGARRAY:
  2069 	    case SLONGLONGARRAY:
  2072             case SLONGLONGARRAY:
  2070 		offs = sIdx * 8;
  2073                 offs = sIdx * 8;
  2071 # ifdef __NEED_LONGLONG_ALIGN
  2074 # ifdef __NEED_LONGLONG_ALIGN
  2072 		offs += 4;
  2075                 offs += 4;
  2073 # endif
  2076 # endif
  2074 		break;
  2077                 break;
  2075 	    case FLOATARRAY:
  2078             case FLOATARRAY:
  2076 		offs = sIdx * sizeof(float);
  2079                 offs = sIdx * sizeof(float);
  2077 		break;
  2080                 break;
  2078 	    case DOUBLEARRAY:
  2081             case DOUBLEARRAY:
  2079 		offs = sIdx * sizeof(double);
  2082                 offs = sIdx * sizeof(double);
  2080 # ifdef __NEED_DOUBLE_ALIGN
  2083 # ifdef __NEED_DOUBLE_ALIGN
  2081 		offs += 4;
  2084                 offs += 4;
  2082 # endif
  2085 # endif
  2083 		break;
  2086                 break;
  2084 	    default:
  2087             default:
  2085 		goto bad;
  2088                 goto bad;
  2086 	}
  2089         }
  2087 
  2090 
  2088 	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  2091         nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  2089 	nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
  2092         nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
  2090 	objSize = _Size(aDataBuffer) - nInstBytes;
  2093         objSize = _Size(aDataBuffer) - nInstBytes;
  2091 	objSize -= offs;
  2094         objSize -= offs;
  2092 	if (__isSmallInteger(nBytes)) {
  2095         if (__isSmallInteger(nBytes)) {
  2093 	    if (__intVal(nBytes) < objSize) {
  2096             if (__intVal(nBytes) < objSize) {
  2094 		objSize = __intVal(nBytes);
  2097                 objSize = __intVal(nBytes);
  2095 	    }
  2098             }
  2096 	}
  2099         }
  2097 
  2100 
  2098 	__BEGIN_INTERRUPTABLE__
  2101         __BEGIN_INTERRUPTABLE__
  2099 	do {
  2102         do {
  2100 	    cp = (char *)__InstPtr(aDataBuffer) + nInstBytes + offs;
  2103             cp = (char *)__InstPtr(aDataBuffer) + nInstBytes + offs;
  2101 	    alen = sizeof(sa);
  2104             alen = sizeof(sa);
  2102 	    n = recvfrom(sock, cp, objSize, flags, (struct sockaddr *) &sa, &alen);
  2105             n = recvfrom(sock, cp, objSize, flags, (struct sockaddr *) &sa, &alen);
  2103 	} while ((n < 0) && (errno == EINTR));
  2106         } while ((n < 0) && (errno == EINTR));
  2104 	__END_INTERRUPTABLE__
  2107         __END_INTERRUPTABLE__
  2105 
  2108 
  2106 	if (n >= 0) {
  2109         if (n >= 0) {
  2107 	    if (__isNonNilObject(addrBytes)) {
  2110             if (__isNonNilObject(addr)) {
  2108 		oClass = __qClass(addrBytes);
  2111                 oClass = __qClass(addr);
  2109 		if ((__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) != BYTEARRAY) 
  2112                 if (! __isBytes(addr) ) 
  2110 		    goto bad;
  2113                     goto bad;
  2111 		nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  2114                 nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  2112 		nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
  2115                 nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
  2113 		objSize = __qSize(addrBytes) - nInstBytes;
  2116                 objSize = __qSize(addr) - nInstBytes;
  2114 		cp = (char *)__InstPtr(addrBytes) + nInstBytes;
  2117                 cp = (char *)__InstPtr(addr) + nInstBytes;
  2115 		if (objSize < alen) 
  2118                 if (objSize < alen) 
  2116 		    goto bad;
  2119                     goto bad;
  2117 
  2120                 
  2118 		myDomain = __INST(domain);
  2121                 /*
  2119 
  2122                  * extract the datagrams address
  2120 		/*
  2123                  */
  2121 		 * extract the datagrams address
  2124                 bcopy((char *)&sa, cp, alen);
  2122 		 */
  2125                 addrLen = __MKSMALLINT(alen);
  2123 		if (0) {
  2126             }
  2124 		    /* for else below */
  2127         }
  2125 		}
  2128         if (n < 0) {
  2126 # ifdef AF_INET
  2129             __INST(lastErrorNumber) = __MKSMALLINT(errno);
  2127 		else if (myDomain == @symbol(inet)) {
  2130         }
  2128 		    if (objSize < 4) 
  2131         nReceived = __MKSMALLINT(n);
  2129 			goto bad;
       
  2130 #  ifdef DGRAM_DEBUG
       
  2131 		    printf("alen: %d s_addr:%x\n", alen, sa.in.sin_addr.s_addr);
       
  2132 #  endif /* DGRAM_DEBUG */
       
  2133 		    addrPort = __MKSMALLINT( ntohs(sa.in.sin_port) );
       
  2134 		    sa.in.sin_addr.s_addr = ntohl(sa.in.sin_addr.s_addr);    
       
  2135 		    cp[0] = (sa.in.sin_addr.s_addr >> 24) & 0xFF;
       
  2136 		    cp[1] = (sa.in.sin_addr.s_addr >> 16) & 0xFF;
       
  2137 		    cp[2] = (sa.in.sin_addr.s_addr >> 8) & 0xFF;
       
  2138 		    cp[3] = (sa.in.sin_addr.s_addr >> 0) & 0xFF;
       
  2139 		    alen = 4;
       
  2140 #  ifdef DGRAM_DEBUG
       
  2141 		    printf("addr:%d.%d.%d.%d\n", cp[0], cp[1], cp[2], cp[3]);
       
  2142 #  endif /* DGRAM_DEBUG */
       
  2143 		}
       
  2144 # endif /* AF_INET */
       
  2145 
       
  2146 # ifdef AF_INET6
       
  2147 		else if (myDomain == @symbol(inet6)) {
       
  2148 		    if (objSize < sizeof(sa.in6.sin6_addr.s6_addr)) 
       
  2149 			goto bad;
       
  2150 		    bcopy(sa.in6.sin6_addr.s6_addr, cp, sizeof(sa.in6.sin6_addr.s6_addr));
       
  2151 		    alen = sizeof(sa.in6.sin6_addr.s6_addr);
       
  2152 		}
       
  2153 # endif /* AF_INET6 */
       
  2154 
       
  2155 # ifdef AF_APPLETALK
       
  2156 		else if (myDomain == @symbol(appletalk)) {
       
  2157 		    if (objSize < 3) 
       
  2158 			goto bad;
       
  2159 		    cp[0] = (sa.at.sat_addr.s_net >> 8) & 0xFF;
       
  2160 		    cp[1] = (sa.at.sat_addr.s_net) & 0xFF;
       
  2161 		    cp[2] = (sa.at.sat_addr.s_node) & 0xFF;
       
  2162 		    alen = 3;
       
  2163 		}
       
  2164 # endif /* AF_APPLETALK */
       
  2165 
       
  2166 		/*
       
  2167 		 * XXXX add addressing stuff for other domains here ...
       
  2168 		 */
       
  2169 # ifdef AF_X25
       
  2170 		else if (myDomain == @symbol(x25)) {
       
  2171 		}
       
  2172 # endif
       
  2173 
       
  2174 # ifdef AF_AX25
       
  2175 		else if (myDomain == @symbol(ax25)) {
       
  2176 		}
       
  2177 # endif
       
  2178 
       
  2179 # ifdef AF_NS
       
  2180 		else if ((myDomain == @symbol(ns)) 
       
  2181 		 || (myDomain == @symbol(xns))) {
       
  2182 		}
       
  2183 # endif
       
  2184 
       
  2185 # ifdef AF_SNA
       
  2186 		else if (myDomain == @symbol(sna)) {
       
  2187 		}
       
  2188 # endif
       
  2189 
       
  2190 # ifdef AF_RAW
       
  2191 		else if (myDomain == @symbol(raw)) {
       
  2192 		}
       
  2193 # endif
       
  2194 
       
  2195 # ifdef AF_ISO
       
  2196 		else if (myDomain == @symbol(iso)) {
       
  2197 		}
       
  2198 # endif
       
  2199 
       
  2200 # ifdef AF_DECnet
       
  2201 		else if (myDomain == @symbol(decnet)) {
       
  2202 		}
       
  2203 # endif
       
  2204 
       
  2205 # ifdef AF_NETBIOS
       
  2206 		else if (myDomain == @symbol(netbios)) {
       
  2207 		}
       
  2208 # endif
       
  2209 
       
  2210 # ifdef AF_IPX
       
  2211 		else if (myDomain == @symbol(ipx)) {
       
  2212 		}
       
  2213 # endif
       
  2214 
       
  2215 # ifdef AF_BRIDGE
       
  2216 		else if (myDomain == @symbol(bridge)) {
       
  2217 		}
       
  2218 # endif
       
  2219 
       
  2220 # ifdef AF_BSC
       
  2221 		else if (myDomain == @symbol(bsc)) {
       
  2222 		}
       
  2223 # endif
       
  2224 
       
  2225 # ifdef AF_ROSE
       
  2226 		else if (myDomain == @symbol(rose)) {
       
  2227 		}
       
  2228 # endif
       
  2229 
       
  2230 # ifdef AF_IRDA
       
  2231 		else if (myDomain == @symbol(irda)) {
       
  2232 		}
       
  2233 # endif
       
  2234 
       
  2235 # if defined(AF_CCITT) && (AF_CCITT != AF_X25)
       
  2236 		else if (myDomain == @symbol(ccitt)) {
       
  2237 		}
       
  2238 # endif
       
  2239 
       
  2240 		addrLen = __MKSMALLINT(alen);
       
  2241 	    }
       
  2242 	}
       
  2243 	if (n < 0) {
       
  2244 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2245 	}
       
  2246 	nReceived = __MKSMALLINT(n);
       
  2247     }
  2132     }
  2248 #endif
  2133 #endif
  2249 bad: ;
  2134 bad: ;
  2250 %}.
  2135 %}.
  2251     nReceived notNil ifTrue:[
  2136     nReceived notNil ifTrue:[
  2252 	nReceived < 0 ifTrue:[
  2137         nReceived < 0 ifTrue:[
  2253 	    'Socket [warning]: ' infoPrint.
  2138             'Socket [warning]: ' infoPrint.
  2254 	    (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR.
  2139             (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR.
  2255 	].
  2140         ].
  2256 	addrLen notNil ifTrue:[
  2141         addrLen notNil ifTrue:[
  2257 	   (anAddressBuffer isKindOf:SocketAddress) ifFalse:[
  2142             (addr == anAddressBuffer) ifFalse:[
  2258 		"/ can be a ByteArray for ST/X compatibility
  2143                 self obsoleteFeatureWarning:'please use a socketAddress argument'.
  2259 		anAddressBuffer replaceFrom:1 to:addrLen with:addrBytes
  2144 
  2260 		domain == #inet ifTrue:[
  2145                 "/ can be a ByteArray for backward compatibility
  2261 		    addrBytes := anAddressBuffer copyFrom:1 to:4.
  2146                 anAddressBuffer replaceFrom:1 to:addrLen with:(addr hostAddress).
  2262 		    anAddressBuffer at:5 put:(addrPort digitByteAt:2).
  2147             ].
  2263 		    anAddressBuffer at:6 put:(addrPort digitByteAt:1).
  2148         ].
  2264 		] ifFalse:[
  2149         ^ nReceived
  2265 		    domain == #appletalk ifTrue:[
       
  2266 			addrBytes := anAddressBuffer copyFrom:1 to:3.
       
  2267 			anAddressBuffer at:4 put:(addrPort digitByteAt:2).
       
  2268 			anAddressBuffer at:5 put:(addrPort digitByteAt:1).
       
  2269 		    ] ifFalse:[
       
  2270 			self error:'please use a SocketAddress'
       
  2271 		    ]
       
  2272 		]
       
  2273 	    ] ifTrue:[
       
  2274 		"/ can be a SocketAddress for ST-80 compatibility
       
  2275 		anAddressBuffer hostAddress:(addrBytes copyTo:addrLen) port:addrPort.
       
  2276 	    ].
       
  2277 	].
       
  2278 	^ nReceived
       
  2279     ].
  2150     ].
  2280     "
  2151     "
  2281      arrive here if you try to receive into an invalid buffer
  2152      arrive here if you try to receive into an invalid buffer
  2282      (i.e. not ByteArray-like), 
  2153      (i.e. not ByteArray-like), 
  2283      or if the addressBuffer is nonNil AND not a ByteArray/String 
  2154      or if the addressBuffer is nonNil AND not a SocketAddress/ByteArray 
  2284      or if the addressBuffer is nonNil AND too small.
  2155      or if the addressBuffer is nonNil AND too small.
  2285     "
  2156     "
  2286     self primitiveFailed
  2157     self primitiveFailed
  2287 !
  2158 !
  2288 
  2159 
  2311     _flags = __longIntVal(flags);
  2182     _flags = __longIntVal(flags);
  2312  
  2183  
  2313     if ((fp != nil) 
  2184     if ((fp != nil) 
  2314      && __isSmallInteger(startIndex)
  2185      && __isSmallInteger(startIndex)
  2315      && __isSmallInteger(count)) {
  2186      && __isSmallInteger(count)) {
  2316 	sock = fileno(__FILEVal(fp));
  2187         sock = fileno(__FILEVal(fp));
  2317 
  2188 
  2318 	oClass = __Class(aDataBuffer);
  2189         oClass = __Class(aDataBuffer);
  2319 	sIdx = __intVal(startIndex) - 1;
  2190         sIdx = __intVal(startIndex) - 1;
  2320 	switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  2191         switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  2321 	    case BYTEARRAY:
  2192             case BYTEARRAY:
  2322 		offs = sIdx;
  2193                 offs = sIdx;
  2323 		break;
  2194                 break;
  2324 	    case WORDARRAY:
  2195             case WORDARRAY:
  2325 	    case SWORDARRAY:
  2196             case SWORDARRAY:
  2326 		offs = sIdx * 2;
  2197                 offs = sIdx * 2;
  2327 		break;
  2198                 break;
  2328 	    case LONGARRAY:
  2199             case LONGARRAY:
  2329 	    case SLONGARRAY:
  2200             case SLONGARRAY:
  2330 		offs = sIdx * 4;
  2201                 offs = sIdx * 4;
  2331 		break;
  2202                 break;
  2332 	    case LONGLONGARRAY:
  2203             case LONGLONGARRAY:
  2333 	    case SLONGLONGARRAY:
  2204             case SLONGLONGARRAY:
  2334 		offs = sIdx * 8;
  2205                 offs = sIdx * 8;
  2335 # ifdef __NEED_LONGLONG_ALIGN
  2206 # ifdef __NEED_LONGLONG_ALIGN
  2336 		offs += 4;
  2207                 offs += 4;
  2337 # endif
  2208 # endif
  2338 		break;
  2209                 break;
  2339 	    case FLOATARRAY:
  2210             case FLOATARRAY:
  2340 		offs = sIdx * sizeof(float);
  2211                 offs = sIdx * sizeof(float);
  2341 		break;
  2212                 break;
  2342 	    case DOUBLEARRAY:
  2213             case DOUBLEARRAY:
  2343 		offs = sIdx * sizeof(double);
  2214                 offs = sIdx * sizeof(double);
  2344 # ifdef __NEED_DOUBLE_ALIGN
  2215 # ifdef __NEED_DOUBLE_ALIGN
  2345 		offs += 4;
  2216                 offs += 4;
  2346 # endif
  2217 # endif
  2347 		break;
  2218                 break;
  2348 	    default:
  2219             default:
  2349 		goto bad;
  2220                 goto bad;
  2350 	}
  2221         }
  2351 	nBytes = __intVal(count);
  2222         nBytes = __intVal(count);
  2352 
  2223 
  2353 	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  2224         nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  2354 	nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
  2225         nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
  2355 	objSize = __qSize(aDataBuffer) - nInstBytes;
  2226         objSize = __qSize(aDataBuffer) - nInstBytes;
  2356 	cp = (char *)__InstPtr(aDataBuffer) + nInstBytes;
  2227         cp = (char *)__InstPtr(aDataBuffer) + nInstBytes;
  2357 	cp += offs;
  2228         cp += offs;
  2358 	if ((offs + nBytes) > objSize) {
  2229         if ((offs + nBytes) > objSize) {
  2359 # ifdef DGRAM_DEBUG
  2230 # ifdef DGRAM_DEBUG
  2360 	    printf("cut off ...\n");
  2231             printf("cut off ...\n");
  2361 # endif
  2232 # endif
  2362 	    nBytes = objSize - offs;
  2233             nBytes = objSize - offs;
  2363 	}
  2234         }
  2364 
  2235 
  2365 # ifdef DGRAM_DEBUG
  2236 # ifdef DGRAM_DEBUG
  2366 	printf("sending %d bytes ...\n", nBytes);
  2237         printf("sending %d bytes ...\n", nBytes);
  2367 # endif
  2238 # endif
  2368 
  2239 
  2369 	__BEGIN_INTERRUPTABLE__
  2240         __BEGIN_INTERRUPTABLE__
  2370 	do {
  2241         do {
  2371 	    n = send(sock, cp, nBytes, _flags);
  2242             n = send(sock, cp, nBytes, _flags);
  2372 	} while ((n < 0) && (errno == EINTR));
  2243         } while ((n < 0) && (errno == EINTR));
  2373 	__END_INTERRUPTABLE__
  2244         __END_INTERRUPTABLE__
  2374 
  2245 
  2375 	if (n < 0) {
  2246         if (n < 0) {
  2376 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
  2247             __INST(lastErrorNumber) = __MKSMALLINT(errno);
  2377 	}
  2248         }
  2378 	RETURN (__MKSMALLINT(n));
  2249         RETURN (__MKSMALLINT(n));
  2379     }
  2250     }
  2380 #endif
  2251 #endif
  2381 bad: ;
  2252 bad: ;
  2382 %}.
  2253 %}.
  2383     "
  2254     "
  2384      arrive here if you try to send from an invalid buffer
  2255      arrive here if you try to send from an invalid buffer (i.e. not ByteArray-like), 
  2385      (i.e. not ByteArray-like), 
       
  2386      or if the addressBuffer is nonNil AND not a ByteArray/String 
       
  2387      or if the addressBuffer is nonNil AND too small.
       
  2388     "
  2256     "
  2389     self primitiveFailed
  2257     self primitiveFailed
  2390 !
  2258 !
  2391 
  2259 
  2392 sendTo:anAddressBuffer buffer:buffer
  2260 sendTo:anAddressBuffer buffer:buffer
  2423      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
  2291      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
  2424      Return the number of bytes transmitted, or a negative number on error.
  2292      Return the number of bytes transmitted, or a negative number on error.
  2425      On error, the unix error code is left in the lastErrorNumber
  2293      On error, the unix error code is left in the lastErrorNumber
  2426      instance variable."
  2294      instance variable."
  2427 
  2295 
  2428     |addrBytes addrLen nReceived portNo|
  2296     |domainClass addr|
  2429 
  2297 
  2430     "/ addressBuffer can be a byteArray (last 2 bytes are portNo, msb-first)
  2298     domainClass := self class socketAddressClassForDomain:domain.
  2431     "/ or (better) an instance of SocketAddress
  2299     domainClass isNil ifTrue:[
  2432     "/
  2300         ^ self error:'invalid (unsupported) domain'.
  2433     (anAddressBuffer isKindOf:SocketAddress) ifFalse:[
  2301     ].
  2434 	domain == #inet ifTrue:[
  2302 
  2435 	    addrBytes := anAddressBuffer copyFrom:1 to:4.
  2303     (anAddressBuffer isKindOf:SocketAddress) ifTrue:[
  2436 	    portNo := ((anAddressBuffer at:5) bitShift:8)
  2304         addr := anAddressBuffer.
  2437 		      + (anAddressBuffer at:6).
  2305     ] ifFalse:[
  2438 	] ifFalse:[
  2306         anAddressBuffer isByteArray ifFalse:[
  2439 	    domain == #appletalk ifTrue:[
  2307             ^ self error:'bad socketAddress argument'
  2440 		addrBytes := anAddressBuffer copyFrom:1 to:3.
  2308         ].
  2441 		portNo := ((anAddressBuffer at:5) bitShift:8)
  2309         addr := domainClass hostAddress:anAddressBuffer.
  2442 			  + (anAddressBuffer at:6).
       
  2443 	    ] ifFalse:[
       
  2444 		self error:'please use a SocketAddress'
       
  2445 	    ]
       
  2446 	].
       
  2447     ] ifTrue:[
       
  2448 	addrBytes := anAddressBuffer hostAddress.
       
  2449 	portNo := anAddressBuffer port.
       
  2450     ].
  2310     ].
  2451 %{
  2311 %{
  2452 #ifndef NO_SOCKET
  2312 #ifndef NO_SOCKET
  2453     OBJ oClass;
  2313     OBJ oClass;
  2454     OBJ fp = __INST(filePointer);
  2314     OBJ fp = __INST(filePointer);
  2455     int nInstVars, nInstBytes, objSize;
  2315     int nInstVars, nInstBytes, objSize;
       
  2316     struct sockaddr *sockaddr_ptr;
       
  2317     int sockAddrOffs, sockaddr_size;    
  2456     int sock;
  2318     int sock;
  2457     union sockaddr_u sa;
       
  2458     struct sockaddr *saPtr = (struct sockaddr *)&sa;
       
  2459     int alen = sizeof(sa);
       
  2460     int n;
  2319     int n;
  2461     char *cp;
  2320     char *cp;
  2462     int _flags = 0;
  2321     int _flags = 0;
  2463     int offs, nBytes;
  2322     int offs, nBytes;
  2464     unsigned long norder;
  2323     unsigned long norder;
  2466     _flags = __longIntVal(flags);
  2325     _flags = __longIntVal(flags);
  2467  
  2326  
  2468     if ((fp != nil) 
  2327     if ((fp != nil) 
  2469      && __isSmallInteger(startIndex)
  2328      && __isSmallInteger(startIndex)
  2470      && __isSmallInteger(count)) {
  2329      && __isSmallInteger(count)) {
  2471 	sock = fileno(__FILEVal(fp));
  2330         sock = fileno(__FILEVal(fp));
  2472 
  2331 
  2473 	if (addrBytes == nil) {
  2332         if (! __isBytes(addr)) {
  2474 	    alen = 0;
  2333             sockaddr_size = 0;
  2475 	    saPtr = (struct sockaddr *)0;
  2334             sockaddr_ptr = (struct sockaddr *)0;
  2476 	} else {
  2335         } else {
  2477 	    if (! __isByteArray(addrBytes)) goto bad;
  2336             int nIndex;
  2478 
  2337             OBJ cls;
  2479 	    cp = (char *)__ByteArrayInstPtr(addrBytes)->ba_element;
  2338 
  2480 	    n = __byteArraySize(addrBytes);
  2339             sockAddrOffs = 0;
  2481 	    if (alen < n) n = alen;
  2340             if ((cls = __qClass(addr)) != @global(ByteArray))
       
  2341                 sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
       
  2342             nIndex = __qSize(addr) - OHDR_SIZE;
       
  2343             sockaddr_size = nIndex - sockAddrOffs;
       
  2344             sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + sockAddrOffs);
       
  2345         }
       
  2346 
       
  2347         oClass = __Class(aDataBuffer);
       
  2348         switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
       
  2349             case BYTEARRAY:
       
  2350                 offs = __intVal(startIndex) - 1;
       
  2351                 break;
       
  2352             case WORDARRAY:
       
  2353             case SWORDARRAY:
       
  2354                 offs = (__intVal(startIndex) - 1) * 2;
       
  2355                 break;
       
  2356             case LONGARRAY:
       
  2357             case SLONGARRAY:
       
  2358                 offs = (__intVal(startIndex) - 1) * 4;
       
  2359                 break;
       
  2360             case LONGLONGARRAY:
       
  2361             case SLONGLONGARRAY:
       
  2362                 offs = (__intVal(startIndex) - 1) * 8;
       
  2363 # ifdef __NEED_LONGLONG_ALIGN
       
  2364                 offs += 4;
       
  2365 # endif
       
  2366                 break;
       
  2367             case FLOATARRAY:
       
  2368                 offs = (__intVal(startIndex) - 1) * sizeof(float);
       
  2369                 break;
       
  2370             case DOUBLEARRAY:
       
  2371                 offs = (__intVal(startIndex) - 1) * sizeof(double);
       
  2372 # ifdef __NEED_DOUBLE_ALIGN
       
  2373                 offs += 4;
       
  2374 # endif
       
  2375                 break;
       
  2376             default:
       
  2377                 goto bad;
       
  2378         }
       
  2379         nBytes = __intVal(count);
       
  2380 
       
  2381         nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
       
  2382         nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
       
  2383         objSize = __qSize(aDataBuffer) - nInstBytes;
       
  2384         if ((offs + nBytes) > objSize) {
  2482 # ifdef DGRAM_DEBUG
  2385 # ifdef DGRAM_DEBUG
  2483 	    printf("address is %d bytes ... %d.%d.%d.%d\n", n, cp[0], cp[1], cp[2], cp[3]);
  2386             printf("cut off ...\n");
  2484 # endif
  2387 # endif
  2485 	    bcopy(cp, &sa.in.sin_addr.s_addr, n);
  2388             nBytes = objSize - offs;
  2486 
  2389         }
  2487 	    if (0) {
  2390 
  2488 		/* for else below */
  2391         __BEGIN_INTERRUPTABLE__
  2489 	    }
  2392         do {
  2490 # ifdef AF_INET
  2393             sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + sockAddrOffs);
  2491 	    else if (__INST(domain) == @symbol(inet)) {
  2394             cp = (char *)__InstPtr(aDataBuffer) + nInstBytes + offs;
  2492 		sa.in.sin_family = AF_INET;
  2395             n = sendto(sock, cp, nBytes, _flags, sockaddr_ptr, sockaddr_size);
  2493 		sa.in.sin_port = htons((u_short) __intVal(portNo)); 
  2396         } while ((n < 0) && (errno == EINTR));
  2494 	    }
  2397         __END_INTERRUPTABLE__
  2495 # endif
  2398 
  2496 # ifdef AF_INET6
  2399         if (n < 0) {
  2497 	    else if (__INST(domain) == @symbol(inet6)) {
  2400             __INST(lastErrorNumber) = __MKSMALLINT(errno);
  2498 		sa.in6.sin6_family = AF_INET6;
  2401         }
  2499 		sa.in6.sin6_port = htons((u_short) __intVal(portNo)); 
  2402         RETURN (__MKSMALLINT(n));
  2500 	    }
       
  2501 # endif
       
  2502 # ifdef AF_APPLETALK
       
  2503 	    else if (__INST(domain) == @symbol(appletalk)) {
       
  2504 		sa.at.sat_family = AF_APPLETALK;
       
  2505 		sa.at.sat_port = __intVal(portNo);
       
  2506 	    }
       
  2507 # endif
       
  2508 # ifdef AF_IRDA
       
  2509 	    else if (__INST(domain) == @symbol(irda)) {
       
  2510 	    }
       
  2511 # endif
       
  2512 	}
       
  2513 
       
  2514 	oClass = __Class(aDataBuffer);
       
  2515 	switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
       
  2516 	    case BYTEARRAY:
       
  2517 		offs = __intVal(startIndex) - 1;
       
  2518 		break;
       
  2519 	    case WORDARRAY:
       
  2520 	    case SWORDARRAY:
       
  2521 		offs = (__intVal(startIndex) - 1) * 2;
       
  2522 		break;
       
  2523 	    case LONGARRAY:
       
  2524 	    case SLONGARRAY:
       
  2525 		offs = (__intVal(startIndex) - 1) * 4;
       
  2526 		break;
       
  2527 	    case LONGLONGARRAY:
       
  2528 	    case SLONGLONGARRAY:
       
  2529 		offs = (__intVal(startIndex) - 1) * 8;
       
  2530 # ifdef __NEED_LONGLONG_ALIGN
       
  2531 		offs += 4;
       
  2532 # endif
       
  2533 		break;
       
  2534 	    case FLOATARRAY:
       
  2535 		offs = (__intVal(startIndex) - 1) * sizeof(float);
       
  2536 		break;
       
  2537 	    case DOUBLEARRAY:
       
  2538 		offs = (__intVal(startIndex) - 1) * sizeof(double);
       
  2539 # ifdef __NEED_DOUBLE_ALIGN
       
  2540 		offs += 4;
       
  2541 # endif
       
  2542 		break;
       
  2543 	    default:
       
  2544 		goto bad;
       
  2545 	}
       
  2546 	nBytes = __intVal(count);
       
  2547 
       
  2548 	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
       
  2549 	nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
       
  2550 	objSize = __qSize(aDataBuffer) - nInstBytes;
       
  2551 	if ((offs + nBytes) > objSize) {
       
  2552 # ifdef DGRAM_DEBUG
       
  2553 	    printf("cut off ...\n");
       
  2554 # endif
       
  2555 	    nBytes = objSize - offs;
       
  2556 	}
       
  2557 
       
  2558 	norder = htonl(sa.in.sin_addr.s_addr);
       
  2559 # ifdef DGRAM_DEBUG
       
  2560 	printf("sending %d bytes ... to ", nBytes);
       
  2561 	printf("%d.%d.%d.%d\n",
       
  2562 		    (norder >> 24) & 0xFF,
       
  2563 		    (norder >> 16) & 0xFF,
       
  2564 		    (norder >> 8) & 0xFF,
       
  2565 		    norder & 0xFF);
       
  2566 # endif
       
  2567 
       
  2568 	__BEGIN_INTERRUPTABLE__
       
  2569 	do {
       
  2570 	    cp = (char *)__InstPtr(aDataBuffer) + nInstBytes + offs;
       
  2571 	    n = sendto(sock, cp, nBytes, _flags, saPtr, alen);
       
  2572 	} while ((n < 0) && (errno == EINTR));
       
  2573 	__END_INTERRUPTABLE__
       
  2574 
       
  2575 	if (n < 0) {
       
  2576 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2577 	}
       
  2578 	RETURN (__MKSMALLINT(n));
       
  2579     }
  2403     }
  2580 #endif
  2404 #endif
  2581 bad: ;
  2405 bad: ;
  2582 %}.
  2406 %}.
  2583     "
  2407     "
  2630 	bindTo:portNrOrNameString 
  2454 	bindTo:portNrOrNameString 
  2631 	address:addressString 
  2455 	address:addressString 
  2632 	reuseAddress:true
  2456 	reuseAddress:true
  2633 !
  2457 !
  2634 
  2458 
  2635 bindTo:portNrOrName address:address reuseAddress:reuse
  2459 bindTo:portNrOrNameOrNil address:hostOrPathNameOrSocketAddrOrNil reuseAddress:reuse
  2636     "low level bind - returns true if ok, false otherwise.
  2460     "low level bind - returns true if ok, false otherwise.
  2637      Currently only non-address binding is supported; 
  2461      Currently only non-address binding is supported; 
  2638      i.e. address must always be nil.
  2462      i.e. address must always be nil.
  2639 
  2463 
  2640      The interpretation of portNrOrName depends on the domain:
  2464      The interpretation of portNrOrName depends on the domain:
  2641 	inet domain uses (4byte) byteArray like internet numbers,
  2465         inet domain uses (4byte) byteArray like internet numbers,
  2642 	unix domain uses pathname strings,
  2466         unix domain uses pathname strings,
  2643 	others use whatever will come up in the future
  2467         others use whatever will come up in the future
  2644 
  2468 
  2645      The reuse boolean argument controls if the SO_REUSEADDR socket option
  2469      The reuse boolean argument controls if the SO_REUSEADDR socket option
  2646      is to be set (to avoid the 'bind: address in use' error).
  2470      is to be set (to avoid the 'bind: address in use' error).
  2647     "
  2471     "
  2648 
  2472 
       
  2473     |ok addr addrName domainClass|
       
  2474 
  2649     filePointer isNil ifTrue:[
  2475     filePointer isNil ifTrue:[
  2650 	^ self errorNotOpen
  2476         ^ self errorNotOpen
  2651     ].
  2477     ].
       
  2478 
       
  2479     domainClass := self class socketAddressClassForDomain:domain.
       
  2480     domainClass isNil ifTrue:[
       
  2481         ^ self error:'invalid (unsupported) domain'.
       
  2482     ].
       
  2483 
       
  2484     "/ backward compatibility: support for byteArray and string arg
       
  2485 
       
  2486     hostOrPathNameOrSocketAddrOrNil isNil ifTrue:[
       
  2487         addr := domainClass anyHost.
       
  2488     ] ifFalse:[
       
  2489         hostOrPathNameOrSocketAddrOrNil isString ifTrue:[
       
  2490             addr := domainClass hostName:hostOrPathNameOrSocketAddrOrNil.
       
  2491             addrName := hostOrPathNameOrSocketAddrOrNil.
       
  2492         ] ifFalse:[
       
  2493             (hostOrPathNameOrSocketAddrOrNil isKindOf:SocketAddress) ifTrue:[
       
  2494                 addr := hostOrPathNameOrSocketAddrOrNil.
       
  2495                 portNrOrNameOrNil notNil ifTrue:[
       
  2496                     addr port:portNrOrNameOrNil.
       
  2497                 ].
       
  2498             ] ifFalse:[
       
  2499                 hostOrPathNameOrSocketAddrOrNil isByteArray ifFalse:[
       
  2500                     ^ self error:'bad host (socketAddress) argument'
       
  2501                 ].
       
  2502                 addr := domainClass hostAddress:hostOrPathNameOrSocketAddrOrNil.
       
  2503             ].
       
  2504         ].
       
  2505     ].
       
  2506     portNrOrNameOrNil notNil ifTrue:[
       
  2507         addr port:portNrOrNameOrNil.
       
  2508     ].
       
  2509 
  2652 %{  /* STACK: 100000 */
  2510 %{  /* STACK: 100000 */
  2653 #ifndef NO_SOCKET
  2511 #ifndef NO_SOCKET
  2654     OBJ t = __INST(filePointer);
  2512     OBJ t = __INST(filePointer);
  2655     OBJ myDomain;
  2513     OBJ myDomain;
  2656     int sock;
  2514     int sock;
  2657     union sockaddr_u sa;
  2515     union sockaddr_u sa;
  2658     int sockaddr_size;
  2516     struct sockaddr *sockaddr_ptr;
       
  2517     int sockaddr_size;    
  2659     int ret;
  2518     int ret;
  2660     int on = 1;
  2519     int on = 1;
  2661     int ok;
  2520     int sockAddrOffs;
  2662 
  2521 
  2663     if (!__isString(__INST(domain)) && !__isSymbol(__INST(domain))) {
  2522     if (! __isBytes(addr)) {
  2664 	DBGPRINTF(("SOCKET: invalid domain arg\n"));
  2523         addr = nil;
  2665 	RETURN (false);
  2524         goto getOutOfHere;
  2666     }
  2525     }
  2667 
  2526 
  2668     ok = 0;
  2527     {
  2669     myDomain = __INST(domain);
  2528         int nIndex;
  2670 
  2529         OBJ cls;
  2671     if (0) {
  2530 
  2672 	/* for else below */
  2531         sockAddrOffs = 0;
  2673     }
  2532         if ((cls = __qClass(addr)) != @global(ByteArray))
  2674 
  2533             sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
  2675 # ifdef AF_INET
  2534         nIndex = __qSize(addr) - OHDR_SIZE;
  2676     else if (myDomain == @symbol(inet)) {
  2535         sockaddr_size = nIndex - sockAddrOffs;
  2677 	/*
  2536         sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + sockAddrOffs);
  2678 	 * INET addresses - port must be a smallinteger or nil
       
  2679 	 */
       
  2680 	sa.in.sin_family = AF_INET;
       
  2681 
       
  2682 	if (portNrOrName == nil) {
       
  2683 	    sa.in.sin_port = 0;
       
  2684 	} else {
       
  2685 	    if (! __isSmallInteger(portNrOrName)) {
       
  2686 		DBGPRINTF(("SOCKET: invalid port arg\n"));
       
  2687 		RETURN (false);
       
  2688 	    }
       
  2689 	    sa.in.sin_port = htons((u_short) __intVal(portNrOrName));
       
  2690 	}
       
  2691 
       
  2692 	/*
       
  2693 	 * INET addresses - addr must be nil, integer or byteArray
       
  2694 	 */
       
  2695 	if (address == nil) {
       
  2696 	    sa.in.sin_addr.s_addr = htonl(INADDR_ANY);
       
  2697 	} else {
       
  2698 	    if (__isInteger(address)) {
       
  2699 		sa.in.sin_addr.s_addr = htonl(__longIntVal(address));
       
  2700 	    } else {
       
  2701 		if (__isByteArray(address)) {
       
  2702 		    unsigned char *cp;
       
  2703 		    int n;
       
  2704 
       
  2705 		    cp = __ByteArrayInstPtr(address)->ba_element;
       
  2706 		    n = __byteArraySize(address);
       
  2707 		    if (n > 4) n = 4;
       
  2708 		    bcopy(cp, &sa.in.sin_addr.s_addr, n);
       
  2709 		} else {
       
  2710 		    unsigned addr;
       
  2711 		    struct hostent *hp ;
       
  2712 
       
  2713 		    if (! __isString(address)) {
       
  2714 			DBGPRINTF(("SOCKET: invalid address arg in bind\n"));
       
  2715 			RETURN (false);
       
  2716 		    }
       
  2717 
       
  2718 		    if ((addr = inet_addr(__stringVal(address))) != -1) {
       
  2719 			/* 
       
  2720 			 * is Internet addr in octet notation 
       
  2721 			 */
       
  2722 			bcopy(&addr, (char *) &sa.in.sin_addr, sizeof(addr)) ; /* set address */
       
  2723 		    } else {
       
  2724 			/* 
       
  2725 			 * do we know the host's address? 
       
  2726 			 */
       
  2727 			GETHOSTBYNAME(hp, __stringVal(address))
       
  2728 			if (hp == NULL) {
       
  2729 			    DBGPRINTF(("SOCKET: unknown host:%s\n", __stringVal(address)));
       
  2730 			    RETURN (false);
       
  2731 			}
       
  2732 			if (hp->h_addrtype != AF_INET) {
       
  2733 			    DBGPRINTF(("SOCKET: host:%s is not an inet host\n", __stringVal(address)));
       
  2734 			    RETURN (false);
       
  2735 			}
       
  2736 			bcopy(hp->h_addr, (char *) &sa.in.sin_addr, hp->h_length) ;
       
  2737 			sa.in.sin_family = hp->h_addrtype;
       
  2738 		    }
       
  2739 		}
       
  2740 	    }
       
  2741 	}
       
  2742 	DBGPRINTF(("SOCKET: bind addr: %x port: %x\n", sa.in.sin_addr.s_addr, sa.in.sin_port));
       
  2743 	sockaddr_size = sizeof(struct sockaddr_in);
       
  2744 	ok = 1;
       
  2745     }
       
  2746 # endif /* AF_INET */
       
  2747 
       
  2748 # ifdef AF_INET6
       
  2749     else if (myDomain == @symbol(inet6)) {
       
  2750 	/*
       
  2751 	 * INET6 addresses - port must be a smallinteger or nil
       
  2752 	 */
       
  2753 	sa.in6.sin6_family = AF_INET6;
       
  2754 
       
  2755 	if (portNrOrName == nil) {
       
  2756 	    sa.in6.sin6_port = 0;
       
  2757 	} else {
       
  2758 	    if (! __isSmallInteger(portNrOrName)) {
       
  2759 		DBGPRINTF(("SOCKET: invalid port arg\n"));
       
  2760 		RETURN (false);
       
  2761 	    }
       
  2762 	    sa.in6.sin6_port = htons((u_short) __intVal(portNrOrName));
       
  2763 	}
       
  2764 
       
  2765 	/*
       
  2766 	 * INET6 addresses - addr must be nil or byteArray or string
       
  2767 	 */
       
  2768 	if (address == nil) {
       
  2769 	    bzero(sa.in6.sin6_addr.s6_addr, sizeof(sa.in6.sin6_addr.s6_addr));
       
  2770 	} else {
       
  2771 	    if (__isByteArray(address)) {
       
  2772 		unsigned char *cp;
       
  2773 		int n;
       
  2774 
       
  2775 		cp = __ByteArrayInstPtr(address)->ba_element;
       
  2776 		n = __byteArraySize(address);
       
  2777 		if (n > sizeof(sa.in6.sin6_addr.s6_addr)) n = sizeof(sa.in6.sin6_addr.s6_addr);
       
  2778 		bcopy(cp, sa.in6.sin6_addr.s6_addr, n);
       
  2779 	    } else {
       
  2780 		unsigned addr;
       
  2781 		struct hostent *hp ;
       
  2782 
       
  2783 		if (! __isString(address)) {
       
  2784 		    DBGPRINTF(("SOCKET: invalid address arg in bind\n"));
       
  2785 		    RETURN (false);
       
  2786 		}
       
  2787 
       
  2788 		/* 
       
  2789 		 * do we know the host's address? 
       
  2790 		 */
       
  2791 		GETHOSTBYNAME(hp, __stringVal(address))
       
  2792 		if (hp == NULL) {
       
  2793 		    DBGPRINTF(("SOCKET: unknown host:%s\n", __stringVal(address)));
       
  2794 		    RETURN (false);
       
  2795 		}
       
  2796 		if (hp->h_addrtype != AF_INET6) {
       
  2797 		    DBGPRINTF(("SOCKET: host:%s is not an ipv6 host\n", __stringVal(address)));
       
  2798 		    RETURN (false);
       
  2799 		}
       
  2800 		bcopy(hp->h_addr, (char *) &sa.in6.sin6_addr, hp->h_length) ;
       
  2801 		sa.in.sin_family = hp->h_addrtype;
       
  2802 	    }
       
  2803 	}
       
  2804 
       
  2805 	DBGPRINTF(("SOCKET: bind addr: %x.%x.%x.%x.%x.%x... port: %x\n", 
       
  2806 			sa.in6.sin6_addr.s6_addr[0], 
       
  2807 			sa.in6.sin6_addr.s6_addr[1], 
       
  2808 			sa.in6.sin6_addr.s6_addr[2], 
       
  2809 			sa.in6.sin6_addr.s6_addr[3], 
       
  2810 			sa.in6.sin6_addr.s6_addr[4], 
       
  2811 			sa.in6.sin6_addr.s6_addr[5], 
       
  2812 			sa.in6.sin6_port));
       
  2813 	sockaddr_size = sizeof(struct sockaddr_in6);
       
  2814 	ok = 1;
       
  2815     }
       
  2816 # endif /* AF_INET6 */
       
  2817 
       
  2818 # ifdef AF_UNIX
       
  2819     /*
       
  2820      * UNIX domain - port is ignored; address must be a string (path)
       
  2821      */
       
  2822     else if (myDomain == @symbol(unix)) {
       
  2823 	char *pathName;
       
  2824 	int l;
       
  2825 
       
  2826 	if (! __isString(portNrOrName)) {
       
  2827 	    DBGPRINTF(("SOCKET: invalid port (pathname) arg\n"));
       
  2828 	    RETURN (false);
       
  2829 	}
       
  2830 	pathName = (char *)__stringVal(portNrOrName);
       
  2831 	l = strlen(pathName);
       
  2832 	if ((l + sizeof ( sa.un.sun_family )) > sizeof(struct sockaddr_un)) {
       
  2833 	    DBGPRINTF(("SOCKET: pathname too long\n"));
       
  2834 	    RETURN (false);
       
  2835 	}
       
  2836 
       
  2837 	strcpy(sa.un.sun_path, pathName);
       
  2838 	sa.un.sun_family = AF_UNIX;
       
  2839 	sockaddr_size = l + sizeof ( sa.un.sun_family );
       
  2840 	ok = 1;
       
  2841     }
       
  2842 # endif /* AF_UNIX */
       
  2843 
       
  2844 # ifdef AF_APPLETALK
       
  2845     /*
       
  2846      * this has never been tested ....
       
  2847      */
       
  2848     else if (myDomain == @symbol(appletalk)) {
       
  2849 	/*
       
  2850 	 * APPLETALK addresses - port must be a smallinteger or nil
       
  2851 	 */
       
  2852 	sa.at.sat_family = AF_APPLETALK;
       
  2853 
       
  2854 	if (portNrOrName == nil) {
       
  2855 	    sa.at.sat_port = 0;
       
  2856 	} else {
       
  2857 	    if (! __isSmallInteger(portNrOrName)) {
       
  2858 		DBGPRINTF(("SOCKET: invalid port arg\n"));
       
  2859 		RETURN (false);
       
  2860 	    }
       
  2861 	    sa.at.sat_port = __intVal(portNrOrName);
       
  2862 	}
       
  2863 
       
  2864 	/*
       
  2865 	 * APPLETALK addresses - addr must be nil, integer or byteArray
       
  2866 	 * if integer, the first byte are the hi net bits, next byte are low net bits,
       
  2867 	 * last byte is node.
       
  2868 	 */
       
  2869 	if (address == nil) {
       
  2870 	    sa.at.sat_addr.s_net = ATADDR_ANYNET;
       
  2871 	    sa.at.sat_addr.s_node = ATADDR_ANYNODE;
       
  2872 	} else {
       
  2873 	    if (__isInteger(address)) {
       
  2874 		unsigned a = __longIntVal(address);
       
  2875 		sa.at.sat_addr.s_net = htons((a >> 8) & 0xFFFF);
       
  2876 		sa.at.sat_addr.s_node = htons(a & 0xFF);
       
  2877 	    } else {
       
  2878 		if (__isByteArray(address)) {
       
  2879 		    unsigned char *cp;
       
  2880 		    int n;
       
  2881 
       
  2882 		    cp = __ByteArrayInstPtr(address)->ba_element;
       
  2883 		    n = __byteArraySize(address);
       
  2884 		    if (n > 3) n = 3;
       
  2885 		    bcopy(cp, &sa.at.sat_addr, n);
       
  2886 		} else {
       
  2887 		    unsigned addr;
       
  2888 		    struct hostent *hp ;
       
  2889 
       
  2890 		    if (! __isString(address)) {
       
  2891 			DBGPRINTF(("SOCKET: invalid address arg in bind\n"));
       
  2892 			RETURN (false);
       
  2893 		    }
       
  2894 
       
  2895 		    /* 
       
  2896 		     * do we know the host's address? 
       
  2897 		     */
       
  2898 		    GETHOSTBYNAME(hp, __stringVal(address))
       
  2899 		    if (hp == NULL) {
       
  2900 			DBGPRINTF(("SOCKET: unknown host: %s\n", __stringVal(address)));
       
  2901 			RETURN (false);
       
  2902 		    }
       
  2903 		    if (hp->h_addrtype != AF_APPLETALK) {
       
  2904 			DBGPRINTF(("SOCKET: host:%s is not an appletalk host\n", __stringVal(address)));
       
  2905 			RETURN (false);
       
  2906 		    }
       
  2907 		    bcopy(hp->h_addr, (char *) &sa.at.sat_addr, hp->h_length) ;
       
  2908 		    sa.at.sat_family = hp->h_addrtype;
       
  2909 		}
       
  2910 	    }
       
  2911 	}
       
  2912 	DBGPRINTF(("SOCKET: bind addr: %x port: %x\n", sa.in.sin_addr.s_addr, sa.in.sin_port));
       
  2913 	sockaddr_size = sizeof(struct sockaddr_at);
       
  2914 	ok = 1;
       
  2915     }
       
  2916 # endif /* AF_APPLETALK */
       
  2917 
       
  2918     /*
       
  2919      * XXXX add addressing stuff for other domains here ...
       
  2920      */
       
  2921 # ifdef AF_X25
       
  2922     else if (myDomain == @symbol(x25)) {
       
  2923     }
       
  2924 # endif
       
  2925 # ifdef AF_AX25
       
  2926     else if (myDomain == @symbol(ax25)) {
       
  2927     }
       
  2928 # endif
       
  2929 # ifdef AF_NS
       
  2930     else if ((myDomain == @symbol(ns)) 
       
  2931      || (myDomain == @symbol(xns))) {
       
  2932     }
       
  2933 # endif
       
  2934 # ifdef AF_DECnet
       
  2935     else if (myDomain == @symbol(decnet)) {
       
  2936     }
       
  2937 # endif
       
  2938 # ifdef AF_SNA
       
  2939     else if (myDomain == @symbol(sna)) {
       
  2940     }
       
  2941 # endif
       
  2942 # ifdef AF_RAW
       
  2943     else if (myDomain == @symbol(raw)) {
       
  2944     }
       
  2945 # endif
       
  2946 # ifdef AF_ISO
       
  2947     else if (myDomain == @symbol(iso)) {
       
  2948     }
       
  2949 # endif
       
  2950 # ifdef AF_NETBIOS
       
  2951     else if (myDomain == @symbol(netbios)) {
       
  2952     }
       
  2953 # endif
       
  2954 # ifdef AF_IPX
       
  2955     else if (myDomain == @symbol(ipx)) {
       
  2956     }
       
  2957 # endif
       
  2958 # ifdef AF_BRIDGE
       
  2959     else if (myDomain == @symbol(bridge)) {
       
  2960     }
       
  2961 # endif
       
  2962 # ifdef AF_BSC
       
  2963     else if (myDomain == @symbol(bsc)) {
       
  2964     }
       
  2965 # endif
       
  2966 # ifdef AF_ROSE
       
  2967     else if (myDomain == @symbol(rose)) {
       
  2968     }
       
  2969 # endif
       
  2970 # ifdef AF_IRDA
       
  2971     else if (myDomain == @symbol(irda)) {
       
  2972     }
       
  2973 # endif
       
  2974 # if defined(AF_CCITT) && (AF_CCITT != AF_X25)
       
  2975     else if (myDomain == @symbol(ccitt)) {
       
  2976     }
       
  2977 # endif
       
  2978 
       
  2979     if (! ok) {
       
  2980 	DBGPRINTF(("SOCKET: unsupported domain\n"));
       
  2981 	RETURN (false);
       
  2982     }
  2537     }
  2983 
  2538 
  2984     sock = fileno(__FILEVal(t));
  2539     sock = fileno(__FILEVal(t));
  2985 
  2540 
  2986 # ifdef SO_REUSEADDR
  2541 # ifdef SO_REUSEADDR
  2987     if (reuse == true) {
  2542     if (reuse == true) {
  2988 	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) {
  2543         if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) {
  2989 	    DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n"));
  2544             DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n"));
  2990 	}
  2545         }
  2991     }
  2546     }
  2992 # endif /* SO_REUSEADDR */
  2547 # endif /* SO_REUSEADDR */
  2993 
  2548 
  2994     __BEGIN_INTERRUPTABLE__
  2549     __BEGIN_INTERRUPTABLE__
  2995     do {
  2550     do {
  2996 	ret = bind(sock, (struct sockaddr *)&sa, sockaddr_size);
  2551         sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + sockAddrOffs);
       
  2552         ret = bind(sock, sockaddr_ptr, sockaddr_size);
  2997     } while ((ret < 0) && (errno == EINTR));
  2553     } while ((ret < 0) && (errno == EINTR));
  2998     __END_INTERRUPTABLE__
  2554     __END_INTERRUPTABLE__
  2999 
  2555 
  3000     if (ret < 0) {
  2556     if (ret < 0) {
  3001 	DBGPRINTF(("SOCKET: bind failed errno=%d\n", errno));
  2557         DBGPRINTF(("SOCKET: bind failed errno=%d\n", errno));
  3002 	__INST(lastErrorNumber) = __MKSMALLINT(errno);
  2558         __INST(lastErrorNumber) = __MKSMALLINT(errno);
  3003 	RETURN (false);
  2559         RETURN (false);
       
  2560     } else {
       
  2561         ok = true;
  3004     }
  2562     }
  3005 
  2563 
  3006     __INST(port) = portNrOrName; __STORE(self, portNrOrName);
       
  3007 
       
  3008     if (0) {
       
  3009 	/* for else below */
       
  3010     }
       
  3011 
       
  3012 # ifdef AF_INET
       
  3013     else if (myDomain == @symbol(inet)) {
       
  3014 	if (! __isSmallInteger(portNrOrName)
       
  3015 	 || (portNrOrName == __MKSMALLINT(0))) {
       
  3016 	    int p;
       
  3017 
       
  3018 	    /*
       
  3019 	     * INET anonymous port - get the actual portNr
       
  3020 	     */
       
  3021 	    if (getsockname(sock, (struct sockaddr *)&sa, &sockaddr_size) < 0) {
       
  3022 		DBGPRINTF(("SOCKET: cannot get peername\n"));
       
  3023 	    } else {
       
  3024 		DBGPRINTF(("SOCKET: anon port=%x\n", sa.in.sin_port));
       
  3025 		p = ntohs(sa.in.sin_port);
       
  3026 		__INST(port) = __MKSMALLINT(p);
       
  3027 	    }
       
  3028 	}
       
  3029     }
       
  3030 # endif
       
  3031 
       
  3032 # ifdef AF_INET6
       
  3033     else if (myDomain == @symbol(inet6)) {
       
  3034 	if (! __isSmallInteger(portNrOrName)
       
  3035 	 || (portNrOrName == __MKSMALLINT(0))) {
       
  3036 	    int p;
       
  3037 
       
  3038 	    /*
       
  3039 	     * INET6 anonymous port - get the actual portNr
       
  3040 	     */
       
  3041 	    if (getsockname(sock, (struct sockaddr *)&sa, &sockaddr_size) < 0) {
       
  3042 		DBGPRINTF(("SOCKET: cannot get peername\n"));
       
  3043 	    } else {
       
  3044 		DBGPRINTF(("SOCKET: anon port=%x\n", sa.in.sin_port));
       
  3045 		p = ntohs(sa.in6.sin6_port);
       
  3046 		__INST(port) = __MKSMALLINT(p);
       
  3047 	    }
       
  3048 	}
       
  3049     }
       
  3050 # endif
       
  3051 
       
  3052 # ifdef AF_APPLETALK
       
  3053     else if (myDomain == @symbol(appletalk)) {
       
  3054 	if (! __isSmallInteger(portNrOrName)
       
  3055 	 || (portNrOrName == __MKSMALLINT(0))) {
       
  3056 	    int p;
       
  3057 
       
  3058 	    /*
       
  3059 	     * APPLETALK anonymous port - get the actual portNr
       
  3060 	     */
       
  3061 	    if (getsockname(sock, (struct sockaddr *)&sa, &sockaddr_size) < 0) {
       
  3062 		DBGPRINTF(("SOCKET: cannot get peername\n"));
       
  3063 	    } else {
       
  3064 		DBGPRINTF(("SOCKET: anon port=%x\n", sa.in.sin_port));
       
  3065 		p = sa.at.sat_port;
       
  3066 		__INST(port) = __MKSMALLINT(p);
       
  3067 	    }
       
  3068 	}
       
  3069     }
       
  3070 # endif
       
  3071 
       
  3072 #else /* NO_SOCKET */
       
  3073     RETURN (false);
       
  3074 #endif /* NO_SOCKET */
  2564 #endif /* NO_SOCKET */
       
  2565 
       
  2566 getOutOfHere: ;
  3075 %}.
  2567 %}.
       
  2568     ok ~~ true ifTrue:[
       
  2569         ^ false
       
  2570     ].
       
  2571 
       
  2572     peer := addr.
       
  2573     port := addr port.
       
  2574     peerName := addrName.
       
  2575 
  3076     ^ true
  2576     ^ true
  3077 
  2577 
  3078     "
  2578     "
  3079      (Socket domain:#inet type:#stream)
  2579      (Socket domain:#inet type:#stream)
  3080 	 bindTo:9999
  2580          bindTo:9999
  3081 	 address:nil
  2581          address:nil
  3082     "
  2582     "
  3083 !
  2583 !
  3084 
  2584 
  3085 closeFile
  2585 closeFile
  3086     "low level close"
  2586     "low level close"
  3111 getSocketError
  2611 getSocketError
  3112     "get the SO_ERROR form the socket, which indicates the 
  2612     "get the SO_ERROR form the socket, which indicates the 
  3113      result of an asynchronous operation"
  2613      result of an asynchronous operation"
  3114 
  2614 
  3115 %{
  2615 %{
       
  2616 #ifndef NO_SOCKET
  3116     OBJ t;
  2617     OBJ t;
  3117     int err;
  2618     int err;
  3118 
  2619 
  3119     t = __INST(filePointer);
  2620     t = __INST(filePointer);
  3120     if (t == nil)
  2621     if (t == nil)
  3121 	err = EBADF;
  2622         err = EBADF;
  3122     else {
  2623     else {
  3123 	int sz, fd;
  2624         int sz, fd;
  3124 
  2625 
  3125 	fd = fileno(__FILEVal(t));
  2626         fd = fileno(__FILEVal(t));
  3126 	sz = sizeof(err);
  2627         sz = sizeof(err);
  3127 	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &sz) < 0)
  2628         if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &sz) < 0)
  3128 	    err = errno;
  2629             err = errno;
  3129     }
  2630     }
  3130 
  2631 
  3131     RETURN(__MKSMALLINT(err));
  2632     RETURN(__MKSMALLINT(err));
       
  2633 #endif
  3132 %}
  2634 %}
  3133 
       
  3134 
       
  3135 !
  2635 !
  3136 
  2636 
  3137 listenFor:aNumber
  2637 listenFor:aNumber
  3138     "same as listenWithBacklog: - for ST-80 compatibility"
  2638     "same as listenWithBacklog: - for ST-80 compatibility"
  3139 
  2639 
  3248 primAcceptOn:aSocket
  2748 primAcceptOn:aSocket
  3249     "accept a connection on a server port (created with:'Socket>>onIPPort:')
  2749     "accept a connection on a server port (created with:'Socket>>onIPPort:')
  3250      usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
  2750      usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
  3251      Return the true if ok; false if not."
  2751      Return the true if ok; false if not."
  3252 
  2752 
  3253     |serverSocketFd addrBytes|
  2753     |serverSocketFd addr addrLen domainClass|
  3254 
  2754 
  3255     filePointer notNil ifTrue:[
  2755     filePointer notNil ifTrue:[
  3256         ^ self errorAlreadyOpen
  2756         ^ self errorAlreadyOpen
  3257     ].
  2757     ].
  3258 
  2758 
  3263         ^ self error:'invalid server socket'
  2763         ^ self error:'invalid server socket'
  3264     ].
  2764     ].
  3265     (serverSocketFd isMemberOf:SmallInteger) ifFalse:[
  2765     (serverSocketFd isMemberOf:SmallInteger) ifFalse:[
  3266         ^ self error:'invalid server socket'
  2766         ^ self error:'invalid server socket'
  3267     ].
  2767     ].
       
  2768 
       
  2769     domainClass := self class socketAddressClassForDomain:domain.
       
  2770     domainClass isNil ifTrue:[
       
  2771         ^ self error:'invalid (unsupported) domain'.
       
  2772     ].
       
  2773     addrLen := domainClass socketAddressSize.
       
  2774     addr := domainClass new.
       
  2775 
  3268 %{  /* STACK: 100000 */
  2776 %{  /* STACK: 100000 */
  3269 #ifndef NO_SOCKET
  2777 #ifndef NO_SOCKET
  3270     FILE *fp;
  2778     FILE *fp;
  3271     int flags;
  2779     int flags;
  3272     int sock, newSock;
  2780     int sock, newSock;
  3273     union sockaddr_u sa;
  2781     union sockaddr_u sa;
  3274     int alen, alen0;
  2782     int alen, alen0;
  3275     struct hostent *he ;
  2783     struct hostent *he ;
  3276     char dotted[20] ;
  2784     char dotted[20] ;
  3277 
  2785 
  3278     if (0) {
  2786     if (!__isSmallInteger(addrLen)) {
  3279         /* for else below */
  2787         DBGPRINTF(("SOCKET: bad addrLen\n"));
       
  2788         RETURN (false);
  3280     }
  2789     }
  3281 # ifdef AF_INET
  2790     alen0 = __intVal(addrLen);
  3282     else if (__INST(domain) == @symbol(inet)) {
       
  3283         alen0 = sizeof(sa.in);
       
  3284     }
       
  3285 # endif
       
  3286 # ifdef AF_INET6
       
  3287     else if (__INST(domain) == @symbol(inet6)) {
       
  3288         alen0 = sizeof(sa.in6);
       
  3289     }
       
  3290 # endif
       
  3291 # ifdef AF_UNIX
       
  3292     else if (__INST(domain) == @symbol(unix)) {
       
  3293         alen0 = sizeof(sa.un);
       
  3294     }
       
  3295 # endif
       
  3296 # ifdef AF_APPLETALK
       
  3297     else if (__INST(domain) == @symbol(appletalk)) {
       
  3298         alen0 = sizeof(sa.at);
       
  3299     }
       
  3300 # endif
       
  3301 
       
  3302     /*
       
  3303      * XXXX add addressing stuff for other domains here ...
       
  3304      */
       
  3305 # ifdef AF_X25
       
  3306     else if (__INST(domain) == @symbol(x25)) {
       
  3307         alen0 = sizeof(sa.x25);
       
  3308     }
       
  3309 # endif
       
  3310 # ifdef AF_AX25
       
  3311     else if (__INST(domain) == @symbol(ax25)) {
       
  3312         alen0 = sizeof(sa.ax25);
       
  3313     }
       
  3314 # endif
       
  3315 # ifdef AF_NS
       
  3316     else if ((__INST(domain) == @symbol(ns)) 
       
  3317      || (__INST(domain) == @symbol(xns))) {
       
  3318     }
       
  3319 # endif
       
  3320 # ifdef AF_DECnet
       
  3321     else if (__INST(domain) == @symbol(decnet)) {
       
  3322         alen0 = sizeof(sa.dn);
       
  3323     }
       
  3324 # endif
       
  3325 # ifdef AF_SNA
       
  3326     else if (__INST(domain) == @symbol(sna)) {
       
  3327         alen0 = sizeof(sa.sna);
       
  3328     }
       
  3329 # endif
       
  3330 # ifdef AF_RAW
       
  3331     else if (__INST(domain) == @symbol(raw)) {
       
  3332     }
       
  3333 # endif
       
  3334 # ifdef AF_ISO
       
  3335     else if (__INST(domain) == @symbol(iso)) {
       
  3336     }
       
  3337 # endif
       
  3338 # ifdef AF_NETBIOS
       
  3339     else if (__INST(domain) == @symbol(netbios)) {
       
  3340     }
       
  3341 # endif
       
  3342 # ifdef AF_IPX
       
  3343     else if (__INST(domain) == @symbol(ipx)) {
       
  3344         alen0 = sizeof(sa.ipx);
       
  3345     }
       
  3346 # endif
       
  3347 # ifdef AF_BRIDGE
       
  3348     else if (__INST(domain) == @symbol(bridge)) {
       
  3349     }
       
  3350 # endif
       
  3351 # ifdef AF_BSC
       
  3352     else if (__INST(domain) == @symbol(bsc)) {
       
  3353     }
       
  3354 # endif
       
  3355 # ifdef AF_ROSE
       
  3356     else if (__INST(domain) == @symbol(rose)) {
       
  3357     }
       
  3358 # endif
       
  3359 # ifdef AF_IRDA
       
  3360     else if (__INST(domain) == @symbol(irda)) {
       
  3361     }
       
  3362 # endif
       
  3363 # if defined(AF_CCITT) && (AF_CCITT != AF_X25)
       
  3364     else if (__INST(domain) == @symbol(ccitt)) {
       
  3365     }
       
  3366 # endif
       
  3367 
       
  3368 
  2791 
  3369     sock = __intVal(serverSocketFd);
  2792     sock = __intVal(serverSocketFd);
  3370 
  2793 
  3371 # if defined(O_NDELAY) && defined(SET_NDELAY)
  2794 # if defined(O_NDELAY) && defined(SET_NDELAY)
  3372     flags = ioctl(sock, F_GETFL, 0);
  2795     flags = ioctl(sock, F_GETFL, 0);
  3389         DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
  2812         DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
  3390         __INST(lastErrorNumber) = __MKSMALLINT(errno);
  2813         __INST(lastErrorNumber) = __MKSMALLINT(errno);
  3391         RETURN (false);
  2814         RETURN (false);
  3392     }
  2815     }
  3393 
  2816 
  3394     /*
  2817     if (__isNonNilObject(addr)) {
  3395      * extract the partners address
  2818         OBJ oClass;
  3396      */
  2819         int nInstVars, nInstBytes, objSize;
  3397     if (0) {
  2820         char *cp;
  3398         /* for else below */
  2821 
       
  2822         oClass = __qClass(addr);
       
  2823         if (! __isBytes(addr) ) {
       
  2824             DBGPRINTF(("SOCKET: bad addr\n"));
       
  2825             close(newSock);
       
  2826             RETURN (false);
       
  2827         }
       
  2828 
       
  2829         nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
       
  2830         nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
       
  2831         objSize = __qSize(addr) - nInstBytes;
       
  2832         cp = (char *)__InstPtr(addr) + nInstBytes;
       
  2833         if (objSize < alen) {
       
  2834             DBGPRINTF(("SOCKET: bad addr\n"));
       
  2835             close(newSock);
       
  2836             RETURN (false);
       
  2837         }
       
  2838 
       
  2839         /*
       
  2840          * extract the partners address
       
  2841          */
       
  2842         bcopy((char *)&sa, cp, alen);
       
  2843         addrLen = __MKSMALLINT(alen);
  3399     }
  2844     }
  3400 
       
  3401 # ifdef AF_INET
       
  3402     else if (__INST(domain) == @symbol(inet)) {
       
  3403 #  ifdef RESOLVE_NAME_NOW
       
  3404         GETHOSTBYADDR(he, (char *) &sa.in.sin_addr, sizeof(sa.in.sin_addr), AF_INET);
       
  3405         if (! he) {
       
  3406             unsigned long norder;
       
  3407 
       
  3408             norder = htonl(sa.in.sin_addr.s_addr) ;
       
  3409             sprintf(dotted, "%d.%d.%d.%d",
       
  3410                     (norder >> 24) & 0xFF,
       
  3411                     (norder >> 16) & 0xFF,
       
  3412                     (norder >> 8) & 0xFF,
       
  3413                     norder & 0xFF);
       
  3414         }
       
  3415         DBGPRINTF(("SOCKET: accepted connection from host %s\n", (he ? he->h_name : dotted))) ;
       
  3416         __INST(peerName) = __MKSTRING((he ? he->h_name : dotted));
       
  3417         __STORESELF(peerName);
       
  3418 #  else
       
  3419         addrBytes = __MKBYTEARRAY(&sa.in, sizeof(sa.in));
       
  3420 #  endif
       
  3421     }
       
  3422 # endif
       
  3423 
       
  3424 # ifdef AF_INET6
       
  3425     else if (__INST(domain) == @symbol(inet6)) {
       
  3426 #  ifdef RESOLVE_NAME_NOW
       
  3427         GETHOSTBYADDR(he, (char *) &sa.in6.sin6_addr, sizeof(sa.in6.sin6_addr), AF_INET6);
       
  3428         if (! he) {
       
  3429             unsigned long norder;
       
  3430 
       
  3431             /*
       
  3432              * XXX: what is inet6's naming convention ?
       
  3433              */
       
  3434             norder = htonl(sa.in.sin_addr.s_addr) ;
       
  3435             sprintf(dotted, "%d.%d.%d.%d.%d.%d...",
       
  3436                     sa.in6.sin6_addr.s6_addr[0],
       
  3437                     sa.in6.sin6_addr.s6_addr[1],
       
  3438                     sa.in6.sin6_addr.s6_addr[2],
       
  3439                     sa.in6.sin6_addr.s6_addr[3],
       
  3440                     sa.in6.sin6_addr.s6_addr[4],
       
  3441                     sa.in6.sin6_addr.s6_addr[5]);
       
  3442         }
       
  3443         DBGPRINTF(("SOCKET: accepted connection from host %s\n", (he ? he->h_name : dotted))) ;
       
  3444         __INST(peerName) = __MKSTRING((he ? he->h_name : dotted));
       
  3445         __STORESELF(peerName);
       
  3446 #  else
       
  3447         addrBytes = __MKBYTEARRAY(&sa.in6, sizeof(sa.in6));
       
  3448 #  endif
       
  3449     }
       
  3450 # endif
       
  3451 
       
  3452 # ifdef AF_UNIX
       
  3453     else if (__INST(domain) == @symbol(unix)) {
       
  3454         DBGPRINTF(("SOCKET: accepted connection on unix socket\n")) ;
       
  3455         /* nothing to be done here */
       
  3456     }
       
  3457 # endif
       
  3458 
       
  3459 # ifdef AF_APPLETALK
       
  3460     else if (__INST(domain) == @symbol(appletalk)) {
       
  3461 #  ifdef RESOLVE_NAME_NOW
       
  3462         GETHOSTBYADDR(he, (char *) &sa.at.sat_addr, sizeof(sa.at.sat_addr), AF_APPLETALK);
       
  3463         if (! he) {
       
  3464             unsigned net;
       
  3465 
       
  3466             /*
       
  3467              * XXX: what is apples naming convention ?
       
  3468              */
       
  3469             net = htons(sa.at.sat_addr.s_net) ;
       
  3470             sprintf(dotted, "%d.%d",
       
  3471                     net,
       
  3472                     sa.at.sat_addr.s_node);
       
  3473         }
       
  3474         DBGPRINTF(("SOCKET: accepted connection from host %s\n", (he ? he->h_name : dotted))) ;
       
  3475         __INST(peerName) = __MKSTRING((he ? he->h_name : dotted));
       
  3476         __STORESELF(peerName);
       
  3477 #  else
       
  3478         addrBytes = __MKBYTEARRAY(&sa.at, sizeof(sa.at));
       
  3479 #  endif
       
  3480     }
       
  3481 # endif
       
  3482 
       
  3483     /*
       
  3484      * XXXX add addressing stuff for other domains here ...
       
  3485      */
       
  3486 # ifdef AF_X25
       
  3487     else if (__INST(domain) == @symbol(x25)) {
       
  3488     }
       
  3489 # endif
       
  3490 # ifdef AF_AX25
       
  3491     else if (__INST(domain) == @symbol(ax25)) {
       
  3492     }
       
  3493 # endif
       
  3494 # ifdef AF_NS
       
  3495     else if ((__INST(domain) == @symbol(ns)) 
       
  3496      || (__INST(domain) == @symbol(xns))) {
       
  3497     }
       
  3498 # endif
       
  3499 # ifdef AF_DECnet
       
  3500     else if (__INST(domain) == @symbol(decnet)) {
       
  3501     }
       
  3502 # endif
       
  3503 # ifdef AF_SNA
       
  3504     else if (__INST(domain) == @symbol(sna)) {
       
  3505     }
       
  3506 # endif
       
  3507 # ifdef AF_RAW
       
  3508     else if (__INST(domain) == @symbol(raw)) {
       
  3509     }
       
  3510 # endif
       
  3511 # ifdef AF_ISO
       
  3512     else if (__INST(domain) == @symbol(iso)) {
       
  3513     }
       
  3514 # endif
       
  3515 # ifdef AF_NETBIOS
       
  3516     else if (__INST(domain) == @symbol(netbios)) {
       
  3517     }
       
  3518 # endif
       
  3519 # ifdef AF_IPX
       
  3520     else if (__INST(domain) == @symbol(ipx)) {
       
  3521     }
       
  3522 # endif
       
  3523 # ifdef AF_BRIDGE
       
  3524     else if (__INST(domain) == @symbol(bridge)) {
       
  3525     }
       
  3526 # endif
       
  3527 # ifdef AF_BSC
       
  3528     else if (__INST(domain) == @symbol(bsc)) {
       
  3529     }
       
  3530 # endif
       
  3531 # ifdef AF_ROSE
       
  3532     else if (__INST(domain) == @symbol(rose)) {
       
  3533     }
       
  3534 # endif
       
  3535 # ifdef AF_IRDA
       
  3536     else if (__INST(domain) == @symbol(irda)) {
       
  3537     }
       
  3538 # endif
       
  3539 # if defined(AF_CCITT) && (AF_CCITT != AF_X25)
       
  3540     else if (__INST(domain) == @symbol(ccitt)) {
       
  3541     }
       
  3542 # endif
       
  3543 
  2845 
  3544     /* 
  2846     /* 
  3545      * make it a FILE * 
  2847      * make it a FILE * 
  3546      */
  2848      */
  3547     fp = fdopen(newSock, "r+");
  2849     fp = fdopen(newSock, "r+");
  3568     mode := #readwrite.
  2870     mode := #readwrite.
  3569     Lobby register:self.
  2871     Lobby register:self.
  3570     binary := false.
  2872     binary := false.
  3571     port := aSocket port.
  2873     port := aSocket port.
  3572 
  2874 
  3573     addrBytes notNil ifTrue:[
  2875     addr notNil ifTrue:[
  3574         addrBytes changeClassTo:(self class socketAddressClassForDomain:domain).
  2876         peer := addr.
  3575         peer := addrBytes.
       
  3576     ].
  2877     ].
  3577 
  2878 
  3578     ^ true
  2879     ^ true
  3579 !
  2880 !
  3580 
  2881 
  4098 
  3399 
  4099     "
  3400     "
  4100      Socket new domain:#inet type:#stream
  3401      Socket new domain:#inet type:#stream
  4101      Socket new domain:#unix type:#stream
  3402      Socket new domain:#unix type:#stream
  4102     "
  3403     "
  4103 !
       
  4104 
       
  4105 for:hostName port:portNr
       
  4106     "setup for a TCP socket (i.e. inet domain, stream type) 
       
  4107      If hostname is nil, a server port is opened,
       
  4108      otherwise a client port to the server on host.
       
  4109 
       
  4110      HISTORIC LEFTOVER:
       
  4111      This method will vanish, as soon as the low level
       
  4112      connect/bind works,"
       
  4113 
       
  4114     self obsoleteMethodWarning.
       
  4115 
       
  4116     filePointer notNil ifTrue:[
       
  4117 	^ self errorAlreadyOpen
       
  4118     ].
       
  4119     (portNr isMemberOf:SmallInteger) ifFalse:[
       
  4120 	self error:'invalid portNr'
       
  4121     ].
       
  4122 %{  /* STACK: 100000 */
       
  4123 #ifndef NO_SOCKET
       
  4124     struct sockaddr_in sa ;
       
  4125     struct hostent *hp ;
       
  4126     int a, sock ;
       
  4127     long addr;
       
  4128     FILE *fp;
       
  4129     int ret;
       
  4130     int on = 1;
       
  4131 
       
  4132     bzero((char *) &sa, sizeof(sa)) ;
       
  4133     sa.sin_family = AF_INET;
       
  4134     sa.sin_addr.s_addr = htonl(INADDR_ANY);
       
  4135 
       
  4136     if ((hostName != nil) && __isString(hostName)){
       
  4137 	bzero(&sa, sizeof(sa)) ;
       
  4138 	if ((addr = inet_addr((char *) __stringVal(hostName))) != -1) {
       
  4139 	    /* 
       
  4140 	     * is Internet addr in octet notation 
       
  4141 	     */
       
  4142 	    bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */
       
  4143 	} else {
       
  4144 	    /* 
       
  4145 	     * do we know the host's address? 
       
  4146 	     */
       
  4147 	    GETHOSTBYNAME(hp, __stringVal(hostName))
       
  4148 	    if (hp == NULL) {
       
  4149 		DBGPRINTF(("SOCKET: unknown host: %s\n", __stringVal(hostName)));
       
  4150 		RETURN ( nil );
       
  4151 	    }
       
  4152 	    bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ;
       
  4153 	    sa.sin_family = hp->h_addrtype;
       
  4154 	}
       
  4155     }
       
  4156 
       
  4157     /*
       
  4158      * create the socket
       
  4159      */
       
  4160     __BEGIN_INTERRUPTABLE__
       
  4161     do {
       
  4162 	sock = socket(sa.sin_family, SOCK_STREAM, 0);
       
  4163     } while ((sock < 0) && (errno == EINTR));
       
  4164     __END_INTERRUPTABLE__
       
  4165     DBGFPRINTF((stderr, "socket create newSock=%d\n", sock));
       
  4166 
       
  4167     if (sock < 0) {
       
  4168 	DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=0) call failed errno=%d\n", sa.sin_family, SOCK_STREAM, errno));
       
  4169 	__INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  4170     } else {
       
  4171 	/* 
       
  4172 	 * connect/bind 
       
  4173 	 */
       
  4174 	sa.sin_port = htons((u_short) __intVal(portNr)) ;
       
  4175 
       
  4176 	__BEGIN_INTERRUPTABLE__
       
  4177 	if (hostName != nil) {
       
  4178 	    do {
       
  4179 		ret = connect(sock, (struct sockaddr *)&sa, sizeof(sa));
       
  4180 	    } while ((ret < 0) && (errno == EINTR));
       
  4181 	} else {
       
  4182 #ifdef SO_REUSEADDR
       
  4183 	    /*
       
  4184 	     * should I also do this for DGRAM sockets ?
       
  4185 	     */
       
  4186 	    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) {
       
  4187 		DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n"));
       
  4188 	    }
       
  4189 #endif /* SO_REUSEADDR */
       
  4190 	    sa.sin_addr.s_addr = htonl(INADDR_ANY);
       
  4191 	    do {
       
  4192 		ret = bind(sock, (struct sockaddr *)&sa, sizeof(sa));
       
  4193 	    } while ((ret < 0) && (errno == EINTR));
       
  4194 	}
       
  4195 	__END_INTERRUPTABLE__
       
  4196 
       
  4197 	if (ret < 0) { 
       
  4198 	    DBGPRINTF(("SOCKET: bind/connect call failed errno=%d\n", errno));
       
  4199 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  4200 	    __BEGIN_INTERRUPTABLE__
       
  4201 	    close(sock) ;
       
  4202 	    DBGFPRINTF((stderr, "socket close (fdopen failed) (%d)\n", sock));
       
  4203 	    __END_INTERRUPTABLE__
       
  4204 	} else {
       
  4205 	    /* 
       
  4206 	     * make it a FILE * 
       
  4207 	     */
       
  4208 	    fp = fdopen(sock, "r+");
       
  4209 	    if (! fp) {
       
  4210 		DBGPRINTF(("SOCKET: fdopen failed\n"));
       
  4211 		__INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  4212 		__BEGIN_INTERRUPTABLE__
       
  4213 		close(sock);
       
  4214 		DBGFPRINTF((stderr, "socket close (fdopen failed) (%d)\n", sock));
       
  4215 		__END_INTERRUPTABLE__
       
  4216 	    } else {
       
  4217 		if (@global(FileOpenTrace) == true) {
       
  4218 		    fprintf(stderr, "fdopen [Socket] -> %x\n", fp);
       
  4219 		}
       
  4220 
       
  4221 #ifdef BUGGY_STDIO_LIB
       
  4222 		setbuf(fp, NULL);
       
  4223 		__INST(buffered) = false;
       
  4224 #endif
       
  4225 		__INST(filePointer) = __MKOBJ(fp);
       
  4226 		__STORESELF(filePointer);
       
  4227 	    }
       
  4228 	}
       
  4229     }
       
  4230 #endif
       
  4231 %}.
       
  4232     filePointer isNil ifTrue:[
       
  4233 	^ nil
       
  4234     ].
       
  4235     mode := #readwrite.
       
  4236     Lobby register:self.
       
  4237     binary := false.
       
  4238 
       
  4239     domain := #inet.
       
  4240     socketType := #stream.
       
  4241     protocol := portNr.
       
  4242     peerName := hostName.
       
  4243 
       
  4244     "
       
  4245      Socket new for:'clam' port:(Socket portOfService:'echo')
       
  4246 
       
  4247      Socket new for:nil port:9999
       
  4248      Socket new for:(OperatingSystem getHostName) port:9999
       
  4249     "
       
  4250 !
       
  4251 
       
  4252 for:hostName udpPort:portNr
       
  4253     "setup for a UDP socket (i.e. inet domain, datagram type) 
       
  4254      if hostname is nil, a server port is opened;
       
  4255      otherwise a client port to the server on host.
       
  4256 
       
  4257      HISTORIC LEFTOVER:
       
  4258      This method will vanish, as soon as the low level
       
  4259      connect/bind works,"
       
  4260 
       
  4261     self obsoleteMethodWarning.
       
  4262 
       
  4263     filePointer notNil ifTrue:[
       
  4264 	^ self errorAlreadyOpen
       
  4265     ].
       
  4266     (portNr isMemberOf:SmallInteger) ifFalse:[
       
  4267 	self error:'invalid portNr'
       
  4268     ].
       
  4269 %{  /* STACK: 100000 */
       
  4270 #ifndef NO_SOCKET
       
  4271     struct sockaddr_in sa ;
       
  4272     struct hostent *hp ;
       
  4273     int a, sock ;
       
  4274     long addr;
       
  4275     FILE *fp;
       
  4276     int ret;
       
  4277 
       
  4278     if (hostName != nil) {
       
  4279 	bzero(&sa, sizeof(sa)) ;
       
  4280 	if ((addr = inet_addr((char *) __stringVal(hostName))) != -1) {
       
  4281 	    /* 
       
  4282 	     * is Internet addr in octet notation 
       
  4283 	     */
       
  4284 	    bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */
       
  4285 	    sa.sin_family = AF_INET ;
       
  4286 	} else {
       
  4287 	    /* 
       
  4288 	     * is hostname - 
       
  4289 	     * do we know the host's address? 
       
  4290 	     */
       
  4291 	    GETHOSTBYNAME(hp, __stringVal(hostName))
       
  4292 	    if (hp == NULL) {
       
  4293 		DBGPRINTF(("SOCKET: unknown host: %s\n", __stringVal(hostName)));
       
  4294 		RETURN ( nil );
       
  4295 	    }
       
  4296 	    bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ;
       
  4297 	    sa.sin_family = hp->h_addrtype ;
       
  4298 	}
       
  4299     } else {
       
  4300 	sa.sin_family = AF_INET;
       
  4301     }
       
  4302 
       
  4303     /*
       
  4304      * create the socket
       
  4305      */
       
  4306     __BEGIN_INTERRUPTABLE__
       
  4307     do {
       
  4308 	sock = socket(sa.sin_family, SOCK_DGRAM, 0);
       
  4309     } while ((sock < 0) && (errno == EINTR));
       
  4310     __END_INTERRUPTABLE__
       
  4311     DBGFPRINTF((stderr, "socket create newSock=%d\n", sock));
       
  4312 
       
  4313     if (sock < 0) {
       
  4314 	DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=0) call failed errno=%d\n", sa.sin_family, SOCK_DGRAM, errno));
       
  4315 	__INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  4316     } else {
       
  4317 	/* 
       
  4318 	 * ok,
       
  4319 	 * connect/bind 
       
  4320 	 */
       
  4321 	__BEGIN_INTERRUPTABLE__
       
  4322 	if (hostName == nil) {
       
  4323 	    sa.sin_addr.s_addr = htonl(INADDR_ANY);
       
  4324 	    do {
       
  4325 		ret = bind(sock, (struct sockaddr *)&sa, sizeof(sa));
       
  4326 	    } while ((ret < 0) && (errno == EINTR));
       
  4327 	} else {
       
  4328 	    sa.sin_port = htons((u_short) __intVal(portNr)) ;
       
  4329 	    do {
       
  4330 		ret = connect(sock, (struct sockaddr *)&sa, sizeof(sa));
       
  4331 	    } while ((ret < 0) && (errno == EINTR));
       
  4332 	}
       
  4333 	__END_INTERRUPTABLE__
       
  4334 
       
  4335 	if (ret < 0) {
       
  4336 	    DBGPRINTF(("SOCKET: bind/connect call failed\n"));
       
  4337 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  4338 	    __BEGIN_INTERRUPTABLE__
       
  4339 	    close(sock) ;
       
  4340 	    DBGFPRINTF((stderr, "socket close (fdopen failed) (%d)\n", sock));
       
  4341 	    __END_INTERRUPTABLE__
       
  4342 	} else {
       
  4343 	    /* 
       
  4344 	     * make it a FILE * 
       
  4345 	     */
       
  4346 	    fp = fdopen(sock, "r+");
       
  4347 	    if (! fp) {
       
  4348 		DBGPRINTF(("SOCKET: fdopen call failed\n"));
       
  4349 		__INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  4350 		__BEGIN_INTERRUPTABLE__
       
  4351 		close(sock);
       
  4352 		DBGFPRINTF((stderr, "socket close (fdopen failed) (%d)\n", sock));
       
  4353 		__END_INTERRUPTABLE__
       
  4354 	    } else {
       
  4355 		if (@global(ExternalStream:FileOpenTrace) == true) {
       
  4356 		    fprintf(stderr, "fdopen [Socket] -> %x\n", fp);
       
  4357 		}
       
  4358 
       
  4359 #ifdef BUGGY_STDIO_LIB
       
  4360 		setbuf(fp, NULL);
       
  4361 		__INST(buffered) = false;
       
  4362 #endif
       
  4363 		__INST(filePointer) = __MKOBJ(fp);
       
  4364 		__STORESELF(filePointer);
       
  4365 	    }
       
  4366 	}
       
  4367     }
       
  4368 #endif
       
  4369 %}.
       
  4370     filePointer isNil ifTrue:[
       
  4371 	^ nil
       
  4372     ].
       
  4373 
       
  4374     mode := #readwrite.
       
  4375     Lobby register:self.
       
  4376     binary := false.
       
  4377 
       
  4378     domain := #inet.
       
  4379     socketType := #datagram.
       
  4380     protocol := portNr.
       
  4381     peerName := hostName.
       
  4382 
       
  4383     "
       
  4384      Socket new for:'clam' udpPort:(Socket portOfService:'echo')
       
  4385     "
       
  4386 ! !
  3404 ! !
  4387 
  3405 
  4388 !Socket methodsFor:'specials'!
  3406 !Socket methodsFor:'specials'!
  4389 
  3407 
  4390 receiveTimeout:seconds
  3408 receiveTimeout:seconds
  4444 ! !
  3462 ! !
  4445 
  3463 
  4446 !Socket class methodsFor:'documentation'!
  3464 !Socket class methodsFor:'documentation'!
  4447 
  3465 
  4448 version
  3466 version
  4449     ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.183 2003-07-15 12:20:11 cg Exp $'
  3467     ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.184 2003-07-17 13:24:40 cg Exp $'
  4450 ! !
  3468 ! !