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 |
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" |
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+"); |
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 |