Date   

Re: APFS & FileSystem attributes

 


On Aug 15, 2017, at 8:25 AM, 2551phil <2551phil@...> wrote:

I’ve had my head stuck in the sand as far as APFS is concerned (I don’t have the hardware to test it) and only just today suddenly wondered: “hell, it is going to mess up all my FileSystem calls is it?"

It wouldn’t be a valid filesystem if it didn’t support the system calls like stat() that NSFileManager uses to get file attributes.

Now, not every filesystem supports every attribute (you’re not going to get file reference counts on a FAT volume), but since APFS was explicitly designed as the successor to HFS+, I’m pretty certain it supports everything HFS+ does.

—Jens


Re: APFS & FileSystem attributes

Sean McBride
 

On Tue, 15 Aug 2017 22:25:41 +0700, 2551phil said:

I’ve had my head stuck in the sand as far as APFS is concerned (I don’t
have the hardware to test it)"
You could presumably test it in a VM, or using a spare old external drive or USB key, or even just create a disk image. You don't need an extra Mac whose boot disk can be wiped.

Sean


Understanding NSNetService and peer-to-peer streaming

Graham Cox
 

Hi all,

I’m trying to add a peer-to-peer communication feature to a game I’m developing.

So far it’s half working, which given the paucity of documentation, I’m actually quite proud of…

Because it’s peer-to-peer, any app can act as both client and server, so getting straight which bit is doing what is quite hard. But for the sake of discussion, I’ll call the service that initiates a connection the server, and the app that receives it the client.

I’m using NSNetService and NSNetServiceBrowser to act as an interface to Bonjour to discover other copies of my game on the network. This part works well - I can advertise myself as a service, and I can receive notifications of other identical services. The ’server' NSNetService receives a -netService:didAcceptConnectionWithInputStream:outputStream:, and schedules those streams in the main run loop and opens them. The ‘server’ also implements -netServiceBrowser:didFindService:moreComing: to wrap the NSNetService representing the client and its streams in a ‘remote player’ object for that client.

I can use the ‘remote player’ object to send data to the client via the streams associated with its NSNetService.

The client receives the data OK, as the stream delegate’s -stream:handleEvent:

So far, so good. But now I need to return data to the ‘server’ peer. The problem is, I don’t know which stream I need to use to do that. When the ‘server’ accepts a connection, it is handed two streams, which are presumably the ones to use. The problem I have is that these streams are just naked streams - there is no associated information that will tell me which ‘client’ they are connected to. At the moment I just schedule these streams in a run loop and open them, and set my general ‘server’ to be their delegate, which is how I am able to receive the data. But given that there will be a pair of these for every connected server, I don’t know which stream to use to return data to a specific server.

I have the idea that what I should do is to wrap the stream pair in another object so I can keep them separate, but that still leaves the problem of identifying that object as being a particular server. I can send that identifying information over the stream the first time I use it, and the ‘client’ can then add that information to the server object, but that seems like a kludge - it is relying on my private protocol to pass information that should already be known to the basic NSNetService infrastructure.

If you’ve followed this, kudos to you. It’s hard to keep straight who is the client and who is the server, to be honest. But even with that muddle, I feel I’m missing something.

If anyone has done something like this successfully and can offer any insights, I’d be most grateful.

—Graham


Re: Understanding NSNetService and peer-to-peer streaming

Quincey Morris
 

On Aug 16, 2017, at 21:24 , Graham Cox <graham@...> wrote:

The problem is, I don’t know which stream I need to use to do that.

I recommend you ask this question in the hated-by-some developer forums (forums.developer.apple.com). Quinn the Eskimo fields questions there most days, and he’s exactly the person to give you the answer. (You might find him on the Apple listserver list for networking too, but I don’t subscribe there.)


Re: Understanding NSNetService and peer-to-peer streaming

 


On Aug 16, 2017, at 9:24 PM, Graham Cox <graham@...> wrote:

So far, so good. But now I need to return data to the ‘server’ peer. The problem is, I don’t know which stream I need to use to do that. When the ‘server’ accepts a connection, it is handed two streams, which are presumably the ones to use. The problem I have is that these streams are just naked streams - there is no associated information that will tell me which ‘client’ they are connected to.

