--- a/Socket.st Fri Jul 23 01:21:04 1999 +0200
+++ b/Socket.st Fri Jul 23 11:03:59 1999 +0200
@@ -1687,20 +1687,29 @@
"
! !
-!Socket methodsFor:'ST-80 mimicri'!
+!Socket methodsFor:'ST-80 compatibility'!
errorReporter
+ "ST-80 mimicry."
+
^ self
!
notReadySignal
- "for now - this is not yet raised"
+ "ST-80 mimicry.
+ for now - this is not yet raised"
^ Signal new
!
readAppendStream
- "ST-80 compatibility"
+ "ST-80 mimicry.
+ In ST-80, socket is not a stream, but referes to one.
+ ST-80 code therefore uses 'Socket readWriteStream' to access
+ the actual stream.
+ In ST/X, sockets inherit from stream, so
+ this method returns the receiver, for transparency"
+
^ self
!
@@ -1708,7 +1717,9 @@
"ST-80 mimicry.
In ST-80, socket is not a stream, but referes to one.
ST-80 code therefore uses 'Socket readStream' to access
- the actual stream. This method returns the receiver, for transparency"
+ the actual stream.
+ In ST/X, sockets inherit from stream, so
+ this method returns the receiver, for transparency"
^ self
@@ -1725,7 +1736,9 @@
"ST-80 mimicry.
In ST-80, socket is not a stream, but referes to one.
ST-80 code therefore uses 'Socket writeStream' to access
- the actual stream. This method returns the receiver, for transparency"
+ the actual stream.
+ In ST/X, sockets inherit from stream, so
+ this method returns the receiver, for transparency"
^ self
@@ -2132,39 +2145,6 @@
!Socket methodsFor:'low level'!
-accept
- "create a new TCP socket from accepting on the receiver.
- This method will suspend the current process if no connection is waiting.
- For ST-80 compatibility"
-
- |newSock|
-
- newSock := self class new.
- (newSock acceptOn:self) ifFalse:[^ nil].
- ^ newSock
-
- "
- |sock newSock|
-
- sock := Socket provide:8004.
- sock listenFor:5.
- newSock := sock accept.
- "
-!
-
-acceptOn:aSocket
- "accept a connection on a server port (created with:'Socket>>onIPPort:')
- usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
- This method will suspend the current process if no connection is waiting.
- Return the true if ok; false if not."
-
- aSocket readWriteWait.
- ^ self blockingAcceptOn:aSocket
-
- "Modified: / 11.3.1996 / 14:21:31 / stefan"
- "Modified: / 1.8.1998 / 23:39:10 / cg"
-!
-
bindAnonymously
^ self
bindTo:0
@@ -2647,6 +2627,134 @@
"
!
+closeFile
+ "low level close"
+
+%{ /* NOCONTEXT */
+#ifndef NO_SOCKET
+
+ OBJ t;
+
+ t = __INST(filePointer);
+ if (t != nil) {
+ FILE *fp;
+
+ fp = __FILEVal(t);
+ fflush(fp);
+ shutdown(fileno(fp), 2);
+ fclose(fp);
+ __INST(filePointer) = nil;
+ }
+#endif
+%}
+!
+
+listenFor:aNumber
+ "same as listenWithBacklog: - for ST-80 compatibility"
+
+ ^ self listenWithBacklog:aNumber
+!
+
+listenWithBacklog:aNumber
+ "start listening; return true if ok, false on error"
+
+ filePointer isNil ifTrue:[
+ ^ self error:'not a valid socket'
+ ].
+%{
+#ifndef NO_SOCKET
+ OBJ fp = __INST(filePointer);
+ int sock;
+ int ret;
+
+ if (! __isSmallInteger(aNumber)) {
+ DBGPRINTF(("SOCKET: invalid arg\n"));
+ RETURN (false);
+ }
+
+ sock = fileno(__FILEVal(fp));
+
+ __BEGIN_INTERRUPTABLE__
+ do {
+ ret = listen(sock, _intVal(aNumber));
+ } while ((ret < 0) && (errno == EINTR));
+ __END_INTERRUPTABLE__
+
+ if (ret < 0) {
+ DBGPRINTF(("SOCKET: listen call failed errno=%d\n", errno));
+ __INST(lastErrorNumber) = __MKSMALLINT(errno);
+ RETURN (false);
+ }
+#else
+ RETURN (false);
+#endif
+%}.
+ ^ true
+!
+
+shutDown
+ "shutDown without flushing "
+
+ filePointer isNil ifTrue:[^ self].
+ Lobby unregister:self.
+
+%{
+#ifndef NO_SOCKET
+
+ OBJ fp;
+
+ fp = __INST(filePointer);
+ if (fp != nil) {
+ FILE *f;
+ int fd;
+
+ __INST(filePointer) = nil;
+ f = __FILEVal(fp);
+ fd = fileno(f);
+ __BEGIN_INTERRUPTABLE__
+ shutdown(fd, 2);
+ close(fd);
+ __END_INTERRUPTABLE__
+ }
+#endif
+%}
+! !
+
+!Socket methodsFor:'low level-accepting'!
+
+accept
+ "create a new TCP socket from accepting on the receiver.
+ This method will suspend the current process if no connection is waiting.
+ For ST-80 compatibility"
+
+ |newSock|
+
+ newSock := self class new.
+ (newSock acceptOn:self) ifFalse:[^ nil].
+ ^ newSock
+
+ "
+ |sock newSock|
+
+ sock := Socket provide:8004.
+ sock listenFor:5.
+ newSock := sock accept.
+ "
+!
+
+acceptOn:aSocket
+ "accept a connection on a server port (created with:'Socket>>onIPPort:')
+ usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
+ This method will suspend the current process if no connection is waiting.
+ Return the true if ok; false if not."
+
+ aSocket readWriteWait.
+ ^ self blockingAcceptOn:aSocket
+
+ "Modified: / 11.3.1996 / 14:21:31 / stefan"
+ "Modified: / 1.8.1998 / 23:39:10 / cg"
+!
+
blockingAcceptOn:aSocket
"accept a connection on a server port (created with:'Socket>>onIPPort:')
usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
@@ -2941,27 +3049,81 @@
^ true
!
-closeFile
- "low level close"
-
-%{ /* NOCONTEXT */
-#ifndef NO_SOCKET
-
- OBJ t;
-
- t = __INST(filePointer);
- if (t != nil) {
- FILE *fp;
-
- fp = __FILEVal(t);
- fflush(fp);
- shutdown(fileno(fp), 2);
- fclose(fp);
- __INST(filePointer) = nil;
- }
-#endif
-%}
-!
+waitForNewConnectionOrDataOnAny:otherConnections timeout:timeoutSeconds
+ "suspend the current process, until either a new connection comes
+ in at the receiver, or data arrives on any of the otherConnections.
+ For a new connection, an accept is performed and the new socket is returned.
+ For an old connection, that socket is returned.
+ In any case, the caller gets a socket to operate on as return value,
+ or nil, if a timeout occured.
+ This method implements the inner wait-primitive of a multi-connection
+ server application."
+
+ "/ first, a quick check if data is already available
+
+ |connection wasBlocked sema|
+
+ self canReadWithoutBlocking ifTrue:[
+ ^ self accept.
+ ].
+ otherConnections do:[:aConnection |
+ aConnection canReadWithoutBlocking ifTrue:[
+ ^ aConnection
+ ]
+ ].
+
+ [
+ "/ check again - prevent incoming interrupts from disturbing our setup
+ wasBlocked := OperatingSystem blockInterrupts.
+
+ self canReadWithoutBlocking ifTrue:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ^ self accept.
+ ].
+ otherConnections do:[:aConnection |
+ aConnection canReadWithoutBlocking ifTrue:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ^ aConnection
+ ]
+ ].
+
+ "/ nope - must wait.
+
+ sema := Semaphore new name:'multiReadWait'.
+ otherConnections do:[:aConnection |
+ Processor signal:sema onInput:(aConnection fileDescriptor).
+ ].
+ Processor signal:sema onInput:(self fileDescriptor).
+ timeoutSeconds notNil ifTrue:[
+ Processor signal:sema afterSeconds:timeoutSeconds
+ ].
+ Processor activeProcess state:#ioWait.
+ sema wait.
+ Processor disableSemaphore:sema.
+
+ ] valueOnUnwindDo:[
+ Processor disableSemaphore:sema.
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ].
+
+ "/ see who it was ...
+
+ self canReadWithoutBlocking ifTrue:[
+ ^ self accept.
+ ].
+ otherConnections do:[:aConnection |
+ aConnection canReadWithoutBlocking ifTrue:[
+ ^ aConnection
+ ]
+ ].
+
+ "/ none - a timeout
+ ^ nil
+
+
+! !
+
+!Socket methodsFor:'low level-connecting'!
connectTo:hostOrPathName port:portNrOrName
"low level connect; connect to port, portNrOrName on host, hostName.
@@ -3397,77 +3559,6 @@
If a non-nil timeout is given, stop trying after that time and return false as well."
^ self connectTo:hostOrPathName port:portNrOrName blocking:false withTimeout:millis
-!
-
-listenFor:aNumber
- "same as listenWithBacklog: - for ST-80 compatibility"
-
- ^ self listenWithBacklog:aNumber
-!
-
-listenWithBacklog:aNumber
- "start listening; return true if ok, false on error"
-
- filePointer isNil ifTrue:[
- ^ self error:'not a valid socket'
- ].
-%{
-#ifndef NO_SOCKET
- OBJ fp = __INST(filePointer);
- int sock;
- int ret;
-
- if (! __isSmallInteger(aNumber)) {
- DBGPRINTF(("SOCKET: invalid arg\n"));
- RETURN (false);
- }
-
- sock = fileno(__FILEVal(fp));
-
- __BEGIN_INTERRUPTABLE__
- do {
- ret = listen(sock, _intVal(aNumber));
- } while ((ret < 0) && (errno == EINTR));
- __END_INTERRUPTABLE__
-
- if (ret < 0) {
- DBGPRINTF(("SOCKET: listen call failed errno=%d\n", errno));
- __INST(lastErrorNumber) = __MKSMALLINT(errno);
- RETURN (false);
- }
-#else
- RETURN (false);
-#endif
-%}.
- ^ true
-!
-
-shutDown
- "shutDown without flushing "
-
- filePointer isNil ifTrue:[^ self].
- Lobby unregister:self.
-
-%{
-#ifndef NO_SOCKET
-
- OBJ fp;
-
- fp = __INST(filePointer);
- if (fp != nil) {
- FILE *f;
- int fd;
-
- __INST(filePointer) = nil;
- f = __FILEVal(fp);
- fd = fileno(f);
- __BEGIN_INTERRUPTABLE__
- shutdown(fd, 2);
- close(fd);
- __END_INTERRUPTABLE__
- }
-#endif
-%}
! !
!Socket methodsFor:'queries'!
@@ -4091,5 +4182,5 @@
!Socket class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.120 1999-07-19 08:04:56 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.121 1999-07-23 09:03:59 cg Exp $'
! !