--- a/Socket.st Sat Jan 24 00:02:47 2015 +0100
+++ b/Socket.st Sat Jan 24 00:44:21 2015 +0100
@@ -255,412 +255,412 @@
examples
"
example (get help info from an nntp server):
- [exBegin]
- |sock|
-
- sock := Socket newTCPclientToHost:'smtp.exept.de' port:'smtp'.
- sock isNil ifTrue:[
- self warn:'no smtp daemon is running'.
- ^ self
- ].
- Transcript showCR:sock nextLine.
-
- sock nextPutAll:'HELO STX socket test'; cr.
- Transcript showCR:sock nextLine.
- sock close
- [exEnd]
+ [exBegin]
+ |sock|
+
+ sock := Socket newTCPclientToHost:'smtp.exept.de' port:'smtp'.
+ sock isNil ifTrue:[
+ self warn:'no smtp daemon is running'.
+ ^ self
+ ].
+ Transcript showCR:sock nextLine.
+
+ sock nextPutAll:'HELO STX socket test'; cr.
+ Transcript showCR:sock nextLine.
+ sock close
+ [exEnd]
example (connect to finger daemon, get users entry):
- [exBegin]
- |sock entry|
-
- sock := Socket newTCPclientToHost:'localhost' port:'finger'.
- sock isNil ifTrue:[
- self warn:'no finger daemon is running'.
- ^ self
- ].
- sock useCRLF:true.
- sock buffered:false.
- sock isNil ifTrue:[
- Transcript showCR:'cannot connect to local finger daemon'
- ] ifFalse:[
- sock nextPutAll:(OperatingSystem getLoginName).
- sock cr.
-
- entry := sock nextLine.
- Transcript showCR:entry.
-
- sock close
- ]
- [exEnd]
+ [exBegin]
+ |sock entry|
+
+ sock := Socket newTCPclientToHost:'localhost' port:'finger'.
+ sock isNil ifTrue:[
+ self warn:'no finger daemon is running'.
+ ^ self
+ ].
+ sock useCRLF:true.
+ sock buffered:false.
+ sock isNil ifTrue:[
+ Transcript showCR:'cannot connect to local finger daemon'
+ ] ifFalse:[
+ sock nextPutAll:(OperatingSystem getLoginName).
+ sock cr.
+
+ entry := sock nextLine.
+ Transcript showCR:entry.
+
+ sock close
+ ]
+ [exEnd]
example (connect to an ftp server):
- [exBegin]
- |sock|
-
- sock := Socket newTCPclientToHost:'www.exept.de' port:'ftp'.
-
- sock buffered:false.
- Transcript showCR:sock nextLine.
- sock nextPutAll:('USER ' , 'anonymous'); cr.
- Transcript showCR:sock nextLine.
- sock nextPutAll:('PASS ' , 'fooBar'); cr.
- Transcript showCR:sock nextLine.
- sock nextPutAll:'HELP'; cr.
- [
- |line|
- line := sock nextLine.
- Transcript showCR:line.
- (line at:4) = $-
- ] whileTrue.
- sock close.
-
- 'dont know enough of the ftp protocol to continue here ...'
- [exEnd]
+ [exBegin]
+ |sock|
+
+ sock := Socket newTCPclientToHost:'www.exept.de' port:'ftp'.
+
+ sock buffered:false.
+ Transcript showCR:sock nextLine.
+ sock nextPutAll:('USER ' , 'anonymous'); cr.
+ Transcript showCR:sock nextLine.
+ sock nextPutAll:('PASS ' , 'fooBar'); cr.
+ Transcript showCR:sock nextLine.
+ sock nextPutAll:'HELP'; cr.
+ [
+ |line|
+ line := sock nextLine.
+ Transcript showCR:line.
+ (line at:4) = $-
+ ] whileTrue.
+ sock close.
+
+ 'dont know enough of the ftp protocol to continue here ...'
+ [exEnd]
example (connect to an snmp server [UDP]):
Note: this is not a real connection, only the destination adress is
- being fixed.
- [exBegin]
- |sock port|
-
- sock := Socket newUDP.
- port := Socket portOfService:'snmp'.
- sock connectTo:'localhost' port:port.
- sock buffered:false.
- Transcript showCR:'got it'.
- sock close.
- [exEnd]
+ being fixed.
+ [exBegin]
+ |sock port|
+
+ sock := Socket newUDP.
+ port := Socket portOfService:'snmp'.
+ sock connectTo:'localhost' port:port.
+ sock buffered:false.
+ Transcript showCR:'got it'.
+ sock close.
+ [exEnd]
example (await connection from a client and read some data):
- [exBegin]
- |connectSock sock|
-
- connectSock := Socket newTCPserverAtPort:9998.
- connectSock isNil ifTrue:[
- Transcript showCR:'socket setup failed.'.
- ] ifFalse:[
- Transcript showCR:'listen ..'.
- (connectSock listenFor:5) ifFalse:[
- Transcript showCR:'listen failed.'.
- ] ifTrue:[
- Transcript showCR:'wait'.
- connectSock readWait.
- Transcript showCR:'accept'.
- sock := connectSock accept.
- sock isNil ifTrue:[
- Transcript showCR:'accept failed.'.
- ] ifFalse:[
- sock buffered:false.
- Transcript showCR:'server: got it'.
- 'can now do transfer via sock'.
- Transcript showCR:'read'.
- Transcript showCR:('got: ' , sock nextLine).
-
- Transcript showCR:'close'.
- sock close
- ].
- connectSock close.
- ]
- ]
- [exEnd]
+ [exBegin]
+ |connectSock sock|
+
+ connectSock := Socket newTCPserverAtPort:9998.
+ connectSock isNil ifTrue:[
+ Transcript showCR:'socket setup failed.'.
+ ] ifFalse:[
+ Transcript showCR:'listen ..'.
+ (connectSock listenFor:5) ifFalse:[
+ Transcript showCR:'listen failed.'.
+ ] ifTrue:[
+ Transcript showCR:'wait'.
+ connectSock readWait.
+ Transcript showCR:'accept'.
+ sock := connectSock accept.
+ sock isNil ifTrue:[
+ Transcript showCR:'accept failed.'.
+ ] ifFalse:[
+ sock buffered:false.
+ Transcript showCR:'server: got it'.
+ 'can now do transfer via sock'.
+ Transcript showCR:'read'.
+ Transcript showCR:('got: ' , sock nextLine).
+
+ Transcript showCR:'close'.
+ sock close
+ ].
+ connectSock close.
+ ]
+ ]
+ [exEnd]
example (connect to above server and send some data):
- [exBegin]
- |sock|
-
- sock := Socket newTCPclientToHost:'localhost' port:9998.
- sock isNil ifTrue:[
- Transcript showCR:'nope'
- ] ifFalse:[
- sock buffered:false.
- Transcript showCR:'client: got it'.
- 'can now do transfer via sock'.
- Transcript showCR:'sending <hello>'.
- sock nextPutLine:'hello'.
- sock close
- ]
- [exEnd]
+ [exBegin]
+ |sock|
+
+ sock := Socket newTCPclientToHost:'localhost' port:9998.
+ sock isNil ifTrue:[
+ Transcript showCR:'nope'
+ ] ifFalse:[
+ sock buffered:false.
+ Transcript showCR:'client: got it'.
+ 'can now do transfer via sock'.
+ Transcript showCR:'sending <hello>'.
+ sock nextPutLine:'hello'.
+ sock close
+ ]
+ [exEnd]
example: UNIX domain socket (await connection from a client and read some data):
- |connectSock sock|
-
- '/tmp/ud_socket' asFilename remove.
- connectSock := Socket newUNIXserverAt:'/tmp/ud_socket'.
- connectSock isNil ifTrue:[
- Transcript showCR:'socket setup failed.'.
- ] ifFalse:[
- Transcript showCR:'listen ..'.
- (connectSock listenFor:5) ifFalse:[
- Transcript showCR:'listen failed.'.
- ] ifTrue:[
- Transcript showCR:'wait'.
- connectSock buffered:false.
- connectSock readWait.
- Transcript showCR:'accept'.
- sock := connectSock accept.
- sock isNil ifTrue:[
- Transcript showCR:'accept failed.'.
- ] ifFalse:[
- sock buffered:false.
- Transcript showCR:'server: got it'.
- 'can now do transfer via sock'.
- Transcript showCR:'read'.
- Transcript showCR:('got: ' , sock nextLine).
-
- Transcript showCR:'close'.
- sock close
- ].
- connectSock close.
- ]
- ]
+ |connectSock sock|
+
+ '/tmp/ud_socket' asFilename remove.
+ connectSock := Socket newUNIXserverAt:'/tmp/ud_socket'.
+ connectSock isNil ifTrue:[
+ Transcript showCR:'socket setup failed.'.
+ ] ifFalse:[
+ Transcript showCR:'listen ..'.
+ (connectSock listenFor:5) ifFalse:[
+ Transcript showCR:'listen failed.'.
+ ] ifTrue:[
+ Transcript showCR:'wait'.
+ connectSock buffered:false.
+ connectSock readWait.
+ Transcript showCR:'accept'.
+ sock := connectSock accept.
+ sock isNil ifTrue:[
+ Transcript showCR:'accept failed.'.
+ ] ifFalse:[
+ sock buffered:false.
+ Transcript showCR:'server: got it'.
+ 'can now do transfer via sock'.
+ Transcript showCR:'read'.
+ Transcript showCR:('got: ' , sock nextLine).
+
+ Transcript showCR:'close'.
+ sock close
+ ].
+ connectSock close.
+ ]
+ ]
example (connect to above server and send some data;
- Notice, this fails, if above server code is executed in the same ST/X image
- (at least on LINUX), since the OS does not correctly handle
- a connect from within an interrupted accept system call
- On SGI's SVR4, this works ok
- [exBegin]
- |sock|
-
- sock := Socket newUNIXclientTo:'/tmp/ud_socket'.
- sock isNil ifTrue:[
- Transcript showCR:'nope'
- ] ifFalse:[
- sock buffered:false.
- Transcript showCR:'client: got it'.
- 'can now do transfer via sock'.
- Transcript showCR:'sending <hello>'.
- sock nextPutLine:'hello'.
- sock close
- ]
- [exEnd]
+ Notice, this fails, if above server code is executed in the same ST/X image
+ (at least on LINUX), since the OS does not correctly handle
+ a connect from within an interrupted accept system call
+ On SGI's SVR4, this works ok
+ [exBegin]
+ |sock|
+
+ sock := Socket newUNIXclientTo:'/tmp/ud_socket'.
+ sock isNil ifTrue:[
+ Transcript showCR:'nope'
+ ] ifFalse:[
+ sock buffered:false.
+ Transcript showCR:'client: got it'.
+ 'can now do transfer via sock'.
+ Transcript showCR:'sending <hello>'.
+ sock nextPutLine:'hello'.
+ sock close
+ ]
+ [exEnd]
example (UDP await packet from a client and read some data):
- [exBegin]
- |udpSock sock addr n dataBuffer|
-
- udpSock := Socket newUDPserverAtPort:9999.
- udpSock isNil ifTrue:[
- Transcript showCR:'socket setup failed.'.
- ] ifFalse:[
- Transcript showCR:'wait'.
- udpSock readWait.
-
- addr := IPSocketAddress new.
- dataBuffer := ByteArray new:1000.
- n := udpSock receiveFrom:addr buffer:dataBuffer start:1 for:dataBuffer size.
- n > 0 ifTrue:[
- Transcript showCR:('got: ' , n printString , 'bytes from ' , addr printString).
- Transcript showCR:('data: ' , (dataBuffer copyTo:n) printString).
- ] ifFalse:[
- Transcript showCR:'read failed'.
- ].
-
- Transcript showCR:'close'.
- udpSock close
- ]
- [exEnd]
+ [exBegin]
+ |udpSock sock addr n dataBuffer|
+
+ udpSock := Socket newUDPserverAtPort:9999.
+ udpSock isNil ifTrue:[
+ Transcript showCR:'socket setup failed.'.
+ ] ifFalse:[
+ Transcript showCR:'wait'.
+ udpSock readWait.
+
+ addr := IPSocketAddress new.
+ dataBuffer := ByteArray new:1000.
+ n := udpSock receiveFrom:addr buffer:dataBuffer start:1 for:dataBuffer size.
+ n > 0 ifTrue:[
+ Transcript showCR:('got: ' , n printString , 'bytes from ' , addr printString).
+ Transcript showCR:('data: ' , (dataBuffer copyTo:n) printString).
+ ] ifFalse:[
+ Transcript showCR:'read failed'.
+ ].
+
+ Transcript showCR:'close'.
+ udpSock close
+ ]
+ [exEnd]
example (connect to above UDP server and send some data;
- [exBegin]
- |sock|
-
- sock := Socket newUDP.
- sock isNil ifTrue:[
- Transcript showCR:'nope'
- ] ifFalse:[
- sock sendTo:(IPSocketAddress new hostName:'localhost' port:9999) buffer:'hello world'.
- sock close
- ]
- [exEnd]
+ [exBegin]
+ |sock|
+
+ sock := Socket newUDP.
+ sock isNil ifTrue:[
+ Transcript showCR:'nope'
+ ] ifFalse:[
+ sock sendTo:(IPSocketAddress new hostName:'localhost' port:9999) buffer:'hello world'.
+ sock close
+ ]
+ [exEnd]
example: pingWalk (try to ping hosts on the local network)
Note: it dosen't use ICMP ping, but tries to reache the echo service,
- which is disabled on most OS.
- [exBegin]
- |myAddress list top hosts walkProcess port|
-
- myAddress := OperatingSystem getNetworkAddresses
- keysAndValuesSelect:[:eachIFName :eachAddress|
- eachAddress isLocal not
- and:[eachIFName = 'wlan0']
- ].
- myAddress := myAddress first hostAddress.
-
- port := Socket portOfService:'echo'.
- port isNil ifTrue:[
- self error:'dont know echo port'.
- ^ self
- ].
-
- top := StandardSystemView new.
- top label:'PING net walk'.
-
- list := ScrollableView for:ListView in:top.
- list origin:0.0@0.0 corner:1.0@1.0.
-
- top openAndWait.
-
- walkProcess := [
- |l low hi direction tryHostID dottedName hostName conn addr|
-
- l := SortedCollection new.
-
- ' only works with type C-net
- the code below could simply do 1 to:254 do:[:hostID }
- but, to probe likely hosts earlier, the probing is done
- ping-pong like around my ip-address (assuming, that other machines
- have numbers around my own)'.
-
- low := hi := (myAddress at:4).
- direction := 1.
-
- [low > 0 or:[hi < 255]] whileTrue:[
- direction > 0 ifTrue:[
- hi := hi + 1.
- tryHostID := hi.
- direction := -1.
- ] ifFalse:[
- low := low - 1.
- tryHostID := low.
- direction := 1.
- ].
- (tryHostID between:1 and:254) ifTrue:[
- dottedName := (myAddress at:1) printString
- , '.' , (myAddress at:2) printString
- , '.' , (myAddress at:3) printString
- , '.' , tryHostID printString.
-
- top label:'PING net walk - trying ' , dottedName.
-
- top windowGroup withCursor:Cursor wait do:[
- conn := Socket newTCPclientToHost:dottedName port:port withTimeout:1000.
- conn notNil ifTrue:[
- addr := Socket ipAddressOfHost:dottedName.
- hostName := Socket hostWithIpAddress:addr.
- hostName isNil ifTrue:[
- hostName :='?'
- ].
- l add:(dottedName paddedTo:15 with:Character space)
- , ' '
- , (hostName paddedTo:15 with:Character space)
- , ' up & reachable'.
- list list:l.
- conn close.
- ]
- ].
- ].
- ].
- top label:'PING reachable hosts'.
- ] forkAt:(Processor userBackgroundPriority).
- walkProcess name:'ping net walker'.
- [exEnd]
-
-
- This example creates a simple UDP server that accepts
- single packets from anybody and broadcasts them to all
- clients that have connected so far.
-
- [exBegin]
- | socket address buffer msgSize clients |
- clients := Set new.
- address := IPSocketAddress new.
- buffer := String new: 1024.
-
- socket := self newUDPserverAtPort: 6666.
-
- Transcript showCR: 'server starting'.
-
- [
- [true] whileTrue: [
- (socket readWaitWithTimeoutMs: 200) ifFalse: [
- msgSize := socket
- receiveFrom: address
- buffer: buffer
- start: 1
- for: buffer size.
-
- clients add: address copy.
- clients do: [ :clientAddress |
- socket
- sendTo: clientAddress
- buffer: buffer
- start: 1
- for: msgSize]]
- ]
- ] ensure:[
- Transcript showCR: 'server shutting down'.
- socket close
- ]
- [exEnd]
+ which is disabled on most OS.
+ [exBegin]
+ |myAddress list top hosts walkProcess port|
+
+ myAddress := OperatingSystem getNetworkAddresses
+ keysAndValuesSelect:[:eachIFName :eachAddress|
+ eachAddress isLocal not
+ and:[eachIFName = 'wlan0']
+ ].
+ myAddress := myAddress first hostAddress.
+
+ port := Socket portOfService:'echo'.
+ port isNil ifTrue:[
+ self error:'dont know echo port'.
+ ^ self
+ ].
+
+ top := StandardSystemView new.
+ top label:'PING net walk'.
+
+ list := ScrollableView for:ListView in:top.
+ list origin:0.0@0.0 corner:1.0@1.0.
+
+ top openAndWait.
+
+ walkProcess := [
+ |l low hi direction tryHostID dottedName hostName conn addr|
+
+ l := SortedCollection new.
+
+ ' only works with type C-net
+ the code below could simply do 1 to:254 do:[:hostID }
+ but, to probe likely hosts earlier, the probing is done
+ ping-pong like around my ip-address (assuming, that other machines
+ have numbers around my own)'.
+
+ low := hi := (myAddress at:4).
+ direction := 1.
+
+ [low > 0 or:[hi < 255]] whileTrue:[
+ direction > 0 ifTrue:[
+ hi := hi + 1.
+ tryHostID := hi.
+ direction := -1.
+ ] ifFalse:[
+ low := low - 1.
+ tryHostID := low.
+ direction := 1.
+ ].
+ (tryHostID between:1 and:254) ifTrue:[
+ dottedName := (myAddress at:1) printString
+ , '.' , (myAddress at:2) printString
+ , '.' , (myAddress at:3) printString
+ , '.' , tryHostID printString.
+
+ top label:'PING net walk - trying ' , dottedName.
+
+ top windowGroup withCursor:Cursor wait do:[
+ conn := Socket newTCPclientToHost:dottedName port:port withTimeout:1000.
+ conn notNil ifTrue:[
+ addr := Socket ipAddressOfHost:dottedName.
+ hostName := Socket hostWithIpAddress:addr.
+ hostName isNil ifTrue:[
+ hostName :='?'
+ ].
+ l add:(dottedName paddedTo:15 with:Character space)
+ , ' '
+ , (hostName paddedTo:15 with:Character space)
+ , ' up & reachable'.
+ list list:l.
+ conn close.
+ ]
+ ].
+ ].
+ ].
+ top label:'PING reachable hosts'.
+ ] forkAt:(Processor userBackgroundPriority).
+ walkProcess name:'ping net walker'.
+ [exEnd]
+
+
+ This example creates a simple UDP server that accepts
+ single packets from anybody and broadcasts them to all
+ clients that have connected so far.
+
+ [exBegin]
+ | socket address buffer msgSize clients |
+ clients := Set new.
+ address := IPSocketAddress new.
+ buffer := String new: 1024.
+
+ socket := self newUDPserverAtPort: 6666.
+
+ Transcript showCR: 'server starting'.
+
+ [
+ [true] whileTrue: [
+ (socket readWaitWithTimeoutMs: 200) ifFalse: [
+ msgSize := socket
+ receiveFrom: address
+ buffer: buffer
+ start: 1
+ for: buffer size.
+
+ clients add: address copy.
+ clients do: [ :clientAddress |
+ socket
+ sendTo: clientAddress
+ buffer: buffer
+ start: 1
+ for: msgSize]]
+ ]
+ ] ensure:[
+ Transcript showCR: 'server shutting down'.
+ socket close
+ ]
+ [exEnd]
send a datagram to above server:
- [exBegin]
-
- | socket address buffer host msg |
-
- host := Dialog
- request: 'What is the name of the server''s host?'
- initialAnswer: 'localhost'.
-
- socket := self newUDP.
-
- address := IPSocketAddress hostName: host port: 6666.
-
- buffer := ByteArray new: 1000.
- [
- [(msg := Dialog request: 'Say something') isEmpty] whileFalse:[
- | replySize stream |
-
- socket writeWait.
- stream := buffer writeStream.
- stream nextPutAll: msg.
- socket sendTo:address buffer:buffer start:1 for:stream position.
- socket readWait.
-
- replySize := socket receiveFrom:address buffer:buffer.
- replySize > 0 ifTrue: [
- Transcript cr; nextPutAll: 'Server acknowledged: '.
- Transcript show: ((buffer copyFrom: 1 to: replySize) asString)
- ]
- ]
- ] ensure: [socket close].
- Transcript cr
- [exEnd]
+ [exBegin]
+
+ | socket address buffer host msg |
+
+ host := Dialog
+ request: 'What is the name of the server''s host?'
+ initialAnswer: 'localhost'.
+
+ socket := self newUDP.
+
+ address := IPSocketAddress hostName: host port: 6666.
+
+ buffer := ByteArray new: 1000.
+ [
+ [(msg := Dialog request: 'Say something') isEmpty] whileFalse:[
+ | replySize stream |
+
+ socket writeWait.
+ stream := buffer writeStream.
+ stream nextPutAll: msg.
+ socket sendTo:address buffer:buffer start:1 for:stream position.
+ socket readWait.
+
+ replySize := socket receiveFrom:address buffer:buffer.
+ replySize > 0 ifTrue: [
+ Transcript cr; nextPutAll: 'Server acknowledged: '.
+ Transcript show: ((buffer copyFrom: 1 to: replySize) asString)
+ ]
+ ]
+ ] ensure: [socket close].
+ Transcript cr
+ [exEnd]
loopBack:
- [exBegin]
-
- |readerTask readingSocket writingSocket|
-
- readingSocket := self newTCPserverAtPort:9999.
- readerTask :=
- [
- |connection|
-
- readingSocket listenFor:1.
- connection := readingSocket accept.
- readingSocket close.
- [connection atEnd] whileFalse:[
- Transcript showCR:(connection nextLine).
- ].
- connection close.
- ] fork.
-
- Delay waitForSeconds:1.
- writingSocket := self newTCPclientToHost:'localhost' port:9999.
- writingSocket nextPutLine:'Hello'.
- writingSocket nextPutLine:'World'.
- writingSocket close.
- [exEnd]
+ [exBegin]
+
+ |readerTask readingSocket writingSocket|
+
+ readingSocket := self newTCPserverAtPort:9999.
+ readerTask :=
+ [
+ |connection|
+
+ readingSocket listenFor:1.
+ connection := readingSocket accept.
+ readingSocket close.
+ [connection atEnd] whileFalse:[
+ Transcript showCR:(connection nextLine).
+ ].
+ connection close.
+ ] fork.
+
+ Delay waitForSeconds:1.
+ writingSocket := self newTCPclientToHost:'localhost' port:9999.
+ writingSocket nextPutLine:'Hello'.
+ writingSocket nextPutLine:'World'.
+ writingSocket close.
+ [exEnd]
"
! !
@@ -2783,46 +2783,46 @@
int rslt;
if (fp == nil) {
- error = @symbol(errorNotOpen);
- goto out;
+ error = @symbol(errorNotOpen);
+ goto out;
}
if (__INST(handleType) == @symbol(socketHandle)) {
- SOCKET socket = SOCKET_FROM_FILE_OBJECT(fp);
-
- if (@global(FileOpenTrace) == true) {
- fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", socket);
- }
-
- // whether the close() will be successful or not - the handle is invalid now!
- __INST(handle) = nil;
- do {
+ SOCKET socket = SOCKET_FROM_FILE_OBJECT(fp);
+
+ if (@global(FileOpenTrace) == true) {
+ fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", socket);
+ }
+
+ // whether the close() will be successful or not - the handle is invalid now!
+ __INST(handle) = nil;
+ do {
#ifdef WIN32
- rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, socket);
+ rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, socket);
#else
- rslt = close(socket);
+ rslt = close(socket);
#endif
- } while((rslt < 0) && (__threadErrno == EINTR));
- if (rslt == 0) {
- RETURN(self);
- }
- error = __mkSmallInteger(__threadErrno);
- }
+ } while((rslt < 0) && (__threadErrno == EINTR));
+ if (rslt == 0) {
+ RETURN(self);
+ }
+ error = __mkSmallInteger(__threadErrno);
+ }
out:;
%}.
error notNil ifTrue:[
- error == #errorNotOpen ifTrue:[
- self errorNotOpen.
- ].
- error isInteger ifTrue:[
- lastErrorNumber := error.
- self writeError:error.
- ^ self.
- ].
- self primitiveFailed:error.
- ^ self.
+ error == #errorNotOpen ifTrue:[
+ self errorNotOpen.
+ ].
+ error isInteger ifTrue:[
+ lastErrorNumber := error.
+ self writeError:error.
+ ^ self.
+ ].
+ self primitiveFailed:error.
+ ^ self.
].
super closeFile.
@@ -2831,8 +2831,8 @@
fp := handle.
fp notNil ifTrue:[
- handle := nil.
- self closeFile:fp
+ handle := nil.
+ self closeFile:fp
]
! !
@@ -2895,7 +2895,7 @@
|serverSocketHandle addr domainClass newHandle|
handle notNil ifTrue:[
- ^ self errorAlreadyOpen
+ ^ self errorAlreadyOpen
].
domain := aServerSocket domain.
@@ -2903,12 +2903,12 @@
handleType := aServerSocket handleType.
serverSocketHandle := aServerSocket fileHandle.
serverSocketHandle isNil ifTrue:[
- ^ self error:'invalid server socket'
+ ^ self error:'invalid server socket'
].
"unix domain sockets do not return a valid peer name on accept"
domainClass := self class socketAddressClassForDomain:domain.
domainClass isNil ifTrue:[
- ^ self error:'invalid (unsupported) domain'.
+ ^ self error:'invalid (unsupported) domain'.
].
addr := domainClass new.
newHandle := OperatingSystem socketAccessor new.
@@ -2930,25 +2930,25 @@
# if defined(O_NONBLOCK) && defined(SET_NDELAY)
if (blocking == false) {
- flags = fcntl(serverSocket, F_GETFL);
- fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK);
+ flags = fcntl(serverSocket, F_GETFL);
+ fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK);
}
# endif
# ifdef DO_WRAP_CALLS
do {
- __threadErrno = 0;
- alen = sizeof(sa);
- newSock = (SOCKET)STX_WSA_CALL3("accept", accept, serverSocket, &sa, &alen);
+ __threadErrno = 0;
+ alen = sizeof(sa);
+ newSock = (SOCKET)STX_WSA_CALL3("accept", accept, serverSocket, &sa, &alen);
} while ((newSock < 0) && (__threadErrno == EINTR));
if (newSock < 0) {
- errno = __threadErrno;
+ errno = __threadErrno;
}
# else
__BEGIN_INTERRUPTABLE__
do {
- alen = sizeof(sa);
- newSock = accept(serverSocket, (struct sockaddr *) &sa, &alen);
+ alen = sizeof(sa);
+ newSock = accept(serverSocket, (struct sockaddr *) &sa, &alen);
} while ((newSock < 0) && (errno == EINTR));
__END_INTERRUPTABLE__
# endif
@@ -2956,41 +2956,41 @@
# if defined(O_NDELAY) && defined(SET_NDELAY)
if (blocking == false) {
- fcntl(serverSocket, F_SETFL, flags);
+ fcntl(serverSocket, F_SETFL, flags);
}
# endif
if (newSock == -1) {
- DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
- __INST(lastErrorNumber) = __MKSMALLINT(errno);
- RETURN (false);
+ DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
+ __INST(lastErrorNumber) = __MKSMALLINT(errno);
+ RETURN (false);
}
if (__isNonNilObject(addr)) {
- OBJ oClass = __qClass(addr);
- int nInstVars, nInstBytes, objSize;
- char *addrP;
-
- if (! __isBytes(addr) ) {
- DBGPRINTF(("SOCKET: bad addr\n"));
- closesocket(newSock);
- RETURN (false);
- }
-
- nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
- nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
- objSize = __qSize(addr) - nInstBytes;
- addrP = (char *)__InstPtr(addr) + nInstBytes;
- if (objSize < alen) {
- DBGPRINTF(("SOCKET: bad addr\n"));
- closesocket(newSock);
- RETURN (false);
- }
-
- /*
- * extract the partners address
- */
- memcpy(addrP, (char *)&sa, alen);
+ OBJ oClass = __qClass(addr);
+ int nInstVars, nInstBytes, objSize;
+ char *addrP;
+
+ if (! __isBytes(addr) ) {
+ DBGPRINTF(("SOCKET: bad addr\n"));
+ closesocket(newSock);
+ RETURN (false);
+ }
+
+ nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+ nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
+ objSize = __qSize(addr) - nInstBytes;
+ addrP = (char *)__InstPtr(addr) + nInstBytes;
+ if (objSize < alen) {
+ DBGPRINTF(("SOCKET: bad addr\n"));
+ closesocket(newSock);
+ RETURN (false);
+ }
+
+ /*
+ * extract the partners address
+ */
+ memcpy(addrP, (char *)&sa, alen);
}
/*
@@ -3008,19 +3008,19 @@
# else // ! WIN32
fp = fdopen(newSock, "r+");
if (! fp) {
- DBGPRINTF(("SOCKET: fdopen call failed\n"));
- __INST(lastErrorNumber) = __MKSMALLINT(errno);
- closesocket(newSock);
- DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock));
- RETURN (false);
+ DBGPRINTF(("SOCKET: fdopen call failed\n"));
+ __INST(lastErrorNumber) = __MKSMALLINT(errno);
+ closesocket(newSock);
+ DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock));
+ RETURN (false);
}
# endif // ! WIN32
if ((@global(FileOpenTrace) == true) || __debugging__) {
# ifdef WIN32
- console_fprintf(stderr, "fdopen [Socket accept] -> fd: %d (H: %"_lx_")\n", _fd, (INT)newSock);
+ console_fprintf(stderr, "fdopen [Socket accept] -> fd: %d (H: %"_lx_")\n", _fd, (INT)newSock);
# else
- console_fprintf(stderr, "fdopen [Socket accept] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock);
+ console_fprintf(stderr, "fdopen [Socket accept] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock);
# endif
}
@@ -3049,7 +3049,7 @@
|ok|
handle isNil ifTrue:[
- ^ self errorNotOpen
+ ^ self errorNotOpen
].
%{ /* STACK: 32000 */
@@ -3057,252 +3057,281 @@
OBJ fp = __INST(handle);
if (fp != nil) {
- SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
- int opt = -1;
- int level = -1;
- int usize = -1;
- int ret;
- union u {
- BOOL u_bool;
- int u_int;
- struct linger u_linger;
+ SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
+ int opt = -1;
+ int level = -1;
+ int usize = -1;
+ int ret;
+ union u {
+ BOOL u_bool;
+ int u_int;
+ struct linger u_linger;
# ifdef IP_ADD_MEMBERSHIP
- struct ip_mreq u_ip_mreq;
+ struct ip_mreq u_ip_mreq;
# endif
- } u;
+# if defined(SO_RCVTIMEO) || defined(SO_SNDTIMEO)
+ struct timeval u_tv;
+# endif
+
+
+ } u;
# ifdef IP_ADD_MEMBERSHIP
- if (option == @symbol(IP_DROP_MEMBERSHIP)) {
- opt = IP_DROP_MEMBERSHIP;
- goto dropOrAdd;
- }
- if (option == @symbol(IP_ADD_MEMBERSHIP)) {
- /* add membership to a multicast group */
- opt = IP_ADD_MEMBERSHIP;
+ if (option == @symbol(IP_DROP_MEMBERSHIP)) {
+ opt = IP_DROP_MEMBERSHIP;
+ goto dropOrAdd;
+ }
+ if (option == @symbol(IP_ADD_MEMBERSHIP)) {
+ /* add membership to a multicast group */
+ opt = IP_ADD_MEMBERSHIP;
dropOrAdd:
- level = IPPROTO_IP;
- usize = sizeof(u.u_ip_mreq);
- if (__isByteArrayLike(arg1) && __isByteArrayLike(arg2)) {
- memcpy(&u.u_ip_mreq.imr_multiaddr, __byteArrayVal(arg1), sizeof(u.u_ip_mreq.imr_multiaddr));
- memcpy(&u.u_ip_mreq.imr_interface, __byteArrayVal(arg2), sizeof(u.u_ip_mreq.imr_interface));
- }
- else
- goto argError;
- }
+ level = IPPROTO_IP;
+ usize = sizeof(u.u_ip_mreq);
+ if (__isByteArrayLike(arg1) && __isByteArrayLike(arg2)) {
+ memcpy(&u.u_ip_mreq.imr_multiaddr, __byteArrayVal(arg1), sizeof(u.u_ip_mreq.imr_multiaddr));
+ memcpy(&u.u_ip_mreq.imr_interface, __byteArrayVal(arg2), sizeof(u.u_ip_mreq.imr_interface));
+ }
+ else
+ goto argError;
+ }
# endif /* IP_ADD_MEMBERSHIP */
# ifdef SO_BROADCAST
- if (option == @symbol(SO_BROADCAST)) {
- /* Enables transmission and receipt of broadcast messages on the socket. */
- opt = SO_BROADCAST;
- level = SOL_SOCKET;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(SO_BROADCAST)) {
+ /* Enables transmission and receipt of broadcast messages on the socket. */
+ opt = SO_BROADCAST;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif /* SO_BROADCAST */
# ifdef SO_CONDITIONAL
# if 0
- if (option == @symbol(SO_CONDITIONAL)) {
- /* Enables sockets to delay the acknowledgment of a connection until after the WSAAccept condition function is called. */
- opt = SO_CONDITIONAL;
- level = SOL_SOCKET;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(SO_CONDITIONAL)) {
+ /* Enables sockets to delay the acknowledgment of a connection until after the WSAAccept condition function is called. */
+ opt = SO_CONDITIONAL;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif
# endif /* SO_CONDITIONAL */
# ifdef SO_DEBUG
- if (option == @symbol(SO_DEBUG)) {
- /* Records debugging information. */
- opt = SO_DEBUG;
- level = SOL_SOCKET;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(SO_DEBUG)) {
+ /* Records debugging information. */
+ opt = SO_DEBUG;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif /* SO_DEBUG */
# ifdef SO_DONTLINGER
- if (option == @symbol(SO_DONTLINGER)) {
- /* Does not block close waiting for unsent data to be sent.
- Setting this option is equivalent to setting SO_LINGER with l_onoff set to zero. */
- opt = SO_DONTLINGER;
- level = SOL_SOCKET;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(SO_DONTLINGER)) {
+ /* Does not block close waiting for unsent data to be sent.
+ Setting this option is equivalent to setting SO_LINGER with l_onoff set to zero. */
+ opt = SO_DONTLINGER;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif /* SO_DONTLINGER */
# ifdef SO_DONTROUTE
- if (option == @symbol(SO_DONTROUTE)) {
- /* Does not route: sends directly to interface.
- Succeeds but is ignored on AF_INET sockets;
- fails on AF_INET6 sockets with WSAENOPROTOOPT.
- Not supported on ATM sockets (results in an error). */
- opt = SO_DONTROUTE;
- level = SOL_SOCKET;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(SO_DONTROUTE)) {
+ /* Does not route: sends directly to interface.
+ Succeeds but is ignored on AF_INET sockets;
+ fails on AF_INET6 sockets with WSAENOPROTOOPT.
+ Not supported on ATM sockets (results in an error). */
+ opt = SO_DONTROUTE;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif /* SO_DONTROUTE */
#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
- if (option == @symbol(TCP_NODELAY)) {
- /* enable/disable TCP_NODELAY (i.e. disable/enable the Nagle algorithm) */
- opt = TCP_NODELAY;
- level = IPPROTO_TCP;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(TCP_NODELAY)) {
+ /* enable/disable TCP_NODELAY (i.e. disable/enable the Nagle algorithm) */
+ opt = TCP_NODELAY;
+ level = IPPROTO_TCP;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif /* TCP_NODELAY */
# ifdef SO_KEEPALIVE
- if (option == @symbol(SO_KEEPALIVE)) {
- /* Sends keep-alives. Not supported on ATM sockets (results in an error). */
- opt = SO_KEEPALIVE;
- level = SOL_SOCKET;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(SO_KEEPALIVE)) {
+ /* Sends keep-alives. Not supported on ATM sockets (results in an error). */
+ opt = SO_KEEPALIVE;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif /* SO_KEEPALIVE */
# ifdef SO_LINGER
- if (option == @symbol(SO_LINGER)) {
- /* Lingers on close if unsent data is present. */
- opt = SO_LINGER;
- level = SOL_SOCKET;
- usize = sizeof(u.u_linger);
- if (arg1 == true) u.u_linger.l_onoff = TRUE;
- else if (arg1 == false) u.u_linger.l_onoff = FALSE;
- else goto argError;
- if (arg2 == nil) u.u_linger.l_linger = 0;
- else if (__isSmallInteger(arg2))u.u_linger.l_linger = __intVal(arg2);
- else goto argError;
- DBGPRINTF(("SOCKET: SO_LINGER %d %d\n", u.u_linger.l_onoff, u.u_linger.l_linger));
- }
+ if (option == @symbol(SO_LINGER)) {
+ /* Lingers on close if unsent data is present. */
+ opt = SO_LINGER;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_linger);
+ if (arg1 == true) u.u_linger.l_onoff = TRUE;
+ else if (arg1 == false) u.u_linger.l_onoff = FALSE;
+ else goto argError;
+ if (arg2 == nil) u.u_linger.l_linger = 0;
+ else if (__isSmallInteger(arg2))u.u_linger.l_linger = __intVal(arg2);
+ else goto argError;
+ DBGPRINTF(("SOCKET: SO_LINGER %d %d\n", u.u_linger.l_onoff, u.u_linger.l_linger));
+ }
# endif /* SO_LINGER */
# ifdef SO_OOBINLINE
- if (option == @symbol(SO_OOBINLINE)) {
- /* Receives OOB data in the normal data stream. */
- opt = SO_OOBINLINE;
- level = SOL_SOCKET;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(SO_OOBINLINE)) {
+ /* Receives OOB data in the normal data stream. */
+ opt = SO_OOBINLINE;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif /* SO_OOBINLINE */
# ifdef SO_RCVBUF
- if (option == @symbol(SO_RCVBUF)) {
- /* Specifies the total per-socket buffer space reserved for receives.
- This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
- opt = SO_RCVBUF;
- level = SOL_SOCKET;
- usize = sizeof(u.u_int);
- if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
- else goto argError;
- }
+ if (option == @symbol(SO_RCVBUF)) {
+ /* Specifies the total per-socket buffer space reserved for receives.
+ This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
+ opt = SO_RCVBUF;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_int);
+ if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
+ else goto argError;
+ }
# endif /* SO_RCVBUF */
# ifdef SO_SNDBUF
- if (option == @symbol(SO_SNDBUF)) {
- /* Specifies the total per-socket buffer space reserved for sends.
- This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
- opt = SO_SNDBUF;
- level = SOL_SOCKET;
- usize = sizeof(u.u_int);
- if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
- else goto argError;
- }
+ if (option == @symbol(SO_SNDBUF)) {
+ /* Specifies the total per-socket buffer space reserved for sends.
+ This is unrelated to SO_MAX_MSG_SIZE or the size of a TCP window. */
+ opt = SO_SNDBUF;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_int);
+ if (__isSmallInteger(arg1))u.u_int = __intVal(arg1);
+ else goto argError;
+ }
# endif /* SO_SNDBUF */
# ifdef SO_REUSEADDR
- if (option == @symbol(SO_REUSEADDR)) {
- /* Allows the socket to be bound to an address that is already in use. */
- opt = SO_REUSEADDR;
- level = SOL_SOCKET;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(SO_REUSEADDR)) {
+ /* Allows the socket to be bound to an address that is already in use. */
+ opt = SO_REUSEADDR;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif /* SO_OOBINLINE */
# ifdef SO_EXCLUSIVEADDRUSE
- if (option == @symbol(SO_EXCLUSIVEADDRUSE)) {
- /* Enables a socket to be bound for exclusive access.
- Does not require administrative privilege. */
- opt = SO_EXCLUSIVEADDRUSE;
- level = SOL_SOCKET;
- usize = sizeof(u.u_bool);
- if (arg1 == true) u.u_bool = TRUE;
- else if (arg1 == false) u.u_bool = FALSE;
- else goto argError;
- }
+ if (option == @symbol(SO_EXCLUSIVEADDRUSE)) {
+ /* Enables a socket to be bound for exclusive access.
+ Does not require administrative privilege. */
+ opt = SO_EXCLUSIVEADDRUSE;
+ level = SOL_SOCKET;
+ usize = sizeof(u.u_bool);
+ if (arg1 == true) u.u_bool = TRUE;
+ else if (arg1 == false) u.u_bool = FALSE;
+ else goto argError;
+ }
# endif /* SO_OOBINLINE */
- if (usize == -1) goto argError;
-
- ok = ( setsockopt( sock, level, opt, (char *)(&u), usize) >= 0) ? true : false;
+# ifdef SO_RCVTIMEO
+ if ((option == @symbol(SO_RCVTIMEO))
+ && __isSmallInteger(arg1)
+ && __isSmallInteger(arg2)) {
+ opt = SO_RCVTIMEO;
+ level = SOL_SOCKET;
+ u.u_tv.tv_sec = __intVal(arg1);
+ u.u_tv.tv_usec = __intVal(arg2);
+ usize = sizeof(u.u_tv);
+ }
+# endif /* SO_RCVTIMEO */
+
+# ifdef SO_SNDTIMEO
+ if ((option == @symbol(SO_SNDTIMEO))
+ && __isSmallInteger(arg1)
+ && __isSmallInteger(arg2)) {
+ opt = SO_SNDTIMEO;
+ level = SOL_SOCKET;
+ u.u_tv.tv_sec = __intVal(arg1);
+ u.u_tv.tv_usec = __intVal(arg2);
+ usize = sizeof(u.u_tv);
+ }
+# endif /* SO_SNDTIMEO */
+
+ if (usize == -1) goto argError;
+
+ ok = ( setsockopt( sock, level, opt, (char *)(&u), usize) >= 0) ? true : false;
}
argError: ;
#endif /* NO_SOCKET */
%}.
ok isNil ifTrue:[
- self primitiveFailed
+ self primitiveFailed
].
ok ifFalse:[
- 'setsocketoption failed' infoPrintCR.
+ 'setsocketoption failed' infoPrintCR.
].
!
shutdown:howNum
"shutDown the socket - inform it that no more I/O will be performed.
- 0 - read side (no further reads)
- the tcp receive window is closed, so the peer cannot send more data.
- 1 - write side (no further writes)
- first, all queued data will be delivered to the peer.
- Then, an orderly release (TCP FIN) is sent to signal the peer,
- that we will not send more data.
- 2 - both read side and write side."
+ 0 - read side (no further reads)
+ the tcp receive window is closed, so the peer cannot send more data.
+ 1 - write side (no further writes)
+ first, all queued data will be delivered to the peer.
+ Then, an orderly release (TCP FIN) is sent to signal the peer,
+ that we will not send more data.
+ 2 - both read side and write side."
%{
#ifndef NO_SOCKET
OBJ __handle = __INST(handle);
if ((__handle != nil) && __isSmallInteger(howNum)) {
- SOCKET sock = SOCKET_FROM_FILE_OBJECT(__handle);
- INT how = __intVal(howNum);
- INT ret;
+ SOCKET sock = SOCKET_FROM_FILE_OBJECT(__handle);
+ INT how = __intVal(howNum);
+ INT ret;
# ifdef DO_WRAP_CALLS
- do {
- __threadErrno = 0;
- DBGFPRINTF((stderr, "SOCKET: shutDown...\n"));
- ret = (INT)STX_WSA_NOINT_CALL2("shutdown", shutdown, sock, how);
- DBGFPRINTF((stderr, "SOCKET: shutDown -> %d (%d)\n", ret, __threadErrno));
- } while ((ret < 0) && (__threadErrno == EINTR));
+ do {
+ __threadErrno = 0;
+ DBGFPRINTF((stderr, "SOCKET: shutDown...\n"));
+ ret = (INT)STX_WSA_NOINT_CALL2("shutdown", shutdown, sock, how);
+ DBGFPRINTF((stderr, "SOCKET: shutDown -> %d (%d)\n", ret, __threadErrno));
+ } while ((ret < 0) && (__threadErrno == EINTR));
# else
- __BEGIN_INTERRUPTABLE__
- shutdown(sock, how);
- __END_INTERRUPTABLE__
+ __BEGIN_INTERRUPTABLE__
+ shutdown(sock, how);
+ __END_INTERRUPTABLE__
# endif
}
#endif
@@ -3568,7 +3597,7 @@
|domainName domainCode typeCode error newHandle|
handle notNil ifTrue:[
- ^ self errorAlreadyOpen
+ ^ self errorAlreadyOpen
].
domainName := SocketAddress domainCodeFromName:domainArg.
domainCode := OperatingSystem domainCodeOf:domainName.
@@ -3590,19 +3619,19 @@
# endif
if (! __isSmallInteger(domainCode)) {
- error = @symbol(badArgument1);
- goto out;
+ error = @symbol(badArgument1);
+ goto out;
}
if (! __isSmallInteger(typeCode)) {
- error = @symbol(badArgument2);
- goto out;
+ error = @symbol(badArgument2);
+ goto out;
}
if (protocolNumber != nil) {
- if (!__isSmallInteger(protocolNumber)) {
- error = @symbol(badArgument3);
- goto out;
- }
- proto = __intVal(protocolNumber);
+ if (!__isSmallInteger(protocolNumber)) {
+ error = @symbol(badArgument3);
+ goto out;
+ }
+ proto = __intVal(protocolNumber);
}
/*
@@ -3614,91 +3643,91 @@
# ifdef WIN32
sock = WSASocket(dom, typ, proto, 0, 0, noInheritFlag);
if (sock == INVALID_SOCKET && noInheritFlag) {
- // tried to open socket with WSA_FLAG_NO_HANDLE_INHERIT
- // This fails on older windows versions, e.g. Windows XP
- sock = WSASocket(dom, typ, proto, 0, 0, 0);
- if (sock != INVALID_SOCKET) {
- // no error without WSA_FLAG_NO_HANDLE_INHERIT,
- // never use this flag again!
- noInheritFlag = 0;
- }
+ // tried to open socket with WSA_FLAG_NO_HANDLE_INHERIT
+ // This fails on older windows versions, e.g. Windows XP
+ sock = WSASocket(dom, typ, proto, 0, 0, 0);
+ if (sock != INVALID_SOCKET) {
+ // no error without WSA_FLAG_NO_HANDLE_INHERIT,
+ // never use this flag again!
+ noInheritFlag = 0;
+ }
}
if (sock == INVALID_SOCKET) {
- errno = WSAGetLastError();
+ errno = WSAGetLastError();
# else // !WIN32
sock = socket(dom, typ, proto);
# if defined(EPROTONOSUPPORT) /* for SGI */
if ((sock < 0) && (proto != 0) && (errno == EPROTONOSUPPORT)) {
- DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n"));
- proto = 0;
- sock = socket(dom, typ, 0);
+ DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n"));
+ proto = 0;
+ sock = socket(dom, typ, 0);
}
# endif
if (sock < 0) {
# endif // !WIN32
- DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno));
- error = __MKSMALLINT(errno);
+ DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno));
+ error = __MKSMALLINT(errno);
} else {
# if defined(SET_LINGER_WHEN_CREATING_SOCKET) && defined(SO_LINGER)
- {
- struct linger l;
-
- l.l_onoff = 1;
- l.l_linger = 30;
- setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
- }
+ {
+ struct linger l;
+
+ l.l_onoff = 1;
+ l.l_linger = 30;
+ setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
+ }
# endif
# ifdef WIN32
- /*
- * make it blocking
- */
- {
- unsigned long zero = 0;
- ioctlsocket(sock, FIONBIO, &zero);
- }
- {
+ /*
+ * make it blocking
+ */
+ {
+ unsigned long zero = 0;
+ ioctlsocket(sock, FIONBIO, &zero);
+ }
+ {
# if 0 && (defined( __BORLANDC__ ) || defined( __MINGW__ ))
- /*
- * make it a FILE *
- */
- __stxWrapApiEnterCritical();
- _fd = _open_osfhandle((long)sock, 0);
- __stxWrapApiLeaveCritical();
+ /*
+ * make it a FILE *
+ */
+ __stxWrapApiEnterCritical();
+ _fd = _open_osfhandle((long)sock, 0);
+ __stxWrapApiLeaveCritical();
# else
- _fd = (int)sock;
+ _fd = (int)sock;
# endif
- DBGPRINTF(("SOCKET: sock=%d fd=%d\n", sock, _fd));
- }
+ DBGPRINTF(("SOCKET: sock=%d fd=%d\n", sock, _fd));
+ }
# else // !WIN32
- fp = fdopen(sock, "r+");
- if (! fp) {
- DBGPRINTF(("SOCKET: fdopen call failed\n"));
- error = __MKSMALLINT(errno);
- __BEGIN_INTERRUPTABLE__
- closesocket(sock);
- DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock));
- __END_INTERRUPTABLE__
- goto out;
- }
+ fp = fdopen(sock, "r+");
+ if (! fp) {
+ DBGPRINTF(("SOCKET: fdopen call failed\n"));
+ error = __MKSMALLINT(errno);
+ __BEGIN_INTERRUPTABLE__
+ closesocket(sock);
+ DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock));
+ __END_INTERRUPTABLE__
+ goto out;
+ }
# endif // !WIN32
- if (@global(FileOpenTrace) == true) {
+ if (@global(FileOpenTrace) == true) {
# ifdef WIN32
- console_fprintf(stderr, "fdopen [Socket create] -> fd: %d (H: %"_lx_")\n", (INT)_fd, (INT)sock);
+ console_fprintf(stderr, "fdopen [Socket create] -> fd: %d (H: %"_lx_")\n", (INT)_fd, (INT)sock);
# else
- console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, sock);
+ console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, sock);
# endif
- }
+ }
# ifdef WIN32
- __externalAddressVal(newHandle) = _fd;
- __INST(handleType) = @symbol(socketHandle);
+ __externalAddressVal(newHandle) = _fd;
+ __INST(handleType) = @symbol(socketHandle);
# else
- __externalAddressVal(newHandle) = fp;
- __INST(handleType) = @symbol(socketFilePointer);
+ __externalAddressVal(newHandle) = fp;
+ __INST(handleType) = @symbol(socketFilePointer);
# endif
}
#endif
@@ -3707,15 +3736,15 @@
"all ok?"
handleType notNil ifTrue:[
- handle := newHandle.
- domain := domainArg.
- socketType := typeArg.
- Lobby register:self.
- ^ self.
+ handle := newHandle.
+ domain := domainArg.
+ socketType := typeArg.
+ Lobby register:self.
+ ^ self.
].
error isInteger ifTrue:[
- lastErrorNumber := error.
- ^ self openError:error.
+ lastErrorNumber := error.
+ ^ self openError:error.
].
^ self primitiveFailed:error.
@@ -3727,19 +3756,19 @@
!Socket methodsFor:'specials'!
-linger:anIntegerOrNil
+linger:anIntegerOrNil
"set the linger behavior on close:
anIntegerOrNil == nil: close returns immediately, socket tries
- to send buffered data in background.
+ to send buffered data in background.
anIntegerOrNil == 0: close returns immediately, bufferd data is discarded.
anIntegerOrNil > 0: close waits this many seconds for buffered data
- to be delivered, after this time buffered data is
- discarded and close returns"
-
- ^ self
- setSocketOption:#'SO_LINGER'
- argument:anIntegerOrNil notNil
- argument:anIntegerOrNil.
+ to be delivered, after this time buffered data is
+ discarded and close returns"
+
+ ^ self
+ setSocketOption:#'SO_LINGER'
+ argument:anIntegerOrNil notNil
+ argument:anIntegerOrNil.
!
receiveBufferSize
@@ -3802,7 +3831,7 @@
|millis|
handle isNil ifTrue:[
- ^ self errorNotOpen
+ ^ self errorNotOpen
].
%{
#if defined(SO_RCVTIMEO) && defined(SOL_SOCKET)
@@ -3814,13 +3843,13 @@
len = sizeof(struct timeval);
if (getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, &len) == 0) {
- __millis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
- millis = __mkSmallInteger(__millis);
+ __millis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+ millis = __mkSmallInteger(__millis);
# if 0
- console_fprintf(stderr, "getsockopt -> s:%d us:%d -> millis:%d\n", tv.tv_sec, tv.tv_usec, __millis);
+ console_fprintf(stderr, "getsockopt -> s:%d us:%d -> millis:%d\n", tv.tv_sec, tv.tv_usec, __millis);
# endif
} else {
- console_fprintf(stderr, "Socket [warning]: getsockopt %d failed; errno=%d\n", sock, errno);
+ console_fprintf(stderr, "Socket [warning]: getsockopt %d failed; errno=%d\n", sock, errno);
}
#endif
%}.
@@ -3836,26 +3865,26 @@
|millis|
handle isNil ifTrue:[
- ^ self errorNotOpen
+ ^ self errorNotOpen
].
millis := (seconds * 1000) rounded.
%{
#if defined(SO_RCVTIMEO) && defined(SOL_SOCKET)
if (__isSmallInteger(millis)) {
- OBJ fp = __INST(handle);
- SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
- int __millis = __intVal(millis);
- struct timeval tv = {0, 0};
-
- tv.tv_sec = __millis / 1000;
- tv.tv_usec = (__millis % 1000) * 1000;
+ OBJ fp = __INST(handle);
+ SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
+ int __millis = __intVal(millis);
+ struct timeval tv = {0, 0};
+
+ tv.tv_sec = __millis / 1000;
+ tv.tv_usec = (__millis % 1000) * 1000;
# if 0
- console_fprintf(stderr, "setsockopt -> millis:%d -> s:%d us:%d \n", __millis, tv.tv_sec, tv.tv_usec);
+ console_fprintf(stderr, "setsockopt -> millis:%d -> s:%d us:%d \n", __millis, tv.tv_sec, tv.tv_usec);
# endif
- if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(struct timeval)) == 0) {
- RETURN(true);
- }
- console_fprintf(stderr, "Socket [warning]: setsockopt %d failed; errno=%d\n", sock, errno);
+ if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(struct timeval)) == 0) {
+ RETURN(true);
+ }
+ console_fprintf(stderr, "Socket [warning]: setsockopt %d failed; errno=%d\n", sock, errno);
}
#endif
%}.
@@ -3922,7 +3951,7 @@
|millis|
handle isNil ifTrue:[
- ^ self errorNotOpen
+ ^ self errorNotOpen
].
%{
#if defined(SO_SNDTIMEO) && defined(SOL_SOCKET)
@@ -3934,13 +3963,13 @@
len = sizeof(struct timeval);
if (getsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, &len) == 0) {
- __millis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
- millis = __mkSmallInteger(__millis);
+ __millis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+ millis = __mkSmallInteger(__millis);
# if 0
- console_fprintf(stderr, "getsockopt -> s:%d us:%d -> millis:%d\n", tv.tv_sec, tv.tv_usec, __millis);
+ console_fprintf(stderr, "getsockopt -> s:%d us:%d -> millis:%d\n", tv.tv_sec, tv.tv_usec, __millis);
# endif
} else {
- console_fprintf(stderr, "Socket [warning]: getsockopt %d failed; errno=%d\n", sock, errno);
+ console_fprintf(stderr, "Socket [warning]: getsockopt %d failed; errno=%d\n", sock, errno);
}
#endif
%}.
@@ -3956,26 +3985,26 @@
|millis|
handle isNil ifTrue:[
- ^ self errorNotOpen
+ ^ self errorNotOpen
].
millis := (seconds * 1000) rounded.
%{
#if defined(SO_SNDTIMEO) && defined(SOL_SOCKET)
if (__isSmallInteger(millis)) {
- OBJ fp = __INST(handle);
- SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
- int __millis = __intVal(millis);
- struct timeval tv = {0, 0};
-
- tv.tv_sec = __millis / 1000;
- tv.tv_usec = (__millis % 1000) * 1000;
+ OBJ fp = __INST(handle);
+ SOCKET sock = SOCKET_FROM_FILE_OBJECT(fp);
+ int __millis = __intVal(millis);
+ struct timeval tv = {0, 0};
+
+ tv.tv_sec = __millis / 1000;
+ tv.tv_usec = (__millis % 1000) * 1000;
# if 0
- console_fprintf(stderr, "setsockopt -> millis:%d -> s:%d us:%d \n", __millis, tv.tv_sec, tv.tv_usec);
+ console_fprintf(stderr, "setsockopt -> millis:%d -> s:%d us:%d \n", __millis, tv.tv_sec, tv.tv_usec);
# endif
- if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(struct timeval)) == 0) {
- RETURN(true);
- }
- console_fprintf(stderr, "Socket [warning]: setsockopt %d failed; errno=%d\n", sock, errno);
+ if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(struct timeval)) == 0) {
+ RETURN(true);
+ }
+ console_fprintf(stderr, "Socket [warning]: setsockopt %d failed; errno=%d\n", sock, errno);
}
#endif
%}.
@@ -4017,41 +4046,41 @@
"first, a quick check if data is already available"
self canReadWithoutBlocking ifTrue:[
- ^ self accept.
+ ^ self accept.
].
otherConnections do:[:aConnection |
- aConnection canReadWithoutBlocking ifTrue:[
- ^ aConnection
- ]
+ aConnection canReadWithoutBlocking ifTrue:[
+ ^ aConnection
+ ]
].
"check again - prevent incoming interrupts from disturbing our setup"
wasBlocked := OperatingSystem blockInterrupts.
[
- 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.
+ 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.
] ifCurtailed:[
- sema notNil ifTrue:[Processor disableSemaphore:sema].
- wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ sema notNil ifTrue:[Processor disableSemaphore:sema].
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
].
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
"see who it was ..."
self canReadWithoutBlocking ifTrue:[
- ^ self accept.
+ ^ self accept.
].
otherConnections do:[:aConnection |
- aConnection canReadWithoutBlocking ifTrue:[
- ^ aConnection
- ]
+ aConnection canReadWithoutBlocking ifTrue:[
+ ^ aConnection
+ ]
].
"none - a timeout"
@@ -4076,10 +4105,9 @@
!Socket class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.306 2014-12-31 09:11:03 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.307 2015-01-23 23:44:21 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.306 2014-12-31 09:11:03 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.307 2015-01-23 23:44:21 cg Exp $'
! !
-