Right. You need to keep track of that yourself, like with a Peer class that can hold onto those streams and act as their delegate.

I have the idea that what I should do is to wrap the stream pair in another object so I can keep them separate, but that still leaves the problem of identifying that object as being a particular server. I can send that identifying information over the stream the first time I use it, and the ‘client’ can then add that information to the server object, but that seems like a kludge - it is relying on my private protocol to pass information that should already be known to the basic NSNetService infrastructure.

NSNetService doesn't really have anything to do with those streams. All Bonjour does is service discovery: it can advertise a service you're running on some port, and it can find other services of a given type. When it resolves a service it gets the IP address and port number. But that's all Bonjour does.

When you ask an NSNetService to open a connection, it just resolves the service and then calls an NSStream factory method to open a TCP socket to that IP address / port. Then it returns you the resulting streams. Its job is done. This is just a convenience method that was added later on to simplify connecting to services.

Once you've opened the streams, you can remember the name of the service that you got them from. Or you can have a protocol that sends the peer name or UUID or whatever over the socket when it opens; it's up to you.

—Jens

PS: What you're implementing sounds exactly like what the Multipeer Connectivity framework does. Are you aware of it? You could probably save yourself a ton of work by using it.


How to store C Arrays as a Property or iVar?

Dave
 

Hi All,

I’ve converted some C code into Objective-C and have some C Array structures like so:

int [10][10]) myArray;

That I want to store in a Property or iVar inside a Wrapper Class. How do I do this?

I’ve tried:


@interface WrapperClass : NSObect
{
int [10][10]) mArray;
}

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

or

_mArray = myArray;


Thanks a lot
All the Best
Dave


Re: How to store C Arrays as a Property or iVar?

Alex Zavatone
 

You can save them as NSIntegers in an NSMutableArray.

The thing about NSDictionaries and NSArrays is that they need to contain NSObjects that are Cocoa Collections.


Someone please correct me if I’m tragically misguided.

But try that, Dave.

Cheers,
Alex Zavatone

On Aug 18, 2017, at 2:07 PM, Dave <dave@...> wrote:

Hi All,

I’ve converted some C code into Objective-C and have some C Array structures like so:

int [10][10]) myArray;

That I want to store in a Property or iVar inside a Wrapper Class. How do I do this?

I’ve tried:


@interface WrapperClass : NSObect
{
int [10][10]) mArray;
}

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

or

_mArray =  myArray;


Thanks a lot
All the Best
Dave






Re: How to store C Arrays as a Property or iVar?

Pascal Bourguignon
 


On 18 Aug 2017, at 21:07, Dave <dave@...> wrote:

Hi All,

I’ve converted some C code into Objective-C and have some C Array structures like so:

int [10][10]) myArray;

That I want to store in a Property or iVar inside a Wrapper Class. How do I do this?

I’ve tried:


@interface WrapperClass : NSObect
{
int [10][10]) mArray;
}

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

or

_mArray =  myArray;


Yep.

Objective-C is C.

You have to know C to be able to program in Objective-C.

In C, arrays are not first class objects.  So you cannot use = to copy arrays (or to take a reference to an array, there’s no such notion in C).

The solution is to write a loop to copy the elements.

void copy_my_array(int src[10][10],int dst[10][10]){
    for(int i=0;i<10;++i){
        for(int j=0;j<10;++j){
            dst[i][j]=src[i][j];}}}

then use:

copy_my_array(myArray,_myArray);

-- 
__Pascal J. Bourguignon__




Re: How to store C Arrays as a Property or iVar?

Jack Brindle
 

Can you publish the actual declarations for myArray and mArray? The ones you show aren’t quite legal and
will be rejected by C compilers.

There isn’t that much different from regular C. In your code, you are not creating a property, but rather an instance variable.
Thus it does not create anything named _mArray. If you created an @property var then the _mArray might work.
Struct assignment does work in Objective C. I don’t remember that arrays may be copied, though. Might that be a C++ extension?

- Jack

On Aug 18, 2017, at 12:07 PM, Dave <dave@...> wrote:

Hi All,

I’ve converted some C code into Objective-C and have some C Array structures like so:

int [10][10]) myArray;

That I want to store in a Property or iVar inside a Wrapper Class. How do I do this?

I’ve tried:


