Difference b/w self.packetFlow.ReadBytes vs socket read - ios

I am trying to read data from packet tunnel NEPacketTunnelProvider.
Right now what i am doing is trying to read the data using
self.packetFlow.readPackets { [weak self] (packets: [Data], protocols: [NSNumber]) in }
function.
It seems to be working fine. But now i want to read the packets by using the network handle of self.packetFlow function like this
let tunFd = self.packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int32
and use this file descriptor to read the packet data from the tunnel. like this
char *buffer1 = malloc(1024);
ssize_t length = read(tunFd, buffer1, 1024);
But now when i read the data from socket like this. It seems like data is not similar to what i am receiving earlier using the self.packetFlow.
Does anybody else know why it is happening. and what should i do get the similar data as in self.packetFlow.readPackets..
Any pointer of help will be appreciated.

I found the answer or my own query. There are 4 bytes of extra protocol information added to the data while we use file descriptor. We need to handle it as well.

Related

Swift Core Bluetooth communication with OBD2

I'm trying to observe velocity of my car using an OBD2, to try if the hardware works i had use the app "Auto Doctor" and it works.
But i need some more features and so i started to create my own application
To send command to the characteristic i use the following code:
var commandSended = String() {
didSet {
if let peripheral = self.peripheralConnected {
for char in characteristicConnected {
peripheral.writeValue(self.commandSended.data(using: .utf8)!, for: char, type: .withoutResponse)
peripheral.writeValue(self.commandSended.data(using: .ascii)!, for: char, type: .withoutResponse)
peripheral.readValue(for: char)
}
} else {
self.myTerminal.printToTerminalCommand("You are not connected to the peripheral")
}
}
}
characteristicConnected: are all the characteristic found
Independently which command i send to the characteristic i receive every time the same amount of byte and i can't decode it using utf8 or ascii.
I hope I have supply you enough information.
The answers from (almost all) OBD2 adapters are ASCII string responses, so you need to decode the NSData into ASCII. To extract the actual payload for your responses, you need to learn about decoding the various car protocols. A lot of this information is freely available on the web, for some things you might want to buy the official SAE standards.
That said, even though you are using Swift, you might be interested in using an OBD2 library that does all the heavy lifting for you. As a matter of fact, I wrote one, which you can download at https://github.com/mickeyl/LTSupportAutomotive.
Update: And since then I rewrote something similar in Swift, which might be even more interesting for you. Please have a look at https://github.com/Cornucopia-Swift/CornucopiaUDS

How can I achieve a socket call like this in iOS (Swift or ObjectiveC)?

This is the code in Java to make the socket call, but I want to know how can I replicate this or something similar in iOS (Swift or Objective-C)
public String MakeSocketRequest() {
DataInputStream inputSt;
DataOutputStream outputSt;
Socket socket = new Socket(InetAddress.getByName("socketurl.io"), 40008);
String jsonStr = "{\"id\":1,\"method\":\"themethod\"}";
inputSt = new DataInputStream(socket.getInputStream());
outputSt = new DataOutputStream(socket.getOutputStream());
PrintWriter pw = new PrintWriter(outputSt);
pw.println(string);
Log.d("PrintWriter", jsonStr);
pw.flush();
BufferedReader bfr = new BufferedReader(new InputStreamReader(inputSt));
JSONObject json = new JSONObject(bfr.readLine());
Log.d("Json", json.toString());
inputSt.close();
outputSt.close();
return json.toString();}
If you want to do it natively without 3rd-party libraries,
then you can use CFStreamCreatePairWithSocketToHost function to create input and output streams (no socket object is needed).
Here's some example code to set this up
And the search shows many more
On iOS you can't write or read the streams immediately, and you have to wait until the socket is connected, and you get a permission to read/write. This is done by implementing NSStreamDelegate.
If you get NSStreamEventHasSpaceAvailable event there, you can write your string to the output stream. You don't need a PrintWriter to just write a string, because it is easy to convert NSString to NSData, and write NSData.
If you get NSStreamEventHasBytesAvailable event, means you can try to read data from the input stream to some buffer (like NSMutableData). There's no builtin BufferedReader with a readLine method, so you will have to buffer the data yourself and detect when a new line character appears there. After that you can cut a part of the buffer until the new line, and convert NSData to NSString (or a JSON object by using NSJSONSerialization).
Note: scheduleInRunLoop calls might look confusing, but they are required to start receiving events via the delegate. It kind of tells the system on which thread you want to receive them.
P.S. I agree with commenters that if you have control over the server code, it's better to use a standard protocol like Socket IO or msgpack instead of inventing your own, because they have better and nicer libraries and wider community support.

