I need a JMeter Pre Processor which will convert a JSON String into a MQTT packet i.e binary data. The binary data will then be sent over the web socket using the JMeter web socket plugin - https://github.com/ptrd/jmeter-websocket-samplers
I am relatively new to JMeter and would appreciate any help on this. Please refer to my earlier question for the project scenario :
Testing a MQTT Client using JMeter
You kindly provided the link to the documentation which says:
The request-response sampler, as well as the single-read and single-write samplers, support both text and binary frames. For binary frames, enter the payload in hexadecimal format, e.g. 0xca 0xfe or ba be
So
Text data can be sent as they are (JSON is more or less plain text)
Binary (non-text) data needs to be converted to hex first
So you need to determine what exactly you need because your current requirement is a little bit vague and contraversial.
If you're looking for a function to convert string to hex - you can go for JSR223 PreProcessor and something like:
def hex(byte[] data) {
def rv = new StringBuilder();
data.each { aByte ->
rv.append('0x').append(String.format("%02x", aByte)).append(' ');
}
return rv.toString();
}
Demo:
More information on Groovy scripting in JMeter: Apache Groovy - Why and How You Should Use It
I'm trying to parse a txt file which is in the format of host-name IP mac-address in Lua. All three separated with spaces, to try and then store it into a table using Lua.
I've tried doing this using :match function but can't see to get it to work.
function parse_input_from_file()
array ={}
file = io.open("test.txt","r")
for line in file:lines() do
local hostname, ip, mac = line:match("(%S+):(%S+):(%S+)")
local client = {hostname, ip, mac}
table.insert(array, client)
print(array[1])
end
end
It keeps on printing the location in memory of where each key/value is stored (I think).
I'm sure this is a relatively easy fix but I can't seem to see it.
If hostname, ip and mac are separated by space your pattern may not use colons.
I added a few changes to store the captures in the client table.
function parse_input_from_file()
local clients ={}
local file = io.open("test.txt","r")
for line in file:lines() do
local client = {}
client.hostname, client.ip, client.mac = line:match("(%S+) (%S+) (%S+)")
table.insert(clients, client)
end
return clients
end
for i,client in ipairs(parse_input_from_file()) do
print(string.format("Client %d: %q %s %s", i, client.hostname, client.ip, client.mac))
end
Alternatively:
local client = table.unpack(line:match("(%S+) (%S+) (%S+)"))
then hostname is client[1] which is not very intuitive.
No colon in the regex:
local sampleLine = "localhost 127.0.0.1 mac123"
local hostname, ip, mac = sampleLine:match("(%S+) (%S+) (%S+)")
print(hostname, ip, mac) -- localhost 127.0.0.1 mac123
I'm updating a Python script to use cryptography's AESGCM primitive so it can interact with a Rails server running OpenSSL's AES-256-GCM implementation.
To begin, I'm simulating an encryption using identical message/key/nonce to see if both implementations produce the same output.
Python 3
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
data = b"a secret message"
aad = None
key = b'7\x98\xc1\xdf\x7f}\xea5?\\6\x17\tlT\xed\xa2a\x0fn\x87.(\x0c\xe4;*4\xda\x8fY\xc8'
aesgcm = AESGCM(key)
nonce = b'\x8ch\xbe\xfcR\xeee\xc1g\xd6\x80\xda'
ct = aesgcm.encrypt(nonce, data, aad)
ct: b'\xa8\xda\xdd\xdc\xca\xe8X\x84\xdb\x85\xef\xa6\xa6\x95\x00PN\x1e\xe7\xb0\x88\xae\xddc0\x19_\xae\x7f\xfd\x0c.'
Rails
cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
data = "a secret message".encode('utf-8')
cipher.key = "7\x98\xc1\xdf\x7f}\xea5?\\6\x17\tlT\xed\xa2a\x0fn\x87.(\x0c\xe4;*4\xda\x8fY\xc8"
cipher.iv = "\x8ch\xbe\xfcR\xeee\xc1g\xd6\x80\xda"
encrypted = cipher.update(data) + cipher.final
encrypted: "\xA8\xDA\xDD\xDC\xCA\xE8X\x84\xDB\x85\xEF\xA6\xA6\x95\x00P"
tag = cipher.auth_tag
tag: "\xB7B\x84h\xDD\xB7y\xCE\x88\xFDI\x9F\xD3\x13\xC51"
From the above examples:
Rails' encrypted is the same as the first part of Python's ct.
Rails' tag is not the same as the second part of Python's ct.
How do I amend one or both of these processes so they produce the same output?
Just found it - the answer lies in how OpenSSL differentially defines data vs auth_data.
The OpenSSL docs are a little confusing in the linked example because they didn't make it clear to me that data refers to the message and auth_data is additional authenticated data.
In my testing, I had mistakenly set auth_data AND data to 'a secret message', which is why data was encrypted consistently but the authenticated data bit at the end was different.
TLDR: data is your message; auth_data is not encrypted and should be set to "" if blank.
After many tries I have concluded that the optimal way to transfer with SSIS data from AS400 (non-unicode) to SQL Server is:
Use native transfer utility to dump data to tsv (tab delimited)
Convert files from utf-8 to unicode
Use bulk insert to put them into SQL Server
In #2 step I have found a ready made code that does this:
string from = #"\\appsrv02\c$\bg_f0101.tsv";
string to = #"\\appsrv02\c$\bg_f0101.txt";
using (StreamReader reader = new StreamReader(from, Encoding.UTF8, false, 1000000))
using (StreamWriter writer = new StreamWriter(to, false, Encoding.Unicode, 1000000))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (line.Length > 0)
writer.WriteLine(line);
}
}
I need to fully understand what is happening here with the encoding and why this is necessary.
How can I replace this script task with a more elegant solution?
I don't have much insight into exactly why you need the utf-8 conversion task, except to say that SQL server - I believe - uses UCS-2 as its native storage format, and this is similiar to UTF-16 which is what your task converts the file to. I'm surprised SSIS can't work with a UTF-8 input source though.
My main point is to answer the "How could I replace this script task with a more elegant solution?":
I have had a lot of success using HiT OLEDB/400 Server. It allows you to set up your AS/400 / iSeries / System i / whatever IBM are calling it this week as a linked server in SQL server, and you can then access the 400's data directly from the server its linked to using the standard 4 part SQL syntax, e.g. SELECT * FROM my400.my400.myLib.myFile.
Or even better, it's much more efficient as a passthrough query using EXEC...AT.
Using this you would not need SSIS at all, you'd just need a simple stored proc with that does an insert into your destination table direct from the 400 data.
I'm trying to send a push notification to APNs using Erlang.
This is the code I came up with so far:
-module(apnstest2).
-export([connect/0]).
connect() ->
application:start(ssl),
ssl:seed("someseedstring"),
Address = "gateway.sandbox.push.apple.com",
Port = 2195,
Cert = "/path/to/Certificate.pem",
Key = "/path/to/Key.unenc.pem",
Options = [{certfile, Cert}, {keyfile, Key}, {mode, binary}],
Timeout = 1000,
{ok, Socket} = ssl:connect(Address, Port, Options, Timeout),
Token = "195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03",
Payload = "{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}",
TokenLength = length(Token),
PayloadLength = length(Payload),
Packet = [<<0:8, TokenLength, Token, PayloadLength, Payload>>],
ssl:send(Socket, list_to_binary(Packet)),
ssl:close(Socket).
The code doesn't take advantage of Erlang's concurrency but is just a prototype. I only want to test if I can send the push in the most simple way.
I think the problem is in the packet being sent to the APNs.
This is the binary format of a push notification:
alt text http://developer.apple.com/IPhone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Art/aps_provider_binary.jpg
How should I create such a packet in Erlang?
Could someone please take a look at my code and tell me where the problem is?
Also I used Erlang's SSL application to create the connection and send the data and I don't know if this is the problem or the packet.
Thanks!
To start with, there is no need for creating a list of a single binary and then calling list_to_binary/1 on it. You can just send the binary itself.
Also, make sure the field lengths and values are appropriate according to the protocol:
TokenLength = 32 = length(Token),
Packet = <<0:8, TokenLength:16/big, Token, PayloadLength:16/big, Payload>>,
ssl:send(Socket, Packet),
Now that we have gotten this far, we will see that length(Token) is in fact 64, not 32:
You forgot to convert the hex string for Token to a binary, so you are sending a 64 byte hex character string instead of 32 binary bytes.
So... making Payload a binary from the start, and making Token a numeric constant, you can do something like the following:
Payload = <<"{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}">>,
PayloadLength = size(Payload),
Packet = <<0:8, 32:16/big,
16#195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03:256/big,
PayloadLength:16/big, Payload/binary>>,
ssl:send(Socket, Packet),
Thanks to Christian for pointing out a number of mistakes in the former revisions of this answer.
I see two mistakes:
Token should be passed in binary and not in hex ascii.
You can't use the binary syntax to turn lists into binaries.
For parsing hex to an integer and then down to binary use something like this:
Token = "dead",
TokenNum = erlang:list_to_integer(Token, 16),
TokenBin = <<TokenNum:32/integer-unit:8>>,
Build the protocol packet with something like this:
TokenBin = ...,
Payload = <<"Payload">>,
PayloadSize = byte_size(Payload),
Packet = <<0:8, 32:16, TokenBin/binary, PayloadSize:16, Payload/binary>>,
Try use a simple library epns(Erlang Push Notifications)
This library can send push notification as APNS and FCM by Erlang side. How use epns(Erlang Push Notifications) library - you can read in README.md. This liblary can used as 3-rd party in project, or you can run it locally for see how this library works:
$ git clone https://github.com/vkatsuba/epns.git
$ cd epns
$ make
Retested on Erlang 20~21