@interface WrapperClass : NSObect
{
int [10][10]) mArray;
}

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

or

_mArray = myArray;


Thanks a lot
All the Best
Dave




Re: How to store C Arrays as a Property or iVar?

 


On Aug 18, 2017, at 12:07 PM, Dave <dave@...> wrote:

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

You can't assign (or compare) arrays in C/C++. You have two options:

(a) Call memcpy:
memcpy(&myArray, &_mArray, sizeof(myArray));

(b) Wrap a struct around the array, since structs are copyable. Drawback is that you now have to refer to the array as a named field of the struct.
typedef struct {
int [10][10]  a;
} MyArrayType;
MyArrayType myArray;
_mArray = myArray;

(This is a pure C issue, so a book like K&R would be helpful.)

—Jens


Re: How to store C Arrays as a Property or iVar?

Alex Zavatone
 


On Aug 18, 2017, at 3:04 PM, Jens Alfke <jens@...> wrote:


On Aug 18, 2017, at 12:07 PM, Dave <dave@...> wrote:

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

You can't assign (or compare) arrays in C/C++. You have two options:

(a) Call memcpy:
memcpy(&myArray, &_mArray, sizeof(myArray));

(b) Wrap a struct around the array, since structs are copyable. Drawback is that you now have to refer to the array as a named field of the struct.
typedef struct {
int [10][10]  a;
} MyArrayType;
MyArrayType myArray;
_mArray = myArray;

(This is a pure C issue, so a book like K&R would be helpful.)

—Jens
_._,_._,_

In that light, is my suggestion useless overhead?



Re: Understanding NSNetService and peer-to-peer streaming

Graham Cox
 

On 18 Aug 2017, at 9:03 am, Graham Cox <graham.cox@...> wrote:

PS: What you're implementing sounds exactly like what the Multipeer Connectivity framework does. Are you aware of it? You could probably save yourself a ton of work by using it.
No, I’ve not heard of it. I did google for possible solutions, but it invariably finds a bunch of Stackoverflow questions, mostly without useful answers. I’ll check it out now I have a name to go by, though actually I’ve solved 90% of my problem and the remaining 10% is clear enough now.

This is a follow-up to my question last week.

I got my NSNetService + Streams approach more or less working, with one small problem (i’ll get to that).

But I also checked out Multipeer Connectivity (MC) and rolled a solution around that as well. The problem I’m running into with MC is that of testing it. While I have multiple devices to test it on, it’s very inconvenient to do that. I’d far rather test it on a single machine if possible. With the NSNetService design, it was quite happy to ‘see’ itself as another peer on the network, and allow a connection, making testing it on the one machine straightforward.

MC seems to go out of its way to prevent that, which on the surface makes sense, because in production you DON’T want your own machine to show up as a remote peer. But it makes testing it really hard. To try and work around it, I tried browsing and advertising using two different MCPeerID objects, with different names. That appears to work, in that the browser sees the advertised service on the same machine as another peer. Unfortunately, it completely fails after the discovery phase to actually connect. So I can test the discovery phase, but not the real meat of the thing, which is the communication.

Does anyone have any experience of MC and know how this can be made to work, or what are good approaches to testing, preferably on a single machine?

At this point the NSNetService design is functioning to a greater degree, because I can connect, even on the same machine. But the problem I’m having there is because it is stream based, I’m finding it difficult to implement something like MC’s message-based approach to communicating. If I send two ‘messages’ too quickly, they get concatented on the stream, and the receiver can’t tell where the boundary is between the two (or more) messages. So if I can solve that problem, it’s likely that the non-MC design will be the one to use, because it actually works in all other respects.

So, how to separate messages that just end up as a stream of bytes? I was thinking I could precede each one with a length field, which seems the simplest idea, assuming that I can be sure I can align the received stream to some sort of ‘frame’, so I can be sure the length field is where I think it is. But if you have any other clever ways, please share!

—Graham


Re: Understanding NSNetService and peer-to-peer streaming

Jack Brindle
 

One suggestion for testing on a single machine is to use VMware Fusion to create multiple macOS VMs. You will want a system with decent speed, but the environment should do exactly what you need with just one physical system.
Note that the current version of Fusion does not yet support High Sierra, so you will need to limit testing to Sierra and below.

- Jack

