204 " |
223 " |
205 ! |
224 ! |
206 |
225 |
207 documentation |
226 documentation |
208 " |
227 " |
209 This class provides access to (unix-)sockets for interprocess communication. |
228 This class provides access to sockets for interprocess communication. |
210 The message protocol is preliminary, until someone tells me how |
229 The message protocol is preliminary, until someone tells me how |
211 other smalltalk's socket interfaces look like. |
230 other smalltalk's socket interfaces look like. |
212 |
231 |
213 Also, currently there is almost no support for other than IP |
232 Also, currently there is almost no support for other than IP and UNIX |
214 sockets - this will be added in the future. |
233 domain sockets - others may be added in the future. |
|
234 (the code is prepared for things like SNA or appletalk support; |
|
235 however, right now, this code is empty and needs work) |
|
236 |
215 Due to historic reasons (I started this class, before I got hold of some |
237 Due to historic reasons (I started this class, before I got hold of some |
216 code using ST-80 Sockets i.e. RemoteInvocation), there is some old interface |
238 code using ST-80 Sockets i.e. RemoteInvocation), there is some old interface |
217 still provided. |
239 still provided. |
218 This will vanish; use the family:type: or newTCPxxx and newUDPxxx interface, |
240 This will vanish; use the #family:type: or #newTCPxxx and #newUDPxxx interfaces, |
219 together with the bind/listen and accept calls, |
241 together with the bind/listen and accept calls, |
220 which are meant to be compatible to ST-80's UnixSocketAccessor interface. |
242 which are meant to be compatible to ST-80's UnixSocketAccessor interface. |
221 |
243 |
222 ST/X does not use IPSocketAddress, UDSocketAddress erc; all addressing |
244 ST/X does not use IPSocketAddress, UDSocketAddress etc; all addressing |
223 is done by passing appropriate string- or byteArray objects containing |
245 is done by passing appropriate string- or byteArray objects containing |
224 the addresses. This may change, too. |
246 the addresses. This may change, too. |
225 |
247 |
226 TODO: cleanup historic leftovers, implement other than inet domain stuff. |
248 TODO: cleanup historic leftovers, implement other than inet domain stuff. |
|
249 (mhmh - how can I test those ?) |
227 |
250 |
228 [author:] |
251 [author:] |
229 Claus Gittinger |
252 Claus Gittinger |
230 " |
253 " |
231 ! |
254 ! |
917 struct hostent *hp ; |
940 struct hostent *hp ; |
918 long addr; |
941 long addr; |
919 |
942 |
920 if (__isString(aHostName)) { |
943 if (__isString(aHostName)) { |
921 bzero(&sa, sizeof(sa)) ; |
944 bzero(&sa, sizeof(sa)) ; |
922 if ((addr = inet_addr((char *) _stringVal(aHostName))) != -1) { |
945 if ((addr = inet_addr((char *) __stringVal(aHostName))) != -1) { |
923 /* is Internet addr in octet notation */ |
946 /* is Internet addr in octet notation */ |
924 bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)); |
947 bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)); |
925 sa.sin_family = AF_INET; |
948 sa.sin_family = AF_INET; |
926 } else { |
949 } else { |
927 /* do we know the host's address? */ |
950 /* do we know the host's address? */ |
928 if ((hp = gethostbyname((char *) _stringVal(aHostName))) == NULL) { |
951 if ((hp = gethostbyname((char *) __stringVal(aHostName))) == NULL) { |
929 DBGPRINTF(("SOCKET: unknown host\n")); |
952 DBGPRINTF(("SOCKET: unknown host\n")); |
930 RETURN ( nil ); |
953 RETURN ( nil ); |
931 } |
954 } |
932 bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ; |
955 bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ; |
933 sa.sin_family = hp->h_addrtype; |
956 sa.sin_family = hp->h_addrtype; |
1031 %{ |
1054 %{ |
1032 #ifndef NO_SOCKET |
1055 #ifndef NO_SOCKET |
1033 struct servent *servent = NULL; |
1056 struct servent *servent = NULL; |
1034 char *protocol; |
1057 char *protocol; |
1035 int tryBoth = 0; |
1058 int tryBoth = 0; |
|
1059 short portNo; |
1036 |
1060 |
1037 if (__isString(aProtocol)) { |
1061 if (__isString(aProtocol)) { |
1038 protocol = __stringVal(aProtocol); |
1062 protocol = __stringVal(aProtocol); |
1039 } else { |
1063 } else { |
1040 protocol = "tcp"; |
1064 protocol = "tcp"; |
1041 tryBoth = 1; |
1065 tryBoth = 1; |
1042 } |
1066 } |
1043 |
1067 |
1044 if (__isSmallInteger(aNameOrNumber)) { |
1068 if (__isSmallInteger(aNameOrNumber)) { |
1045 servent = getservbyport(htons(_intVal(aNameOrNumber)), protocol); |
1069 portNo = __intVal(aNameOrNumber); |
|
1070 servent = getservbyport(htons(portNo), protocol); |
1046 if (servent != NULL) { |
1071 if (servent != NULL) { |
1047 RETURN ( aNameOrNumber ); |
1072 RETURN ( aNameOrNumber ); |
1048 } |
1073 } |
1049 if (tryBoth) { |
1074 if (tryBoth) { |
1050 servent = getservbyport(htons(_intVal(aNameOrNumber)), "udp"); |
1075 servent = getservbyport(htons(portNo), "udp"); |
1051 if (servent != NULL) { |
1076 if (servent != NULL) { |
1052 RETURN ( aNameOrNumber ); |
1077 RETURN ( aNameOrNumber ); |
1053 } |
1078 } |
1054 } |
1079 } |
1055 RETURN ( aNameOrNumber ); |
1080 RETURN ( aNameOrNumber ); |
1056 } |
1081 } |
1057 if (__isString(aNameOrNumber)) { |
1082 |
1058 servent = getservbyname((char *) _stringVal(aNameOrNumber), protocol); |
1083 if (__isString(aNameOrNumber) || __isSymbol(aNameOrNumber)) { |
|
1084 servent = getservbyname((char *) __stringVal(aNameOrNumber), protocol); |
1059 if (servent != NULL) { |
1085 if (servent != NULL) { |
1060 RETURN ( __MKSMALLINT(ntohs(servent->s_port)) ); |
1086 RETURN ( __MKSMALLINT(ntohs(servent->s_port)) ); |
1061 } |
1087 } |
1062 if (tryBoth) { |
1088 if (tryBoth) { |
1063 servent = getservbyname((char *) _stringVal(aNameOrNumber), "udp"); |
1089 servent = getservbyname((char *) __stringVal(aNameOrNumber), "udp"); |
1064 if (servent != NULL) { |
1090 if (servent != NULL) { |
1065 RETURN ( __MKSMALLINT(ntohs(servent->s_port)) ); |
1091 RETURN ( __MKSMALLINT(ntohs(servent->s_port)) ); |
1066 } |
1092 } |
1067 } |
1093 } |
1068 RETURN ( nil ); |
1094 RETURN ( nil ); |
1080 "returns the protocol (as string) for a given service |
1106 "returns the protocol (as string) for a given service |
1081 or nil if no such service exists." |
1107 or nil if no such service exists." |
1082 %{ |
1108 %{ |
1083 #ifndef NO_SOCKET |
1109 #ifndef NO_SOCKET |
1084 struct servent *servent = NULL; |
1110 struct servent *servent = NULL; |
|
1111 short portNo; |
1085 |
1112 |
1086 if (__isSmallInteger(aNameOrNumber)) { |
1113 if (__isSmallInteger(aNameOrNumber)) { |
1087 servent = getservbyport(htons(_intVal(aNameOrNumber)), "tcp") ; |
1114 portNo = __intVal(aNameOrNumber); |
|
1115 servent = getservbyport(htons(portNo), "tcp") ; |
1088 if (servent == NULL) { |
1116 if (servent == NULL) { |
1089 servent = getservbyport(htons(_intVal(aNameOrNumber)), "udp") ; |
1117 servent = getservbyport(htons(portNo), "udp") ; |
1090 if (servent == NULL) { |
1118 if (servent == NULL) { |
1091 RETURN ( nil ); |
1119 RETURN ( nil ); |
1092 } |
1120 } |
1093 } |
1121 } |
1094 } else { |
1122 } else { |
1095 if (__isString(aNameOrNumber)) { |
1123 if (__isString(aNameOrNumber)) { |
1096 servent = getservbyname((char *) _stringVal(aNameOrNumber), "tcp"); |
1124 servent = getservbyname((char *) __stringVal(aNameOrNumber), "tcp"); |
1097 if (servent == NULL) { |
1125 if (servent == NULL) { |
1098 servent = getservbyname((char *) _stringVal(aNameOrNumber), "udp"); |
1126 servent = getservbyname((char *) __stringVal(aNameOrNumber), "udp"); |
1099 if (servent == NULL) { |
1127 if (servent == NULL) { |
1100 RETURN ( nil ); |
1128 RETURN ( nil ); |
1101 } |
1129 } |
1102 } |
1130 } |
1103 } |
1131 } |
1216 OBJ oClass, myDomain; |
1244 OBJ oClass, myDomain; |
1217 OBJ fp = __INST(filePointer); |
1245 OBJ fp = __INST(filePointer); |
1218 int nInstVars, nInstBytes, objSize; |
1246 int nInstVars, nInstBytes, objSize; |
1219 int sock; |
1247 int sock; |
1220 union { |
1248 union { |
1221 struct sockaddr_in in; |
1249 struct sockaddr_in in; |
1222 } sa; |
1250 } sa; |
1223 int alen; |
1251 int alen; |
1224 int n; |
1252 int n; |
1225 char *cp; |
1253 char *cp; |
1226 int flags = 0; |
1254 int flags = 0; |
1227 |
1255 |
1228 if (fp != nil) { |
1256 if (fp != nil) { |
1229 sock = fileno(__FILEVal(fp)); |
1257 sock = fileno(__FILEVal(fp)); |
1230 |
1258 |
1231 oClass = __Class(aDataBuffer); |
1259 oClass = __Class(aDataBuffer); |
1232 switch (_intVal(_ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
1260 switch (_intVal(_ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
1233 case BYTEARRAY: |
1261 case BYTEARRAY: |
1234 case WORDARRAY: |
1262 case WORDARRAY: |
1235 case LONGARRAY: |
1263 case LONGARRAY: |
1236 case FLOATARRAY: |
1264 case FLOATARRAY: |
1237 case DOUBLEARRAY: |
1265 case DOUBLEARRAY: |
1238 break; |
1266 break; |
1239 default: |
1267 default: |
1240 goto bad; |
1268 goto bad; |
1241 } |
1269 } |
1242 |
1270 |
1243 nInstVars = _intVal(_ClassInstPtr(oClass)->c_ninstvars); |
1271 nInstVars = _intVal(_ClassInstPtr(oClass)->c_ninstvars); |
1244 nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ); |
1272 nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ); |
1245 objSize = _Size(aDataBuffer) - nInstBytes; |
1273 objSize = _Size(aDataBuffer) - nInstBytes; |
1246 cp = (char *)__InstPtr(aDataBuffer) + nInstBytes; |
1274 cp = (char *)__InstPtr(aDataBuffer) + nInstBytes; |
1247 if (__isSmallInteger(startIndex)) { |
1275 if (__isSmallInteger(startIndex)) { |
1248 cp += __intVal(startIndex); |
1276 cp += __intVal(startIndex); |
1249 objSize -= __intVal(startIndex); |
1277 objSize -= __intVal(startIndex); |
1250 } |
1278 } |
1251 if (__isSmallInteger(nBytes)) { |
1279 if (__isSmallInteger(nBytes)) { |
1252 if (__intVal(nBytes) < objSize) { |
1280 if (__intVal(nBytes) < objSize) { |
1253 objSize = __intVal(nBytes); |
1281 objSize = __intVal(nBytes); |
1254 } |
1282 } |
1255 } |
1283 } |
1256 |
1284 |
1257 __BEGIN_INTERRUPTABLE__ |
1285 __BEGIN_INTERRUPTABLE__ |
1258 do { |
1286 do { |
1259 if (addrBytes == nil) { |
1287 if (addrBytes == nil) { |
1260 n = recvfrom(sock, cp, objSize, flags, (struct sockaddr *) 0, 0); |
1288 n = recvfrom(sock, cp, objSize, flags, (struct sockaddr *) 0, 0); |
1261 } else { |
1289 } else { |
1262 n = recvfrom(sock, cp, objSize, flags, (struct sockaddr *) &sa, &alen); |
1290 n = recvfrom(sock, cp, objSize, flags, (struct sockaddr *) &sa, &alen); |
1263 } |
1291 } |
1264 } while ((n < 0) && (errno == EINTR)); |
1292 } while ((n < 0) && (errno == EINTR)); |
1265 __END_INTERRUPTABLE__ |
1293 __END_INTERRUPTABLE__ |
1266 |
1294 |
1267 if (n >= 0) { |
1295 if (n >= 0) { |
1268 if (addrBytes != nil) { |
1296 if (addrBytes != nil) { |
1269 oClass = __Class(addrBytes); |
1297 oClass = __Class(addrBytes); |
1270 if ((_intVal(_ClassInstPtr(oClass)->c_flags) & ARRAYMASK) != BYTEARRAY) |
1298 if ((_intVal(_ClassInstPtr(oClass)->c_flags) & ARRAYMASK) != BYTEARRAY) |
1271 goto bad; |
1299 goto bad; |
1272 nInstVars = _intVal(_ClassInstPtr(oClass)->c_ninstvars); |
1300 nInstVars = _intVal(_ClassInstPtr(oClass)->c_ninstvars); |
1273 nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ); |
1301 nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ); |
1274 objSize = _Size(addrBytes) - nInstBytes; |
1302 objSize = _Size(addrBytes) - nInstBytes; |
1275 cp = (char *)__InstPtr(addrBytes) + nInstBytes; |
1303 cp = (char *)__InstPtr(addrBytes) + nInstBytes; |
1276 if (objSize < alen) |
1304 if (objSize < alen) |
1277 goto bad; |
1305 goto bad; |
1278 |
1306 |
1279 myDomain = __INST(domain); |
1307 myDomain = __INST(domain); |
1280 # ifdef AF_UNIX |
1308 # ifdef AF_UNIX |
1281 if (myDomain == @symbol(unix)) { |
1309 if (myDomain == @symbol(unix)) { |
1282 cp[0] = (sa.in.sin_addr.s_addr >> 24) & 0xFF; |
1310 cp[0] = (sa.in.sin_addr.s_addr >> 24) & 0xFF; |
1283 cp[2] = (sa.in.sin_addr.s_addr >> 16) & 0xFF; |
1311 cp[2] = (sa.in.sin_addr.s_addr >> 16) & 0xFF; |
1284 cp[3] = (sa.in.sin_addr.s_addr >> 8) & 0xFF; |
1312 cp[3] = (sa.in.sin_addr.s_addr >> 8) & 0xFF; |
1285 cp[4] = (sa.in.sin_addr.s_addr >> 0) & 0xFF; |
1313 cp[4] = (sa.in.sin_addr.s_addr >> 0) & 0xFF; |
1286 alen = 4; |
1314 alen = 4; |
1287 } |
1315 } |
1288 # endif |
1316 # endif |
1289 /* |
1317 /* |
1290 * XXXX add addressing stuff for other domains here ... |
1318 * XXXX add addressing stuff for other domains here ... |
1291 */ |
1319 */ |
1292 # ifdef AF_X25 |
1320 # ifdef AF_X25 |
1293 if (myDomain == @symbol(x25)) { |
1321 if (myDomain == @symbol(x25)) { |
1294 } |
1322 } |
1295 # endif |
1323 # endif |
1296 # ifdef AF_NS |
1324 # ifdef AF_NS |
1297 if (myDomain == @symbol(ns)) { |
1325 if (myDomain == @symbol(ns)) { |
1298 } |
1326 } |
1299 # endif |
1327 # endif |
1300 # ifdef AF_APPLETALK |
1328 # ifdef AF_APPLETALK |
1301 if (myDomain == @symbol(appletalk)) { |
1329 if (myDomain == @symbol(appletalk)) { |
1302 } |
1330 } |
1303 # endif |
1331 # endif |
1304 # ifdef AF_SNA |
1332 # ifdef AF_SNA |
1305 if (myDomain == @symbol(sna)) { |
1333 if (myDomain == @symbol(sna)) { |
1306 } |
1334 } |
1307 # endif |
1335 # endif |
1308 # ifdef AF_NS |
1336 # ifdef AF_NS |
1309 if (myDomain == @symbol(xns)) { |
1337 if (myDomain == @symbol(xns)) { |
1310 } |
1338 } |
1311 # endif |
1339 # endif |
1312 # ifdef AF_RAW |
1340 # ifdef AF_RAW |
1313 if (myDomain == @symbol(raw)) { |
1341 if (myDomain == @symbol(raw)) { |
1314 } |
1342 } |
1315 # endif |
1343 # endif |
1316 |
1344 # ifdef AF_ISO |
1317 addrLen = __MKSMALLINT(alen); |
1345 if (myDomain == @symbol(iso)) { |
1318 } |
1346 } |
1319 } |
1347 # endif |
1320 if (n < 0) { |
1348 # ifdef AF_DECnet |
1321 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
1349 if (myDomain == @symbol(decnet)) { |
1322 } |
1350 } |
1323 nReceived = __MKSMALLINT(n); |
1351 # endif |
|
1352 # ifdef AF_NETBIOS |
|
1353 if (myDomain == @symbol(decnet)) { |
|
1354 } |
|
1355 # endif |
|
1356 # if defined(AF_CCITT) && (AF_CCITT != AF_X25) |
|
1357 if (myDomain == @symbol(ccitt)) { |
|
1358 } |
|
1359 # endif |
|
1360 |
|
1361 addrLen = __MKSMALLINT(alen); |
|
1362 } |
|
1363 } |
|
1364 if (n < 0) { |
|
1365 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
|
1366 } |
|
1367 nReceived = __MKSMALLINT(n); |
1324 } |
1368 } |
1325 #endif |
1369 #endif |
1326 bad: ; |
1370 bad: ; |
1327 %}. |
1371 %}. |
1328 nReceived notNil ifTrue:[ |
1372 nReceived notNil ifTrue:[ |
1329 nReceived < 0 ifTrue:[ |
1373 nReceived < 0 ifTrue:[ |
1330 'Socket [warning]: ' infoPrint. |
1374 'Socket [warning]: ' infoPrint. |
1331 (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR. |
1375 (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR. |
1332 ]. |
1376 ]. |
1333 addrLen notNil ifTrue:[ |
1377 addrLen notNil ifTrue:[ |
1334 anAddressBuffer class isBytes ifTrue:[ |
1378 anAddressBuffer class isBytes ifTrue:[ |
1335 anAddressBuffer replaceFrom:1 to:addrLen with:addrBytes |
1379 anAddressBuffer replaceFrom:1 to:addrLen with:addrBytes |
1336 ] ifFalse:[ |
1380 ] ifFalse:[ |
1337 "/ can be SocketAddress for ST-80 compatibility |
1381 "/ can be SocketAddress for ST-80 compatibility |
1338 anAddressBuffer hostAddress:(addrBytes copyTo:addrLen) |
1382 anAddressBuffer hostAddress:(addrBytes copyTo:addrLen) |
1339 ]. |
1383 ]. |
1340 ]. |
1384 ]. |
1341 ^ nReceived |
1385 ^ nReceived |
1342 ]. |
1386 ]. |
1343 " |
1387 " |
1344 arrive here if you try to receive into an invalid buffer |
1388 arrive here if you try to receive into an invalid buffer |
1345 (i.e. not ByteArray-like), |
1389 (i.e. not ByteArray-like), |
1346 or if the addressBuffer is nonNil AND not a ByteArray/String |
1390 or if the addressBuffer is nonNil AND not a ByteArray/String |
1572 "low level bind - returns true if ok, false otherwise. |
1616 "low level bind - returns true if ok, false otherwise. |
1573 Currently only non-address binding is supported; |
1617 Currently only non-address binding is supported; |
1574 i.e. address must always be nil. |
1618 i.e. address must always be nil. |
1575 |
1619 |
1576 The interpretation of portNrOrName depends on the domain: |
1620 The interpretation of portNrOrName depends on the domain: |
1577 inet domain uses (4byte) byteArray like internet numbers, |
1621 inet domain uses (4byte) byteArray like internet numbers, |
1578 unix domain uses pathname strings, |
1622 unix domain uses pathname strings, |
1579 others use whatever will come up in the future |
1623 others use whatever will come up in the future |
1580 |
1624 |
1581 The reuse boolean argument controls if the SO_REUSEADDR socket option |
1625 The reuse boolean argument controls if the SO_REUSEADDR socket option |
1582 is to be set (to avoid the 'bind: address in use' error). |
1626 is to be set (to avoid the 'bind: address in use' error). |
1583 " |
1627 " |
1584 |
1628 |
1585 filePointer isNil ifTrue:[ |
1629 filePointer isNil ifTrue:[ |
1586 ^ self error:'not a valid socket' |
1630 ^ self error:'not a valid socket' |
1587 ]. |
1631 ]. |
1588 %{ |
1632 %{ |
1589 #ifndef NO_SOCKET |
1633 #ifndef NO_SOCKET |
1590 OBJ t = __INST(filePointer); |
1634 OBJ t = __INST(filePointer); |
1591 OBJ myDomain; |
1635 OBJ myDomain; |
1592 int sock; |
1636 int sock; |
1593 union { |
1637 union { |
1594 struct sockaddr_in in; |
1638 struct sockaddr_in in; |
1595 struct sockaddr_un un; |
1639 # ifdef AF_UNIX |
|
1640 struct sockaddr_un un; |
|
1641 # endif /* AF_UNIX */ |
1596 } sa; |
1642 } sa; |
1597 int sockaddr_size; |
1643 int sockaddr_size; |
1598 int ret; |
1644 int ret; |
1599 int on = 1; |
1645 int on = 1; |
1600 int ok; |
1646 int ok; |
1601 |
1647 |
1602 if (!__isString(__INST(domain)) && !__isSymbol(__INST(domain))) { |
1648 if (!__isString(__INST(domain)) && !__isSymbol(__INST(domain))) { |
1603 DBGPRINTF(("SOCKET: invalid domain arg\n")); |
1649 DBGPRINTF(("SOCKET: invalid domain arg\n")); |
1604 RETURN (false); |
1650 RETURN (false); |
1605 } |
1651 } |
1606 |
1652 |
1607 ok = 0; |
1653 ok = 0; |
1608 myDomain = __INST(domain); |
1654 myDomain = __INST(domain); |
1609 # ifdef AF_INET |
1655 # ifdef AF_INET |
1610 if (myDomain == @symbol(inet)) { |
1656 if (myDomain == @symbol(inet)) { |
1611 /* |
1657 /* |
1612 * INET addresses - port must be a smallinteger or nil |
1658 * INET addresses - port must be a smallinteger or nil |
1613 */ |
1659 */ |
1614 sa.in.sin_family = AF_INET; |
1660 sa.in.sin_family = AF_INET; |
1615 |
1661 |
1616 if (portNrOrName == nil) { |
1662 if (portNrOrName == nil) { |
1617 sa.in.sin_port = 0; |
1663 sa.in.sin_port = 0; |
1618 } else { |
1664 } else { |
1619 if (! __isSmallInteger(portNrOrName)) { |
1665 if (! __isSmallInteger(portNrOrName)) { |
1620 DBGPRINTF(("SOCKET: invalid port arg\n")); |
1666 DBGPRINTF(("SOCKET: invalid port arg\n")); |
1621 RETURN (false); |
1667 RETURN (false); |
1622 } |
1668 } |
1623 sa.in.sin_port = htons((u_short) _intVal(portNrOrName)); |
1669 sa.in.sin_port = htons((u_short) _intVal(portNrOrName)); |
1624 } |
1670 } |
1625 |
1671 |
1626 /* |
1672 /* |
1627 * INET addresses - addr must be nil, integer or byteArray |
1673 * INET addresses - addr must be nil, integer or byteArray |
1628 */ |
1674 */ |
1629 if (address == nil) { |
1675 if (address == nil) { |
1630 sa.in.sin_addr.s_addr = htonl(INADDR_ANY); |
1676 sa.in.sin_addr.s_addr = htonl(INADDR_ANY); |
1631 } else { |
1677 } else { |
1632 if (__isInteger(address)) { |
1678 if (__isInteger(address)) { |
1633 sa.in.sin_addr.s_addr = htonl(__longIntVal(address)); |
1679 sa.in.sin_addr.s_addr = htonl(__longIntVal(address)); |
1634 } else { |
1680 } else { |
1635 if (__isByteArray(address)) { |
1681 if (__isByteArray(address)) { |
1636 unsigned char *cp; |
1682 unsigned char *cp; |
1637 int n; |
1683 int n; |
1638 |
1684 |
1639 cp = __ByteArrayInstPtr(address)->ba_element; |
1685 cp = __ByteArrayInstPtr(address)->ba_element; |
1640 n = __byteArraySize(address); |
1686 n = __byteArraySize(address); |
1641 if (n > 4) n = 4; |
1687 if (n > 4) n = 4; |
1642 bcopy(cp, &sa.in.sin_addr.s_addr, n); |
1688 bcopy(cp, &sa.in.sin_addr.s_addr, n); |
1643 } else { |
1689 } else { |
1644 char *hostName; |
1690 char *hostName; |
1645 unsigned addr; |
1691 unsigned addr; |
1646 struct hostent *hp ; |
1692 struct hostent *hp ; |
1647 |
1693 |
1648 if (! __isString(address)) { |
1694 if (! __isString(address)) { |
1649 DBGPRINTF(("SOCKET: invalid address arg in bind\n")); |
1695 DBGPRINTF(("SOCKET: invalid address arg in bind\n")); |
1650 RETURN (false); |
1696 RETURN (false); |
1651 } |
1697 } |
1652 |
1698 |
1653 hostName = (char *) _stringVal(address); |
1699 hostName = (char *) __stringVal(address); |
1654 |
1700 |
1655 if ((addr = inet_addr(hostName)) != -1) { |
1701 if ((addr = inet_addr(hostName)) != -1) { |
1656 /* |
1702 /* |
1657 * is Internet addr in octet notation |
1703 * is Internet addr in octet notation |
1658 */ |
1704 */ |
1659 bcopy(&addr, (char *) &sa.in.sin_addr, sizeof(addr)) ; /* set address */ |
1705 bcopy(&addr, (char *) &sa.in.sin_addr, sizeof(addr)) ; /* set address */ |
1660 } else { |
1706 } else { |
1661 /* |
1707 /* |
1662 * do we know the host's address? |
1708 * do we know the host's address? |
1663 */ |
1709 */ |
1664 if ((hp = gethostbyname(hostName)) == NULL) { |
1710 if ((hp = gethostbyname(hostName)) == NULL) { |
1665 DBGPRINTF(("SOCKET: unknown host:%s\n", hostName)); |
1711 DBGPRINTF(("SOCKET: unknown host:%s\n", hostName)); |
1666 RETURN (false); |
1712 RETURN (false); |
1667 } |
1713 } |
1668 bcopy(hp->h_addr, (char *) &sa.in.sin_addr, hp->h_length) ; |
1714 bcopy(hp->h_addr, (char *) &sa.in.sin_addr, hp->h_length) ; |
1669 sa.in.sin_family = hp->h_addrtype; |
1715 sa.in.sin_family = hp->h_addrtype; |
1670 } |
1716 } |
1671 } |
1717 } |
1672 } |
1718 } |
1673 } |
1719 } |
1674 DBGPRINTF(("SOCKET: bind addr: %x port: %x\n", sa.in.sin_addr.s_addr, sa.in.sin_port)); |
1720 DBGPRINTF(("SOCKET: bind addr: %x port: %x\n", sa.in.sin_addr.s_addr, sa.in.sin_port)); |
1675 sockaddr_size = sizeof(struct sockaddr_in); |
1721 sockaddr_size = sizeof(struct sockaddr_in); |
1676 ok = 1; |
1722 ok = 1; |
1677 } |
1723 } |
1678 # endif |
1724 # endif |
1679 # ifdef AF_UNIX |
1725 # ifdef AF_UNIX |
1680 if (myDomain == @symbol(unix)) { |
1726 if (myDomain == @symbol(unix)) { |
1681 char *pathName; |
1727 char *pathName; |
1682 int l; |
1728 int l; |
1683 |
1729 |
1684 if (! __isString(portNrOrName)) { |
1730 if (! __isString(portNrOrName)) { |
1685 DBGPRINTF(("SOCKET: invalid port (pathname) arg\n")); |
1731 DBGPRINTF(("SOCKET: invalid port (pathname) arg\n")); |
1686 RETURN (false); |
1732 RETURN (false); |
1687 } |
1733 } |
1688 pathName = __stringVal(portNrOrName); |
1734 pathName = __stringVal(portNrOrName); |
1689 l = strlen(pathName); |
1735 l = strlen(pathName); |
1690 if ((l + sizeof ( sa.un.sun_family )) > sizeof(struct sockaddr_un)) { |
1736 if ((l + sizeof ( sa.un.sun_family )) > sizeof(struct sockaddr_un)) { |
1691 DBGPRINTF(("SOCKET: pathname too long\n")); |
1737 DBGPRINTF(("SOCKET: pathname too long\n")); |
1692 RETURN (false); |
1738 RETURN (false); |
1693 } |
1739 } |
1694 |
1740 |
1695 strcpy(sa.un.sun_path, pathName); |
1741 strcpy(sa.un.sun_path, pathName); |
1696 sa.un.sun_family = AF_UNIX; |
1742 sa.un.sun_family = AF_UNIX; |
1697 sockaddr_size = l + sizeof ( sa.un.sun_family ); |
1743 sockaddr_size = l + sizeof ( sa.un.sun_family ); |
1698 ok = 1; |
1744 ok = 1; |
1699 } |
1745 } |
1700 # endif |
1746 # endif |
1701 /* |
1747 /* |
1702 * XXXX add addressing stuff for other domains here ... |
1748 * XXXX add addressing stuff for other domains here ... |
1703 */ |
1749 */ |
1723 # endif |
1773 # endif |
1724 # ifdef AF_RAW |
1774 # ifdef AF_RAW |
1725 if (myDomain == @symbol(raw)) { |
1775 if (myDomain == @symbol(raw)) { |
1726 } |
1776 } |
1727 # endif |
1777 # endif |
|
1778 # ifdef AF_ISO |
|
1779 if (myDomain == @symbol(iso)) { |
|
1780 } |
|
1781 # endif |
|
1782 # ifdef AF_NETBIOS |
|
1783 if (myDomain == @symbol(decnet)) { |
|
1784 } |
|
1785 # endif |
|
1786 # if defined(AF_CCITT) && (AF_CCITT != AF_X25) |
|
1787 if (myDomain == @symbol(ccitt)) { |
|
1788 } |
|
1789 # endif |
1728 |
1790 |
1729 if (! ok) { |
1791 if (! ok) { |
1730 DBGPRINTF(("SOCKET: unsupported domain\n")); |
1792 DBGPRINTF(("SOCKET: unsupported domain\n")); |
1731 RETURN (false); |
1793 RETURN (false); |
1732 } |
1794 } |
1733 |
1795 |
1734 sock = fileno(__FILEVal(t)); |
1796 sock = fileno(__FILEVal(t)); |
1735 |
1797 |
1736 # ifdef SO_REUSEADDR |
1798 # ifdef SO_REUSEADDR |
1737 if (reuse == true) { |
1799 if (reuse == true) { |
1738 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) { |
1800 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) { |
1739 DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n")); |
1801 DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n")); |
1740 } |
1802 } |
1741 } |
1803 } |
1742 # endif /* SO_REUSEADDR */ |
1804 # endif /* SO_REUSEADDR */ |
1743 |
1805 |
1744 __BEGIN_INTERRUPTABLE__ |
1806 __BEGIN_INTERRUPTABLE__ |
1745 do { |
1807 do { |
1746 ret = bind(sock, (struct sockaddr *)&sa, sockaddr_size); |
1808 ret = bind(sock, (struct sockaddr *)&sa, sockaddr_size); |
1747 } while ((ret < 0) && (errno == EINTR)); |
1809 } while ((ret < 0) && (errno == EINTR)); |
1748 __END_INTERRUPTABLE__ |
1810 __END_INTERRUPTABLE__ |
1749 |
1811 |
1750 if (ret < 0) { |
1812 if (ret < 0) { |
1751 DBGPRINTF(("SOCKET: bind failed errno=%d\n", errno)); |
1813 DBGPRINTF(("SOCKET: bind failed errno=%d\n", errno)); |
1752 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
1814 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
1753 RETURN (false); |
1815 RETURN (false); |
1754 } |
1816 } |
1755 |
1817 |
1756 __INST(port) = portNrOrName; __STORE(self, portNrOrName); |
1818 __INST(port) = portNrOrName; __STORE(self, portNrOrName); |
1757 |
1819 |
1758 # ifdef AF_INET |
1820 # ifdef AF_INET |
1759 |
1821 |
1760 if (myDomain == @symbol(inet)) { |
1822 if (myDomain == @symbol(inet)) { |
1761 if (! __isSmallInteger(portNrOrName) |
1823 if (! __isSmallInteger(portNrOrName) |
1762 || (portNrOrName == __MKSMALLINT(0))) { |
1824 || (portNrOrName == __MKSMALLINT(0))) { |
1763 int p; |
1825 int p; |
1764 |
1826 |
1765 /* |
1827 /* |
1766 * INET anonymous port - get the actual portNr |
1828 * INET anonymous port - get the actual portNr |
1767 */ |
1829 */ |
1768 if (getsockname(sock, (struct sockaddr *)&sa, &sockaddr_size) < 0) { |
1830 if (getsockname(sock, (struct sockaddr *)&sa, &sockaddr_size) < 0) { |
1769 DBGPRINTF(("SOCKET: cannot get peername\n")); |
1831 DBGPRINTF(("SOCKET: cannot get peername\n")); |
1770 } else { |
1832 } else { |
1771 DBGPRINTF(("SOCKET: anon port=%x\n", sa.in.sin_port)); |
1833 DBGPRINTF(("SOCKET: anon port=%x\n", sa.in.sin_port)); |
1772 p = ntohs(sa.in.sin_port); |
1834 p = ntohs(sa.in.sin_port); |
1773 __INST(port) = __MKSMALLINT(p); |
1835 __INST(port) = __MKSMALLINT(p); |
1774 } |
1836 } |
1775 } |
1837 } |
1776 } |
1838 } |
1777 # endif |
1839 # endif |
1778 #else /* NO_SOCKET */ |
1840 #else /* NO_SOCKET */ |
1779 RETURN (false); |
1841 RETURN (false); |
1780 #endif /* NO_SOCKET */ |
1842 #endif /* NO_SOCKET */ |
1781 %}. |
1843 %}. |
1782 ^ true |
1844 ^ true |
1783 |
1845 |
1784 " |
1846 " |
1785 (Socket domain:#inet type:#stream) |
1847 (Socket domain:#inet type:#stream) |
1786 bindTo:9999 |
1848 bindTo:9999 |
1787 address:nil |
1849 address:nil |
1788 " |
1850 " |
1789 ! |
1851 ! |
1790 |
1852 |
1791 blockingAcceptOn:aSocket |
1853 blockingAcceptOn:aSocket |
1792 "accept a connection on a server port (created with:'Socket>>onIPPort:') |
1854 "accept a connection on a server port (created with:'Socket>>onIPPort:') |
1996 n = __byteArraySize(hostOrPathName); |
2148 n = __byteArraySize(hostOrPathName); |
1997 if (n > 4) n = 4; |
2149 if (n > 4) n = 4; |
1998 bcopy(cp, &sa.in.sin_addr.s_addr, n); |
2150 bcopy(cp, &sa.in.sin_addr.s_addr, n); |
1999 } else { |
2151 } else { |
2000 if (! __isString(hostOrPathName)) { |
2152 if (! __isString(hostOrPathName)) { |
2001 DBGPRINTF(("SOCKET: invalid hostname arg\n")); |
2153 DBGPRINTF(("SOCKET: invalid hostname arg\n")); |
2002 RETURN (false); |
2154 RETURN (false); |
2003 } |
2155 } |
2004 |
2156 |
2005 hostName = (char *) _stringVal(hostOrPathName); |
2157 hostName = (char *) __stringVal(hostOrPathName); |
2006 |
2158 |
2007 if ((addr = inet_addr(hostName)) != -1) { |
2159 if ((addr = inet_addr(hostName)) != -1) { |
2008 /* |
2160 /* |
2009 * is Internet addr in octet notation |
2161 * is Internet addr in octet notation |
2010 */ |
2162 */ |
2011 bcopy(&addr, (char *) &sa.in.sin_addr, sizeof(addr)) ; /* set address */ |
2163 bcopy(&addr, (char *) &sa.in.sin_addr, sizeof(addr)) ; /* set address */ |
2012 } else { |
2164 } else { |
2013 /* |
2165 /* |
2014 * do we know the host's address? |
2166 * do we know the host's address? |
2015 */ |
2167 */ |
2016 if ((hp = gethostbyname(hostName)) == NULL) { |
2168 if ((hp = gethostbyname(hostName)) == NULL) { |
2017 DBGPRINTF(("SOCKET: unknown host:%s\n", hostName)); |
2169 DBGPRINTF(("SOCKET: unknown host:%s\n", hostName)); |
2018 RETURN (false); |
2170 RETURN (false); |
2019 } |
2171 } |
2020 bcopy(hp->h_addr, (char *) &sa.in.sin_addr, hp->h_length) ; |
2172 bcopy(hp->h_addr, (char *) &sa.in.sin_addr, hp->h_length) ; |
2021 sa.in.sin_family = hp->h_addrtype; |
2173 sa.in.sin_family = hp->h_addrtype; |
2022 } |
2174 } |
2023 } |
2175 } |
2024 |
2176 |
2025 DBGPRINTF(("SOCKET: connect addr: %x port: %d\n", sa.in.sin_addr, sa.in.sin_port)); |
2177 DBGPRINTF(("SOCKET: connect addr: %x port: %d\n", sa.in.sin_addr, sa.in.sin_port)); |
2026 |
2178 |
2498 sa.sin_family = AF_INET; |
2681 sa.sin_family = AF_INET; |
2499 sa.sin_addr.s_addr = htonl(INADDR_ANY); |
2682 sa.sin_addr.s_addr = htonl(INADDR_ANY); |
2500 |
2683 |
2501 if ((hostName != nil) && __isString(hostName)){ |
2684 if ((hostName != nil) && __isString(hostName)){ |
2502 bzero(&sa, sizeof(sa)) ; |
2685 bzero(&sa, sizeof(sa)) ; |
2503 if ((addr = inet_addr((char *) _stringVal(hostName))) != -1) { |
2686 if ((addr = inet_addr((char *) __stringVal(hostName))) != -1) { |
2504 /* |
2687 /* |
2505 * is Internet addr in octet notation |
2688 * is Internet addr in octet notation |
2506 */ |
2689 */ |
2507 bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */ |
2690 bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */ |
2508 } else { |
2691 } else { |
2509 /* |
2692 /* |
2510 * do we know the host's address? |
2693 * do we know the host's address? |
2511 */ |
2694 */ |
2512 if ((hp = gethostbyname((char *) _stringVal(hostName))) == NULL) { |
2695 if ((hp = gethostbyname((char *) __stringVal(hostName))) == NULL) { |
2513 DBGPRINTF(("SOCKET: unknown host\n")); |
2696 DBGPRINTF(("SOCKET: unknown host\n")); |
2514 RETURN ( nil ); |
2697 RETURN ( nil ); |
2515 } |
2698 } |
2516 bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ; |
2699 bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ; |
2517 sa.sin_family = hp->h_addrtype; |
2700 sa.sin_family = hp->h_addrtype; |
2632 FILE *fp; |
2815 FILE *fp; |
2633 int ret; |
2816 int ret; |
2634 |
2817 |
2635 if (hostName != nil) { |
2818 if (hostName != nil) { |
2636 bzero(&sa, sizeof(sa)) ; |
2819 bzero(&sa, sizeof(sa)) ; |
2637 if ((addr = inet_addr((char *) _stringVal(hostName))) != -1) { |
2820 if ((addr = inet_addr((char *) __stringVal(hostName))) != -1) { |
2638 /* |
2821 /* |
2639 * is Internet addr in octet notation |
2822 * is Internet addr in octet notation |
2640 */ |
2823 */ |
2641 bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */ |
2824 bcopy(&addr, (char *) &sa.sin_addr, sizeof(addr)) ; /* set address */ |
2642 sa.sin_family = AF_INET ; |
2825 sa.sin_family = AF_INET ; |
2643 } else { |
2826 } else { |
2644 /* |
2827 /* |
2645 * is hostname - |
2828 * is hostname - |
2646 * do we know the host's address? |
2829 * do we know the host's address? |
2647 */ |
2830 */ |
2648 if ((hp = gethostbyname((char *) _stringVal(hostName))) == NULL) { |
2831 if ((hp = gethostbyname((char *) __stringVal(hostName))) == NULL) { |
2649 DBGPRINTF(("SOCKET: unknown host\n")); |
2832 DBGPRINTF(("SOCKET: unknown host\n")); |
2650 RETURN ( nil ); |
2833 RETURN ( nil ); |
2651 } |
2834 } |
2652 bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ; |
2835 bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length) ; |
2653 sa.sin_family = hp->h_addrtype ; |
2836 sa.sin_family = hp->h_addrtype ; |