Raknet connection issue on Unity3D + iOS (il2cpp) - ios

I have weird issue running the last version of Raknet on iOS with Unity3D: I get CONNECTION_ATTEMPT_FAILED when trying to connect to the server.
Now let's me detail the issue:
he exact same Library connects fine when used in an ObjectiveC application, so the issue seems to be Unity3D related.
I already managed to pinpoint my issue to be located in Raknet reliability layer:
Apparently, during the last step of the connection process (when the connection handshake as been completed) the reliability layer of the server thinks that the ID_CONNECTION_REQUEST packet received from the client is an acknowledgment instead of a message. Therefore it doesn't answer. Ultimately after a few tries, (and a 10s timeout) the client fails with the CONNECTION_ATTEMPT_FAILED error.
Does anybody there as an idea? I will update the question when I manage to get more info.
Update
We are using Unity3D 5.1.1f1
We managed to find a workaround! See answer for more information. As the workaround doesn't tell us much about what really happened, I would gladly hear some C++/XCode/Unity/iOS/AppleLLVM6.1 experts around here explain what really happened.

The issue was that the Raknet header wasn't properly generated by the iOS client. Namely we were sending ACK messages in place of simple packets. The rest of the message was considered as garbage by the server and the packet was dropped. The client kept trying to send the corrupted handshake packet a few times before timeouting.
This doesn't tell us why, doesn't it? Apparently the serialize method of the class DatagramHeaderFormat wasn't called as it should have been when running Raknet in Unity (iOS). Something else (and I don't know what) was linked in place of this method and was filling the BitStream with a corrupted header.
I am quite sure that the serialize method wasn't called because printf calls from inside weren't displayed in the console.
We renamed DatagramHeaderFormat::serialize into DatagramHeaderFormat::serializeHeader and... voila, it works.
Now I only want to understand what did the compiler (and why).

Related

Bonjour/NSNetService Data written to NSOutputStream never makes it to the other side (includesPeerToPeer = true)

