David T. Lewis uploaded a new version of Network to project The Trunk:
http://source.squeak.org/trunk/Network-dtl.130.mcz
==================== Summary ====================
Name: Network-dtl.130
Author: dtl
Time: 19 June 2012, 10:25:07.904 pm
UUID: 096acbec-d676-47d7-95d0-63b57aefaa35
Ancestors: Network-dtl.129
Merge Network-chc.120 from inbox:
Name: Network-chc.120
Author: chc
Time: 7 November 2011, 9:59:44.904 am
UUID: c50a16b2-5a12-409d-a31e-2d46f4a55fc2
Ancestors: Network-tonyg.119
http://lists.squeakfoundation.org/pipermail/squeak-dev/2010-June/151440.html
FileList>>labelString was changed but perhaps it didn't change to accommodate ServerDirectory. As such the FTP folder in FileList has been broken. The process chokes in:
pathAndPattern
^directory fullName, directory slash, pattern
because ServerDirectory has neither #fullName nor #slash. I've added them and now the FTP directory at the bottom of the file list in FileList works again.
=============== Diff against Network-dtl.129 ===============
Item was added:
+ ----- Method: ServerDirectory>>fullName (in category 'accessing') -----
+ fullName
+ ^server!
Item was added:
+ ----- Method: ServerDirectory>>slash (in category 'accessing') -----
+ slash
+ ^'/'!
David T. Lewis uploaded a new version of Network to project The Trunk:
http://source.squeak.org/trunk/Network-dtl.129.mcz
==================== Summary ====================
Name: Network-dtl.129
Author: dtl
Time: 19 June 2012, 10:18:16.162 pm
UUID: c7ba60cc-b3bf-4afb-98b2-9917d145f97a
Ancestors: Network-dtl.128
Merge Network-mtf.115 from the inbox:
Name: Network-mtf.115
Author: mtf
Time: 15 May 2011, 9:49:51.176 pm
UUID: 31a375ff-af51-cd48-836d-57292a91d1ec
Ancestors: Network-ul.114
made multicast sending when the network is disconnected not result in an infinite loop. I don't know if this is correct or not,. To reproduce:
- Unplug your network
- Do a dummy multicast send:
Socket newUDP sendData: 'XXX' toHost: #[239 99 99 99] port: 9999
- Result before patch: infinite loop
- Result after patch: NetworkError
Issue originally discovered in OpenCobalt's UPnP service
=============== Diff against Network-dtl.128 ===============
Item was changed:
----- Method: Socket>>sendUDPData:toHost:port: (in category 'datagrams') -----
sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber
"Send a UDP packet containing the given data to the specified host/port."
| bytesToSend bytesSent count |
bytesToSend := aStringOrByteArray size.
bytesSent := 0.
[bytesSent < bytesToSend] whileTrue: [
(self waitForSendDoneFor: 20)
ifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].
count := self primSocket: socketHandle
sendUDPData: aStringOrByteArray
toHost: hostAddress asByteArray
port: portNumber
startIndex: bytesSent + 1
count: bytesToSend - bytesSent.
+ count isZero ifTrue: [NetworkError signal: 'failed to send data']..
bytesSent := bytesSent + count].
^ bytesSent
!
David T. Lewis uploaded a new version of Network to project The Trunk:
http://source.squeak.org/trunk/Network-dtl.129.mcz
==================== Summary ====================
Name: Network-dtl.129
Author: dtl
Time: 19 June 2012, 10:18:16.162 pm
UUID: c7ba60cc-b3bf-4afb-98b2-9917d145f97a
Ancestors: Network-dtl.128
Merge Network-mtf.115 from the inbox:
Name: Network-mtf.115
Author: mtf
Time: 15 May 2011, 9:49:51.176 pm
UUID: 31a375ff-af51-cd48-836d-57292a91d1ec
Ancestors: Network-ul.114
made multicast sending when the network is disconnected not result in an infinite loop. I don't know if this is correct or not,. To reproduce:
- Unplug your network
- Do a dummy multicast send:
Socket newUDP sendData: 'XXX' toHost: #[239 99 99 99] port: 9999
- Result before patch: infinite loop
- Result after patch: NetworkError
Issue originally discovered in OpenCobalt's UPnP service
=============== Diff against Network-dtl.128 ===============
Item was changed:
----- Method: Socket>>sendUDPData:toHost:port: (in category 'datagrams') -----
sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber
"Send a UDP packet containing the given data to the specified host/port."
| bytesToSend bytesSent count |
bytesToSend := aStringOrByteArray size.
bytesSent := 0.
[bytesSent < bytesToSend] whileTrue: [
(self waitForSendDoneFor: 20)
ifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].
count := self primSocket: socketHandle
sendUDPData: aStringOrByteArray
toHost: hostAddress asByteArray
port: portNumber
startIndex: bytesSent + 1
count: bytesToSend - bytesSent.
+ count isZero ifTrue: [NetworkError signal: 'failed to send data']..
bytesSent := bytesSent + count].
^ bytesSent
!
David T. Lewis uploaded a new version of Network to project The Trunk:
http://source.squeak.org/trunk/Network-dtl.129.mcz
==================== Summary ====================
Name: Network-dtl.129
Author: dtl
Time: 19 June 2012, 10:18:16.162 pm
UUID: c7ba60cc-b3bf-4afb-98b2-9917d145f97a
Ancestors: Network-dtl.128
Merge Network-mtf.115 from the inbox:
Name: Network-mtf.115
Author: mtf
Time: 15 May 2011, 9:49:51.176 pm
UUID: 31a375ff-af51-cd48-836d-57292a91d1ec
Ancestors: Network-ul.114
made multicast sending when the network is disconnected not result in an infinite loop. I don't know if this is correct or not,. To reproduce:
- Unplug your network
- Do a dummy multicast send:
Socket newUDP sendData: 'XXX' toHost: #[239 99 99 99] port: 9999
- Result before patch: infinite loop
- Result after patch: NetworkError
Issue originally discovered in OpenCobalt's UPnP service
=============== Diff against Network-dtl.128 ===============
Item was changed:
----- Method: Socket>>sendUDPData:toHost:port: (in category 'datagrams') -----
sendUDPData: aStringOrByteArray toHost: hostAddress port: portNumber
"Send a UDP packet containing the given data to the specified host/port."
| bytesToSend bytesSent count |
bytesToSend := aStringOrByteArray size.
bytesSent := 0.
[bytesSent < bytesToSend] whileTrue: [
(self waitForSendDoneFor: 20)
ifFalse: [ConnectionTimedOut signal: 'send data timeout; data not sent'].
count := self primSocket: socketHandle
sendUDPData: aStringOrByteArray
toHost: hostAddress asByteArray
port: portNumber
startIndex: bytesSent + 1
count: bytesToSend - bytesSent.
+ count isZero ifTrue: [NetworkError signal: 'failed to send data']..
bytesSent := bytesSent + count].
^ bytesSent
!
David T. Lewis uploaded a new version of Network to project The Trunk:
http://source.squeak.org/trunk/Network-dtl.127.mcz
==================== Summary ====================
Name: Network-dtl.127
Author: dtl
Time: 13 June 2012, 10:24:48.022 pm
UUID: ba365401-387d-4dff-acb1-1b81b3bc8383
Ancestors: Network-dtl.126
Protect SocketAddressInformation creation with a mutex semaphore because it calls primitives that maintain state within the SocketPlugin.
Raise ConnectionTimedOut if a connection request has actually timed out, otherwise raise ConnectionRefused.
Fix exception message in connectTo:port:waitForConnectionFor: to use hostAddress printString because hostAddress is now a SocketAddress.
=============== Diff against Network-dtl.126 ===============
Item was changed:
----- Method: Socket>>connectTo:port:waitForConnectionFor: (in category 'connection open/close') -----
connectTo: hostAddress port: port waitForConnectionFor: timeout
"Initiate a connection to the given port at the given host
address. Waits until the connection is established or time outs."
self connectNonBlockingTo: hostAddress port: port.
self
waitForConnectionFor: timeout
+ ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', hostAddress printString]
+ ifRefused: [ConnectionRefused signal: 'Cannot connect to ', hostAddress printString]!
- ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to '
- , self remoteSocketAddress hostNumber , ':' , port asString]!
Item was changed:
----- Method: Socket>>connectTo:waitForConnectionFor: (in category 'ipv6') -----
connectTo: aSocketAddress waitForConnectionFor: timeout
self connectNonBlockingTo: aSocketAddress.
self
waitForConnectionFor: timeout
+ ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', aSocketAddress printString]
+ ifRefused: [ConnectionRefused signal: 'Cannot connect to ', aSocketAddress printString]!
- ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', aSocketAddress printString]!
Item was changed:
----- Method: Socket>>waitForConnectionFor: (in category 'waiting') -----
waitForConnectionFor: timeout
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
^self
waitForConnectionFor: timeout
ifTimedOut: [ConnectionTimedOut signal: 'Failed to connect in ', timeout asString, ' seconds']
+ ifRefused: [ConnectionRefused signal: 'Failed to connect in ', timeout asString, ' seconds']
!
Item was changed:
----- Method: Socket>>waitForConnectionFor:ifTimedOut: (in category 'waiting') -----
waitForConnectionFor: timeout ifTimedOut: timeoutBlock
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
+ ^ self waitForConnectionFor: timeout ifTimedOut: timeoutBlock ifRefused: timeoutBlock
+ !
- | startTime msecsDelta msecsEllapsed status |
- startTime := Time millisecondClockValue.
- msecsDelta := (timeout * 1000) truncated.
- status := self primSocketConnectionStatus: socketHandle.
- [(status = WaitingForConnection) and: [(msecsEllapsed := Time millisecondsSince: startTime) < msecsDelta]]
- whileTrue: [
- semaphore waitTimeoutMSecs: msecsDelta - msecsEllapsed.
- status := self primSocketConnectionStatus: socketHandle].
-
- status = Connected ifFalse: [^timeoutBlock value].
- ^ true!
Item was added:
+ ----- Method: Socket>>waitForConnectionFor:ifTimedOut:ifRefused: (in category 'waiting') -----
+ waitForConnectionFor: timeout ifTimedOut: timeoutBlock ifRefused: refusedBlock
+ "Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
+
+ | startTime msecsDelta msecsEllapsed status |
+ startTime := Time millisecondClockValue.
+ msecsDelta := (timeout * 1000) truncated.
+ status := self primSocketConnectionStatus: socketHandle.
+ status = Connected ifTrue: [^true].
+ [(status = WaitingForConnection) and: [(msecsEllapsed := Time millisecondsSince: startTime) < msecsDelta]]
+ whileTrue: [
+ semaphore waitTimeoutMSecs: msecsDelta - msecsEllapsed.
+ status := self primSocketConnectionStatus: socketHandle].
+ status = Connected
+ ifFalse: [
+ status = WaitingForConnection
+ ifTrue: [timeoutBlock value]
+ ifFalse: [refusedBlock value].
+ ^false].
+ ^ true!
Item was changed:
----- Method: Socket>>waitForConnectionUntil: (in category 'waiting') -----
waitForConnectionUntil: deadline
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
| status |
status := self primSocketConnectionStatus: socketHandle.
+ self isConnected ifTrue: [^status].
[(status = WaitingForConnection) and: [Time millisecondClockValue < deadline]]
whileTrue: [
semaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).
status := self primSocketConnectionStatus: socketHandle].
^ status = Connected
!
Item was changed:
Object subclass: #SocketAddressInformation
instanceVariableNames: 'socketAddress addressFamily socketType protocol'
+ classVariableNames: 'AddressFamilyINET4 AddressFamilyINET6 AddressFamilyLocal AddressFamilyUnspecified NumericFlag PassiveFlag PrimitiveAccessProtect ProtocolTCP ProtocolUDP ProtocolUnspecified SocketTypeDGram SocketTypeStream SocketTypeUnspecified'
- classVariableNames: 'AddressFamilyINET4 AddressFamilyINET6 AddressFamilyLocal AddressFamilyUnspecified NumericFlag PassiveFlag ProtocolTCP ProtocolUDP ProtocolUnspecified SocketTypeDGram SocketTypeStream SocketTypeUnspecified'
poolDictionaries: ''
category: 'Network-Kernel'!
!SocketAddressInformation commentStamp: '<historical>' prior: 0!
I represent a local or remote network service.
Instance Variables
addressFamily: <SmallInteger> the address family (unix, inet4, inet6, ...) in which the service address is available.
protocol: <SmallInteger> the protocol (tcp, udp, ...) that the service uses.
socketAddress: <SocketAddress> the socket address at which the service can be contacted or created.
socketType: <SmallInteger> the type (stream, dgram) of the socket that should be created for communication with the service.
!
Item was changed:
----- Method: SocketAddressInformation class>>forHost:service:flags:addressFamily:socketType:protocol: (in category 'instance creation') -----
forHost: hostName service: servName flags: flags addressFamily: family socketType: type protocol: protocol
| result addr |
+ PrimitiveAccessProtect critical: [
+ NetNameResolver initializeNetwork.
+ NetNameResolver
+ primGetAddressInfoHost: hostName
+ service: servName
+ flags: flags
+ family: family
+ type: type
+ protocol: protocol.
+ result := OrderedCollection new.
+ [(addr := NetNameResolver nextSocketAddressInformation) notNil]
+ whileTrue: [result add: addr]].
+ ^ result!
- NetNameResolver initializeNetwork.
- NetNameResolver primGetAddressInfoHost: hostName service: servName flags: flags family: family type: type protocol: protocol.
- result := OrderedCollection new.
- [(addr := NetNameResolver nextSocketAddressInformation) notNil] whileTrue: [result add: addr].
- ^result!
Item was changed:
----- Method: SocketAddressInformation class>>initialize (in category 'class initialization') -----
+ initialize
+ "SocketAddressInformation initialize"
- initialize "SocketAddressInformation initialize"
NumericFlag := 1.
PassiveFlag := 2.
AddressFamilyUnspecified := 0.
AddressFamilyLocal := 1.
AddressFamilyINET4 := 2.
AddressFamilyINET6 := 3.
SocketTypeUnspecified := 0.
SocketTypeStream := 1.
SocketTypeDGram := 2.
ProtocolUnspecified := 0.
ProtocolTCP := 1.
+ ProtocolUDP := 2.
+
+ "SocketPlugin maintains internal state across primitive calls, so methods that rely
+ on the result of sequential primitive calls require concurrency control."
+ PrimitiveAccessProtect := Semaphore forMutualExclusion.
+ !
- ProtocolUDP := 2.!
Item was changed:
----- Method: SocketAddressInformation>>connect (in category 'circuit setup') -----
connect
| sock |
socketType == SocketTypeStream ifFalse: [^nil].
sock := Socket newTCP: addressFamily.
sock connectTo: socketAddress.
sock waitForConnectionFor: Socket standardTimeout
+ ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', self printString]
+ ifRefused: [ConnectionRefused signal: 'Cannot connect to ', self printString].
- ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', self printString].
^sock!
David T. Lewis uploaded a new version of Network to project The Trunk:
http://source.squeak.org/trunk/Network-dtl.127.mcz
==================== Summary ====================
Name: Network-dtl.127
Author: dtl
Time: 13 June 2012, 10:24:48.022 pm
UUID: ba365401-387d-4dff-acb1-1b81b3bc8383
Ancestors: Network-dtl.126
Protect SocketAddressInformation creation with a mutex semaphore because it calls primitives that maintain state within the SocketPlugin.
Raise ConnectionTimedOut if a connection request has actually timed out, otherwise raise ConnectionRefused.
Fix exception message in connectTo:port:waitForConnectionFor: to use hostAddress printString because hostAddress is now a SocketAddress.
=============== Diff against Network-dtl.126 ===============
Item was changed:
----- Method: Socket>>connectTo:port:waitForConnectionFor: (in category 'connection open/close') -----
connectTo: hostAddress port: port waitForConnectionFor: timeout
"Initiate a connection to the given port at the given host
address. Waits until the connection is established or time outs."
self connectNonBlockingTo: hostAddress port: port.
self
waitForConnectionFor: timeout
+ ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', hostAddress printString]
+ ifRefused: [ConnectionRefused signal: 'Cannot connect to ', hostAddress printString]!
- ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to '
- , self remoteSocketAddress hostNumber , ':' , port asString]!
Item was changed:
----- Method: Socket>>connectTo:waitForConnectionFor: (in category 'ipv6') -----
connectTo: aSocketAddress waitForConnectionFor: timeout
self connectNonBlockingTo: aSocketAddress.
self
waitForConnectionFor: timeout
+ ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', aSocketAddress printString]
+ ifRefused: [ConnectionRefused signal: 'Cannot connect to ', aSocketAddress printString]!
- ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', aSocketAddress printString]!
Item was changed:
----- Method: Socket>>waitForConnectionFor: (in category 'waiting') -----
waitForConnectionFor: timeout
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
^self
waitForConnectionFor: timeout
ifTimedOut: [ConnectionTimedOut signal: 'Failed to connect in ', timeout asString, ' seconds']
+ ifRefused: [ConnectionRefused signal: 'Failed to connect in ', timeout asString, ' seconds']
!
Item was changed:
----- Method: Socket>>waitForConnectionFor:ifTimedOut: (in category 'waiting') -----
waitForConnectionFor: timeout ifTimedOut: timeoutBlock
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
+ ^ self waitForConnectionFor: timeout ifTimedOut: timeoutBlock ifRefused: timeoutBlock
+ !
- | startTime msecsDelta msecsEllapsed status |
- startTime := Time millisecondClockValue.
- msecsDelta := (timeout * 1000) truncated.
- status := self primSocketConnectionStatus: socketHandle.
- [(status = WaitingForConnection) and: [(msecsEllapsed := Time millisecondsSince: startTime) < msecsDelta]]
- whileTrue: [
- semaphore waitTimeoutMSecs: msecsDelta - msecsEllapsed.
- status := self primSocketConnectionStatus: socketHandle].
-
- status = Connected ifFalse: [^timeoutBlock value].
- ^ true!
Item was added:
+ ----- Method: Socket>>waitForConnectionFor:ifTimedOut:ifRefused: (in category 'waiting') -----
+ waitForConnectionFor: timeout ifTimedOut: timeoutBlock ifRefused: refusedBlock
+ "Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
+
+ | startTime msecsDelta msecsEllapsed status |
+ startTime := Time millisecondClockValue.
+ msecsDelta := (timeout * 1000) truncated.
+ status := self primSocketConnectionStatus: socketHandle.
+ status = Connected ifTrue: [^true].
+ [(status = WaitingForConnection) and: [(msecsEllapsed := Time millisecondsSince: startTime) < msecsDelta]]
+ whileTrue: [
+ semaphore waitTimeoutMSecs: msecsDelta - msecsEllapsed.
+ status := self primSocketConnectionStatus: socketHandle].
+ status = Connected
+ ifFalse: [
+ status = WaitingForConnection
+ ifTrue: [timeoutBlock value]
+ ifFalse: [refusedBlock value].
+ ^false].
+ ^ true!
Item was changed:
----- Method: Socket>>waitForConnectionUntil: (in category 'waiting') -----
waitForConnectionUntil: deadline
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
| status |
status := self primSocketConnectionStatus: socketHandle.
+ self isConnected ifTrue: [^status].
[(status = WaitingForConnection) and: [Time millisecondClockValue < deadline]]
whileTrue: [
semaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).
status := self primSocketConnectionStatus: socketHandle].
^ status = Connected
!
Item was changed:
Object subclass: #SocketAddressInformation
instanceVariableNames: 'socketAddress addressFamily socketType protocol'
+ classVariableNames: 'AddressFamilyINET4 AddressFamilyINET6 AddressFamilyLocal AddressFamilyUnspecified NumericFlag PassiveFlag PrimitiveAccessProtect ProtocolTCP ProtocolUDP ProtocolUnspecified SocketTypeDGram SocketTypeStream SocketTypeUnspecified'
- classVariableNames: 'AddressFamilyINET4 AddressFamilyINET6 AddressFamilyLocal AddressFamilyUnspecified NumericFlag PassiveFlag ProtocolTCP ProtocolUDP ProtocolUnspecified SocketTypeDGram SocketTypeStream SocketTypeUnspecified'
poolDictionaries: ''
category: 'Network-Kernel'!
!SocketAddressInformation commentStamp: '<historical>' prior: 0!
I represent a local or remote network service.
Instance Variables
addressFamily: <SmallInteger> the address family (unix, inet4, inet6, ...) in which the service address is available.
protocol: <SmallInteger> the protocol (tcp, udp, ...) that the service uses.
socketAddress: <SocketAddress> the socket address at which the service can be contacted or created.
socketType: <SmallInteger> the type (stream, dgram) of the socket that should be created for communication with the service.
!
Item was changed:
----- Method: SocketAddressInformation class>>forHost:service:flags:addressFamily:socketType:protocol: (in category 'instance creation') -----
forHost: hostName service: servName flags: flags addressFamily: family socketType: type protocol: protocol
| result addr |
+ PrimitiveAccessProtect critical: [
+ NetNameResolver initializeNetwork.
+ NetNameResolver
+ primGetAddressInfoHost: hostName
+ service: servName
+ flags: flags
+ family: family
+ type: type
+ protocol: protocol.
+ result := OrderedCollection new.
+ [(addr := NetNameResolver nextSocketAddressInformation) notNil]
+ whileTrue: [result add: addr]].
+ ^ result!
- NetNameResolver initializeNetwork.
- NetNameResolver primGetAddressInfoHost: hostName service: servName flags: flags family: family type: type protocol: protocol.
- result := OrderedCollection new.
- [(addr := NetNameResolver nextSocketAddressInformation) notNil] whileTrue: [result add: addr].
- ^result!
Item was changed:
----- Method: SocketAddressInformation class>>initialize (in category 'class initialization') -----
+ initialize
+ "SocketAddressInformation initialize"
- initialize "SocketAddressInformation initialize"
NumericFlag := 1.
PassiveFlag := 2.
AddressFamilyUnspecified := 0.
AddressFamilyLocal := 1.
AddressFamilyINET4 := 2.
AddressFamilyINET6 := 3.
SocketTypeUnspecified := 0.
SocketTypeStream := 1.
SocketTypeDGram := 2.
ProtocolUnspecified := 0.
ProtocolTCP := 1.
+ ProtocolUDP := 2.
+
+ "SocketPlugin maintains internal state across primitive calls, so methods that rely
+ on the result of sequential primitive calls require concurrency control."
+ PrimitiveAccessProtect := Semaphore forMutualExclusion.
+ !
- ProtocolUDP := 2.!
Item was changed:
----- Method: SocketAddressInformation>>connect (in category 'circuit setup') -----
connect
| sock |
socketType == SocketTypeStream ifFalse: [^nil].
sock := Socket newTCP: addressFamily.
sock connectTo: socketAddress.
sock waitForConnectionFor: Socket standardTimeout
+ ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', self printString]
+ ifRefused: [ConnectionRefused signal: 'Cannot connect to ', self printString].
- ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', self printString].
^sock!
David T. Lewis uploaded a new version of Network to project The Trunk:
http://source.squeak.org/trunk/Network-dtl.127.mcz
==================== Summary ====================
Name: Network-dtl.127
Author: dtl
Time: 13 June 2012, 10:24:48.022 pm
UUID: ba365401-387d-4dff-acb1-1b81b3bc8383
Ancestors: Network-dtl.126
Protect SocketAddressInformation creation with a mutex semaphore because it calls primitives that maintain state within the SocketPlugin.
Raise ConnectionTimedOut if a connection request has actually timed out, otherwise raise ConnectionRefused.
Fix exception message in connectTo:port:waitForConnectionFor: to use hostAddress printString because hostAddress is now a SocketAddress.
=============== Diff against Network-dtl.126 ===============
Item was changed:
----- Method: Socket>>connectTo:port:waitForConnectionFor: (in category 'connection open/close') -----
connectTo: hostAddress port: port waitForConnectionFor: timeout
"Initiate a connection to the given port at the given host
address. Waits until the connection is established or time outs."
self connectNonBlockingTo: hostAddress port: port.
self
waitForConnectionFor: timeout
+ ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', hostAddress printString]
+ ifRefused: [ConnectionRefused signal: 'Cannot connect to ', hostAddress printString]!
- ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to '
- , self remoteSocketAddress hostNumber , ':' , port asString]!
Item was changed:
----- Method: Socket>>connectTo:waitForConnectionFor: (in category 'ipv6') -----
connectTo: aSocketAddress waitForConnectionFor: timeout
self connectNonBlockingTo: aSocketAddress.
self
waitForConnectionFor: timeout
+ ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', aSocketAddress printString]
+ ifRefused: [ConnectionRefused signal: 'Cannot connect to ', aSocketAddress printString]!
- ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', aSocketAddress printString]!
Item was changed:
----- Method: Socket>>waitForConnectionFor: (in category 'waiting') -----
waitForConnectionFor: timeout
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
^self
waitForConnectionFor: timeout
ifTimedOut: [ConnectionTimedOut signal: 'Failed to connect in ', timeout asString, ' seconds']
+ ifRefused: [ConnectionRefused signal: 'Failed to connect in ', timeout asString, ' seconds']
!
Item was changed:
----- Method: Socket>>waitForConnectionFor:ifTimedOut: (in category 'waiting') -----
waitForConnectionFor: timeout ifTimedOut: timeoutBlock
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
+ ^ self waitForConnectionFor: timeout ifTimedOut: timeoutBlock ifRefused: timeoutBlock
+ !
- | startTime msecsDelta msecsEllapsed status |
- startTime := Time millisecondClockValue.
- msecsDelta := (timeout * 1000) truncated.
- status := self primSocketConnectionStatus: socketHandle.
- [(status = WaitingForConnection) and: [(msecsEllapsed := Time millisecondsSince: startTime) < msecsDelta]]
- whileTrue: [
- semaphore waitTimeoutMSecs: msecsDelta - msecsEllapsed.
- status := self primSocketConnectionStatus: socketHandle].
-
- status = Connected ifFalse: [^timeoutBlock value].
- ^ true!
Item was added:
+ ----- Method: Socket>>waitForConnectionFor:ifTimedOut:ifRefused: (in category 'waiting') -----
+ waitForConnectionFor: timeout ifTimedOut: timeoutBlock ifRefused: refusedBlock
+ "Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
+
+ | startTime msecsDelta msecsEllapsed status |
+ startTime := Time millisecondClockValue.
+ msecsDelta := (timeout * 1000) truncated.
+ status := self primSocketConnectionStatus: socketHandle.
+ status = Connected ifTrue: [^true].
+ [(status = WaitingForConnection) and: [(msecsEllapsed := Time millisecondsSince: startTime) < msecsDelta]]
+ whileTrue: [
+ semaphore waitTimeoutMSecs: msecsDelta - msecsEllapsed.
+ status := self primSocketConnectionStatus: socketHandle].
+ status = Connected
+ ifFalse: [
+ status = WaitingForConnection
+ ifTrue: [timeoutBlock value]
+ ifFalse: [refusedBlock value].
+ ^false].
+ ^ true!
Item was changed:
----- Method: Socket>>waitForConnectionUntil: (in category 'waiting') -----
waitForConnectionUntil: deadline
"Wait up until the given deadline for a connection to be established. Return true if it is established by the deadline, false if not."
| status |
status := self primSocketConnectionStatus: socketHandle.
+ self isConnected ifTrue: [^status].
[(status = WaitingForConnection) and: [Time millisecondClockValue < deadline]]
whileTrue: [
semaphore waitTimeoutMSecs: (deadline - Time millisecondClockValue).
status := self primSocketConnectionStatus: socketHandle].
^ status = Connected
!
Item was changed:
Object subclass: #SocketAddressInformation
instanceVariableNames: 'socketAddress addressFamily socketType protocol'
+ classVariableNames: 'AddressFamilyINET4 AddressFamilyINET6 AddressFamilyLocal AddressFamilyUnspecified NumericFlag PassiveFlag PrimitiveAccessProtect ProtocolTCP ProtocolUDP ProtocolUnspecified SocketTypeDGram SocketTypeStream SocketTypeUnspecified'
- classVariableNames: 'AddressFamilyINET4 AddressFamilyINET6 AddressFamilyLocal AddressFamilyUnspecified NumericFlag PassiveFlag ProtocolTCP ProtocolUDP ProtocolUnspecified SocketTypeDGram SocketTypeStream SocketTypeUnspecified'
poolDictionaries: ''
category: 'Network-Kernel'!
!SocketAddressInformation commentStamp: '<historical>' prior: 0!
I represent a local or remote network service.
Instance Variables
addressFamily: <SmallInteger> the address family (unix, inet4, inet6, ...) in which the service address is available.
protocol: <SmallInteger> the protocol (tcp, udp, ...) that the service uses.
socketAddress: <SocketAddress> the socket address at which the service can be contacted or created.
socketType: <SmallInteger> the type (stream, dgram) of the socket that should be created for communication with the service.
!
Item was changed:
----- Method: SocketAddressInformation class>>forHost:service:flags:addressFamily:socketType:protocol: (in category 'instance creation') -----
forHost: hostName service: servName flags: flags addressFamily: family socketType: type protocol: protocol
| result addr |
+ PrimitiveAccessProtect critical: [
+ NetNameResolver initializeNetwork.
+ NetNameResolver
+ primGetAddressInfoHost: hostName
+ service: servName
+ flags: flags
+ family: family
+ type: type
+ protocol: protocol.
+ result := OrderedCollection new.
+ [(addr := NetNameResolver nextSocketAddressInformation) notNil]
+ whileTrue: [result add: addr]].
+ ^ result!
- NetNameResolver initializeNetwork.
- NetNameResolver primGetAddressInfoHost: hostName service: servName flags: flags family: family type: type protocol: protocol.
- result := OrderedCollection new.
- [(addr := NetNameResolver nextSocketAddressInformation) notNil] whileTrue: [result add: addr].
- ^result!
Item was changed:
----- Method: SocketAddressInformation class>>initialize (in category 'class initialization') -----
+ initialize
+ "SocketAddressInformation initialize"
- initialize "SocketAddressInformation initialize"
NumericFlag := 1.
PassiveFlag := 2.
AddressFamilyUnspecified := 0.
AddressFamilyLocal := 1.
AddressFamilyINET4 := 2.
AddressFamilyINET6 := 3.
SocketTypeUnspecified := 0.
SocketTypeStream := 1.
SocketTypeDGram := 2.
ProtocolUnspecified := 0.
ProtocolTCP := 1.
+ ProtocolUDP := 2.
+
+ "SocketPlugin maintains internal state across primitive calls, so methods that rely
+ on the result of sequential primitive calls require concurrency control."
+ PrimitiveAccessProtect := Semaphore forMutualExclusion.
+ !
- ProtocolUDP := 2.!
Item was changed:
----- Method: SocketAddressInformation>>connect (in category 'circuit setup') -----
connect
| sock |
socketType == SocketTypeStream ifFalse: [^nil].
sock := Socket newTCP: addressFamily.
sock connectTo: socketAddress.
sock waitForConnectionFor: Socket standardTimeout
+ ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', self printString]
+ ifRefused: [ConnectionRefused signal: 'Cannot connect to ', self printString].
- ifTimedOut: [ConnectionTimedOut signal: 'Cannot connect to ', self printString].
^sock!