Can we disable the NSStream bytes/space available callbacks using CFSocketDisableCallbacks() on NSStream underling socket?

Hi,


I am using NSStream for TLS communication with remote server. Now is there any way we can disable NSStream read/space callbacks and enable it again as this is possible with CFSocket. I tried to get the underlying socket of the NSStream using 'CFReadStreamCopyProperty((__bridge CFReadStreamRef)((NSInputStream *)stream), kCFStreamPropertySocketNativeHandle)' and tried to call CFSocketDisableCallbacks() on it but it did not disable the bytes/space available callbacks.


Is this possible with NSStream? The reason behing this is I do not want to keep buffer for storing the read bytes from NSInputStream and the consumer for those bytes is asynchronous.


Regards!

Answered by DTS Engineer in 159269022

Now is there any way we can disable NSStream read/space callbacks and enable it again as this is possible with CFSocket.

Not really. You could try unscheduling the stream but that’d put you well off the beaten path.

I tried to get the underlying socket of the NSStream … and tried to call

CFSocketDisableCallbacks
on it but it did not disable the bytes/space available callbacks.

CFSocketStream does not necessarily use CFSocket. There used to be a direct relationship back in the day but things have moved on a lot since then.

The reason behing this is I do not want to keep buffer for storing the read bytes from NSInputStream and the consumer for those bytes is asynchronous.

I’m not sure I understand your requirements, but it sounds like you can simply stop responding to

.HasBytesAvailable
messages. When you use NSStream in async mode, I/O is based on an ‘interlock’ mechanism:
  1. you get a

    .HasBytesAvailable
    event
  2. you make a

    read(_:maxLength:)
    call
  3. you get another

    .HasBytesAvailable
    event

Similarly for

.HasSpaceAvailable
and
write(_:maxLength:)
.

Step 3 doesn’t happen until step 2 is done. Thus, if you want to implement receive-side flow control on the stream (because of send-side flow control on your sink), skip step 2. Typically this involves a flag to record that you got, and ignored, a

.HasBytesAvailable
event. That way, when send-side flow control is lifted on the sink, you know that you can immediately resume at step 2.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Accepted Answer

Now is there any way we can disable NSStream read/space callbacks and enable it again as this is possible with CFSocket.

Not really. You could try unscheduling the stream but that’d put you well off the beaten path.

I tried to get the underlying socket of the NSStream … and tried to call

CFSocketDisableCallbacks
on it but it did not disable the bytes/space available callbacks.

CFSocketStream does not necessarily use CFSocket. There used to be a direct relationship back in the day but things have moved on a lot since then.

The reason behing this is I do not want to keep buffer for storing the read bytes from NSInputStream and the consumer for those bytes is asynchronous.

I’m not sure I understand your requirements, but it sounds like you can simply stop responding to

.HasBytesAvailable
messages. When you use NSStream in async mode, I/O is based on an ‘interlock’ mechanism:
  1. you get a

    .HasBytesAvailable
    event
  2. you make a

    read(_:maxLength:)
    call
  3. you get another

    .HasBytesAvailable
    event

Similarly for

.HasSpaceAvailable
and
write(_:maxLength:)
.

Step 3 doesn’t happen until step 2 is done. Thus, if you want to implement receive-side flow control on the stream (because of send-side flow control on your sink), skip step 2. Typically this involves a flag to record that you got, and ignored, a

.HasBytesAvailable
event. That way, when send-side flow control is lifted on the sink, you know that you can immediately resume at step 2.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks Quinn. I would try this.

Is is also the case with 'getBuffer'? Can I use 'getBuffer' instead of read and the NSStream would not call bytesAvailable until I call getBuffer?

Is is also the case with 'getBuffer'?

-getBuffer:length:
is quite useless (I’ve been working with NSStreams for decades and I’ve never found any place where it actually helps). In the case of a socket stream,
-getBuffer:length:
will always returns false because the socket buffer is inside the kernel, and thus not accessible to code running in your process.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Can we disable the NSStream bytes/space available callbacks using CFSocketDisableCallbacks() on NSStream underling socket?
 
 
Q