I have an iOS app that establish a peer-to-peer connection through Bonjour/NSNetService. (based on the WiTap sample code)
In some cases, both devices won’t receive data anymore after a few seconds while they are still able to write data out (i.e. without an error being reported).
The data written to the NSOutputStream never makes it to the NSInputStream of the other side.
The strange part is that sending and receiving works right after the connection is established. It seems to go bad after a few seconds.
If I set includesPeerToPeer = false it is not happening anymore. Does anyone having the same issue? I need to use peer to peer because is required to use bluetooth.
Thanks
My first guess would be that you're writing data to the stream before you get a stream event telling you that it is ready to accept more data.
If that isn't the problem, then either it's a bug in your code (which you haven't posted any of) or... well, it is possible that the class in question still doesn't work correctly. See:
https://developer.apple.com/library/ios/qa/qa1546/_index.html
If that's the case, you might have to drop down to Core Foundation briefly.

Detecting a closed connection

I have an Grails application which does the following:
When a request is received from the client side, the server starts creating a zip file for that request and sends it back to the client machine. The amount of time the server takes in order to create the zip file is very high, and even though the connection is lost between the client and the server, the zip file is generated by the server continuously for 3 days or so, using 100% of the CPU, and sending the response somewhere, probably a dead-end.
I tried looking out a way to resolve this, and I find that socket programming is a way in order to detect the connection loss.
This question may look broad, but I just want to know the ways, a connection loss can be found out, so that I can dig around that approach and find out the solution.
Check if the object holding the results of the connect() method is null.
You can also wrap a try catch statement around the code that attempts the connection, and print out the exception if it fails so you know where/what happened.

Detect "Delay write failed" occurence

I am loosing my patience with "delay write failed" errors. It silently disconnects the database from the application so nothing gets saved in the database while using it. Is there a way to detect the occurrence itself so I can flash a warning ? Or perhaps monitoring the connection itself for a disconnection ? Everyone seems to miss the balloon tip from the Windows XP so I figured to flash a more visible warning that the application must be restarted. It seems Microsoft has found a way to force people to upgrade....
I suppose this could be done with a timer and constantly check connected users:
cxlabel1.Caption := IntToStr(DataModule2.ABSDatabase1.GetDBFileConnectionsCount);
But I was thinking more of checking/detecting for the occurence itself. Is there something in Delphi that can detect this?
I would like to hear your ideas on this...
Putting this as an answer because the comment length is limited.
I have seen this before. IIRC, the problem you have is that the Delayed Write Error is an OS error, it has nothing to do with your application. Windows has already told you that the write has been committed correctly to disk. You would have to try and hook into the OS errors to see when this is happening.
You need to get the network issues resolved because that's where the problem is. In our situation it was a faulty router that was causing the problem.
It's unfair to expect users to check for the error message and then handle it. They could be out at lunch when it occurs as it's not immediate. They also have no way of know what has been saved and what hasn't. It's only a matter of time before your database is corrupted.
The problem with a timer is that it might tell you everything is fine because it triggers after the network resolves the problems.
A far better approach would be to switch to a Client/Server database. You can do this by setting up your own server that listens for web service or another remote call or switch to a database that supports client/server instead of using a file based database. This will tell you immediately when there is a problem with the save of data.

BlackBerry Connection Transport Descriptors

I'm wondering if someone could point me in the right direction for this problem. A bit of introduction:
In an app we maintan we just rewrote our network layer to remove support for OS 4. We're using the cleaner ConnectionFactory provided in OS 5. Please note the issues we're encountering are device-only, not simulator related.
There are two ways or app has connectivity, a data thread that polls specific urls and stores data, and a "generic web view" (a BrowserField).
So far it seems there's no problems with the data thread connectivity, it properly builds the urls based off transport type and downloads the data correctly. In the BrowserField we have a different problem. There's an OS 6 curve causing problems (no other OS 6 device though) when we open the BrowserField with a URL there's a chance it will show a "Could not select proper transport descriptor" message - the most common culprit is WAP2.
I guess we're a bit baffled that BlackBerry doesn't seem to handle the transport descriptor choosing as well as we had hoped. Does anyone have any recommendations?
Due to its length, I've posted our connection utility class on gist: https://gist.github.com/3490101
The most common connection form, used by the data thread, is the getUrlAsString(String etag) function, which does a GET and caches the response based off the etag/url.
To build URLs for our BrowserField we use the buildURLTransport(String url) function, which gets a connection on the url, determines the transport information, and returns the built URL.
TL;DR: There's an oddity in a BrowserField we can't seem to debug, we'd appreciate a new set of eyes: we think there's something wrong in the above posted gist in the buildURLTransport(String url) function.
Thanks a tonne in advance.
Be careful with your code because getUrlAsString isn't thread safe. I didn't understand why you keep reference to the ConnectionFactory sometimes why you don't for other.
I aslo didn't understand why do you need method buildUrlTransport. Why don't use BrowserFieldConfig together with ConnectionFactory for BrowserField as here.
So I would instantiate one ConnectionFactory, configure it with your specific parameters and use it everywhere. In case of preferences change I would recreate ConnectionFactory and update BrowserFieldConfig. Sure this code should be thread safe.
Also be more consistent - sometimes you use quick connection check, sometimes you don't.

Blackberry application works in simulator but not device

I read some of the similar posts on this site that deal with what seems to be the same issue and the responses didn't really seem to clarify things for me.
My application works fine in the simulator. I believe I'm on Bold 9000 with OS 4.6. The app is signed.
My app makes an HTTP call via 3G to fetch an XML result. type is application/xhtml+xml.
In the device, it gives no error. it makes no visual sign of error. I tell the try catch to print the results to the screen and I get nothing.
HttpConnection was taken right out of the demos and works fine in sim.
Since it gives no error, I begin to reflect back on things I recall reading back when the project began. deviceside=true? Something like that?
My request is simply HttpConnection connection = (HttpConnection)Connector.open(url);
where url is just a standard url, no get vars.
Based on the amount of time I see the connection arrows in the corner of the screen, I assume the app is launching the initial communication to my server, then either getting a bad result, or it gets results and the persistent store is not functioning as expected.
I have no idea where to begin with this. Posting code would be ridiculous since it would be basically my whole app.
I guess my question is if anyone knows of any major differences with device versus simulator that could cause something like http connection or persistent store to fail?
A build setting? An OS restriction? Any standard procedure I may have just not known about that everyone should do before beginning device testing?
Thanks
Just providing the URL will not work. You will have to append some info after the URL to determine the transport method your HTTP connection will use. For instance http://example.com;deviceside=true will use DirectTCP (you might also have to supply APN information but that's saved on the device for my phone). http://example.com;interface=wifi will use wi-fi. On OS 5 there's a ConnectionFactory class that makes this a lot easier. Here's a link that goes into more detail.
This was a tough one for me!
As Jonathan said you have to put some parameters in the url to make it work on the device. You shouldn't do it by hand but use the ConnectionFactory instead.
As you may thing this would just make it work but it doesn't!
The real problem is that not the url has been altered because it has ;interface=wifi;deviceside=true in it (in my case). Depending on the webserver accepting your request this could broke the code.
A solution I tried and that works is try to happend a fake parameter like
&foo=true -> &foo=true;deviceside=true
This will result as a standard parameter for the webserver but your device would use it to driver your connection.
On the simulator this work without this extra code because behind it there is a BIS server for you. On the device (as in my case) there isn't because I'm using a development device unregistered and without SIM (just wifi).
Another point is that the HttpConnection class doesn't handle HTTP 302 Redirect and if you get one you have to handle it manually.
It's probably an issue with the APN not being specified. See my answer for this question for details:
video streaming over http in blackberry
I would make this a comment, but I think I don't have enough rep yet for that... So I'll just answer and hope this doesn't get hosed for just pasting in some links.
I've been working on this exact sort of networking issue on our app this past week, and it is indeed tricky as some others have pointed out. Here are two links which really helped us out using HTTP on different devices, especially older devices which do not provide ConnectionFactory.
http://supportforums.blackberry.com/t5/Java-Development/Connecting-your-BlackBerry-http-and-socket-connections-to-the/td-p/206242
The first one has some code examples, including demonstration of querying the system's ServiceBook and CoverageInfo classes to make a decision about what kind of connection will work.

Resources