Swift Send Hex Data Over TCP Socket - swift

I'm working on a solution to send commands to a point of sale receipt printer and having some issues getting the command format right. Ive got a socket open to the device and thats working, because incorrect commands are printed. What the SPEC calls for in this command is to send the following:
1B 07 or in decimal 27 7. Which in ASCII is ESC_KEY BEL. The only example the spec shows is for .NET:
MSComm1.Output = Chr$(&H1B) & Chr$(&H07)
What I've been trying:
// Socket is open previously using CFStreamCreatePairWithSocketToHost.
var cmd = "27 07"
if let dataString = "\(cmd)\r".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false), let oStream = self.outputStream {
self.outputData.append(dataString)
if oStream.hasSpaceAvailable {
oStream.write(UnsafePointer((self.outputData.first! as NSData).bytes), maxLength: self.outputData.first!length)
}
}
The data is getting there, but I think the format of the message is wrong. Any help would be appreciated.

Just create a byte (aka UInt8) array with the data that you want
to send, and pass that directly to the write() method of NSOutputStream:
let cmd: [UInt8] = [0x1B, 0x07]
oStream.write(cmd, maxLength: cmd.count)
Note that you send bytes to the output stream, not hex data.
It makes not difference at all if you create the array with hexadecimal
integer literals as above, or as
let cmd: [UInt8] = [27, 7]
the data is exactly the same.

Related

Converting bytes from UDP Server

I am creating a windows UDP tunnel using wintun driver. I have written a code to receive data from the server and send it to the windows tunnel using the function send_packet and allocatesendpacket. The error I get is that I can read data only as bytes from the UDP server but it causes a mismatch when I pass it to the send_packet function. The error is as follows:
mismatched types
expected struct `wintun::Packet`, found `&[u8]`
Code for send_packet and allocatesendpacket
https://github.com/nulldotblack/wintun/blob/main/src/session.rs
Code for packet struct data type
https://github.com/nulldotblack/wintun/blob/main/src/packet.rs
Link for other dependencies
https://github.com/nulldotblack/wintun
How do I convert the bytes (variable buffer below) to Packet struct data type?. The error of mismatch occurs when I declare the value of a variable packet with the value of the received buffer variable, so that packet variable can be sent to tunnel.
My code:
let socket = UdpSocket::bind("6.0.0.1:8000") //create client socket object with ip and port
.expect("Could not bind client socket");
socket.connect("6.0.0.10:8888") //SERVER IP /PORT
let writer_session = session.clone();
let writer =
std::thread::spawn(move || {
info!("Starting writer");
while RUNNING.load(Ordering::Relaxed) {
let mut buffer = [0u8; 20000];
socket.recv_from(&mut buffer) //get message from server
.expect("Could not read into buffer");
let leng1 = buffer.len();
let mut packet = writer_session.allocate_send_packet(leng1.try_into().unwrap()).unwrap();
packet = &buffer[0..leng1]; //ERROR occurs here
writer_session.send_packet(packet);
}
});
You have two errors the first caused by trying to assign a slice to packet directly which is solved by copying the buffer into packet instead:
packet.bytes_mut().copy_from_slice(&buffer);
The second is that you are not using the length returned by recv_from but instead using the length of the whole buffer which may lead to reading past the end of the read data although memory address is valid. You should do this instead:
let mut buffer = [0u8; 20000];
let (leng1, src_addr) = socket.recv_from(&mut buffer) //get message from server
.expect("Could not read into buffer");
let buffer = &mut buffer[..leng1];
To copy the contents of buffer into packet, you can use slice::copy_from_slice:
packet.bytes_mut().copy_from_slice(&buffer);

Swift: Writing outputStream