On Aug 20, 2017, at 7:00 PM, Graham Cox <graham@...> wrote:


On 18 Aug 2017, at 9:03 am, Graham Cox <graham.cox@...> wrote:

PS: What you're implementing sounds exactly like what the Multipeer Connectivity framework does. Are you aware of it? You could probably save yourself a ton of work by using it.
No, I’ve not heard of it. I did google for possible solutions, but it invariably finds a bunch of Stackoverflow questions, mostly without useful answers. I’ll check it out now I have a name to go by, though actually I’ve solved 90% of my problem and the remaining 10% is clear enough now.

This is a follow-up to my question last week.

I got my NSNetService + Streams approach more or less working, with one small problem (i’ll get to that).

But I also checked out Multipeer Connectivity (MC) and rolled a solution around that as well. The problem I’m running into with MC is that of testing it. While I have multiple devices to test it on, it’s very inconvenient to do that. I’d far rather test it on a single machine if possible. With the NSNetService design, it was quite happy to ‘see’ itself as another peer on the network, and allow a connection, making testing it on the one machine straightforward.

MC seems to go out of its way to prevent that, which on the surface makes sense, because in production you DON’T want your own machine to show up as a remote peer. But it makes testing it really hard. To try and work around it, I tried browsing and advertising using two different MCPeerID objects, with different names. That appears to work, in that the browser sees the advertised service on the same machine as another peer. Unfortunately, it completely fails after the discovery phase to actually connect. So I can test the discovery phase, but not the real meat of the thing, which is the communication.

Does anyone have any experience of MC and know how this can be made to work, or what are good approaches to testing, preferably on a single machine?

At this point the NSNetService design is functioning to a greater degree, because I can connect, even on the same machine. But the problem I’m having there is because it is stream based, I’m finding it difficult to implement something like MC’s message-based approach to communicating. If I send two ‘messages’ too quickly, they get concatented on the stream, and the receiver can’t tell where the boundary is between the two (or more) messages. So if I can solve that problem, it’s likely that the non-MC design will be the one to use, because it actually works in all other respects.

So, how to separate messages that just end up as a stream of bytes? I was thinking I could precede each one with a length field, which seems the simplest idea, assuming that I can be sure I can align the received stream to some sort of ‘frame’, so I can be sure the length field is where I think it is. But if you have any other clever ways, please share!

—Graham






Re: Understanding NSNetService and peer-to-peer streaming

Alex Zavatone
 

On Aug 20, 2017, at 9:10 PM, Jack Brindle <jackbrindle@...> wrote:

One suggestion for testing on a single machine is to use VMware Fusion to create multiple macOS VMs. You will want a system with decent speed, but the environment should do exactly what you need with just one physical system.
Note that the current version of Fusion does not yet support High Sierra, so you will need to limit testing to Sierra and below.

- Jack
This. This. This. This.

Create a VM of your current OS. Duplicate it as needed and make changes to each OS image to suit your needs.

It’s a massive timesaver with fast SSDs.


Re: APFS & FileSystem attributes

2551phil
 

On 16 Aug 2017, at 09:42, Sean McBride <sean@...> wrote:

You could presumably test it in a VM, or using a spare old external drive or USB key, or even just create a disk image. You don't need an extra Mac whose boot disk can be wiped.

You do if you want to test APFS, which is only available for SSD or Fusion disks the last time I checked.

Admittedly, I haven’t yet checked the release notes for the most recent beta, but I've been having problems getting previous betas of HS to install on Parallels anyway.


Best


Phil
@sqwarq


Re: APFS & FileSystem attributes

Alex Zavatone
 

What is HS?

On Aug 21, 2017, at 10:44 AM, 2551phil <2551phil@...> wrote:



On 16 Aug 2017, at 09:42, Sean McBride <sean@...> wrote:

You could presumably test it in a VM, or using a spare old external drive or USB key, or even just create a disk image. You don't need an extra Mac whose boot disk can be wiped.

You do if you want to test APFS, which is only available for SSD or Fusion disks the last time I checked.

Admittedly, I haven’t yet checked the release notes for the most recent beta, but I've been having problems getting previous betas of HS to install on Parallels anyway.


Best


Phil
@sqwarq




Re: APFS & FileSystem attributes

2551phil
 