Convert BLE 4.0 data into usable information using Swift (iOS)

This is my first BLE project using swift and would greatly appreciate any direction you guys have out there. My arduino is using a red bear lab BLE mini to send integers (between 1 and 1200) from a sensor to my iPhone app. I am able to find and connect to the device and transfer the data. I, at least for the past three days, cannot figure how to convert that data back to usable information.
For example in the didUpdateValueForCharacteristic function if I print:
print(characteristic.value!.bytes)
I get a return that looks like:
0x000000013cdb5f80
If I were to print characteristic.value! I would get something that looked like:
<hc>
It seems that I've read everything on the internet about this and still cannot figure out how to get this reading back to the integer being sent. It would be greatly appreciated if someone would be willing to give me some guidance here.
Thanks in advance!
UPDATE: Based on the feedback I'm posting some code that I've used but is not returning what I need. I've attempted to turn the value into an integer using the following:
var out : NSInteger = 0
let data = NSData(bytes: characteristic.value!.bytes, length: sizeof(NSInteger))
data.getBytes(&out, length: sizeof(NSInteger))
print("Integer: \(out)")
This returns the integer 64816. I'm expecting a number between 0 and 1200 so this is either wrong or I'm missing a step.
I've also attempted to turn the data into a string using:
var string1 = NSString(data: characteristic.value!, encoding: NSUTF8StringEncoding) as! String
print("String: \(string1)")
This just unwraps a nil value and crashes.
First confirm they type of object being returned. The value property is of NSData type, so you can use the following code to convert it to NSString.
- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
Finally after three days of struggling I figured this out. Answer had nothing to do with the swift code. Instead my baud rate on the arduino was too slow. Increasing this solved everything.

PRNG in iOS KeyChain

My boss is asking me, which PRGN (Pseudo Random Number Generator) is using our iOS App for encrypting and decrypting data.
We are using the native KeyChain services for storing the data and I don't know what to answer since we are using the KeyChainItemWrapper for accessing the single items i.e. password, ports, etc. in our App and there is not too much reference about this.
I already debugged the app to see if I find something but I couldn't find something yet.
Any help would be appreciated,
thanks
If you need random bytes as opposed to a a random number:
randomBytes: returns count random bytes in *bytes, allocated by the caller.
Returns 0 on success or -1 if something went wrong, check errno to find out the real error.
#import <Security/Security.h>
+ (NSData *)randomBytes:(size_t)count
{
NSMutableData *data = [NSMutableData dataWithLength:count];
SecRandomCopyBytes( kSecRandomDefault,
data.length,
data.mutableBytes);
return data;
}
Be sure to add the Security framework.

How to send structure data in socket programming?

I'm studying c socket programming lately,so I write an example for practice of Client–server model. I use structure as message data to send to server, server processes the data. when i run in the IOS simulator, it's right, but in the device it's wrong, I find that the structure data which the server receives from the devices client is different from the client message data! I'm sorry my English is very bad.
my structure code is:
typedef struct Message
{
char msg[4000];
char name[256];
bool isBroadcast;
bool islogin;
USER userInfo;
}__attribute__((packed)) MessageType;
user code is :
typedef struct user
{
int id_number;
char name[256];
char password[20];
char *p_chatlog;
struct sockaddr user_addr;
int sock;
} __attribute__((packed)) USER;
send code is :
MessageType *loginMsg = (MessageType *)malloc(sizeof(MessageType));
bzero(loginMsg, sizeof(MessageType));
loginMsg->islogin = true;
const char *name_str = [userName.text UTF8String];
memcpy(&(loginMsg->userInfo.name), name_str, strlen(name_str));
const char *password_str = [password.text UTF8String];
memcpy(&(loginMsg->userInfo.password), password_str, strlen(password_str));
write(m_sock, loginMsg, sizeof(MessageType));
free(loginMsg);
server receive code use read() function, then make the receive chars transform structure type.
I would suggest that you make sure you send the data in network byte order; use the htonl, htons and ntohl, ntohs system functions. Different devices may well be a different endianness. Also, you probably shouldn't just send a struct over the network, even in network byte order, you would be better devising a simple protocol to send the data you require - it's more maintainable and flexible. You also can't guarantee your write has sent all of the data you requested, you should check the return results of both your read and write to ensure you have the amount you expect.
Incidentally, it is recommended to avoid the POSIX networking library for iOS and use the native implementation where possible.

Resources