I'm testing to connect and send a simple message to a host and I've used this guide http://studyswift.blogspot.com/2016/01/connect-mac-iphone-to-simple-python.html.
So far I'm able to connect to the server and when I tried to write on the output stream .
let data : NSData = "hello".data(using: String.Encoding.utf8)! as NSData
outStream?.write(UnsafePointer<UInt8>(data.bytes), maxLength: data.length)
I got error on write(UnsafePointer(data.bytes), ...
Cannot convert value of type 'UnsafeRawPointer' to expected argument type 'RawPointer'

How to convert bytes to swift array

I need to send an array through HTTP to my swift client but I'm not sure how to convert the bytes I've received to a swift array.
I've looked it up on google multiple times with multiple different ways of saying what I'm trying to do but all I'm getting is topics that say "convert byte array to swift string"
AF.request(exampleUrl).response { response in
if let data = response.data, let s = String(data: data, encoding: .utf8) {
debugPrint(s)
let myArray = decodeSomehow(data: data)
debugPrint(myArray[0]) // hooray
}
}
I need to be able to decode arrays sent from my server but my efforts to find the solution to this problem have yielded no results.
btw server is made with firebase functions and is run on Google frontend
and coded with typescript
also to clarify I do not want to take the bytes and put them into an array, I want to decode the bytes into what they originally were on the server aka an array (originally a typescript array but if it is possible to make it a swift array that would be 👌)
The Data class is an advance version of [UInt8]. Normally, working directly with Data class is recommended. If you really want to convert it to [UInt8], simply
let arr = [UInt8](data)
or
let arr = Array(data)
Hope it helps... (Thanks LEO for your best Comment)
let string = "Hello World"
print(Array(string.utf8))
I figured out how to do what I was trying to do...
In the end, I solved my own problem lol
all I needed to do was decode it with swiftyjson
thank you all for your answers
AF.request(exampleUrl).response { response in
if let data = response.data, let s = String(data: data, encoding: .utf8) {
let arr = JSON(data)
debugPrint(arr)
debugPrint(arr[0][0])
debugPrint(s)
}
}
output

Converting base64 string to hex to readable string: Swift

I am working with some 3rd party data. The data they are returning from our request is suppose to be base64 encoded into a string. They provide these instructions for converting it to a readable format:
*First, converting the Base64 string to hexadecimals using the open-source "tomeko" online tool: http://tomeko.net/online_tools/base64.php?lang=en.
Second, in the SAE J2735 standard, all messages are sent as a MessageFrame. The MessageFrame contains information about which particular type of message is included within the MessageFrame. The proper way to decode the hexadecimals from step #1, is to select MessageFrame under the ASN.1 message in the open-source Marben online decoder tool: http://www.marben-products.com/asn.1/services/decoder-asn1-automotive.html.
*
I'm working on an iPhone app so reaching out to these sites for the conversion is not optimal. I decoded the B64 string into hex with this code:
func convert64EncodedToHex(_ data:Data) -> String {
return data.map{ String(format: "%02x", $0) }.joined()
}
which came back as so:
5B224142 4E464141 41414F51 6F414141 63414545 4E427055 476C5141 45434B67 796C6A4C 49414442 44515A2B 686E3641 4341686F 4D77517A 42414251 51304753 675A4B41 41774961 44536F4E 4B674163 454E426D 43475949 41514347 677A7544 4F34225D
But when I plug that into the Marben decoder it fails:
<error>
<description>Unexpected end of stream reached when decoding</description>
<nature>fr.marben.asnsdk.japi.InconsistentStructureException</nature>
<ErrorOffset>72</ErrorOffset>
<ValuePath>SPAT.intersections.IntersectionState#1.states.MovementState#1.state-time-speed.MovementEvent#1.regional.SEQUENCE#1.regExtValue</ValuePath>
</error>
Eventually I would need to decode the hex into readable string in the app so I was wondering:
Why my b64 to hex code seems to be failing
how to transform hex to readable string
EDIT
OK, on the Marben site I was selecting the wrong drop down for decoding. Selecting MessageFrame provided a successful result so the b64 to hex I have is working. New problem arose from that is I can't decipher these results:
68 bytes decoded.
* DECODING SUCCESSFUL *
A couple of problems.
The hex string you provided translates to an original response of:
["ABNFAAAAOQoAAAcAEENBpUGlQAECKgyljLIADBDQZ+hn6ACAhoMwQzBABQQ0GSgZKAAwIaDSoNKgAcENBmCGYIAQCGgzuDO4"]
Perhaps they sent it to you in a JSON array? Bottom line, you need to trim out the [" and "] before you do anything else with this. For example, if it was JSON, you could parse the JSON before you base64-decode it:
do {
let array = try JSONDecoder().decode([String].self, from: originalJSONData)
if let base64String = array.first {
// use `base64String` here
}
} catch {
print(error)
}
If you want the data associated with that base64 string, you'd do something like:
let base64String = "ABNFAAAAOQoAAAcAEENBpUGlQAECKgyljLIADBDQZ+hn6ACAhoMwQzBABQQ0GSgZKAAwIaDSoNKgAcENBmCGYIAQCGgzuDO4"
let payload = Data(base64Encoded: base64String)!
If you merely want to display that as a hex string (I'm not sure why you'd want to do that), the easiest way is:
print(payload as NSData)
That would display
<00134500 0000390a 00000700 104341a5 41a54001 022a0ca5 8cb2000c 10d067e8 67e80080 86833043 30400504 34192819 28003021 a0d2a0d2 a001c10d 06608660 80100868 33b833b8>
If you really need that hex String representation, you can use the routine you have in your question (but do it on the base64-decoded payload, rather than the base64 string):
let payloadString = payload.map { String(format: "%02x", $0) }
.joined()
print(payloadString)
That will return:
001345000000390a00000700104341a541a54001022a0ca58cb2000c10d067e867e8008086833043304005043419281928003021a0d2a0d2a001c10d066086608010086833b833b8
Personally, the hex strings (in step 3 and 4) are interesting if you want to visually examine the binary payload, but probably you really need the original payload (in step 2). As I look at this data, it's not immediately obvious what this "3rd party data" returned, so I cannot comment further on that, but you presumably have some mechanism to consume this payload.

Swift: converting OPUS example file only returns "-4" (OPUS_INVALID_PACKET). How to strip header?

I have successfully added https://github.com/chrisballinger/Opus-iOS to my project and I am able to call the functions declared in its header.
I want to convert from OPUS to AAC so my first step would be to decode my opus file. However, it keeps throwing an error code.
The file I am using is the 2-second file from https://people.xiph.org/~giles/2012/opus/.
This is my code
let url = Bundle.main.url(forResource: "detodos", withExtension: "opus")
print(url) //prints path correctly
var bytes = [UInt8]()
if let data = NSData(contentsOf: url!) {
var buffer = [UInt8](repeating: 0, count: data.length)
data.getBytes(&buffer, length: data.length)
bytes = buffer
let d = opus_decoder_create(48000, 1, nil)
var sampleBuffer = [opus_int16](repeating: 0, count: data.length)
print(opus_int32(bytes.count)) //6270
let w = opus_decode(d!, bytes, opus_int32(bytes.count), &sampleBuffer, opus_int32(5760), opus_int32(1))
print(sampleBuffer) // [0,0,...] every time
print(w) //-4 every time
//-4 = OPUS_INVALID_PACKET
}
I would've guessed that in this very minimal implementation nothing should go wrong but apparently it does. Printing my bytes object returns tons of different numbers so I know for a fact it doesn't stay at all-0's.
I realized that it might be due to the method expecting pure "audio data" but the file also contains a header etc. How can I strip this off?
The opus library decodes Opus packets. You give it an Opus packet and it decodes it; one packet at a time. You are trying to give it an entire Ogg Opus file, including all of the headers, framing, tags, and other metadata.
The easiest way to decode an entire Ogg Opus file is with the opusfile library. It can even stream the data from a URL if you want, so that you don't have to download it all before you start decoding as you are doing here. Alternatively, instead of opusfile you could use the ogg library to extract packets from the file and then pass each audio packet to the opus library for decoding.