On 21 Aug 2017, at 22:45, Alex Zavatone <zav@...> wrote:

What is HS?


High Sierra. 


Re: APFS & FileSystem attributes

Steve Mills
 

On Aug 21, 2017, at 10:46 AM, Alex Zavatone <zav@...> wrote:

What is HS?

I'm guessing High Sierra, macOS 10.13. Yet another reason why people should use version numbers and not these silly, meaningless code names.

Sent from iCloud's ridiculous UI, so, sorry about the formatting

 


Re: Understanding NSNetService and peer-to-peer streaming

 


On Aug 20, 2017, at 7:00 PM, Graham Cox <graham@...> wrote:

If I send two ‘messages’ too quickly, they get concatented on the stream, and the receiver can’t tell where the boundary is between the two (or more) messages.

This is a classic newbie networking mistake. (No offense I hope!) TCP is a stream, and there is absolutely no delimiter between writes, and no association between the number of bytes written vs. the number read at the receiver. It's true that if you only intermittently send bytes, the receiver will usually receive the same number of bytes from its read call … but not always, depending on circumstances, because the data can get broken up at arbitrary locations.

To send and receive messages you have to delimit them somehow. The classic ways are to prefix every message with a count, or to have a reserved byte sequence that denotes end-of-message. (Pascal strings and C strings, anyone?) The former is better as long as you know the message length ahead of time. 

So for example, on the sending end just write a 32-bit byte count (big- or little-endian, pick one), then the message. On the receiving end, have a resizable read buffer (an NSMutableData works well) and keep reading bytes into it, growing if necessary. After each read decode the message length at the start, then check if you have that many more bytes in the buffer; if so, hand the message to the higher-level code, then delete the count and the message from the buffer, so what remains starts at the next message boundary. Then check if you've got another complete message, and when you don't, issue another read.

I have a protocol/framework called BLIP that's basically this to the nth power. It does message queueing, multiplexing, high/low priority, message headers (like HTTP), etc. Might be overkill for your needs, but check it out.

—Jens


Re: Understanding NSNetService and peer-to-peer streaming

Graham Cox
 

On 22 Aug 2017, at 2:46 am, Jens Alfke <jens@...> wrote:


On Aug 20, 2017, at 7:00 PM, Graham Cox <graham@...> wrote:

If I send two ‘messages’ too quickly, they get concatented on the stream, and the receiver can’t tell where the boundary is between the two (or more) messages.
This is a classic newbie networking mistake. (No offense I hope!)

None at all! I have very little experience in this area.


TCP is a stream, and there is absolutely no delimiter between writes, and no association between the number of bytes written vs. the number read at the receiver. It's true that if you only intermittently send bytes, the receiver will usually receive the same number of bytes from its read call … but not always, depending on circumstances, because the data can get broken up at arbitrary locations.

To send and receive messages you have to delimit them somehow. The classic ways are to prefix every message with a count, or to have a reserved byte sequence that denotes end-of-message. (Pascal strings and C strings, anyone?) The former is better as long as you know the message length ahead of time.

So for example, on the sending end just write a 32-bit byte count (big- or little-endian, pick one), then the message. On the receiving end, have a resizable read buffer (an NSMutableData works well) and keep reading bytes into it, growing if necessary. After each read decode the message length at the start, then check if you have that many more bytes in the buffer; if so, hand the message to the higher-level code, then delete the count and the message from the buffer, so what remains starts at the next message boundary. Then check if you've got another complete message, and when you don't, issue another read.
Great, I was hoping someone would help me in exactly this way. I thought the length field approach would work, but those with more experience may steer me in a better direction. Good to know I was thinking along the right lines.

The data I’m sending is actually a plist. I am using [NSPropertyListSerialization writePropertyList:toStream:…], which is very convenient. But call it twice and the other end gets confused. It surprised me a little bit because I would have thought that having provided such a convenient method for writing a plist to a stream, the apparently equally convenient inverse method would be able to sort this problem out for itself. But no, it appears not. Which makes me wonder in what case it is useful.

I have a protocol/framework called BLIP that's basically this to the nth power. It does message queueing, multiplexing, high/low priority, message headers (like HTTP), etc. Might be overkill for your needs, but check it out.
I definitely will!

many thanks,

—Graham

181 - 200 of 1475