Bug 31167 - General issues trying to use classes CFReadStream and CFWriteStream
Summary: General issues trying to use classes CFReadStream and CFWriteStream
Status: CONFIRMED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll (show other bugs)
Version: XI 8.10
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Manuel de la Peña
URL:
Depends on:
Blocks:
 
Reported: 2015-06-16 15:55 UTC by Jon Goldberger [MSFT]
Modified: 2017-02-27 16:30 UTC (History)
4 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments

Description Jon Goldberger [MSFT] 2015-06-16 15:55:28 UTC
## Description

Trying to port some code to use VOIP with UDP and to keep playing the VOIP audio while the app is backgrounded. The issues I have come across are:

1. CFWriteStream's constructor is "internal" while CFReadStream's constructor is public.

2. Both have a DoSetProperty override that is protected, so I can not access this method in order to get to the private P/Invoked method CFReadStreamSetProperty

3. Tried subclassing CFReadStream and making a public method to in turn call DoSetProperty, but once I had this subclass, I am unable to pass an instance of this subclass into another method that takes a CFReadStream and CFWriteStream as out parameters:
CFStream.CreatePairWithSocketToHost(new System.Net.IPEndPoint(new System.Net.IPAddress(new byte[]{127,0,0,1}), 1111), out readStream, out writeStream);
where readStream is an instance of a subclass of CFReadStream, I get a compiler error that MyCFReadStream can not be implicitly converted to a CFReadStream, but casting it to a CFReadStream causes a compiler error, so:
CFStream.CreatePairWithSocketToHost(new System.Net.IPEndPoint(new System.Net.IPAddress(new byte[]{127,0,0,1}), 1111), out (CFReadStream)readStream, out writeStream);
causes error "a ref or out argument must be an assignable variable."


##

Might be able to avoid CFStream classes for the use case that this came up in and just use NSStream which seems to "work as expected" as far as having access to the needed methods, etc.
Comment 1 RogerH 2015-08-10 16:15:49 UTC
I also have a need for CFReadStreamSetProperty and CFWriteStreamSetProperty.

I am already using NSStream in my iOS app for normal sockets and for SSL/TLS sockets.

I want to use NSStream with a secure socket to a remote server which has a self signed certificate.
There are extra properties which can be given to the CFReadStream and CFWriteStream.

Obj-C code from a Blog tells me to implement something like this

NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
 kCFNull,kCFStreamSSLPeerName,
nil];
            
CFReadStreamSetProperty((CFReadStreamRef)inStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
CFWriteStreamSetProperty((CFWriteStreamRef)outStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);


It looks like the CFReadStreamSetProperties (and CFWriteStreamSetProperties) cannot be called from my application.
Comment 2 David Lilley 2016-10-13 14:20:03 UTC
DoSetProperty &
Comment 3 David Lilley 2016-10-13 14:46:50 UTC
I also think they should be made public  I am using to connected to home webdav servers and often they have self signed cert, which I need to set to be allowed to use. of course the user is made aware of ignoring ssl checks.

beside CFReadStream does not use DoSetProperty itself so pointless to be protected

For those are interested my work around.

NSDictionary aDictionary = NSDictionary.FromObjectAndKey (NSNumber.FromBoolean(false), new NSString("kCFStreamSSLValidatesCertificateChain"));
                    _CFReadStreamSetProperty (aStream, new NSString ("kCFStreamPropertySSLSettings"), aDictionary);
 
...


//https://github.com/xamarin/xamarin-macios/blob/master/src/CoreFoundation/CFReadStream.cs
 [DllImport (Constants.CoreFoundationLibrary)]
        [return: MarshalAs (UnmanagedType.I1)]
        extern static /* Boolean */ bool CFReadStreamSetProperty (/* CFReadStreamRef */ IntPtr stream, /* CFStreamRef */ IntPtr propertyName, /* CFTypeRef */ IntPtr propertyValue);

        bool _CFReadStreamSetProperty (CFReadStream aStream, NSString name, INativeObject value)
        {
            if (name == null)
                throw new ArgumentNullException ("name");
            return CFReadStreamSetProperty (aStream.Handle, name.Handle, value == null ? IntPtr.Zero : value.Handle);
        }
Comment 4 Manuel de la Peña 2017-02-27 16:30:22 UTC
Hello,

I agree, there is no actual reason for it to be protected, I'll update the source to expose the method AND will make sure that the property keys are accessible via Fields.

Thx for the bug report.

Note You need to log in before you can comment on or make changes to this bug.