Socket.st
changeset 1935 326f8d31e7ca
parent 1911 cb6a52d6944a
child 1938 831af28cc848
equal deleted inserted replaced
1934:fee89061a2e0 1935:326f8d31e7ca
  1515     "Modified: / 31-05-2007 / 17:59:53 / cg"
  1515     "Modified: / 31-05-2007 / 17:59:53 / cg"
  1516 !
  1516 !
  1517 
  1517 
  1518 listenOn:aPortNr backlogSize:aNumber
  1518 listenOn:aPortNr backlogSize:aNumber
  1519     self bindTo:aPortNr address:nil.
  1519     self bindTo:aPortNr address:nil.
  1520     self listenWithBacklog:aNumber
  1520     self listenFor:aNumber
  1521 
  1521 
  1522     "Created: / 31-05-2007 / 17:59:47 / cg"
  1522     "Created: / 31-05-2007 / 17:59:47 / cg"
  1523 !
  1523 !
  1524 
  1524 
  1525 peerName
  1525 peerName
  1528 
  1528 
  1529     ^ self getPeer
  1529     ^ self getPeer
  1530 !
  1530 !
  1531 
  1531 
  1532 primSocketLocalPort:aSocket
  1532 primSocketLocalPort:aSocket
  1533     ^ port
  1533     ^ self port
  1534 !
  1534 !
  1535 
  1535 
  1536 sendData: aStringOrByteArray
  1536 sendData: aStringOrByteArray
  1537 	"Send all of the data in the given array, even if it requires multiple calls to send it all.
  1537 	"Send all of the data in the given array, even if it requires multiple calls to send it all.
  1538 	 Return the number of bytes sent."
  1538 	 Return the number of bytes sent."
  1586     self readWait
  1586     self readWait
  1587 
  1587 
  1588     "Created: / 04-06-2007 / 21:28:40 / cg"
  1588     "Created: / 04-06-2007 / 21:28:40 / cg"
  1589 ! !
  1589 ! !
  1590 
  1590 
  1591 !Socket methodsFor:'closing'!
  1591 !Socket methodsFor:'accepting connections'!
  1592 
  1592 
  1593 shutDown
  1593 accept
  1594     "shutDown and close the socket"
  1594     "create a new TCP socket from accepting on the receiver.
  1595 
  1595      This method will suspend the current process if no connection is waiting.
  1596     self shutdown:2.
  1596      For ST-80 compatibility"
  1597     self close
  1597 
  1598 !
  1598     |newSock|
  1599 
  1599 
  1600 shutDownInput
  1600     self readWait.
  1601     "shutDown the input side of the socket.
  1601     newSock := self class new.
  1602      Any read on the socket will signal end-of-file from now on.
  1602     (newSock primAcceptOn:self blocking:false) ifFalse:[
  1603      The other side MAY be informed, that no more data will be accepted
  1603         "should raise an error here"
  1604      (e.g. setting the TCP-Windowsize to 0)"
  1604         ^ nil
  1605 
  1605     ].
  1606     self shutdown:0.
  1606     ^ newSock
  1607 !
  1607 
  1608 
  1608     "
  1609 shutDownOutput
  1609      |sock newSock|
  1610     "shutDown the output side of the socket.
  1610 
  1611      Any write to the socket will signal end-of-file from now on.
  1611      sock := Socket provide:8004.
  1612      The other side will get a end-of-file condition,
  1612      sock listenFor:5.
  1613      after the last buffered data has been read"
  1613      newSock := sock accept.
  1614 
  1614     "
  1615     self shutdown:1.
  1615 !
       
  1616 
       
  1617 blockingAccept
       
  1618     "create a new TCP socket from accepting on the receiver.
       
  1619      This method will suspend the smalltalk image with all smalltalk processes if no connection is waiting.
       
  1620      For ST-80 compatibility"
       
  1621 
       
  1622     |newSock|
       
  1623 
       
  1624     newSock := self class new.
       
  1625     (newSock primAcceptOn:self blocking:true) ifFalse:[
       
  1626         "should raise an error here"
       
  1627         ^ nil
       
  1628     ].
       
  1629     ^ newSock
  1616 ! !
  1630 ! !
  1617 
  1631 
  1618 !Socket methodsFor:'datagram transmission'!
  1632 !Socket methodsFor:'binding'!
  1619 
       
  1620 receiveBuffer:aDataBuffer start:startIndex for:nBytes
       
  1621     "receive data
       
  1622      Return the number of bytes received, or a negative number on error.
       
  1623      On error, the unix error code is left in the lastErrorNumber
       
  1624      instance variable.
       
  1625      The thread blocks until data arrives - you may want to wait before
       
  1626      receiving, using #readWait or #readWaitWithTimeout:."
       
  1627 
       
  1628     |nReceived|
       
  1629 
       
  1630 %{
       
  1631 #ifndef NO_SOCKET
       
  1632     OBJ fp = __INST(filePointer);
       
  1633 
       
  1634     if (fp != nil) {
       
  1635 	SOCKET sock;
       
  1636 	int objSize, offs;
       
  1637 	int n;
       
  1638 	char *extPtr;
       
  1639 	unsigned char *buffer;
       
  1640 	unsigned char *allocatedBuffer;
       
  1641 	int flags = 0;
       
  1642 
       
  1643 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  1644 
       
  1645 	if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad;
       
  1646 	if (__isSmallInteger(nBytes)) {
       
  1647 	    if (__intVal(nBytes) < objSize) {
       
  1648 		objSize = __intVal(nBytes);
       
  1649 	    }
       
  1650 	}
       
  1651 
       
  1652 # ifdef DO_WRAP_CALLS
       
  1653 	if (extPtr) {
       
  1654 	    buffer = extPtr + offs;
       
  1655 	} else {
       
  1656 	    allocatedBuffer = buffer = (char *)malloc(objSize);
       
  1657 	}
       
  1658 
       
  1659 	do {
       
  1660 	    __threadErrno = 0;
       
  1661 	    n = STX_WSA_CALL4("recv", recv, sock, buffer, objSize, flags);
       
  1662 	} while ((n < 0) && (__threadErrno == EINTR));
       
  1663 
       
  1664 	if (allocatedBuffer) {
       
  1665 	    if (n > 0) {
       
  1666 		bcopy(allocatedBuffer, (char *)__InstPtr(aDataBuffer) + offs, n);
       
  1667 	    }
       
  1668 	    free(allocatedBuffer);
       
  1669 	}
       
  1670 # else
       
  1671 	__BEGIN_INTERRUPTABLE__
       
  1672 	do {
       
  1673 	    if (extPtr) {
       
  1674 		n = recv(sock, extPtr + offs, objSize, flags);
       
  1675 	    } else {
       
  1676 		n = recv(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, flags);
       
  1677 	    }
       
  1678 	} while ((n < 0) && (errno == EINTR));
       
  1679 	__END_INTERRUPTABLE__
       
  1680 # endif
       
  1681 
       
  1682 	if (n < 0) {
       
  1683 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  1684 	}
       
  1685 	nReceived = __MKSMALLINT(n);
       
  1686     }
       
  1687 #endif
       
  1688 bad: ;
       
  1689 %}.
       
  1690     nReceived notNil ifTrue:[
       
  1691 	nReceived < 0 ifTrue:[
       
  1692 	    'Socket [warning]: ' infoPrint.
       
  1693 	    (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR.
       
  1694 	].
       
  1695 	^ nReceived
       
  1696     ].
       
  1697     "
       
  1698      arrive here if you try to receive into an invalid buffer (i.e. not ByteArray-like)
       
  1699     "
       
  1700     self primitiveFailed
       
  1701 !
       
  1702 
       
  1703 receiveFrom:anAddressBuffer buffer:aDataBuffer
       
  1704     "receive datagramm data - put address of originating host into
       
  1705      anAddressBuffer, data into aBuffer.
       
  1706      Both must be ByteArray-like. The addressBuffer must
       
  1707      provide space for a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  1708      Return the number of bytes received, or a negative number on error.
       
  1709      On error, the unix error code is left in the lastErrorNumber
       
  1710      instance variable."
       
  1711 
       
  1712     ^ self receiveFrom:anAddressBuffer buffer:aDataBuffer start:1 for:(aDataBuffer size)
       
  1713 !
       
  1714 
       
  1715 receiveFrom:anAddressBuffer buffer:aDataBuffer start:startIndex for:nBytes
       
  1716     "receive datagramm data
       
  1717      - put address of originating host into anAddressBuffer, data into aBuffer.
       
  1718      For backward compatibility, the addressBuffer may be a non-SocketAddress;
       
  1719      then, it must be a byteArray with appropriate size for the addressBytes.
       
  1720 
       
  1721      Return the number of bytes received, or a negative number on error.
       
  1722      On error, the unix error code is left in the lastErrorNumber
       
  1723      instance variable.
       
  1724      The thread blocks until data arrives - you may want to wait before
       
  1725      receiving, using #readWait or #readWaitWithTimeout:."
       
  1726 
       
  1727     |domainClass addr addrLen nReceived|
       
  1728 
       
  1729     domainClass := self class socketAddressClassForDomain:domain.
       
  1730     domainClass isNil ifTrue:[
       
  1731 	^ self error:'invalid (unsupported) domain'.
       
  1732     ].
       
  1733     (anAddressBuffer isKindOf:SocketAddress) ifTrue:[
       
  1734 	anAddressBuffer class == domainClass ifFalse:[
       
  1735 	    ^ self error:'addressBuffer class mismatch (domain)'.
       
  1736 	].
       
  1737 	addr := anAddressBuffer.
       
  1738     ] ifFalse:[
       
  1739 	anAddressBuffer notNil ifTrue:[
       
  1740 	    addr := domainClass new.
       
  1741 	].
       
  1742     ].
       
  1743 
       
  1744 %{
       
  1745 #ifndef NO_SOCKET
       
  1746     OBJ fp = __INST(filePointer);
       
  1747 
       
  1748     if (fp != nil) {
       
  1749 	SOCKET sock;
       
  1750 	int objSize;
       
  1751 	union sockaddr_u sa;
       
  1752 	unsigned int alen = 0;
       
  1753 	int n, offs;
       
  1754 	int flags = 0;
       
  1755 	char *extPtr;
       
  1756 	unsigned char *allocatedBuffer = NULL;
       
  1757 	unsigned char *buffer = NULL;
       
  1758 
       
  1759 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  1760 
       
  1761 	if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad;
       
  1762 	if (__isSmallInteger(nBytes)) {
       
  1763 	    if (__intVal(nBytes) < objSize) {
       
  1764 		objSize = __intVal(nBytes);
       
  1765 	    }
       
  1766 	}
       
  1767 # ifdef DO_WRAP_CALLS
       
  1768 	if (extPtr) {
       
  1769 	    buffer = extPtr + offs;
       
  1770 	} else {
       
  1771 	    allocatedBuffer = buffer = (char *)malloc(objSize);
       
  1772 	}
       
  1773 
       
  1774 	do {
       
  1775 	    __threadErrno = 0;
       
  1776 	    alen = sizeof(sa);
       
  1777 	    n = STX_WSA_CALL6("recvfrom", recvfrom, sock, buffer, objSize, flags, (struct sockaddr *)&sa, &alen);
       
  1778 	} while ((n < 0) && (__threadErrno == EINTR));
       
  1779 
       
  1780 	if (allocatedBuffer) {
       
  1781 	    if (n > 0) {
       
  1782 		bcopy(allocatedBuffer, (char *)__InstPtr(aDataBuffer) + offs, n);
       
  1783 	    }
       
  1784 	    free(allocatedBuffer);
       
  1785 	}
       
  1786 # else
       
  1787 	__BEGIN_INTERRUPTABLE__
       
  1788 	do {
       
  1789 	    alen = sizeof(sa);
       
  1790 	    if (extPtr) {
       
  1791 		n = recvfrom(sock, extPtr + offs, objSize, flags, (struct sockaddr *) &sa, &alen);
       
  1792 	    } else {
       
  1793 		n = recvfrom(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, flags, (struct sockaddr *) &sa, &alen);
       
  1794 	    }
       
  1795 	} while ((n < 0) && (errno == EINTR));
       
  1796 	__END_INTERRUPTABLE__
       
  1797 # endif
       
  1798 
       
  1799 	if (n >= 0) {
       
  1800 	    if (__isNonNilObject(addr)) {
       
  1801 		char *addrPtr;
       
  1802 		OBJ oClass;
       
  1803 		int nInstVars, nInstBytes, objSize;
       
  1804 
       
  1805 		oClass = __qClass(addr);
       
  1806 		if (! __isBytes(addr) )
       
  1807 		    goto bad;
       
  1808 		nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
       
  1809 		nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
       
  1810 		objSize = __qSize(addr) - nInstBytes;
       
  1811 		addrPtr = (char *)__InstPtr(addr) + nInstBytes;
       
  1812 		if (objSize < alen)
       
  1813 		    goto bad;
       
  1814 
       
  1815 		/*
       
  1816 		 * extract the datagrams address
       
  1817 		 */
       
  1818 		bcopy((char *)&sa, addrPtr, alen);
       
  1819 		addrLen = __MKSMALLINT(alen);
       
  1820 	    }
       
  1821 	}
       
  1822 	if (n < 0) {
       
  1823 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  1824 	}
       
  1825 	nReceived = __MKSMALLINT(n);
       
  1826     }
       
  1827 #endif
       
  1828 bad: ;
       
  1829 %}.
       
  1830     nReceived notNil ifTrue:[
       
  1831 	nReceived < 0 ifTrue:[
       
  1832 	    'Socket [warning]: ' infoPrint.
       
  1833 	    (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR.
       
  1834 	].
       
  1835 	addrLen notNil ifTrue:[
       
  1836 	    (addr == anAddressBuffer) ifFalse:[
       
  1837 		self obsoleteFeatureWarning:'please use a socketAddress argument'.
       
  1838 
       
  1839 		" can be a ByteArray for backward compatibility "
       
  1840 		anAddressBuffer replaceFrom:1 to:addrLen with:(addr hostAddress).
       
  1841 	    ].
       
  1842 	].
       
  1843 	^ nReceived
       
  1844     ].
       
  1845     "
       
  1846      arrive here if you try to receive into an invalid buffer
       
  1847      (i.e. not ByteArray-like),
       
  1848      or if the addressBuffer is nonNil AND not a SocketAddress/ByteArray
       
  1849      or if the addressBuffer is nonNil AND too small.
       
  1850     "
       
  1851     self primitiveFailed
       
  1852 !
       
  1853 
       
  1854 sendBuffer:aDataBuffer start:startIndex for:nBytes flags:flags
       
  1855     "send data.
       
  1856      Both must be ByteArray-like. The bytes in the addressBuffer must
       
  1857      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  1858      Return the number of bytes transmitted, or a negative number on error.
       
  1859      On error, the unix error code is left in the lastErrorNumber
       
  1860      instance variable."
       
  1861 
       
  1862     |nReceived portNo|
       
  1863 
       
  1864 %{
       
  1865 #ifndef NO_SOCKET
       
  1866     OBJ fp = __INST(filePointer);
       
  1867 
       
  1868     if ((fp != nil)
       
  1869      && __isSmallInteger(startIndex)
       
  1870      && __isSmallInteger(nBytes)) {
       
  1871 	SOCKET sock;
       
  1872 	int objSize;
       
  1873 	int n;
       
  1874 	char *extPtr;
       
  1875 	int _flags = 0;
       
  1876 	int offs;
       
  1877 	unsigned long norder;
       
  1878 	unsigned char *buffer;
       
  1879 	unsigned char *allocatedBuffer;
       
  1880 
       
  1881 	_flags = __longIntVal(flags);
       
  1882 
       
  1883 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  1884 
       
  1885 	if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad;
       
  1886 	if (__isSmallInteger(nBytes)) {
       
  1887 	    if (__intVal(nBytes) < objSize) {
       
  1888 		objSize = __intVal(nBytes);
       
  1889 	    }
       
  1890 	}
       
  1891 
       
  1892 # ifdef DGRAM_DEBUG
       
  1893 	console_printf("sending %d bytes ...\n", nBytes);
       
  1894 # endif
       
  1895 
       
  1896 #ifdef DO_WRAP_CALLS
       
  1897 	if (extPtr) {
       
  1898 	    buffer = extPtr + offs;
       
  1899 	} else {
       
  1900 	    allocatedBuffer = buffer = (char *)malloc(objSize);
       
  1901 	    bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize);
       
  1902 	}
       
  1903 
       
  1904 	do {
       
  1905 	    __threadErrno = 0;
       
  1906 	    n = STX_WSA_CALL4("send", send, sock, buffer, objSize, _flags);
       
  1907 	} while ((n < 0) && (__threadErrno == EINTR));
       
  1908 
       
  1909 	if (allocatedBuffer) {
       
  1910 	    free(allocatedBuffer);
       
  1911 	}
       
  1912 #else
       
  1913 	__BEGIN_INTERRUPTABLE__
       
  1914 	do {
       
  1915 	    if (extPtr) {
       
  1916 		n = send(sock, extPtr + offs, objSize, _flags);
       
  1917 	    } else {
       
  1918 		n = send(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags);
       
  1919 	    }
       
  1920 	} while ((n < 0) && (errno == EINTR));
       
  1921 	__END_INTERRUPTABLE__
       
  1922 #endif
       
  1923 
       
  1924 	if (n < 0) {
       
  1925 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  1926 	}
       
  1927 	RETURN (__MKSMALLINT(n));
       
  1928     }
       
  1929 #endif
       
  1930 bad: ;
       
  1931 %}.
       
  1932     "
       
  1933      arrive here if you try to send from an invalid buffer (i.e. not ByteArray-like),
       
  1934     "
       
  1935     self primitiveFailed
       
  1936 !
       
  1937 
       
  1938 sendTo:anAddressBuffer buffer:buffer
       
  1939     "send datagramm data - fetch address of destination host from
       
  1940      anAddressBuffer, data from aDataBuffer.
       
  1941      Both must be ByteArray-like. The bytes in the addressBuffer must
       
  1942      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  1943      Return the number of bytes transmitted, or a negative number on error.
       
  1944      On error, the unix error code is left in the lastErrorNumber
       
  1945      instance variable.
       
  1946      Flags is currently ignored; it is there for ST-80 compatibility."
       
  1947 
       
  1948     ^ self sendTo:anAddressBuffer buffer:buffer start:1 for:buffer size flags:0
       
  1949 !
       
  1950 
       
  1951 sendTo:anAddressBuffer buffer:buffer start:startIndex for:count
       
  1952     "send datagramm data - fetch address of destination host from
       
  1953      anAddressBuffer, data from aDataBuffer.
       
  1954      Both must be ByteArray-like. The bytes in the addressBuffer must
       
  1955      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  1956      Return the number of bytes transmitted, or a negative number on error.
       
  1957      On error, the unix error code is left in the lastErrorNumber
       
  1958      instance variable.
       
  1959      Flags is currently ignored; it is there for ST-80 compatibility."
       
  1960 
       
  1961     ^ self sendTo:anAddressBuffer buffer:buffer start:startIndex for:count flags:0
       
  1962 !
       
  1963 
       
  1964 sendTo:anAddressBuffer buffer:aDataBuffer start:startIndex for:nBytes flags:flags
       
  1965     "send datagramm data - fetch address of destination host from
       
  1966      anAddressBuffer, data from aDataBuffer starting at startIndex,
       
  1967      sending count bytes.
       
  1968      Both must be ByteArray-like. The bytes in the addressBuffer must
       
  1969      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  1970      Return the number of bytes transmitted, or a negative number on error.
       
  1971      On error, the unix error code is left in the lastErrorNumber
       
  1972      instance variable."
       
  1973 
       
  1974     |domainClass addr|
       
  1975 
       
  1976     domainClass := self class socketAddressClassForDomain:domain.
       
  1977     domainClass isNil ifTrue:[
       
  1978 	^ self error:'invalid (unsupported) domain'.
       
  1979     ].
       
  1980 
       
  1981     (anAddressBuffer isKindOf:SocketAddress) ifTrue:[
       
  1982 	addr := anAddressBuffer.
       
  1983     ] ifFalse:[
       
  1984 	anAddressBuffer isByteArray ifFalse:[
       
  1985 	    ^ self error:'bad socketAddress argument'
       
  1986 	].
       
  1987 	addr := domainClass hostAddress:anAddressBuffer.
       
  1988     ].
       
  1989 %{
       
  1990 #ifndef NO_SOCKET
       
  1991     OBJ fp = __INST(filePointer);
       
  1992 
       
  1993     if ((fp != nil)
       
  1994      && __isSmallInteger(startIndex)
       
  1995      && __isSmallInteger(nBytes)) {
       
  1996 	SOCKET sock;
       
  1997 	int objSize;
       
  1998 	struct sockaddr *sockaddr_ptr;
       
  1999 	union sockaddr_u sa;
       
  2000 	int alen = 0;
       
  2001 	int sockAddrOffs, sockaddr_size;
       
  2002 	int n;
       
  2003 	char *extPtr;
       
  2004 	int _flags = 0;
       
  2005 	int offs;
       
  2006 	unsigned long norder;
       
  2007 	unsigned char *buffer;
       
  2008 	unsigned char *allocatedBuffer;
       
  2009 
       
  2010 	_flags = __longIntVal(flags);
       
  2011 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  2012 
       
  2013 	if (! __isBytes(addr)) {
       
  2014 	    sockaddr_size = 0;
       
  2015 	    sockaddr_ptr = (struct sockaddr *)0;
       
  2016 	} else {
       
  2017 	    int nIndex;
       
  2018 	    OBJ cls;
       
  2019 
       
  2020 	    sockAddrOffs = 0;
       
  2021 	    if ((cls = __qClass(addr)) != @global(ByteArray))
       
  2022 		sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
       
  2023 	    nIndex = __qSize(addr) - OHDR_SIZE;
       
  2024 	    sockaddr_size = nIndex - sockAddrOffs;
       
  2025 	    if (sockaddr_size > sizeof(sa)) {
       
  2026 		console_fprintf(stderr, "Socket [warning]: bad socketAddr\n");
       
  2027 		goto bad;
       
  2028 	    }
       
  2029 	    bcopy((__byteArrayVal(addr) + sockAddrOffs), &sa, sockaddr_size);
       
  2030 	    sockaddr_ptr = (struct sockaddr *)(&sa);
       
  2031 	}
       
  2032 
       
  2033 	if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad;
       
  2034 	if (__isSmallInteger(nBytes)) {
       
  2035 	    if (__intVal(nBytes) < objSize) {
       
  2036 		objSize = __intVal(nBytes);
       
  2037 	    }
       
  2038 	}
       
  2039 
       
  2040 #ifdef DO_WRAP_CALLS
       
  2041 	if (extPtr) {
       
  2042 	    buffer = extPtr + offs;
       
  2043 	} else {
       
  2044 	    allocatedBuffer = buffer = (char *)malloc(objSize);
       
  2045 	    bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize);
       
  2046 	}
       
  2047 
       
  2048 	do {
       
  2049 	    __threadErrno = 0;
       
  2050 	    n = STX_WSA_CALL6("sendto", sendto, sock, buffer, objSize, _flags, sockaddr_ptr, sockaddr_size);
       
  2051 	} while ((n < 0) && (__threadErrno == EINTR));
       
  2052 
       
  2053 	if (allocatedBuffer) {
       
  2054 	    free(allocatedBuffer);
       
  2055 	}
       
  2056 #else
       
  2057 	__BEGIN_INTERRUPTABLE__
       
  2058 	do {
       
  2059 	    if (extPtr) {
       
  2060 		n = sendto(sock, extPtr + offs, objSize, _flags, sockaddr_ptr, sockaddr_size);
       
  2061 	    } else {
       
  2062 		n = sendto(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags, sockaddr_ptr, sockaddr_size);
       
  2063 	    }
       
  2064 	} while ((n < 0) && (errno == EINTR));
       
  2065 	__END_INTERRUPTABLE__
       
  2066 #endif
       
  2067 
       
  2068 	if (n < 0) {
       
  2069 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2070 	}
       
  2071 	RETURN (__MKSMALLINT(n));
       
  2072     }
       
  2073 #endif
       
  2074 bad: ;
       
  2075 %}.
       
  2076     "
       
  2077      arrive here if you try to send from an invalid buffer
       
  2078      (i.e. not ByteArray-like),
       
  2079      or if the addressBuffer is nonNil AND not a ByteArray/String
       
  2080      or if the addressBuffer is nonNil AND too small.
       
  2081     "
       
  2082     self primitiveFailed
       
  2083 ! !
       
  2084 
       
  2085 !Socket methodsFor:'low level'!
       
  2086 
  1633 
  2087 bindAnonymously
  1634 bindAnonymously
  2088     "bind to any address. A free port will be allocated.
  1635     "bind to any address. A free port will be allocated.
  2089      Our own socket address will be determined after conection set up.
  1636      Our own socket address will be determined after conection set up.
  2090      This is the default after the socket has been created"
  1637      This is the default after the socket has been created"
  2277                                                         with:hostOrPathNameOrSocketAddrOrNil
  1824                                                         with:hostOrPathNameOrSocketAddrOrNil
  2278                                                         with:error).
  1825                                                         with:error).
  2279         ^ true.
  1826         ^ true.
  2280     ].
  1827     ].
  2281 
  1828 
  2282     peer := addr.
       
  2283     port := addr port.
  1829     port := addr port.
  2284     peerName := addrName.
       
  2285 
  1830 
  2286     ^ true
  1831     ^ true
  2287 
  1832 
  2288     "
  1833     "
  2289      (Socket domain:#inet type:#stream)
  1834      (Socket domain:#inet type:#stream)
  2290          bindTo:21
  1835          bindTo:21
  2291          address:nil
  1836          address:nil
  2292     "
  1837     "
  2293 ! !
       
  2294 
       
  2295 !Socket protectedMethodsFor:'low level'!
       
  2296 
       
  2297 closeFile
       
  2298     "low level close"
       
  2299 
       
  2300 %{  /* NOCONTEXT */
       
  2301 #ifndef NO_SOCKET
       
  2302     OBJ t;
       
  2303 
       
  2304     t = __INST(filePointer);
       
  2305     if (t != nil) {
       
  2306 	FILE *fp;
       
  2307 	SOCKET sock;
       
  2308 	int fd;
       
  2309 
       
  2310 	__INST(filePointer) = nil;
       
  2311 	fp = __FILEVal(t);
       
  2312 	fd = fileno(fp);
       
  2313 	sock = SOCKET_FROM_FD(fd);
       
  2314 
       
  2315 # ifdef xxDO_WRAP_CALLS
       
  2316 	{ int ret;
       
  2317 
       
  2318 	  do {
       
  2319 	    __threadErrno = 0;
       
  2320 	    ret = STX_C_CALL1("fclose", fclose, fp);
       
  2321 	  } while ((ret < 0) && (__threadErrno == EINTR));
       
  2322 
       
  2323 #  ifdef WIN32
       
  2324 	  do {
       
  2325 	    __threadErrno = 0;
       
  2326 	    ret = STX_WSA_CALL1("closesocket", closesocket, sock);
       
  2327 	  } while ((ret < 0) && (__threadErrno == EINTR));
       
  2328 	  closesocket(sock);
       
  2329 #  endif
       
  2330 	}
       
  2331 # else /* !DO_WRAP_CALLS */
       
  2332 
       
  2333 	DBGFPRINTF((stderr, "SOCKET: fflush %x (%d %d)\n", fp, fileno(fp), sock));
       
  2334 	fflush(fp);
       
  2335 
       
  2336 #  if defined(CLOSESOCKET_BEFORE_FCLOSE)
       
  2337 	DBGFPRINTF((stderr, "SOCKET: closesocket (%d)\n", sock));
       
  2338 	closesocket(sock);
       
  2339 #  endif
       
  2340 	if ((@global(FileOpenTrace) == true) || __debugging__) {
       
  2341 	    console_fprintf(stderr, "SOCKET: fclose %x (%d %d)\n", fp, fileno(fp), sock);
       
  2342 	}
       
  2343 	fclose(fp);
       
  2344 
       
  2345 #  if defined(CLOSESOCKET_AFTER_FCLOSE)
       
  2346 	DBGFPRINTF((stderr, "SOCKET: closesocket (%d)\n", sock));
       
  2347 	closesocket(sock);
       
  2348 #  endif
       
  2349 # endif /* !DO_WRAP_CALLS */
       
  2350     }
       
  2351 #endif /* NO_SOCKET */
       
  2352 %}
       
  2353 ! !
       
  2354 
       
  2355 !Socket methodsFor:'low level'!
       
  2356 
       
  2357 getSocketError
       
  2358     "get the SO_ERROR form the socket, which indicates the
       
  2359      result of an asynchronous operation"
       
  2360 
       
  2361 %{
       
  2362 #ifndef NO_SOCKET
       
  2363     OBJ fp;
       
  2364     int err;
       
  2365 
       
  2366     fp = __INST(filePointer);
       
  2367     if (fp == nil) {
       
  2368 	err = EBADF;
       
  2369     } else {
       
  2370 	unsigned int sz;
       
  2371 	SOCKET sock;
       
  2372 
       
  2373 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  2374 	sz = sizeof(err);
       
  2375 	if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {
       
  2376 # ifdef WIN32
       
  2377 	    errno = WSAGetLastError();
       
  2378 # endif
       
  2379 	    err = errno;
       
  2380 	}
       
  2381     }
       
  2382 
       
  2383     RETURN(__MKSMALLINT(err));
       
  2384 #endif
       
  2385 %}
       
  2386 !
  1838 !
  2387 
  1839 
  2388 listenFor:aNumber
  1840 listenFor:aNumber
  2389     "same as listenWithBacklog: - for ST-80 compatibility"
  1841     "start listening; return true if ok, false on error
  2390 
  1842      aNumber is the number of connect requests, that may be queued on the socket"
  2391     ^ self listenWithBacklog:aNumber
       
  2392 !
       
  2393 
       
  2394 listenWithBacklog:aNumber
       
  2395     "start listening; return true if ok, false on error"
       
  2396 
  1843 
  2397     filePointer isNil ifTrue:[
  1844     filePointer isNil ifTrue:[
  2398 	^ self errorNotOpen
  1845         ^ self errorNotOpen
  2399     ].
  1846     ].
  2400 %{
  1847 %{
  2401 #ifndef NO_SOCKET
  1848 #ifndef NO_SOCKET
  2402     OBJ fp = __INST(filePointer);
  1849     OBJ fp = __INST(filePointer);
  2403     SOCKET sock;
  1850     SOCKET sock;
  2404     int ret;
  1851     int ret;
  2405 
  1852 
  2406     if (! __isSmallInteger(aNumber)) {
  1853     if (! __isSmallInteger(aNumber)) {
  2407 	DBGPRINTF(("SOCKET: invalid arg\n"));
  1854         DBGPRINTF(("SOCKET: invalid arg\n"));
  2408 	RETURN (false);
  1855         RETURN (false);
  2409     }
  1856     }
  2410 
  1857 
  2411     sock = SOCKET_FROM_FILE_OBJECT(fp);
  1858     sock = SOCKET_FROM_FILE_OBJECT(fp);
  2412 
  1859 
  2413 #ifdef LISTEN_BLOCKS
  1860 #ifdef LISTEN_BLOCKS
  2414 # ifdef DO_WRAP_CALLS
  1861 # ifdef DO_WRAP_CALLS
  2415     do {
  1862     do {
  2416 	__threadErrno = 0;
  1863         __threadErrno = 0;
  2417 	ret = STX_WSA_CALL2("listen", listen, sock, __intVal(aNumber));
  1864         ret = STX_WSA_CALL2("listen", listen, sock, __intVal(aNumber));
  2418     } while ((ret < 0) && (__threadErrno == EINTR));
  1865     } while ((ret < 0) && (__threadErrno == EINTR));
  2419 # else
  1866 # else
  2420     __BEGIN_INTERRUPTABLE__
  1867     __BEGIN_INTERRUPTABLE__
  2421     do {
  1868     do {
  2422 	ret = listen(sock, __intVal(aNumber));
  1869         ret = listen(sock, __intVal(aNumber));
  2423     } while ((ret < 0) && (errno == EINTR));
  1870     } while ((ret < 0) && (errno == EINTR));
  2424     __END_INTERRUPTABLE__
  1871     __END_INTERRUPTABLE__
  2425 # endif
  1872 # endif
  2426 #else
  1873 #else
  2427     ret = listen(sock, __intVal(aNumber));
  1874     ret = listen(sock, __intVal(aNumber));
  2428 #endif
  1875 #endif
  2429 
  1876 
  2430     if (ret < 0) {
  1877     if (ret < 0) {
  2431 	DBGPRINTF(("SOCKET: listen call failed errno=%d\n", errno));
  1878         DBGPRINTF(("SOCKET: listen call failed errno=%d\n", errno));
  2432 	__INST(lastErrorNumber) = __MKSMALLINT(errno);
  1879         __INST(lastErrorNumber) = __MKSMALLINT(errno);
  2433 	RETURN (false);
  1880         RETURN (false);
  2434     }
  1881     }
  2435 #else
  1882 #else
  2436     RETURN (false);
  1883     RETURN (false);
  2437 #endif
  1884 #endif
  2438 %}.
  1885 %}.
  2439     listening := true.
  1886     listening := true.
  2440     ^ true
  1887     ^ true
  2441 ! !
  1888 ! !
  2442 
  1889 
  2443 !Socket protectedMethodsFor:'low level'!
  1890 !Socket methodsFor:'closing'!
  2444 
  1891 
  2445 setSocketOption:option argument:arg1 argument:arg2
  1892 shutDown
  2446     |ok|
  1893     "shutDown and close the socket"
  2447 
  1894 
  2448 %{  /* STACK: 32000 */
  1895     self shutdown:2.
  2449     OBJ fp = __INST(filePointer);
  1896     self close
  2450 
  1897 !
  2451     if (fp != nil) {
  1898 
  2452 	SOCKET sock;
  1899 shutDownInput
  2453 	int opt = -1;
  1900     "shutDown the input side of the socket.
  2454 	int level = -1;
  1901      Any read on the socket will signal end-of-file from now on.
  2455 	int usize = -1;
  1902      The other side MAY be informed, that no more data will be accepted
  2456 	int ret;
  1903      (e.g. setting the TCP-Windowsize to 0)"
  2457 	union u {
  1904 
  2458 	    BOOL        u_bool;
  1905     self shutdown:0.
  2459 	    int         u_int;
  1906 !
  2460 	    struct linger u_linger;
  1907 
  2461 	} u;
  1908 shutDownOutput
  2462 
  1909     "shutDown the output side of the socket.
  2463 	sock = SOCKET_FROM_FILE_OBJECT(fp);
  1910      Any write to the socket will signal end-of-file from now on.
  2464 
  1911      The other side will get a end-of-file condition,
  2465 # ifdef SO_BROADCAST
  1912      after the last buffered data has been read"
  2466 	if (option == @symbol(SO_BROADCAST)) {
  1913 
  2467 	    /* Enables transmission and receipt of broadcast messages on the socket. */
  1914     self shutdown:1.
  2468 	    opt = SO_BROADCAST;
       
  2469 	    level = SOL_SOCKET;
       
  2470 	    usize = sizeof(u.u_bool);
       
  2471 	    if (arg1 == true) u.u_bool = TRUE;
       
  2472 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2473 	    else goto argError;
       
  2474 	}
       
  2475 # endif /* SO_BROADCAST */
       
  2476 
       
  2477 # ifdef SO_CONDITIONAL
       
  2478 #  if 0
       
  2479 	if (option == @symbol(SO_CONDITIONAL)) {
       
  2480 	    /* Enables sockets to delay the acknowledgment of a connection until after the WSAAccept condition function is called. */
       
  2481 	    opt = SO_CONDITIONAL;
       
  2482 	    level = SOL_SOCKET;
       
  2483 	    usize = sizeof(u.u_bool);
       
  2484 	    if (arg1 == true) u.u_bool = TRUE;
       
  2485 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2486 	    else goto argError;
       
  2487 	}
       
  2488 #  endif
       
  2489 # endif /* SO_CONDITIONAL */
       
  2490 
       
  2491 # ifdef SO_DEBUG
       
  2492 	if (option == @symbol(SO_DEBUG)) {
       
  2493 	    /* Records debugging information. */
       
  2494 	    opt = SO_DEBUG;
       
  2495 	    level = SOL_SOCKET;
       
  2496 	    usize = sizeof(u.u_bool);
       
  2497 	    if (arg1 == true) u.u_bool = TRUE;
       
  2498 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2499 	    else goto argError;
       
  2500 	}
       
  2501 # endif /* SO_DEBUG */
       
  2502 
       
  2503 # ifdef SO_DONTLINGER
       
  2504 	    if (option == @symbol(SO_DONTLINGER)) {
       
  2505 		/* Does not block close waiting for unsent data to be sent.
       
  2506 		   Setting this option is equivalent to setting SO_LINGER with l_onoff set to zero. */
       
  2507 		opt = SO_DONTLINGER;
       
  2508 		level = SOL_SOCKET;
       
  2509 		usize = sizeof(u.u_bool);
       
  2510 		if (arg1 == true) u.u_bool = TRUE;
       
  2511 		else if (arg1 == false) u.u_bool = FALSE;
       
  2512 		else goto argError;
       
  2513 	    }
       
  2514 # endif /* SO_DONTLINGER */
       
  2515 
       
  2516 # ifdef SO_DONTROUTE
       
  2517 	if (option == @symbol(SO_DONTROUTE)) {
       
  2518 	    /* Does not route: sends directly to interface.
       
  2519 	       Succeeds but is ignored on AF_INET sockets;
       
  2520 	       fails on AF_INET6 sockets with WSAENOPROTOOPT.
       
  2521 	       Not supported on ATM sockets (results in an error). */
       
  2522 	    opt = SO_DONTROUTE;
       
  2523 	    level = SOL_SOCKET;
       
  2524 	    usize = sizeof(u.u_bool);
       
  2525 	    if (arg1 == true) u.u_bool = TRUE;
       
  2526 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2527 	    else goto argError;
       
  2528 	}
       
  2529 # endif /* SO_DONTROUTE */
       
  2530 
       
  2531 # ifdef SO_KEEPALIVE
       
  2532 	if (option == @symbol(SO_KEEPALIVE)) {
       
  2533 	    /* Sends keep-alives. Not supported on ATM sockets (results in an error). */
       
  2534 	    opt = SO_KEEPALIVE;
       
  2535 	    level = SOL_SOCKET;
       
  2536 	    usize = sizeof(u.u_bool);
       
  2537 	    if (arg1 == true) u.u_bool = TRUE;
       
  2538 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2539 	    else goto argError;
       
  2540 	}
       
  2541 # endif /* SO_KEEPALIVE */
       
  2542 
       
  2543 # ifdef SO_LINGER
       
  2544 	if (option == @symbol(SO_LINGER)) {
       
  2545 	    /* Lingers on close if unsent data is present. */
       
  2546 	    opt = SO_LINGER;
       
  2547 	    level = SOL_SOCKET;
       
  2548 	    usize = sizeof(u.u_linger);
       
  2549 	    if (arg1 == true) u.u_linger.l_onoff = TRUE;
       
  2550 	    else if (arg1 == false) u.u_linger.l_onoff = FALSE;
       
  2551 	    else goto argError;
       
  2552 	    if (arg2 == nil) u.u_linger.l_linger = 0;
       
  2553 	    else if (__isSmallInteger(arg2))u.u_linger.l_linger = __intVal(arg2);
       
  2554 	    else goto argError;
       
  2555 	    DBGPRINTF(("SOCKET: SO_LINGER %d %d\n", u.u_linger.l_onoff, u.u_linger.l_linger));
       
  2556 	}
       
  2557 # endif /* SO_LINGER */
       
  2558 
       
  2559 # ifdef SO_OOBINLINE
       
  2560 	if (option == @symbol(SO_OOBINLINE)) {
       
  2561 	    /* Receives OOB data in the normal data stream. */
       
  2562 	    opt = SO_OOBINLINE;
       
  2563 	    level = SOL_SOCKET;
       
  2564 	    usize = sizeof(u.u_bool);
       
  2565 	    if (arg1 == true) u.u_bool = TRUE;
       
  2566 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2567 	    else goto argError;
       
  2568 	}
       
  2569 # endif /* SO_OOBINLINE */
       
  2570 
       
  2571 # ifdef SO_RCVBUF
       
  2572 	if (option == @symbol(SO_RCVBUF)) {
       
  2573 	    /* Specifies the total per-socket buffer space reserved for receives.
       
  2574 	       This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
       
  2575 	    opt = SO_RCVBUF;
       
  2576 	    level = SOL_SOCKET;
       
  2577 	    usize = sizeof(u.u_int);
       
  2578 	    if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
       
  2579 	    else goto argError;
       
  2580 	}
       
  2581 # endif /* SO_RCVBUF */
       
  2582 
       
  2583 # ifdef SO_SNDBUF
       
  2584 	if (option == @symbol(SO_SNDBUF)) {
       
  2585 	    /* Specifies the total per-socket buffer space reserved for sends.
       
  2586 	       This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
       
  2587 	    opt = SO_SNDBUF;
       
  2588 	    level = SOL_SOCKET;
       
  2589 	    usize = sizeof(u.u_int);
       
  2590 	    if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
       
  2591 	    else goto argError;
       
  2592 	}
       
  2593 # endif /* SO_SNDBUF */
       
  2594 
       
  2595 # ifdef SO_REUSEADDR
       
  2596 	if (option == @symbol(SO_REUSEADDR)) {
       
  2597 	    /* Allows the socket to be bound to an address that is already in use.  */
       
  2598 	    opt = SO_REUSEADDR;
       
  2599 	    level = SOL_SOCKET;
       
  2600 	    usize = sizeof(u.u_bool);
       
  2601 	    if (arg1 == true) u.u_bool = TRUE;
       
  2602 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2603 	    else goto argError;
       
  2604 	}
       
  2605 # endif /* SO_OOBINLINE */
       
  2606 
       
  2607 # ifdef SO_EXCLUSIVEADDRUSE
       
  2608 	if (option == @symbol(SO_EXCLUSIVEADDRUSE)) {
       
  2609 	    /* Enables a socket to be bound for exclusive access.
       
  2610 	       Does not require administrative privilege.  */
       
  2611 	    opt = SO_EXCLUSIVEADDRUSE;
       
  2612 	    level = SOL_SOCKET;
       
  2613 	    usize = sizeof(u.u_bool);
       
  2614 	    if (arg1 == true) u.u_bool = TRUE;
       
  2615 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2616 	    else goto argError;
       
  2617 	}
       
  2618 # endif /* SO_OOBINLINE */
       
  2619 
       
  2620 	if (usize == -1) goto argError;
       
  2621 
       
  2622 	ok = ( setsockopt( sock, level, opt, &u, usize) >= 0) ? true : false;
       
  2623     }
       
  2624 argError: ;
       
  2625 
       
  2626 %}.
       
  2627     ok isNil ifTrue:[
       
  2628 	self primitiveFailed
       
  2629     ].
       
  2630     ok ifFalse:[
       
  2631 	'setsocketoption failed' infoPrintCR.
       
  2632     ].
       
  2633 ! !
  1915 ! !
  2634 
  1916 
  2635 !Socket methodsFor:'low level'!
  1917 !Socket methodsFor:'connecting'!
  2636 
       
  2637 shutdown: howNum
       
  2638     "shutDown the socket - inform it that no more I/O will be performed.
       
  2639 	 0 - read side   (no further reads)
       
  2640 	 1 - write side  (no further writes)
       
  2641 	 2 - both        (no further I/O at all)
       
  2642      shutDown:2
       
  2643 	discards any pending data
       
  2644 	(as opposed to close, which might wait until data is delivered as set by LINGER)"
       
  2645 
       
  2646 %{
       
  2647 #ifndef NO_SOCKET
       
  2648 
       
  2649     OBJ fp;
       
  2650 
       
  2651     fp = __INST(filePointer);
       
  2652     if ((fp != nil) && __isSmallInteger(howNum)) {
       
  2653 	SOCKET sock;
       
  2654 	int ret;
       
  2655 
       
  2656 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  2657 # ifdef DO_WRAP_CALLS
       
  2658 	do {
       
  2659 	    __threadErrno = 0;
       
  2660 	    DBGFPRINTF((stderr, "SOCKET: shutDown...\n"));
       
  2661 	    ret = STX_WSA_CALL2("shutdown", shutdown, sock, __intVal(howNum));
       
  2662 	    DBGFPRINTF((stderr, "SOCKET: shutDown -> %d (%d)\n", ret, __threadErrno));
       
  2663 	} while ((ret < 0) && (__threadErrno == EINTR));
       
  2664 # else
       
  2665 	__BEGIN_INTERRUPTABLE__
       
  2666 	shutdown(sock, __intVal(howNum));
       
  2667 	__END_INTERRUPTABLE__
       
  2668 # endif
       
  2669     }
       
  2670 #endif
       
  2671 %}.
       
  2672 ! !
       
  2673 
       
  2674 !Socket methodsFor:'low level-accepting'!
       
  2675 
       
  2676 accept
       
  2677     "create a new TCP socket from accepting on the receiver.
       
  2678      This method will suspend the current process if no connection is waiting.
       
  2679      For ST-80 compatibility"
       
  2680 
       
  2681     |newSock|
       
  2682 
       
  2683     newSock := self class new.
       
  2684     (newSock acceptOn:self) ifFalse:[^ nil].
       
  2685     ^ newSock
       
  2686 
       
  2687     "
       
  2688      |sock newSock|
       
  2689 
       
  2690      sock := Socket provide:8004.
       
  2691      sock listenFor:5.
       
  2692      newSock := sock accept.
       
  2693     "
       
  2694 !
       
  2695 
       
  2696 acceptOn:aSocket
       
  2697     "accept a connection on a server port (created with:'Socket>>onIPPort:')
       
  2698      usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
       
  2699      This method will suspend the current process if no connection is waiting.
       
  2700      Return the true if ok; false if not."
       
  2701 
       
  2702     aSocket readWait.
       
  2703     ^ self primAcceptOn:aSocket blocking:false.
       
  2704 
       
  2705     "Modified: / 11.3.1996 / 14:21:31 / stefan"
       
  2706     "Modified: / 1.8.1998 / 23:39:10 / cg"
       
  2707 !
       
  2708 
       
  2709 blockingAccept
       
  2710     "create a new TCP socket from accepting on the receiver.
       
  2711      This method will suspend the current process if no connection is waiting.
       
  2712      For ST-80 compatibility"
       
  2713 
       
  2714     |newSock|
       
  2715 
       
  2716     newSock := self class new.
       
  2717     (newSock blockingAcceptOn:self) ifFalse:[^ nil].
       
  2718     ^ newSock
       
  2719 !
       
  2720 
       
  2721 blockingAcceptOn:aSocket
       
  2722     "accept a connection on a server port (created with:'Socket>>onIPPort:')
       
  2723      usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
       
  2724      This method will suspend the current process if no connection is waiting.
       
  2725      Return the true if ok; false if not."
       
  2726 
       
  2727     ^ self primAcceptOn:aSocket blocking:true.
       
  2728 !
       
  2729 
       
  2730 pollingWaitForNewConnectionOrDataOnAny:otherConnections timeout:timeoutSeconds
       
  2731     <resource: #obsolete>
       
  2732     "stupid MSDOS does not support select on sockets (sigh).
       
  2733      Must poll here."
       
  2734 
       
  2735     |millis newConnection|
       
  2736 
       
  2737     millis := timeoutSeconds * 1000.
       
  2738     [millis > 0] whileTrue:[
       
  2739 	otherConnections size > 0 ifTrue:[
       
  2740 	    otherConnections do:[:aConnection |
       
  2741 		aConnection canReadWithoutBlocking ifTrue:[
       
  2742 		    ^ aConnection
       
  2743 		]
       
  2744 	    ].
       
  2745 	].
       
  2746 	newConnection := self blockingAccept.
       
  2747 	newConnection notNil ifTrue:[^ newConnection].
       
  2748 	Delay waitForMilliseconds:20.
       
  2749 	millis := millis - 20.
       
  2750     ].
       
  2751     ^ nil.
       
  2752 !
       
  2753 
       
  2754 pollingWaitForNewConnectionWithTimeout:timeoutSeconds
       
  2755     <resource: #obsolete>
       
  2756     "stupid MSDOS does not support select on sockets (sigh).
       
  2757      Must poll here."
       
  2758 
       
  2759     |millis newConnection|
       
  2760 
       
  2761     timeoutSeconds notNil ifTrue:[
       
  2762 	millis := timeoutSeconds * 1000.
       
  2763     ].
       
  2764     [millis isNil or:[millis > 0]] whileTrue:[
       
  2765 	newConnection := self blockingAccept.
       
  2766 	newConnection notNil ifTrue:[^ newConnection].
       
  2767 	Delay waitForMilliseconds:20.
       
  2768 	millis notNil ifTrue:[
       
  2769 	    millis := millis - 20.
       
  2770 	]
       
  2771     ].
       
  2772     ^ nil.
       
  2773 !
       
  2774 
       
  2775 primAcceptOn:aSocket blocking:blocking
       
  2776     "accept a connection on a server port (created with:'Socket>>onIPPort:')
       
  2777      usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
       
  2778      Return the true if ok; false if not."
       
  2779 
       
  2780     |serverSocketFd addr addrLen domainClass|
       
  2781 
       
  2782     filePointer notNil ifTrue:[
       
  2783 	^ self errorAlreadyOpen
       
  2784     ].
       
  2785 
       
  2786     domain := aSocket domain.
       
  2787     socketType := aSocket type.
       
  2788     serverSocketFd := aSocket fileDescriptor.
       
  2789     serverSocketFd isNil ifTrue:[
       
  2790 	^ self error:'invalid server socket'
       
  2791     ].
       
  2792     (serverSocketFd isMemberOf:SmallInteger) ifFalse:[
       
  2793 	^ self error:'invalid server socket'
       
  2794     ].
       
  2795 
       
  2796     domainClass := self class socketAddressClassForDomain:domain.
       
  2797     domainClass isNil ifTrue:[
       
  2798 	^ self error:'invalid (unsupported) domain'.
       
  2799     ].
       
  2800     addrLen := domainClass socketAddressSize.
       
  2801     addr := domainClass new.
       
  2802 
       
  2803 %{  /* STACK: 100000 */
       
  2804 #ifndef NO_SOCKET
       
  2805     FILE *fp;
       
  2806     int flags;
       
  2807     SOCKET sock, newSock;
       
  2808     union sockaddr_u sa;
       
  2809     unsigned int alen, alen0;
       
  2810     struct hostent *he ;
       
  2811     char dotted[20] ;
       
  2812 
       
  2813     if (!__isSmallInteger(addrLen)) {
       
  2814 	DBGPRINTF(("SOCKET: bad addrLen\n"));
       
  2815 	RETURN (false);
       
  2816     }
       
  2817     alen0 = __intVal(addrLen);
       
  2818     sock = SOCKET_FROM_FD(__intVal(serverSocketFd));
       
  2819 
       
  2820     if (blocking == false) {
       
  2821 # if defined(O_NONBLOCK) && defined(SET_NDELAY)
       
  2822 	flags = fcntl(sock, F_GETFL);
       
  2823 	fcntl(sock, F_SETFL, flags | O_NONBLOCK);
       
  2824 # endif
       
  2825     }
       
  2826 
       
  2827 # ifdef DO_WRAP_CALLS
       
  2828     do {
       
  2829 	__threadErrno = 0;
       
  2830 	alen = alen0;
       
  2831 	newSock = STX_WSA_CALL3("accept", accept, sock, &sa, &alen);
       
  2832     } while ((newSock < 0) && (__threadErrno == EINTR));
       
  2833 # else
       
  2834     __BEGIN_INTERRUPTABLE__
       
  2835     do {
       
  2836 	alen = alen0;
       
  2837 	newSock = accept(sock, (struct sockaddr *) &sa, &alen);
       
  2838     } while ((newSock < 0) && (errno == EINTR));
       
  2839     __END_INTERRUPTABLE__
       
  2840 # endif
       
  2841     DBGFPRINTF((stderr, "SOCKET: accept newSock=%d\n", newSock));
       
  2842 
       
  2843     if (blocking == false) {
       
  2844 # if defined(O_NDELAY) && defined(SET_NDELAY)
       
  2845 	fcntl(sock, F_SETFL, flags);
       
  2846 # endif
       
  2847     }
       
  2848 
       
  2849     if (newSock < 0) {
       
  2850 	DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
       
  2851 	__INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2852 	RETURN (false);
       
  2853     }
       
  2854 
       
  2855     if (__isNonNilObject(addr)) {
       
  2856 	OBJ oClass;
       
  2857 	int nInstVars, nInstBytes, objSize;
       
  2858 	char *cp;
       
  2859 
       
  2860 	oClass = __qClass(addr);
       
  2861 	if (! __isBytes(addr) ) {
       
  2862 	    DBGPRINTF(("SOCKET: bad addr\n"));
       
  2863 	    closesocket(newSock);
       
  2864 	    RETURN (false);
       
  2865 	}
       
  2866 
       
  2867 	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
       
  2868 	nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
       
  2869 	objSize = __qSize(addr) - nInstBytes;
       
  2870 	cp = (char *)__InstPtr(addr) + nInstBytes;
       
  2871 	if (objSize < alen) {
       
  2872 	    DBGPRINTF(("SOCKET: bad addr\n"));
       
  2873 	    closesocket(newSock);
       
  2874 	    RETURN (false);
       
  2875 	}
       
  2876 
       
  2877 	/*
       
  2878 	 * extract the partners address
       
  2879 	 */
       
  2880 	bcopy((char *)&sa, cp, alen);
       
  2881 	addrLen = __MKSMALLINT(alen);
       
  2882     }
       
  2883 
       
  2884     /*
       
  2885      * make it a FILE *
       
  2886      */
       
  2887 # ifdef WIN32
       
  2888     {
       
  2889 	int _fd = _open_osfhandle(newSock, 0);
       
  2890 	fp = fdopen(_fd, "r+");
       
  2891 	DBGPRINTF(("SOCKET: sock=%d fd=%d fp=%x\n",newSock,_fd, fp));
       
  2892     }
       
  2893 # else
       
  2894     fp = fdopen(newSock, "r+");
       
  2895 # endif
       
  2896 
       
  2897     if (! fp) {
       
  2898 	DBGPRINTF(("SOCKET: fdopen call failed\n"));
       
  2899 	__INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2900 #  ifdef DO_WRAP_CALLS
       
  2901 	{
       
  2902 	  int ret;
       
  2903 	  do {
       
  2904 	      __threadErrno = 0;
       
  2905 	      ret = STX_WSA_CALL1("closesocket", closesocket, newSock);
       
  2906 	  } while ((ret < 0) && (__threadErrno == EINTR));
       
  2907 	}
       
  2908 #  else
       
  2909 	closesocket(newSock);
       
  2910 #  endif
       
  2911 	DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock));
       
  2912 	RETURN (false);
       
  2913     }
       
  2914 
       
  2915     if ((@global(FileOpenTrace) == true) || __debugging__) {
       
  2916 # ifdef WIN32
       
  2917 	{
       
  2918 	    HANDLE h;
       
  2919 	    int _fd = fileno(fp);
       
  2920 	    h = (HANDLE)_get_osfhandle(_fd);
       
  2921 	    console_fprintf(stderr, "fdopen [Socket] -> %x (fd: %d) (H: %x)\n", fp, _fd, h);
       
  2922 	}
       
  2923 # else
       
  2924 	console_fprintf(stderr, "fdopen [Socket] -> %x (fd: %d)\n", fp, newSock);
       
  2925 # endif
       
  2926     }
       
  2927 
       
  2928 # ifdef BUGGY_STDIO_LIB
       
  2929     setbuf(fp, NULL);
       
  2930     __INST(buffered) = false;
       
  2931 # endif
       
  2932 
       
  2933 # if 0
       
  2934     // The original code was:
       
  2935     __INST(filePointer) = __MKOBJ((INT)fp); __STORESELF(filePointer);
       
  2936     // but for that, gcc generates wrong code, which loads self (volatile) into
       
  2937     // a register (bp), then calls __MKOBJ, then stores indirect bp.
       
  2938     // That is wrong if a scavenge occurs in MKOBJ, as bp is now still pointing to the old
       
  2939     // object.
       
  2940 # endif
       
  2941     {
       
  2942 	OBJ t;
       
  2943 
       
  2944 	t = __MKOBJ(fp);
       
  2945 	__INST(filePointer) = t;
       
  2946 	__STORE(self, t);
       
  2947     }
       
  2948 #endif /* not NO_SOCKET */
       
  2949 %}.
       
  2950     mode := #readwrite.
       
  2951     Lobby register:self.
       
  2952     binary := false.
       
  2953     port := aSocket port.
       
  2954 
       
  2955     addr notNil ifTrue:[
       
  2956 	peer := addr.
       
  2957     ].
       
  2958 
       
  2959     ^ true
       
  2960 !
       
  2961 
       
  2962 waitForNewConnectionOrDataOnAny:otherConnections timeout:timeoutSeconds
       
  2963     "suspend the current process, until either a new connection comes
       
  2964      in at the receiver, or data arrives on any of the otherConnections.
       
  2965      For a new connection, an accept is performed and the new socket is returned.
       
  2966      For an old connection, that socket is returned.
       
  2967      In any case, the caller gets a socket to operate on as return value,
       
  2968      or nil, if a timeout occured.
       
  2969      This method implements the inner wait-primitive of a multi-connection
       
  2970      server application."
       
  2971 
       
  2972 
       
  2973     |wasBlocked sema|
       
  2974 
       
  2975     "first, a quick check if data is already available"
       
  2976     self canReadWithoutBlocking ifTrue:[
       
  2977 	^ self accept.
       
  2978     ].
       
  2979     otherConnections do:[:aConnection |
       
  2980 	aConnection canReadWithoutBlocking ifTrue:[
       
  2981 	    ^ aConnection
       
  2982 	]
       
  2983     ].
       
  2984 
       
  2985     [
       
  2986 	"check again - prevent incoming interrupts from disturbing our setup"
       
  2987 	wasBlocked := OperatingSystem blockInterrupts.
       
  2988 
       
  2989 	self canReadWithoutBlocking ifTrue:[
       
  2990 	    ^ self accept.
       
  2991 	].
       
  2992 	otherConnections do:[:aConnection |
       
  2993 	    aConnection canReadWithoutBlocking ifTrue:[
       
  2994 		^ aConnection
       
  2995 	    ]
       
  2996 	].
       
  2997 
       
  2998 	"nope - must wait"
       
  2999 	sema := Semaphore new name:'multiReadWait'.
       
  3000 	otherConnections do:[:aConnection |
       
  3001 	    Processor signal:sema onInput:(aConnection fileDescriptor).
       
  3002 	].
       
  3003 	Processor signal:sema onInput:(self fileDescriptor).
       
  3004 	timeoutSeconds notNil ifTrue:[
       
  3005 	    Processor signal:sema afterSeconds:timeoutSeconds
       
  3006 	].
       
  3007 	Processor activeProcess state:#ioWait.
       
  3008 	sema wait.
       
  3009     ] ensure:[
       
  3010 	sema notNil ifTrue:[Processor disableSemaphore:sema].
       
  3011 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
       
  3012     ].
       
  3013 
       
  3014     "see who it was ..."
       
  3015     self canReadWithoutBlocking ifTrue:[
       
  3016 	^ self accept.
       
  3017     ].
       
  3018     otherConnections do:[:aConnection |
       
  3019 	aConnection canReadWithoutBlocking ifTrue:[
       
  3020 	    ^ aConnection
       
  3021 	]
       
  3022     ].
       
  3023 
       
  3024     "none - a timeout"
       
  3025     ^ nil
       
  3026 !
       
  3027 
       
  3028 waitForNewConnectionWithTimeout:timeoutSeconds
       
  3029     "suspend the current process, until a new connection comes
       
  3030      in at the receiver or a timeout occurs.
       
  3031      For a new connection, an accept is performed and the new socket is returned.
       
  3032      Returns nil, if a timeout occured.
       
  3033      This method implements the inner wait-primitive of a single-connection
       
  3034      server application."
       
  3035 
       
  3036     (self readWaitWithTimeout:timeoutSeconds) ifTrue:[
       
  3037 	"a timeout occurred - no connection within timeout"
       
  3038 	^ nil
       
  3039     ].
       
  3040     ^ self accept.
       
  3041 ! !
       
  3042 
       
  3043 !Socket methodsFor:'low level-connecting'!
       
  3044 
  1918 
  3045 connectTo:hostOrPathName port:portNrOrName
  1919 connectTo:hostOrPathName port:portNrOrName
  3046     "low level connect; connect to port, portNrOrNameOrNil on host, hostName.
  1920     "low level connect; connect to port, portNrOrNameOrNil on host, hostName.
  3047      For backward compatibility, host may be also a string or a byteArray,
  1921      For backward compatibility, host may be also a string or a byteArray,
  3048      but it is recommended to pass socketAddress instances.
  1922      but it is recommended to pass socketAddress instances.
  3217         err ~~ 0 ifTrue:[
  2091         err ~~ 0 ifTrue:[
  3218             lastErrorNumber := err.
  2092             lastErrorNumber := err.
  3219             ^ false.
  2093             ^ false.
  3220         ].
  2094         ].
  3221     ].
  2095     ].
  3222     port := portNrOrNameOrNil.
  2096 
  3223     peer := addr.
  2097     peer := addr.
  3224     peerName := addrName.
  2098     peerName := addrName.
       
  2099     port isNil ifTrue:[
       
  2100         "socket has not been explicitly bound,
       
  2101          after connect it has been bound implicitly - fetch the port"
       
  2102         port := self getFullSocketAddress port.
       
  2103     ].
  3225     ^ true
  2104     ^ true
  3226 
  2105 
  3227     "
  2106     "
  3228        |sock|
  2107        |sock|
  3229        sock := Socket newTCP.
  2108        sock := Socket newTCP.
  3235        sock connectTo:'localhost' port:9876 withTimeout:2000.
  2114        sock connectTo:'localhost' port:9876 withTimeout:2000.
  3236        sock
  2115        sock
  3237     "
  2116     "
  3238 ! !
  2117 ! !
  3239 
  2118 
       
  2119 !Socket methodsFor:'datagram transmission'!
       
  2120 
       
  2121 receiveBuffer:aDataBuffer start:startIndex for:nBytes
       
  2122     "receive data
       
  2123      Return the number of bytes received, or a negative number on error.
       
  2124      On error, the unix error code is left in the lastErrorNumber
       
  2125      instance variable.
       
  2126      The thread blocks until data arrives - you may want to wait before
       
  2127      receiving, using #readWait or #readWaitWithTimeout:."
       
  2128 
       
  2129     |nReceived|
       
  2130 
       
  2131 %{
       
  2132 #ifndef NO_SOCKET
       
  2133     OBJ fp = __INST(filePointer);
       
  2134 
       
  2135     if (fp != nil) {
       
  2136 	SOCKET sock;
       
  2137 	int objSize, offs;
       
  2138 	int n;
       
  2139 	char *extPtr;
       
  2140 	unsigned char *buffer;
       
  2141 	unsigned char *allocatedBuffer;
       
  2142 	int flags = 0;
       
  2143 
       
  2144 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  2145 
       
  2146 	if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad;
       
  2147 	if (__isSmallInteger(nBytes)) {
       
  2148 	    if (__intVal(nBytes) < objSize) {
       
  2149 		objSize = __intVal(nBytes);
       
  2150 	    }
       
  2151 	}
       
  2152 
       
  2153 # ifdef DO_WRAP_CALLS
       
  2154 	if (extPtr) {
       
  2155 	    buffer = extPtr + offs;
       
  2156 	} else {
       
  2157 	    allocatedBuffer = buffer = (char *)malloc(objSize);
       
  2158 	}
       
  2159 
       
  2160 	do {
       
  2161 	    __threadErrno = 0;
       
  2162 	    n = STX_WSA_CALL4("recv", recv, sock, buffer, objSize, flags);
       
  2163 	} while ((n < 0) && (__threadErrno == EINTR));
       
  2164 
       
  2165 	if (allocatedBuffer) {
       
  2166 	    if (n > 0) {
       
  2167 		bcopy(allocatedBuffer, (char *)__InstPtr(aDataBuffer) + offs, n);
       
  2168 	    }
       
  2169 	    free(allocatedBuffer);
       
  2170 	}
       
  2171 # else
       
  2172 	__BEGIN_INTERRUPTABLE__
       
  2173 	do {
       
  2174 	    if (extPtr) {
       
  2175 		n = recv(sock, extPtr + offs, objSize, flags);
       
  2176 	    } else {
       
  2177 		n = recv(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, flags);
       
  2178 	    }
       
  2179 	} while ((n < 0) && (errno == EINTR));
       
  2180 	__END_INTERRUPTABLE__
       
  2181 # endif
       
  2182 
       
  2183 	if (n < 0) {
       
  2184 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2185 	}
       
  2186 	nReceived = __MKSMALLINT(n);
       
  2187     }
       
  2188 #endif
       
  2189 bad: ;
       
  2190 %}.
       
  2191     nReceived notNil ifTrue:[
       
  2192 	nReceived < 0 ifTrue:[
       
  2193 	    'Socket [warning]: ' infoPrint.
       
  2194 	    (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR.
       
  2195 	].
       
  2196 	^ nReceived
       
  2197     ].
       
  2198     "
       
  2199      arrive here if you try to receive into an invalid buffer (i.e. not ByteArray-like)
       
  2200     "
       
  2201     self primitiveFailed
       
  2202 !
       
  2203 
       
  2204 receiveFrom:anAddressBuffer buffer:aDataBuffer
       
  2205     "receive datagramm data - put address of originating host into
       
  2206      anAddressBuffer, data into aBuffer.
       
  2207      Both must be ByteArray-like. The addressBuffer must
       
  2208      provide space for a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  2209      Return the number of bytes received, or a negative number on error.
       
  2210      On error, the unix error code is left in the lastErrorNumber
       
  2211      instance variable."
       
  2212 
       
  2213     ^ self receiveFrom:anAddressBuffer buffer:aDataBuffer start:1 for:(aDataBuffer size)
       
  2214 !
       
  2215 
       
  2216 receiveFrom:anAddressBuffer buffer:aDataBuffer start:startIndex for:nBytes
       
  2217     "receive datagramm data
       
  2218      - put address of originating host into anAddressBuffer, data into aBuffer.
       
  2219      For backward compatibility, the addressBuffer may be a non-SocketAddress;
       
  2220      then, it must be a byteArray with appropriate size for the addressBytes.
       
  2221 
       
  2222      Return the number of bytes received, or a negative number on error.
       
  2223      On error, the unix error code is left in the lastErrorNumber
       
  2224      instance variable.
       
  2225      The thread blocks until data arrives - you may want to wait before
       
  2226      receiving, using #readWait or #readWaitWithTimeout:."
       
  2227 
       
  2228     |domainClass addr addrLen nReceived|
       
  2229 
       
  2230     domainClass := self class socketAddressClassForDomain:domain.
       
  2231     domainClass isNil ifTrue:[
       
  2232 	^ self error:'invalid (unsupported) domain'.
       
  2233     ].
       
  2234     (anAddressBuffer isKindOf:SocketAddress) ifTrue:[
       
  2235 	anAddressBuffer class == domainClass ifFalse:[
       
  2236 	    ^ self error:'addressBuffer class mismatch (domain)'.
       
  2237 	].
       
  2238 	addr := anAddressBuffer.
       
  2239     ] ifFalse:[
       
  2240 	anAddressBuffer notNil ifTrue:[
       
  2241 	    addr := domainClass new.
       
  2242 	].
       
  2243     ].
       
  2244 
       
  2245 %{
       
  2246 #ifndef NO_SOCKET
       
  2247     OBJ fp = __INST(filePointer);
       
  2248 
       
  2249     if (fp != nil) {
       
  2250 	SOCKET sock;
       
  2251 	int objSize;
       
  2252 	union sockaddr_u sa;
       
  2253 	unsigned int alen = 0;
       
  2254 	int n, offs;
       
  2255 	int flags = 0;
       
  2256 	char *extPtr;
       
  2257 	unsigned char *allocatedBuffer = NULL;
       
  2258 	unsigned char *buffer = NULL;
       
  2259 
       
  2260 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  2261 
       
  2262 	if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad;
       
  2263 	if (__isSmallInteger(nBytes)) {
       
  2264 	    if (__intVal(nBytes) < objSize) {
       
  2265 		objSize = __intVal(nBytes);
       
  2266 	    }
       
  2267 	}
       
  2268 # ifdef DO_WRAP_CALLS
       
  2269 	if (extPtr) {
       
  2270 	    buffer = extPtr + offs;
       
  2271 	} else {
       
  2272 	    allocatedBuffer = buffer = (char *)malloc(objSize);
       
  2273 	}
       
  2274 
       
  2275 	do {
       
  2276 	    __threadErrno = 0;
       
  2277 	    alen = sizeof(sa);
       
  2278 	    n = STX_WSA_CALL6("recvfrom", recvfrom, sock, buffer, objSize, flags, (struct sockaddr *)&sa, &alen);
       
  2279 	} while ((n < 0) && (__threadErrno == EINTR));
       
  2280 
       
  2281 	if (allocatedBuffer) {
       
  2282 	    if (n > 0) {
       
  2283 		bcopy(allocatedBuffer, (char *)__InstPtr(aDataBuffer) + offs, n);
       
  2284 	    }
       
  2285 	    free(allocatedBuffer);
       
  2286 	}
       
  2287 # else
       
  2288 	__BEGIN_INTERRUPTABLE__
       
  2289 	do {
       
  2290 	    alen = sizeof(sa);
       
  2291 	    if (extPtr) {
       
  2292 		n = recvfrom(sock, extPtr + offs, objSize, flags, (struct sockaddr *) &sa, &alen);
       
  2293 	    } else {
       
  2294 		n = recvfrom(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, flags, (struct sockaddr *) &sa, &alen);
       
  2295 	    }
       
  2296 	} while ((n < 0) && (errno == EINTR));
       
  2297 	__END_INTERRUPTABLE__
       
  2298 # endif
       
  2299 
       
  2300 	if (n >= 0) {
       
  2301 	    if (__isNonNilObject(addr)) {
       
  2302 		char *addrPtr;
       
  2303 		OBJ oClass;
       
  2304 		int nInstVars, nInstBytes, objSize;
       
  2305 
       
  2306 		oClass = __qClass(addr);
       
  2307 		if (! __isBytes(addr) )
       
  2308 		    goto bad;
       
  2309 		nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
       
  2310 		nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
       
  2311 		objSize = __qSize(addr) - nInstBytes;
       
  2312 		addrPtr = (char *)__InstPtr(addr) + nInstBytes;
       
  2313 		if (objSize < alen)
       
  2314 		    goto bad;
       
  2315 
       
  2316 		/*
       
  2317 		 * extract the datagrams address
       
  2318 		 */
       
  2319 		bcopy((char *)&sa, addrPtr, alen);
       
  2320 		addrLen = __MKSMALLINT(alen);
       
  2321 	    }
       
  2322 	}
       
  2323 	if (n < 0) {
       
  2324 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2325 	}
       
  2326 	nReceived = __MKSMALLINT(n);
       
  2327     }
       
  2328 #endif
       
  2329 bad: ;
       
  2330 %}.
       
  2331     nReceived notNil ifTrue:[
       
  2332 	nReceived < 0 ifTrue:[
       
  2333 	    'Socket [warning]: ' infoPrint.
       
  2334 	    (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR.
       
  2335 	].
       
  2336 	addrLen notNil ifTrue:[
       
  2337 	    (addr == anAddressBuffer) ifFalse:[
       
  2338 		self obsoleteFeatureWarning:'please use a socketAddress argument'.
       
  2339 
       
  2340 		" can be a ByteArray for backward compatibility "
       
  2341 		anAddressBuffer replaceFrom:1 to:addrLen with:(addr hostAddress).
       
  2342 	    ].
       
  2343 	].
       
  2344 	^ nReceived
       
  2345     ].
       
  2346     "
       
  2347      arrive here if you try to receive into an invalid buffer
       
  2348      (i.e. not ByteArray-like),
       
  2349      or if the addressBuffer is nonNil AND not a SocketAddress/ByteArray
       
  2350      or if the addressBuffer is nonNil AND too small.
       
  2351     "
       
  2352     self primitiveFailed
       
  2353 !
       
  2354 
       
  2355 sendBuffer:aDataBuffer start:startIndex for:nBytes flags:flags
       
  2356     "send data.
       
  2357      Both must be ByteArray-like. The bytes in the addressBuffer must
       
  2358      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  2359      Return the number of bytes transmitted, or a negative number on error.
       
  2360      On error, the unix error code is left in the lastErrorNumber
       
  2361      instance variable."
       
  2362 
       
  2363     |nReceived portNo|
       
  2364 
       
  2365 %{
       
  2366 #ifndef NO_SOCKET
       
  2367     OBJ fp = __INST(filePointer);
       
  2368 
       
  2369     if ((fp != nil)
       
  2370      && __isSmallInteger(startIndex)
       
  2371      && __isSmallInteger(nBytes)) {
       
  2372 	SOCKET sock;
       
  2373 	int objSize;
       
  2374 	int n;
       
  2375 	char *extPtr;
       
  2376 	int _flags = 0;
       
  2377 	int offs;
       
  2378 	unsigned long norder;
       
  2379 	unsigned char *buffer;
       
  2380 	unsigned char *allocatedBuffer;
       
  2381 
       
  2382 	_flags = __longIntVal(flags);
       
  2383 
       
  2384 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  2385 
       
  2386 	if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad;
       
  2387 	if (__isSmallInteger(nBytes)) {
       
  2388 	    if (__intVal(nBytes) < objSize) {
       
  2389 		objSize = __intVal(nBytes);
       
  2390 	    }
       
  2391 	}
       
  2392 
       
  2393 # ifdef DGRAM_DEBUG
       
  2394 	console_printf("sending %d bytes ...\n", nBytes);
       
  2395 # endif
       
  2396 
       
  2397 #ifdef DO_WRAP_CALLS
       
  2398 	if (extPtr) {
       
  2399 	    buffer = extPtr + offs;
       
  2400 	} else {
       
  2401 	    allocatedBuffer = buffer = (char *)malloc(objSize);
       
  2402 	    bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize);
       
  2403 	}
       
  2404 
       
  2405 	do {
       
  2406 	    __threadErrno = 0;
       
  2407 	    n = STX_WSA_CALL4("send", send, sock, buffer, objSize, _flags);
       
  2408 	} while ((n < 0) && (__threadErrno == EINTR));
       
  2409 
       
  2410 	if (allocatedBuffer) {
       
  2411 	    free(allocatedBuffer);
       
  2412 	}
       
  2413 #else
       
  2414 	__BEGIN_INTERRUPTABLE__
       
  2415 	do {
       
  2416 	    if (extPtr) {
       
  2417 		n = send(sock, extPtr + offs, objSize, _flags);
       
  2418 	    } else {
       
  2419 		n = send(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags);
       
  2420 	    }
       
  2421 	} while ((n < 0) && (errno == EINTR));
       
  2422 	__END_INTERRUPTABLE__
       
  2423 #endif
       
  2424 
       
  2425 	if (n < 0) {
       
  2426 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2427 	}
       
  2428 	RETURN (__MKSMALLINT(n));
       
  2429     }
       
  2430 #endif
       
  2431 bad: ;
       
  2432 %}.
       
  2433     "
       
  2434      arrive here if you try to send from an invalid buffer (i.e. not ByteArray-like),
       
  2435     "
       
  2436     self primitiveFailed
       
  2437 !
       
  2438 
       
  2439 sendTo:anAddressBuffer buffer:buffer
       
  2440     "send datagramm data - fetch address of destination host from
       
  2441      anAddressBuffer, data from aDataBuffer.
       
  2442      Both must be ByteArray-like. The bytes in the addressBuffer must
       
  2443      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  2444      Return the number of bytes transmitted, or a negative number on error.
       
  2445      On error, the unix error code is left in the lastErrorNumber
       
  2446      instance variable.
       
  2447      Flags is currently ignored; it is there for ST-80 compatibility."
       
  2448 
       
  2449     ^ self sendTo:anAddressBuffer buffer:buffer start:1 for:buffer size flags:0
       
  2450 !
       
  2451 
       
  2452 sendTo:anAddressBuffer buffer:buffer start:startIndex for:count
       
  2453     "send datagramm data - fetch address of destination host from
       
  2454      anAddressBuffer, data from aDataBuffer.
       
  2455      Both must be ByteArray-like. The bytes in the addressBuffer must
       
  2456      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  2457      Return the number of bytes transmitted, or a negative number on error.
       
  2458      On error, the unix error code is left in the lastErrorNumber
       
  2459      instance variable.
       
  2460      Flags is currently ignored; it is there for ST-80 compatibility."
       
  2461 
       
  2462     ^ self sendTo:anAddressBuffer buffer:buffer start:startIndex for:count flags:0
       
  2463 !
       
  2464 
       
  2465 sendTo:anAddressBuffer buffer:aDataBuffer start:startIndex for:nBytes flags:flags
       
  2466     "send datagramm data - fetch address of destination host from
       
  2467      anAddressBuffer, data from aDataBuffer starting at startIndex,
       
  2468      sending count bytes.
       
  2469      Both must be ByteArray-like. The bytes in the addressBuffer must
       
  2470      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
       
  2471      Return the number of bytes transmitted, or a negative number on error.
       
  2472      On error, the unix error code is left in the lastErrorNumber
       
  2473      instance variable."
       
  2474 
       
  2475     |domainClass addr|
       
  2476 
       
  2477     domainClass := self class socketAddressClassForDomain:domain.
       
  2478     domainClass isNil ifTrue:[
       
  2479 	^ self error:'invalid (unsupported) domain'.
       
  2480     ].
       
  2481 
       
  2482     (anAddressBuffer isKindOf:SocketAddress) ifTrue:[
       
  2483 	addr := anAddressBuffer.
       
  2484     ] ifFalse:[
       
  2485 	anAddressBuffer isByteArray ifFalse:[
       
  2486 	    ^ self error:'bad socketAddress argument'
       
  2487 	].
       
  2488 	addr := domainClass hostAddress:anAddressBuffer.
       
  2489     ].
       
  2490 %{
       
  2491 #ifndef NO_SOCKET
       
  2492     OBJ fp = __INST(filePointer);
       
  2493 
       
  2494     if ((fp != nil)
       
  2495      && __isSmallInteger(startIndex)
       
  2496      && __isSmallInteger(nBytes)) {
       
  2497 	SOCKET sock;
       
  2498 	int objSize;
       
  2499 	struct sockaddr *sockaddr_ptr;
       
  2500 	union sockaddr_u sa;
       
  2501 	int alen = 0;
       
  2502 	int sockAddrOffs, sockaddr_size;
       
  2503 	int n;
       
  2504 	char *extPtr;
       
  2505 	int _flags = 0;
       
  2506 	int offs;
       
  2507 	unsigned long norder;
       
  2508 	unsigned char *buffer;
       
  2509 	unsigned char *allocatedBuffer;
       
  2510 
       
  2511 	_flags = __longIntVal(flags);
       
  2512 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  2513 
       
  2514 	if (! __isBytes(addr)) {
       
  2515 	    sockaddr_size = 0;
       
  2516 	    sockaddr_ptr = (struct sockaddr *)0;
       
  2517 	} else {
       
  2518 	    int nIndex;
       
  2519 	    OBJ cls;
       
  2520 
       
  2521 	    sockAddrOffs = 0;
       
  2522 	    if ((cls = __qClass(addr)) != @global(ByteArray))
       
  2523 		sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
       
  2524 	    nIndex = __qSize(addr) - OHDR_SIZE;
       
  2525 	    sockaddr_size = nIndex - sockAddrOffs;
       
  2526 	    if (sockaddr_size > sizeof(sa)) {
       
  2527 		console_fprintf(stderr, "Socket [warning]: bad socketAddr\n");
       
  2528 		goto bad;
       
  2529 	    }
       
  2530 	    bcopy((__byteArrayVal(addr) + sockAddrOffs), &sa, sockaddr_size);
       
  2531 	    sockaddr_ptr = (struct sockaddr *)(&sa);
       
  2532 	}
       
  2533 
       
  2534 	if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad;
       
  2535 	if (__isSmallInteger(nBytes)) {
       
  2536 	    if (__intVal(nBytes) < objSize) {
       
  2537 		objSize = __intVal(nBytes);
       
  2538 	    }
       
  2539 	}
       
  2540 
       
  2541 #ifdef DO_WRAP_CALLS
       
  2542 	if (extPtr) {
       
  2543 	    buffer = extPtr + offs;
       
  2544 	} else {
       
  2545 	    allocatedBuffer = buffer = (char *)malloc(objSize);
       
  2546 	    bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize);
       
  2547 	}
       
  2548 
       
  2549 	do {
       
  2550 	    __threadErrno = 0;
       
  2551 	    n = STX_WSA_CALL6("sendto", sendto, sock, buffer, objSize, _flags, sockaddr_ptr, sockaddr_size);
       
  2552 	} while ((n < 0) && (__threadErrno == EINTR));
       
  2553 
       
  2554 	if (allocatedBuffer) {
       
  2555 	    free(allocatedBuffer);
       
  2556 	}
       
  2557 #else
       
  2558 	__BEGIN_INTERRUPTABLE__
       
  2559 	do {
       
  2560 	    if (extPtr) {
       
  2561 		n = sendto(sock, extPtr + offs, objSize, _flags, sockaddr_ptr, sockaddr_size);
       
  2562 	    } else {
       
  2563 		n = sendto(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags, sockaddr_ptr, sockaddr_size);
       
  2564 	    }
       
  2565 	} while ((n < 0) && (errno == EINTR));
       
  2566 	__END_INTERRUPTABLE__
       
  2567 #endif
       
  2568 
       
  2569 	if (n < 0) {
       
  2570 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2571 	}
       
  2572 	RETURN (__MKSMALLINT(n));
       
  2573     }
       
  2574 #endif
       
  2575 bad: ;
       
  2576 %}.
       
  2577     "
       
  2578      arrive here if you try to send from an invalid buffer
       
  2579      (i.e. not ByteArray-like),
       
  2580      or if the addressBuffer is nonNil AND not a ByteArray/String
       
  2581      or if the addressBuffer is nonNil AND too small.
       
  2582     "
       
  2583     self primitiveFailed
       
  2584 ! !
       
  2585 
       
  2586 !Socket protectedMethodsFor:'low level'!
       
  2587 
       
  2588 closeFile
       
  2589     "low level close"
       
  2590 
       
  2591 %{  /* NOCONTEXT */
       
  2592 #ifndef NO_SOCKET
       
  2593     OBJ t;
       
  2594 
       
  2595     t = __INST(filePointer);
       
  2596     if (t != nil) {
       
  2597 	FILE *fp;
       
  2598 	SOCKET sock;
       
  2599 	int fd;
       
  2600 
       
  2601 	__INST(filePointer) = nil;
       
  2602 	fp = __FILEVal(t);
       
  2603 	fd = fileno(fp);
       
  2604 	sock = SOCKET_FROM_FD(fd);
       
  2605 
       
  2606 # ifdef xxDO_WRAP_CALLS
       
  2607 	{ int ret;
       
  2608 
       
  2609 	  do {
       
  2610 	    __threadErrno = 0;
       
  2611 	    ret = STX_C_CALL1("fclose", fclose, fp);
       
  2612 	  } while ((ret < 0) && (__threadErrno == EINTR));
       
  2613 
       
  2614 #  ifdef WIN32
       
  2615 	  do {
       
  2616 	    __threadErrno = 0;
       
  2617 	    ret = STX_WSA_CALL1("closesocket", closesocket, sock);
       
  2618 	  } while ((ret < 0) && (__threadErrno == EINTR));
       
  2619 	  closesocket(sock);
       
  2620 #  endif
       
  2621 	}
       
  2622 # else /* !DO_WRAP_CALLS */
       
  2623 
       
  2624 	DBGFPRINTF((stderr, "SOCKET: fflush %x (%d %d)\n", fp, fileno(fp), sock));
       
  2625 	fflush(fp);
       
  2626 
       
  2627 #  if defined(CLOSESOCKET_BEFORE_FCLOSE)
       
  2628 	DBGFPRINTF((stderr, "SOCKET: closesocket (%d)\n", sock));
       
  2629 	closesocket(sock);
       
  2630 #  endif
       
  2631 	if ((@global(FileOpenTrace) == true) || __debugging__) {
       
  2632 	    console_fprintf(stderr, "SOCKET: fclose %x (%d %d)\n", fp, fileno(fp), sock);
       
  2633 	}
       
  2634 	fclose(fp);
       
  2635 
       
  2636 #  if defined(CLOSESOCKET_AFTER_FCLOSE)
       
  2637 	DBGFPRINTF((stderr, "SOCKET: closesocket (%d)\n", sock));
       
  2638 	closesocket(sock);
       
  2639 #  endif
       
  2640 # endif /* !DO_WRAP_CALLS */
       
  2641     }
       
  2642 #endif /* NO_SOCKET */
       
  2643 %}
       
  2644 ! !
       
  2645 
       
  2646 !Socket methodsFor:'low level'!
       
  2647 
       
  2648 getSocketAdress
       
  2649     "BAD SPELLING, of #getSocketAddress, kept for compatibility with swazoo"
       
  2650 
       
  2651     <resource: #obsolete>
       
  2652 
       
  2653     ^ self getSocketAddress
       
  2654 !
       
  2655 
       
  2656 getSocketError
       
  2657     "get the SO_ERROR form the socket, which indicates the
       
  2658      result of an asynchronous operation"
       
  2659 
       
  2660 %{
       
  2661 #ifndef NO_SOCKET
       
  2662     OBJ fp;
       
  2663     int err;
       
  2664 
       
  2665     fp = __INST(filePointer);
       
  2666     if (fp == nil) {
       
  2667 	err = EBADF;
       
  2668     } else {
       
  2669 	unsigned int sz;
       
  2670 	SOCKET sock;
       
  2671 
       
  2672 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  2673 	sz = sizeof(err);
       
  2674 	if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {
       
  2675 # ifdef WIN32
       
  2676 	    errno = WSAGetLastError();
       
  2677 # endif
       
  2678 	    err = errno;
       
  2679 	}
       
  2680     }
       
  2681 
       
  2682     RETURN(__MKSMALLINT(err));
       
  2683 #endif
       
  2684 %}
       
  2685 !
       
  2686 
       
  2687 listenWithBacklog:aNumber
       
  2688     <resource: #obsolete>
       
  2689     "same as listenFor: - backward compatibility with old ST/X"
       
  2690 
       
  2691     ^ self listenFor:aNumber
       
  2692 !
       
  2693 
       
  2694 pollingWaitForNewConnectionOrDataOnAny:otherConnections timeout:timeoutSeconds
       
  2695     <resource: #obsolete>
       
  2696     "stupid MSDOS does not support select on sockets (sigh).
       
  2697      Must poll here."
       
  2698 
       
  2699     |millis newConnection|
       
  2700 
       
  2701     millis := timeoutSeconds * 1000.
       
  2702     [millis > 0] whileTrue:[
       
  2703 	otherConnections size > 0 ifTrue:[
       
  2704 	    otherConnections do:[:aConnection |
       
  2705 		aConnection canReadWithoutBlocking ifTrue:[
       
  2706 		    ^ aConnection
       
  2707 		]
       
  2708 	    ].
       
  2709 	].
       
  2710 	newConnection := self blockingAccept.
       
  2711 	newConnection notNil ifTrue:[^ newConnection].
       
  2712 	Delay waitForMilliseconds:20.
       
  2713 	millis := millis - 20.
       
  2714     ].
       
  2715     ^ nil.
       
  2716 !
       
  2717 
       
  2718 pollingWaitForNewConnectionWithTimeout:timeoutSeconds
       
  2719     <resource: #obsolete>
       
  2720     "stupid MSDOS does not support select on sockets (sigh).
       
  2721      Must poll here."
       
  2722 
       
  2723     |millis newConnection|
       
  2724 
       
  2725     timeoutSeconds notNil ifTrue:[
       
  2726 	millis := timeoutSeconds * 1000.
       
  2727     ].
       
  2728     [millis isNil or:[millis > 0]] whileTrue:[
       
  2729 	newConnection := self blockingAccept.
       
  2730 	newConnection notNil ifTrue:[^ newConnection].
       
  2731 	Delay waitForMilliseconds:20.
       
  2732 	millis notNil ifTrue:[
       
  2733 	    millis := millis - 20.
       
  2734 	]
       
  2735     ].
       
  2736     ^ nil.
       
  2737 !
       
  2738 
       
  2739 primAcceptOn:aSocket blocking:blocking
       
  2740     "accept a connection on a server port (created with:'Socket>>onIPPort:')
       
  2741      usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
       
  2742      Return the true if ok; false if not.
       
  2743      If blocking is true, the accept() syscall (and the whole smalltalk image)
       
  2744      will block, until a connection is accepted.
       
  2745      If blocking is false, this call will return immediately, if there is no connection pending."
       
  2746 
       
  2747     |serverSocketFd addr addrLen domainClass|
       
  2748 
       
  2749     filePointer notNil ifTrue:[
       
  2750         ^ self errorAlreadyOpen
       
  2751     ].
       
  2752 
       
  2753     domain := aSocket domain.
       
  2754     socketType := aSocket type.
       
  2755     serverSocketFd := aSocket fileDescriptor.
       
  2756     serverSocketFd isNil ifTrue:[
       
  2757         ^ self error:'invalid server socket'
       
  2758     ].
       
  2759     (serverSocketFd isMemberOf:SmallInteger) ifFalse:[
       
  2760         ^ self error:'invalid server socket'
       
  2761     ].
       
  2762 
       
  2763     domainClass := self class socketAddressClassForDomain:domain.
       
  2764     domainClass isNil ifTrue:[
       
  2765         ^ self error:'invalid (unsupported) domain'.
       
  2766     ].
       
  2767     addrLen := domainClass socketAddressSize.
       
  2768     addr := domainClass new.
       
  2769 
       
  2770 %{  /* STACK: 100000 */
       
  2771 #ifndef NO_SOCKET
       
  2772     FILE *fp;
       
  2773     int flags;
       
  2774     SOCKET sock, newSock;
       
  2775     union sockaddr_u sa;
       
  2776     unsigned int alen, alen0;
       
  2777     struct hostent *he ;
       
  2778     char dotted[20] ;
       
  2779 
       
  2780     if (!__isSmallInteger(addrLen)) {
       
  2781         DBGPRINTF(("SOCKET: bad addrLen\n"));
       
  2782         RETURN (false);
       
  2783     }
       
  2784     alen0 = __intVal(addrLen);
       
  2785     sock = SOCKET_FROM_FD(__intVal(serverSocketFd));
       
  2786 
       
  2787     if (blocking == false) {
       
  2788 # if defined(O_NONBLOCK) && defined(SET_NDELAY)
       
  2789         flags = fcntl(sock, F_GETFL);
       
  2790         fcntl(sock, F_SETFL, flags | O_NONBLOCK);
       
  2791 # endif
       
  2792     }
       
  2793 
       
  2794 # ifdef DO_WRAP_CALLS
       
  2795     do {
       
  2796         __threadErrno = 0;
       
  2797         alen = alen0;
       
  2798         newSock = STX_WSA_CALL3("accept", accept, sock, &sa, &alen);
       
  2799     } while ((newSock < 0) && (__threadErrno == EINTR));
       
  2800 # else
       
  2801     __BEGIN_INTERRUPTABLE__
       
  2802     do {
       
  2803         alen = alen0;
       
  2804         newSock = accept(sock, (struct sockaddr *) &sa, &alen);
       
  2805     } while ((newSock < 0) && (errno == EINTR));
       
  2806     __END_INTERRUPTABLE__
       
  2807 # endif
       
  2808     DBGFPRINTF((stderr, "SOCKET: accept newSock=%d\n", newSock));
       
  2809 
       
  2810     if (blocking == false) {
       
  2811 # if defined(O_NDELAY) && defined(SET_NDELAY)
       
  2812         fcntl(sock, F_SETFL, flags);
       
  2813 # endif
       
  2814     }
       
  2815 
       
  2816     if (newSock < 0) {
       
  2817         DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
       
  2818         __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2819         RETURN (false);
       
  2820     }
       
  2821 
       
  2822     if (__isNonNilObject(addr)) {
       
  2823         OBJ oClass;
       
  2824         int nInstVars, nInstBytes, objSize;
       
  2825         char *cp;
       
  2826 
       
  2827         oClass = __qClass(addr);
       
  2828         if (! __isBytes(addr) ) {
       
  2829             DBGPRINTF(("SOCKET: bad addr\n"));
       
  2830             closesocket(newSock);
       
  2831             RETURN (false);
       
  2832         }
       
  2833 
       
  2834         nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
       
  2835         nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
       
  2836         objSize = __qSize(addr) - nInstBytes;
       
  2837         cp = (char *)__InstPtr(addr) + nInstBytes;
       
  2838         if (objSize < alen) {
       
  2839             DBGPRINTF(("SOCKET: bad addr\n"));
       
  2840             closesocket(newSock);
       
  2841             RETURN (false);
       
  2842         }
       
  2843 
       
  2844         /*
       
  2845          * extract the partners address
       
  2846          */
       
  2847         bcopy((char *)&sa, cp, alen);
       
  2848         addrLen = __MKSMALLINT(alen);
       
  2849     }
       
  2850 
       
  2851     /*
       
  2852      * make it a FILE *
       
  2853      */
       
  2854 # ifdef WIN32
       
  2855     {
       
  2856         int _fd = _open_osfhandle(newSock, 0);
       
  2857         fp = fdopen(_fd, "r+");
       
  2858         DBGPRINTF(("SOCKET: sock=%d fd=%d fp=%x\n",newSock,_fd, fp));
       
  2859     }
       
  2860 # else
       
  2861     fp = fdopen(newSock, "r+");
       
  2862 # endif
       
  2863 
       
  2864     if (! fp) {
       
  2865         DBGPRINTF(("SOCKET: fdopen call failed\n"));
       
  2866         __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  2867 #  ifdef DO_WRAP_CALLS
       
  2868         {
       
  2869           int ret;
       
  2870           do {
       
  2871               __threadErrno = 0;
       
  2872               ret = STX_WSA_CALL1("closesocket", closesocket, newSock);
       
  2873           } while ((ret < 0) && (__threadErrno == EINTR));
       
  2874         }
       
  2875 #  else
       
  2876         closesocket(newSock);
       
  2877 #  endif
       
  2878         DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock));
       
  2879         RETURN (false);
       
  2880     }
       
  2881 
       
  2882     if ((@global(FileOpenTrace) == true) || __debugging__) {
       
  2883 # ifdef WIN32
       
  2884         {
       
  2885             HANDLE h;
       
  2886             int _fd = fileno(fp);
       
  2887             h = (HANDLE)_get_osfhandle(_fd);
       
  2888             console_fprintf(stderr, "fdopen [Socket] -> %x (fd: %d) (H: %x)\n", fp, _fd, h);
       
  2889         }
       
  2890 # else
       
  2891         console_fprintf(stderr, "fdopen [Socket] -> %x (fd: %d)\n", fp, newSock);
       
  2892 # endif
       
  2893     }
       
  2894 
       
  2895 # ifdef BUGGY_STDIO_LIB
       
  2896     setbuf(fp, NULL);
       
  2897     __INST(buffered) = false;
       
  2898 # endif
       
  2899 
       
  2900 # if 0
       
  2901     // The original code was:
       
  2902     __INST(filePointer) = __MKOBJ((INT)fp); __STORESELF(filePointer);
       
  2903     // but for that, gcc generates wrong code, which loads self (volatile) into
       
  2904     // a register (bp), then calls __MKOBJ, then stores indirect bp.
       
  2905     // That is wrong if a scavenge occurs in MKOBJ, as bp is now still pointing to the old
       
  2906     // object.
       
  2907 # endif
       
  2908     {
       
  2909         OBJ t;
       
  2910 
       
  2911         t = __MKOBJ(fp);
       
  2912         __INST(filePointer) = t;
       
  2913         __STORE(self, t);
       
  2914     }
       
  2915 #endif /* not NO_SOCKET */
       
  2916 %}.
       
  2917     mode := #readwrite.
       
  2918     Lobby register:self.
       
  2919     binary := false.
       
  2920     port := aSocket port.
       
  2921 
       
  2922     addr notNil ifTrue:[
       
  2923         peer := addr.
       
  2924     ].
       
  2925 
       
  2926     ^ true
       
  2927 ! !
       
  2928 
       
  2929 !Socket protectedMethodsFor:'low level'!
       
  2930 
       
  2931 setSocketOption:option argument:arg1 argument:arg2
       
  2932     |ok|
       
  2933 
       
  2934 %{  /* STACK: 32000 */
       
  2935     OBJ fp = __INST(filePointer);
       
  2936 
       
  2937     if (fp != nil) {
       
  2938 	SOCKET sock;
       
  2939 	int opt = -1;
       
  2940 	int level = -1;
       
  2941 	int usize = -1;
       
  2942 	int ret;
       
  2943 	union u {
       
  2944 	    BOOL        u_bool;
       
  2945 	    int         u_int;
       
  2946 	    struct linger u_linger;
       
  2947 	} u;
       
  2948 
       
  2949 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  2950 
       
  2951 # ifdef SO_BROADCAST
       
  2952 	if (option == @symbol(SO_BROADCAST)) {
       
  2953 	    /* Enables transmission and receipt of broadcast messages on the socket. */
       
  2954 	    opt = SO_BROADCAST;
       
  2955 	    level = SOL_SOCKET;
       
  2956 	    usize = sizeof(u.u_bool);
       
  2957 	    if (arg1 == true) u.u_bool = TRUE;
       
  2958 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2959 	    else goto argError;
       
  2960 	}
       
  2961 # endif /* SO_BROADCAST */
       
  2962 
       
  2963 # ifdef SO_CONDITIONAL
       
  2964 #  if 0
       
  2965 	if (option == @symbol(SO_CONDITIONAL)) {
       
  2966 	    /* Enables sockets to delay the acknowledgment of a connection until after the WSAAccept condition function is called. */
       
  2967 	    opt = SO_CONDITIONAL;
       
  2968 	    level = SOL_SOCKET;
       
  2969 	    usize = sizeof(u.u_bool);
       
  2970 	    if (arg1 == true) u.u_bool = TRUE;
       
  2971 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2972 	    else goto argError;
       
  2973 	}
       
  2974 #  endif
       
  2975 # endif /* SO_CONDITIONAL */
       
  2976 
       
  2977 # ifdef SO_DEBUG
       
  2978 	if (option == @symbol(SO_DEBUG)) {
       
  2979 	    /* Records debugging information. */
       
  2980 	    opt = SO_DEBUG;
       
  2981 	    level = SOL_SOCKET;
       
  2982 	    usize = sizeof(u.u_bool);
       
  2983 	    if (arg1 == true) u.u_bool = TRUE;
       
  2984 	    else if (arg1 == false) u.u_bool = FALSE;
       
  2985 	    else goto argError;
       
  2986 	}
       
  2987 # endif /* SO_DEBUG */
       
  2988 
       
  2989 # ifdef SO_DONTLINGER
       
  2990 	    if (option == @symbol(SO_DONTLINGER)) {
       
  2991 		/* Does not block close waiting for unsent data to be sent.
       
  2992 		   Setting this option is equivalent to setting SO_LINGER with l_onoff set to zero. */
       
  2993 		opt = SO_DONTLINGER;
       
  2994 		level = SOL_SOCKET;
       
  2995 		usize = sizeof(u.u_bool);
       
  2996 		if (arg1 == true) u.u_bool = TRUE;
       
  2997 		else if (arg1 == false) u.u_bool = FALSE;
       
  2998 		else goto argError;
       
  2999 	    }
       
  3000 # endif /* SO_DONTLINGER */
       
  3001 
       
  3002 # ifdef SO_DONTROUTE
       
  3003 	if (option == @symbol(SO_DONTROUTE)) {
       
  3004 	    /* Does not route: sends directly to interface.
       
  3005 	       Succeeds but is ignored on AF_INET sockets;
       
  3006 	       fails on AF_INET6 sockets with WSAENOPROTOOPT.
       
  3007 	       Not supported on ATM sockets (results in an error). */
       
  3008 	    opt = SO_DONTROUTE;
       
  3009 	    level = SOL_SOCKET;
       
  3010 	    usize = sizeof(u.u_bool);
       
  3011 	    if (arg1 == true) u.u_bool = TRUE;
       
  3012 	    else if (arg1 == false) u.u_bool = FALSE;
       
  3013 	    else goto argError;
       
  3014 	}
       
  3015 # endif /* SO_DONTROUTE */
       
  3016 
       
  3017 # ifdef SO_KEEPALIVE
       
  3018 	if (option == @symbol(SO_KEEPALIVE)) {
       
  3019 	    /* Sends keep-alives. Not supported on ATM sockets (results in an error). */
       
  3020 	    opt = SO_KEEPALIVE;
       
  3021 	    level = SOL_SOCKET;
       
  3022 	    usize = sizeof(u.u_bool);
       
  3023 	    if (arg1 == true) u.u_bool = TRUE;
       
  3024 	    else if (arg1 == false) u.u_bool = FALSE;
       
  3025 	    else goto argError;
       
  3026 	}
       
  3027 # endif /* SO_KEEPALIVE */
       
  3028 
       
  3029 # ifdef SO_LINGER
       
  3030 	if (option == @symbol(SO_LINGER)) {
       
  3031 	    /* Lingers on close if unsent data is present. */
       
  3032 	    opt = SO_LINGER;
       
  3033 	    level = SOL_SOCKET;
       
  3034 	    usize = sizeof(u.u_linger);
       
  3035 	    if (arg1 == true) u.u_linger.l_onoff = TRUE;
       
  3036 	    else if (arg1 == false) u.u_linger.l_onoff = FALSE;
       
  3037 	    else goto argError;
       
  3038 	    if (arg2 == nil) u.u_linger.l_linger = 0;
       
  3039 	    else if (__isSmallInteger(arg2))u.u_linger.l_linger = __intVal(arg2);
       
  3040 	    else goto argError;
       
  3041 	    DBGPRINTF(("SOCKET: SO_LINGER %d %d\n", u.u_linger.l_onoff, u.u_linger.l_linger));
       
  3042 	}
       
  3043 # endif /* SO_LINGER */
       
  3044 
       
  3045 # ifdef SO_OOBINLINE
       
  3046 	if (option == @symbol(SO_OOBINLINE)) {
       
  3047 	    /* Receives OOB data in the normal data stream. */
       
  3048 	    opt = SO_OOBINLINE;
       
  3049 	    level = SOL_SOCKET;
       
  3050 	    usize = sizeof(u.u_bool);
       
  3051 	    if (arg1 == true) u.u_bool = TRUE;
       
  3052 	    else if (arg1 == false) u.u_bool = FALSE;
       
  3053 	    else goto argError;
       
  3054 	}
       
  3055 # endif /* SO_OOBINLINE */
       
  3056 
       
  3057 # ifdef SO_RCVBUF
       
  3058 	if (option == @symbol(SO_RCVBUF)) {
       
  3059 	    /* Specifies the total per-socket buffer space reserved for receives.
       
  3060 	       This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
       
  3061 	    opt = SO_RCVBUF;
       
  3062 	    level = SOL_SOCKET;
       
  3063 	    usize = sizeof(u.u_int);
       
  3064 	    if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
       
  3065 	    else goto argError;
       
  3066 	}
       
  3067 # endif /* SO_RCVBUF */
       
  3068 
       
  3069 # ifdef SO_SNDBUF
       
  3070 	if (option == @symbol(SO_SNDBUF)) {
       
  3071 	    /* Specifies the total per-socket buffer space reserved for sends.
       
  3072 	       This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
       
  3073 	    opt = SO_SNDBUF;
       
  3074 	    level = SOL_SOCKET;
       
  3075 	    usize = sizeof(u.u_int);
       
  3076 	    if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
       
  3077 	    else goto argError;
       
  3078 	}
       
  3079 # endif /* SO_SNDBUF */
       
  3080 
       
  3081 # ifdef SO_REUSEADDR
       
  3082 	if (option == @symbol(SO_REUSEADDR)) {
       
  3083 	    /* Allows the socket to be bound to an address that is already in use.  */
       
  3084 	    opt = SO_REUSEADDR;
       
  3085 	    level = SOL_SOCKET;
       
  3086 	    usize = sizeof(u.u_bool);
       
  3087 	    if (arg1 == true) u.u_bool = TRUE;
       
  3088 	    else if (arg1 == false) u.u_bool = FALSE;
       
  3089 	    else goto argError;
       
  3090 	}
       
  3091 # endif /* SO_OOBINLINE */
       
  3092 
       
  3093 # ifdef SO_EXCLUSIVEADDRUSE
       
  3094 	if (option == @symbol(SO_EXCLUSIVEADDRUSE)) {
       
  3095 	    /* Enables a socket to be bound for exclusive access.
       
  3096 	       Does not require administrative privilege.  */
       
  3097 	    opt = SO_EXCLUSIVEADDRUSE;
       
  3098 	    level = SOL_SOCKET;
       
  3099 	    usize = sizeof(u.u_bool);
       
  3100 	    if (arg1 == true) u.u_bool = TRUE;
       
  3101 	    else if (arg1 == false) u.u_bool = FALSE;
       
  3102 	    else goto argError;
       
  3103 	}
       
  3104 # endif /* SO_OOBINLINE */
       
  3105 
       
  3106 	if (usize == -1) goto argError;
       
  3107 
       
  3108 	ok = ( setsockopt( sock, level, opt, &u, usize) >= 0) ? true : false;
       
  3109     }
       
  3110 argError: ;
       
  3111 
       
  3112 %}.
       
  3113     ok isNil ifTrue:[
       
  3114 	self primitiveFailed
       
  3115     ].
       
  3116     ok ifFalse:[
       
  3117 	'setsocketoption failed' infoPrintCR.
       
  3118     ].
       
  3119 ! !
       
  3120 
       
  3121 !Socket methodsFor:'low level'!
       
  3122 
       
  3123 shutdown: howNum
       
  3124     "shutDown the socket - inform it that no more I/O will be performed.
       
  3125 	 0 - read side   (no further reads)
       
  3126 	 1 - write side  (no further writes)
       
  3127 	 2 - both        (no further I/O at all)
       
  3128      shutDown:2
       
  3129 	discards any pending data
       
  3130 	(as opposed to close, which might wait until data is delivered as set by LINGER)"
       
  3131 
       
  3132 %{
       
  3133 #ifndef NO_SOCKET
       
  3134 
       
  3135     OBJ fp;
       
  3136 
       
  3137     fp = __INST(filePointer);
       
  3138     if ((fp != nil) && __isSmallInteger(howNum)) {
       
  3139 	SOCKET sock;
       
  3140 	int ret;
       
  3141 
       
  3142 	sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  3143 # ifdef DO_WRAP_CALLS
       
  3144 	do {
       
  3145 	    __threadErrno = 0;
       
  3146 	    DBGFPRINTF((stderr, "SOCKET: shutDown...\n"));
       
  3147 	    ret = STX_WSA_CALL2("shutdown", shutdown, sock, __intVal(howNum));
       
  3148 	    DBGFPRINTF((stderr, "SOCKET: shutDown -> %d (%d)\n", ret, __threadErrno));
       
  3149 	} while ((ret < 0) && (__threadErrno == EINTR));
       
  3150 # else
       
  3151 	__BEGIN_INTERRUPTABLE__
       
  3152 	shutdown(sock, __intVal(howNum));
       
  3153 	__END_INTERRUPTABLE__
       
  3154 # endif
       
  3155     }
       
  3156 #endif
       
  3157 %}.
       
  3158 ! !
       
  3159 
  3240 !Socket methodsFor:'printing & storing'!
  3160 !Socket methodsFor:'printing & storing'!
  3241 
  3161 
  3242 printOn:aStream
  3162 printOn:aStream
  3243     aStream nextPutAll:self className; nextPutAll:'(protocol='.
  3163     aStream nextPutAll:self className; nextPutAll:'(protocol='.
  3244     protocol printOn:aStream.
  3164     protocol printOn:aStream.
  3245     aStream nextPutAll:' port='.
  3165     aStream nextPutAll:' port='.
  3246     port printOn:aStream.
  3166     self port printOn:aStream.
  3247     aStream nextPutAll:' peer='.
  3167     aStream nextPutAll:' peer='.
  3248     peer printOn:aStream.
  3168     peer printOn:aStream.
  3249     aStream nextPut:$).
  3169     aStream nextPut:$).
  3250 ! !
  3170 ! !
  3251 
  3171 
  3256 
  3176 
  3257     ^ domain
  3177     ^ domain
  3258 !
  3178 !
  3259 
  3179 
  3260 getFullSocketAddress
  3180 getFullSocketAddress
  3261     "implemented for swazoo project (primitive code cant be loaded as extension)
  3181     "implemented for swazoo project (primitive code can't be loaded as extension)
  3262      Answer my own address (I am bound to this address).
  3182      Answer my own address (I am bound to this address).
  3263      Note that this address may change after a connect or accept."
  3183      Note that this address may change after a connect or accept."
  3264 
  3184 
  3265     |error domainClass addr addrLen|
  3185     |error domainClass addr addrLen|
  3266 
  3186 
  3267     filePointer isNil ifTrue:[
  3187     filePointer isNil ifTrue:[
  3268 	^ self errorNotOpen
  3188         ^ self errorNotOpen
  3269     ].
  3189     ].
  3270 
  3190 
  3271     domainClass := self class socketAddressClassForDomain:domain.
  3191     domainClass := self class socketAddressClassForDomain:domain.
  3272     domainClass isNil ifTrue:[
  3192     domainClass isNil ifTrue:[
  3273 	^ self error:'invalid (unsupported) domain'.
  3193         ^ self error:'invalid (unsupported) domain'.
  3274     ].
  3194     ].
  3275     addrLen := domainClass socketAddressSize.
  3195     addrLen := domainClass socketAddressSize.
  3276     addr := domainClass new.
  3196     addr := domainClass new.
  3277 
  3197 
  3278 %{
  3198 %{
  3284     unsigned int alen, alen0;
  3204     unsigned int alen, alen0;
  3285     char *addrP;
  3205     char *addrP;
  3286     int addrObjSize, nAddrInstBytes;
  3206     int addrObjSize, nAddrInstBytes;
  3287 
  3207 
  3288     if (!__isSmallInteger(addrLen)) {
  3208     if (!__isSmallInteger(addrLen)) {
  3289 	DBGPRINTF(("SOCKET: bad addrLen\n"));
  3209         DBGPRINTF(("SOCKET: bad addrLen\n"));
  3290 	error = @symbol(badArgument);
  3210         error = @symbol(badArgument);
  3291 	goto err;
  3211         goto err;
  3292     }
  3212     }
  3293     alen = alen0 = __intVal(addrLen);
  3213     alen = alen0 = __intVal(addrLen);
  3294 
  3214 
  3295     if (!__isNonNilObject(addr) || !__isBytes(addr)) {
  3215     if (!__isNonNilObject(addr) || !__isBytes(addr)) {
  3296 	DBGPRINTF(("SOCKET: bad addr\n"));
  3216         DBGPRINTF(("SOCKET: bad addr\n"));
  3297 	error = @symbol(badArgument);
  3217         error = @symbol(badArgument);
  3298 	goto err;
  3218         goto err;
  3299     }
  3219     }
  3300 
  3220 
  3301     {
  3221     {
  3302 	OBJ addrClass;
  3222         OBJ addrClass;
  3303 	int nAddrInstVars;
  3223         int nAddrInstVars;
  3304 
  3224 
  3305 	addrClass = __qClass(addr);
  3225         addrClass = __qClass(addr);
  3306 	nAddrInstVars = __intVal(__ClassInstPtr(addrClass)->c_ninstvars);
  3226         nAddrInstVars = __intVal(__ClassInstPtr(addrClass)->c_ninstvars);
  3307 	nAddrInstBytes = OHDR_SIZE + (nAddrInstVars * sizeof(OBJ));
  3227         nAddrInstBytes = OHDR_SIZE + (nAddrInstVars * sizeof(OBJ));
  3308 	addrObjSize = __qSize(addr) - nAddrInstBytes;
  3228         addrObjSize = __qSize(addr) - nAddrInstBytes;
  3309 	if (addrObjSize < alen0) {
  3229         if (addrObjSize < alen0) {
  3310 	    DBGPRINTF(("SOCKET: bad addr/alen\n"));
  3230             DBGPRINTF(("SOCKET: bad addr/alen\n"));
  3311 	    error = @symbol(badArgument);
  3231             error = @symbol(badArgument);
  3312 	    goto err;
  3232             goto err;
  3313 	}
  3233         }
  3314     }
  3234     }
  3315 
  3235 
  3316     sock = SOCKET_FROM_FILE_OBJECT(fp);
  3236     sock = SOCKET_FROM_FILE_OBJECT(fp);
  3317 # ifdef WIN32
  3237 # ifdef WIN32
  3318     __threadErrno = 0;
  3238     __threadErrno = 0;
  3319 # endif
  3239 # endif
  3320     ret = getsockname(sock, (struct sockaddr *)&sa, &alen);
  3240     ret = getsockname(sock, (struct sockaddr *)&sa, &alen);
  3321     if (ret < 0) {
  3241     if (ret < 0) {
  3322 # ifdef WIN32
  3242 # ifdef WIN32
  3323 	errno = WSAGetLastError();
  3243         errno = WSAGetLastError();
  3324 # endif
  3244 # endif
  3325 	DBGPRINTF(("SOCKET: getsocketname failed ret=%d errno=%d\n", ret, errno));
  3245         DBGPRINTF(("SOCKET: getsocketname failed ret=%d errno=%d\n", ret, errno));
  3326 	error = __MKSMALLINT(errno);
  3246         error = __MKSMALLINT(errno);
  3327 	goto err;
  3247         goto err;
  3328     }
  3248     }
  3329 
  3249 
  3330     if (addrObjSize < alen) {
  3250     if (addrObjSize < alen) {
  3331 	DBGPRINTF(("SOCKET: bad addr\n"));
  3251         DBGPRINTF(("SOCKET: bad addr\n"));
  3332 	error = @symbol(badArgument);
  3252         error = @symbol(badArgument);
  3333 	goto err;
  3253         goto err;
  3334     }
  3254     }
  3335 
  3255 
  3336     addrP = (char *)__InstPtr(addr) + nAddrInstBytes;
  3256     addrP = (char *)__InstPtr(addr) + nAddrInstBytes;
  3337     bcopy((char *)&sa, addrP, alen);
  3257     bcopy((char *)&sa, addrP, alen);
  3338 
  3258 
  3342 #else /* NO_SOCKET */
  3262 #else /* NO_SOCKET */
  3343     error = @symbol(notImplemented);
  3263     error = @symbol(notImplemented);
  3344 #endif /* NO_SOCKET */
  3264 #endif /* NO_SOCKET */
  3345 %}.
  3265 %}.
  3346     error notNil ifTrue:[
  3266     error notNil ifTrue:[
  3347 	^ self errorReporter reportOn:error
  3267         ^ self errorReporter reportOn:error
  3348     ].
  3268     ].
  3349     ^ addr
  3269     ^ addr
  3350 !
  3270 !
  3351 
  3271 
  3352 getName
  3272 getName
  3353     "return the name; here, we return the ports name"
  3273     "return the name; here, we return the ports name"
  3354 
  3274 
  3355     ^ port printString
  3275     ^ self port printString
  3356 !
  3276 !
  3357 
  3277 
  3358 getPeer
  3278 getPeer
  3359     "ST-80 compatibility: return an IPSocketAddress instance representing
  3279     "ST-80 compatibility: return an IPSocketAddress instance representing
  3360      my hostname/port combination.
  3280      my hostname/port combination.
  3361      If you are interested in the hostname, use getPeerName directly."
  3281      If you are interested in the hostname, use getPeerName directly."
  3362 
  3282 
  3363     peer isNil ifTrue:[
       
  3364 	peer := self class peerFromDomain:domain name:peerName port:port.
       
  3365     ].
       
  3366     ^ peer
  3283     ^ peer
  3367 !
  3284 !
  3368 
  3285 
  3369 getPeerName
  3286 getPeerName
  3370     "return the peer name; thats the hostname (or dotted name) of the
  3287     "return the peer name; thats the hostname (or dotted name) of the
  3380     "implemented for swazoo project primitive code cant load as extension
  3297     "implemented for swazoo project primitive code cant load as extension
  3381      answer my own address (I am bound to this address).
  3298      answer my own address (I am bound to this address).
  3382      Note that this address may change after connect or accept."
  3299      Note that this address may change after connect or accept."
  3383 
  3300 
  3384     ^ self getFullSocketAddress hostAddress
  3301     ^ self getFullSocketAddress hostAddress
  3385     "/ ^ self getFullSocketAddress copyFrom:5 to:8
       
  3386 !
       
  3387 
       
  3388 getSocketAdress
       
  3389     "BAD SPELLING, of #getSocketAddress, kept for compatibility with swazoo"
       
  3390 
       
  3391     <resource: #obsolete>
       
  3392 
       
  3393     ^ self getSocketAddress
       
  3394 !
  3302 !
  3395 
  3303 
  3396 isActive
  3304 isActive
  3397     "return true, if the receiver has a connection"
  3305     "return true, if the receiver has a connection"
  3398 
  3306 
  3401 
  3309 
  3402 isConnected
  3310 isConnected
  3403     "return true, if the receiver has a connection"
  3311     "return true, if the receiver has a connection"
  3404 
  3312 
  3405     ^ self isActive
  3313     ^ self isActive
  3406       and:[port notNil
  3314         and:[peer notNil]
  3407       and:[peerName notNil or:[peer notNil]]]
       
  3408 !
       
  3409 
       
  3410 old_getFullSocketAddress
       
  3411     "implemented for swazoo project primitive code cant load as extension
       
  3412      answer my own address (I am bound to this address).
       
  3413      Note that this address may change after connect or accept."
       
  3414 
       
  3415     |socketAddress error|
       
  3416 
       
  3417     filePointer isNil ifTrue:[
       
  3418 	^ self errorNotOpen
       
  3419     ].
       
  3420     socketAddress := ByteArray new:16.
       
  3421 
       
  3422 %{
       
  3423 #ifndef NO_SOCKET
       
  3424     OBJ fp = __INST(filePointer);
       
  3425     SOCKET sock;
       
  3426     unsigned int sockaddr_size;
       
  3427     int ret;
       
  3428 
       
  3429     if (!__isNonNilObject(socketAddress) ||
       
  3430 	(__intVal(__ClassInstPtr(__qClass(socketAddress))->c_flags) & ARRAYMASK) != BYTEARRAY) {
       
  3431 	error = @symbol(badArgument1);
       
  3432 	goto err;
       
  3433     }
       
  3434     sockaddr_size = __byteArraySize(socketAddress);
       
  3435 
       
  3436     sock = SOCKET_FROM_FILE_OBJECT(fp);
       
  3437     ret = getsockname(sock, (struct sockaddr *)__byteArrayVal(socketAddress), &sockaddr_size);
       
  3438     if (ret < 0) {
       
  3439 # ifdef WIN32
       
  3440 	errno = WSAGetLastError();
       
  3441 # endif
       
  3442 	DBGPRINTF(("SOCKET: getsocketname failed errno=%d\n", errno));
       
  3443 	error = __MKSMALLINT(errno);
       
  3444     }
       
  3445 err:;
       
  3446 #else /* NO_SOCKET */
       
  3447     error = @symbol(notImplemented);
       
  3448 #endif /* NO_SOCKET */
       
  3449 %}.
       
  3450     error notNil ifTrue:[
       
  3451 	^ self errorReporter reportOn:error
       
  3452     ].
       
  3453     ^ socketAddress
       
  3454 !
  3315 !
  3455 
  3316 
  3456 port
  3317 port
  3457     "return the port number (or name for unix-sockets) to which the socket is bound"
  3318     "return the port number (or name for unix-sockets) to which the socket is bound
  3458 
  3319      - so this is the local port."
  3459 "/ sometimes maybe we do am lazy fetch of the port
  3320 
  3460 "/    port == 0 ifTrue:[ |p|
  3321 "/    port isNil ifTrue:[
  3461 "/        p := self getPort.
  3322 "/        port := self getFullSocketAddress port.
  3462 "/        p notNil ifTrue:[
       
  3463 "/            port := p
       
  3464 "/        ]
       
  3465 "/    ].
  3323 "/    ].
       
  3324 
  3466     ^ port
  3325     ^ port
  3467 !
  3326 !
  3468 
  3327 
  3469 type
  3328 type
  3470     "return the sockets connection type (i.e. #datagram, #stream etc)"
  3329     "return the sockets connection type (i.e. #datagram, #stream etc)"
  3996 #endif
  3855 #endif
  3997 %}.
  3856 %}.
  3998     ^ false
  3857     ^ false
  3999 ! !
  3858 ! !
  4000 
  3859 
       
  3860 !Socket methodsFor:'waiting'!
       
  3861 
       
  3862 waitForNewConnectionOrDataOnAny:otherConnections timeout:timeoutSeconds
       
  3863     "suspend the current process, until either a new connection comes
       
  3864      in at the receiver, or data arrives on any of the otherConnections.
       
  3865      For a new connection, an accept is performed and the new socket is returned.
       
  3866      For an old connection, that socket is returned.
       
  3867      In any case, the caller gets a socket to operate on as return value,
       
  3868      or nil, if a timeout occured.
       
  3869      This method implements the inner wait-primitive of a multi-connection
       
  3870      server application."
       
  3871 
       
  3872 
       
  3873     |wasBlocked sema|
       
  3874 
       
  3875     "first, a quick check if data is already available"
       
  3876     self canReadWithoutBlocking ifTrue:[
       
  3877 	^ self accept.
       
  3878     ].
       
  3879     otherConnections do:[:aConnection |
       
  3880 	aConnection canReadWithoutBlocking ifTrue:[
       
  3881 	    ^ aConnection
       
  3882 	]
       
  3883     ].
       
  3884 
       
  3885     [
       
  3886 	"check again - prevent incoming interrupts from disturbing our setup"
       
  3887 	wasBlocked := OperatingSystem blockInterrupts.
       
  3888 
       
  3889 	self canReadWithoutBlocking ifTrue:[
       
  3890 	    ^ self accept.
       
  3891 	].
       
  3892 	otherConnections do:[:aConnection |
       
  3893 	    aConnection canReadWithoutBlocking ifTrue:[
       
  3894 		^ aConnection
       
  3895 	    ]
       
  3896 	].
       
  3897 
       
  3898 	"nope - must wait"
       
  3899 	sema := Semaphore new name:'multiReadWait'.
       
  3900 	otherConnections do:[:aConnection |
       
  3901 	    Processor signal:sema onInput:(aConnection fileDescriptor).
       
  3902 	].
       
  3903 	Processor signal:sema onInput:(self fileDescriptor).
       
  3904 	timeoutSeconds notNil ifTrue:[
       
  3905 	    Processor signal:sema afterSeconds:timeoutSeconds
       
  3906 	].
       
  3907 	Processor activeProcess state:#ioWait.
       
  3908 	sema wait.
       
  3909     ] ensure:[
       
  3910 	sema notNil ifTrue:[Processor disableSemaphore:sema].
       
  3911 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
       
  3912     ].
       
  3913 
       
  3914     "see who it was ..."
       
  3915     self canReadWithoutBlocking ifTrue:[
       
  3916 	^ self accept.
       
  3917     ].
       
  3918     otherConnections do:[:aConnection |
       
  3919 	aConnection canReadWithoutBlocking ifTrue:[
       
  3920 	    ^ aConnection
       
  3921 	]
       
  3922     ].
       
  3923 
       
  3924     "none - a timeout"
       
  3925     ^ nil
       
  3926 !
       
  3927 
       
  3928 waitForNewConnectionWithTimeout:timeoutSeconds
       
  3929     "suspend the current process, until a new connection comes
       
  3930      in at the receiver or a timeout occurs.
       
  3931      For a new connection, an accept is performed and the new socket is returned.
       
  3932      Returns nil, if a timeout occured.
       
  3933      This method implements the inner wait-primitive of a single-connection
       
  3934      server application."
       
  3935 
       
  3936     (self readWaitWithTimeout:timeoutSeconds) ifTrue:[
       
  3937 	"a timeout occurred - no connection within timeout"
       
  3938 	^ nil
       
  3939     ].
       
  3940     ^ self accept.
       
  3941 ! !
       
  3942 
  4001 !Socket class methodsFor:'documentation'!
  3943 !Socket class methodsFor:'documentation'!
  4002 
  3944 
  4003 version
  3945 version
  4004     ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.242 2007-11-08 14:04:43 stefan Exp $'
  3946     ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.243 2008-03-28 12:47:59 stefan Exp $'
  4005 ! !
  3947 ! !