Message exchange between Paho java & javascript client not happening - mqtt
How can I send a message from paho java client to paho javascript client.
String topic = "chatWith/904";
String content = "Message from MqttPublishSample";
int qos = 0;
String broker = "tcp://127.0.0.1:1883";
String clientId = "JavaSample";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
System.out.println("Connecting to broker: "+broker);
sampleClient.connect(connOpts);
System.out.println("Connected");
System.out.println("Publishing message: "+content);
MqttMessage message = new MqttMessage(content.getBytes());
message.setQos(qos);
sampleClient.publish(topic, message);
System.out.println("Message published");
sampleClient.disconnect();
System.out.println("Disconnected");
System.exit(0);
} catch(MqttException me) {
me.printStackTrace();
}
Message exchange between two JS client is happening. But between Javasript & java client, message exchange is not happening.
Here is JS code
client = new Messaging.Client(host, Number(port), clientId);
client.onConnect = onConnect;
client.onMessageArrived = onMessageArrived;
client.onMessageDelivered = onMessageDelivered;
client.onConnectionLost = onConnectionLost;
var willMessage = createByteMessage({
id: '',
'msgType':'USER_STATUS',
'status': 'Offline',
'senderId': myUserId,
'senderName': myName
}, statusTopic);
willMessage.retained = true;
client.connect({
userName:user,
password:password,
onSuccess:onConnect,
onFailure:onFailure,
'willMessage': willMessage
});
Here port is 8083 and mqtt broker is emqtt
client.config
testclientid0
testclientid1 127.0.0.1
testclientid2 192.168.0.1/24
emqttd.config
% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ft=erlang ts=4 sw=4 et
[{kernel, [
{start_timer, true},
{start_pg2, true}
]},
{sasl, [
{sasl_error_logger, {file, "log/emqttd_sasl.log"}}
]},
{ssl, [
%{versions, ['tlsv1.2', 'tlsv1.1']}
]},
{lager, [
{colored, true},
{async_threshold, 5000},
{error_logger_redirect, false},
{crash_log, "log/emqttd_crash.log"},
{handlers, [
%%{lager_console_backend, info},
%%NOTICE: Level >= error
%%{lager_emqtt_backend, error},
{lager_file_backend, [
{formatter_config, [time, " ", pid, " [",severity,"] ", message, "\n"]},
{file, "log/emqttd_error.log"},
{level, error},
{size, 104857600},
{date, "$D0"},
{count, 30}
]}
]}
]},
{esockd, [
{logger, {lager, error}}
]},
{emqttd, [
%% Authentication and Authorization
{access, [
%% Authetication. Anonymous Default
{auth, [
%% Authentication with username, password
%{username, []},
%% Authentication with clientid
%{clientid, [{password, no}, {file, "etc/clients.config"}]},
%% Authentication with LDAP
% {ldap, [
% {servers, ["localhost"]},
% {port, 389},
% {timeout, 30},
% {user_dn, "uid=$u,ou=People,dc=example,dc=com"},
% {ssl, fasle},
% {sslopts, [
% {"certfile", "ssl.crt"},
% {"keyfile", "ssl.key"}]}
% ]},
%% Allow all
{anonymous, []}
]},
%% ACL config
{acl, [
%% Internal ACL module
{internal, [{file, "etc/acl.config"}, {nomatch, allow}]}
]}
]},
%% MQTT Protocol Options
{mqtt, [
%% Packet
{packet, [
%% Max ClientId Length Allowed
{max_clientid_len, 512},
%% Max Packet Size Allowed, 64K default
{max_packet_size, 65536}
]},
%% Client
{client, [
%% Socket is connected, but no 'CONNECT' packet received
{idle_timeout, 30} %% seconds
]},
%% Session
{session, [
%% Max number of QoS 1 and 2 messages that can be “in flight” at one time.
%% 0 means no limit
{max_inflight, 100},
%% Retry interval for redelivering QoS1/2 messages.
{unack_retry_interval, 60},
%% Awaiting PUBREL Timeout
{await_rel_timeout, 20},
%% Max Packets that Awaiting PUBREL, 0 means no limit
{max_awaiting_rel, 0},
%% Statistics Collection Interval(seconds)
{collect_interval, 0},
%% Expired after 2 day (unit: minute)
{expired_after, 2880}
]},
%% Queue
{queue, [
%% simple | priority
{type, simple},
%% Topic Priority: 0~255, Default is 0
%% {priority, [{"topic/1", 10}, {"topic/2", 8}]},
%% Max queue length. Enqueued messages when persistent client disconnected,
%% or inflight window is full.
{max_length, infinity},
%% Low-water mark of queued messages
{low_watermark, 0.2},
%% High-water mark of queued messages
{high_watermark, 0.6},
%% Queue Qos0 messages?
{queue_qos0, true}
]}
]},
%% Broker Options
{broker, [
%% System interval of publishing broker $SYS messages
{sys_interval, 60},
%% Retained messages
{retained, [
%% Expired after seconds, never expired if 0
{expired_after, 0},
%% Max number of retained messages
{max_message_num, 100000},
%% Max Payload Size of retained message
{max_playload_size, 65536}
]},
%% PubSub and Router
{pubsub, [
%% Default should be scheduler numbers
{pool_size, 8},
%% Store Subscription: true | false
{subscription, true},
%% Route aging time(seconds)
{route_aging, 5}
]},
%% Bridge
{bridge, [
%%TODO: bridge queue size
{max_queue_len, 10000},
%% Ping Interval of bridge node
{ping_down_interval, 1} %seconds
]}
]},
%% Modules
{modules, [
%% Client presence management module.
%% Publish messages when client connected or disconnected
{presence, [{qos, 0}]},
%% Subscribe topics automatically when client connected
{subscription, [
%% $c will be replaced by clientid
%% {"$queue/clients/$c", 1},
%% Static subscriptions from backend
backend
]}
%% Rewrite rules
%% {rewrite, [{file, "etc/rewrite.config"}]}
]},
%% Plugins
{plugins, [
%% Plugin App Library Dir
{plugins_dir, "./plugins"},
%% File to store loaded plugin names.
{loaded_file, "./data/loaded_plugins"}
]},
%% Listeners
{listeners, [
{mqtt, 1883, [
%% Size of acceptor pool
{acceptors, 16},
%% Maximum number of concurrent clients
{max_clients, 512},
%% Socket Access Control
{access, [{allow, all}]},
%% Connection Options
{connopts, [
%% Rate Limit. Format is 'burst, rate', Unit is KB/Sec
%% {rate_limit, "100,10"} %% 100K burst, 10K rate
]},
%% Socket Options
{sockopts, [
%Set buffer if hight thoughtput
%{recbuf, 4096},
%{sndbuf, 4096},
%{buffer, 4096},
%{nodelay, true},
{backlog, 1024}
]}
]},
{mqtts, 8883, [
%% Size of acceptor pool
{acceptors, 4},
%% Maximum number of concurrent clients
{max_clients, 512},
%% Socket Access Control
{access, [{allow, all}]},
%% SSL certificate and key files
{ssl, [{certfile, "etc/ssl/ssl.crt"},
{keyfile, "etc/ssl/ssl.key"}]},
%% Socket Options
{sockopts, [
{backlog, 1024}
%{buffer, 4096},
]}
]},
%% WebSocket over HTTPS Listener
%% {https, 8083, [
%% %% Size of acceptor pool
%% {acceptors, 4},
%% %% Maximum number of concurrent clients
%% {max_clients, 512},
%% %% Socket Access Control
%% {access, [{allow, all}]},
%% %% SSL certificate and key files
%% {ssl, [{certfile, "etc/ssl/ssl.crt"},
%% {keyfile, "etc/ssl/ssl.key"}]},
%% %% Socket Options
%% {sockopts, [
%% %{buffer, 4096},
%% {backlog, 1024}
%% ]}
%%]},
%% HTTP and WebSocket Listener
{http, 8083, [
%% Size of acceptor pool
{acceptors, 4},
%% Maximum number of concurrent clients
{max_clients, 64},
%% Socket Access Control
{access, [{allow, all}]},
%% Socket Options
{sockopts, [
{backlog, 1024}
%{buffer, 4096},
]}
]}
]},
%% Erlang System Monitor
{sysmon, [
%% Long GC, don't monitor in production mode for:
%% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421
{long_gc, false},
%% Long Schedule(ms)
{long_schedule, 240},
%% 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM.
%% 8 * 1024 * 1024
{large_heap, 8388608},
%% Busy Port
{busy_port, false},
%% Busy Dist Port
{busy_dist_port, true}
]}
]}
].
Related
How to variabilize sshTransfer in a jenkinsfile?
I'm currently using a simple pipeline in order to delete logs older than 7 days on my servers. I have 4 servers where the logs are in the same place, and thus 4 times the same sshTransfer command. Is there anyway to variabilize those 4 redundant "sshTransfer". Here is my code for more clarity :) stage('Cleanup logs') { steps { script { echo "1. Connection to server 1" sshPublisher ( publishers:[ sshPublisherDesc( configName: server1, transfers:[ sshTransfer( execCommand:"find /var/opt/application/log/* -mtime +6 -type f -delete", execTimeout: 20000, ) ] ) ] ) echo "2. Connection to server 2" sshPublisher ( publishers:[ sshPublisherDesc( configName: server2, transfers:[ sshTransfer( execCommand:"find /var/opt/application/log/* -mtime +6 -type f -delete", execTimeout: 20000, ) ] ) ] ) echo "3. Connection to server 3" sshPublisher ( publishers:[ sshPublisherDesc( configName: server3, transfers:[ sshTransfer( execCommand:"find /var/opt/application/log/* -mtime +6 -type f -delete", execTimeout: 20000, ) ] ) ] ) echo "4. Connection to server 4" sshPublisher ( publishers:[ sshPublisherDesc( configName: server4, transfers:[ sshTransfer( execCommand:"find /var/opt/application/log/* -mtime +6 -type f -delete", execTimeout: 20000, ) ] ) ] ) } } } Thank you !
OpenVPN v3 Dbus client not receiving all signals
I'm writing an Applet for Linux Mint/Cinnamon to manage OpenVPN v3 connections. In order to avoid synchronous calls that can cause the DE to stutter or freeze, I'm writing a simple DBus client using the Gio and GLib libraries provided by GJS. This allows an asynchronous, partly event-driven approach and should avoid any nasty side effects. It's my first time using any of these technologies but the OpenVPN DBus API is pretty well documented and the API docs for Gio and GLib are also good. The problem I have is with signal subscriptions, specifically the StatusChange signal published by the net.openvpn.v3.sessions service. A bunch of these signals are published whenever a connection is established, paused, resumed or closed. Most of the signals are picked up by my subscribed listener, but not all of them. In particular, I don't receive the session closed signal. Using the dbus-monitor commandline tool, you can see all the StatusChange signals published when a connection is established (7 signals) and then closed (2 signals): $ sudo dbus-monitor --system "type='signal',interface='net.openvpn.v3.sessions',member='StatusChange'" ... // Connect: signal time=1625847543.107244 sender=:1.891 -> destination=:1.892 serial=2745 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange uint32 3 uint32 27 string "session_path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49, backend_pid=42584" signal time=1625847543.116395 sender=:1.891 -> destination=:1.892 serial=2762 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange uint32 3 uint32 17 string "session_path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49 backend_busname=net.openvpn.v3.backends.be42585 backend_path=/net/openvpn/v3/backends/session" signal time=1625847543.117286 sender=:1.891 -> destination=(null destination) serial=2764 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange uint32 2 uint32 2 string "config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232" signal time=1625847543.638519 sender=:1.891 -> destination=(null destination) serial=2775 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange uint32 2 uint32 2 string "config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232" signal time=1625847543.638533 sender=:1.891 -> destination=(null destination) serial=2776 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange uint32 2 uint32 6 string "" signal time=1625847543.735357 sender=:1.891 -> destination=(null destination) serial=2777 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange uint32 2 uint32 6 string "" signal time=1625847543.974784 sender=:1.891 -> destination=(null destination) serial=2778 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange uint32 2 uint32 7 string "" // Disconnect: signal time=1625847646.846790 sender=:1.891 -> destination=:1.892 serial=2834 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange uint32 3 uint32 28 string "Session closed" signal time=1625847646.848262 sender=:1.891 -> destination=:1.892 serial=2839 path=/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.openvpn.v3.sessions; member=StatusChange uint32 3 uint32 19 string "" The following code creates a subscription that, as far as I can tell, should receive the same signals as above. Note I'm using the lower-level approach to obtain a subscription here; the subscription is made on the global connection, rather than via a DBusProxy for a specific object path. I've tried both approaches (same result) but the following should be a closer analogue to the dbus-monitor command above. subscribeToStatusChangeSignals() { this.statusChangeHandlerId = Gio.DBus.system.signal_subscribe( 'net.openvpn.v3.sessions', 'net.openvpn.v3.sessions', 'StatusChange', null, null, Gio.DBusSignalFlags.NONE, this._handleGlobalStatusChangeSignal ); } _handleGlobalStatusChangeSignal(connection, sender, path, iface, signal, params) { let container = params.deep_unpack(); let statusMajorCode = container[0]; let statusMinorCode = container[1]; let statusMajor = lookupStatusMajor(statusMajorCode); // lookup the corresponding text let statusMinor = lookupStatusMinor(statusMinorCode); // from something resembling an enum let message = container[2]; global.log(`Received StatusChange signal path: [${path}] Status Major: [${statusMajorCode} - ${statusMajor}] Status Minor: [${statusMinorCode} - ${statusMinor}] Message: [${message}]` ); } The resulting logs when opening and closing the same connection as before: // Connect: Cjs-Message: 18:19:03.117: JS LOG: [LookingGlass/info] Received StatusChange signal path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49] Status Major: [2 - CONNECTION] Status Minor: [2 - CFG_OK] Message: [config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232] Cjs-Message: 18:19:03.638: JS LOG: [LookingGlass/info] Received StatusChange signal path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49] Status Major: [2 - CONNECTION] Status Minor: [2 - CFG_OK] Message: [config_path=/net/openvpn/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232] Cjs-Message: 18:19:03.639: JS LOG: [LookingGlass/info] Received StatusChange signal path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49] Status Major: [2 - CONNECTION] Status Minor: [6 - CONN_CONNECTING] Message: [] Cjs-Message: 18:19:03.735: JS LOG: [LookingGlass/info] Received StatusChange signal path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49] Status Major: [2 - CONNECTION] Status Minor: [6 - CONN_CONNECTING] Message: [] Cjs-Message: 18:19:03.974: JS LOG: [LookingGlass/info] Received StatusChange signal path: [/net/openvpn/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49] Status Major: [2 - CONNECTION] Status Minor: [7 - CONN_CONNECTED] Message: [] // Disconnect: <nada> One pattern i've noticed is that the signals i do receive all have a null destination in the dbus-monitor output: ... sender=:1.891 -> destination=(null destination) ... while the signals I don't receive have a specific destination: ... sender=:1.891 -> destination=:1.892 ... Presumably these are direct signals intended for a particular recipient, rather than signals broadcast to all interested subscribers, but I haven't found this explained anywhere in the docs. So the question is, why do I receive some signals but not all? Is this by design, or an issue with Gio, or (more likely) an issue with how I'm using it?
After a bit more digging it appears this behaviour is by design - Signals that carry a destination value are treated as unicast messages. Subscribers other than the intended recipient will only receive such messages if they are configured to eavesdrop. Presumably this is the case for dbus-monitor. Source: DBus Specification (Message Routing)
getting {badarith,[{erlang,'+',[error,0],[]}, while performing arithmetic operation in TSUNG using Erlang snippet
I have wriiten a arithmetic snippet using TSUNG-Erlang function but unable to get through it successfully ; getting following error in my TSUNG controller's log , TSUNG-Erlang Snippet, <setdynvars sourcetype="file" fileid="NBILM_testUsers" delimiter=";" order="iter"> <var name="minnum"/> <var name="maxnum"/> </setdynvars> <setdynvars sourcetype="eval" code='fun({Pid,DynVars})-> {ok,Maxfound}=ts_dynvars:lookup(maxnum,DynVars), Maxstr = lists:flatten(io_lib:format("~p",[Maxfound])), {MAX, _} = string:to_integer(Maxstr), {ok,Minfound}=ts_dynvars:lookup(minnum,DynVars), Minstr = lists:flatten(io_lib:format("~p",[Minfound])), {MIN, _} = string:to_integer(Minstr), {ok,Countern} = ts_dynvars:lookup(counter,DynVars,999), Counternstr = lists:flatten(io_lib:format("~p",[Countern])), {Counternum, _} = string:to_integer(Counternstr), Mnum1 = MAX + Counternum rem ( 2 - 1 ), Mnum1 end. '> <var name="mnum" /> </setdynvars> Erroneous log events from TSUNG Controller, =INFO REPORT==== 5-May-2017::11:42:40 === ts_client:(5:<0.134.0>) Stop in state think, reason= {badarith, [{erlang, '+', [error,0], []}, {erl_eval, do_apply,6, [{file, "erl_eval.erl"}, {line, 669}]}, {erl_eval, expr,5, [{file, "erl_eval.erl"}, {line, 438}]}, {erl_eval, exprs,5, [{file, "erl_eval.erl"}, {line, 122}]}, {ts_client, handle_next_action, 1, [{file, "src/tsung/ts_client.erl"}, {line, 459}]}, {gen_fsm, handle_msg, 7, [{file, "gen_fsm.erl"}, {line, 518}]}, {proc_lib, init_p_do_apply, 3, [{file, "proc_lib.erl"}, {line, 239}]}]} =ERROR REPORT==== 5-May-2017::11:42:40 === ** State machine <0.134.0> terminating ** Last message in was {timeout,#Ref<0.0.8.22>,end_thinktime} ** When State == think ** Data == {state_rcv,none, {{0,0,0,0},0}, undefined,0,10000,"xyz",80,ts_tcp, {proto_opts,negociate,"/http-bind/",false,"/chat", "binary",10,3,600000,infinity,infinity,32768,32768, undefined,undefined,[],false,true}, false,1,undefined,true,undefined, {1493,964755,255814}, 18,18,false,undefined,0,[],<<>>, {http,0,0,-1, {none,none}, false,false, {false,false}, [],"tsung",[]}, 0,1,524288,524288, [{tsung_userid,1}], ts_http,[],undefined,full} Reason for termination = {badarith,[{erlang,'+',[error,0],[]}, {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,669}]}, {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,438}]}, {erl_eval,exprs,5,[{file,"erl_eval.erl"},{line,122}]}, {ts_client,handle_next_action,1, [{file,"src/tsung/ts_client.erl"},{line,459}]}, {gen_fsm,handle_msg,7,[{file,"gen_fsm.erl"},{line,518}]}, {proc_lib,init_p_do_apply,3, [{file,"proc_lib.erl"},{line,239}]}]} It would be really helpful, if someone can point what am doing incorrectly.
The message says that in the line Mnum1 = MAX + Counternum rem ( 2 - 1 ), you are trying to add error with 0 (by the way Counternum rem ( 2 - 1 ) is always equal to 0 so there must be an error here). Max is the result of {MAX, _} = string:to_integer(Maxstr),, it is equal to error if Maxstr is not a string starting by an integer: "123" will return {123,[]} "123 ab" will return {123," ab"} "a123" will return {error,no_integer} an_atom will return {error,not_a_list} To debug further verify the value of Maxfound and Maxstr you can also shorten your code using the function io:fread/2 which will directly return an integer.
How to make Erlang client/server connect with arguments/nodes from config?
I'm writing a client/server System in Erlang and can't get them to connect. The nodes they should use are stored in config files, which are loaded upon starting them. They also use several distributed data structures. Problem is, I'm first starting the data structure, then the server (works fine) but when I start the client, it doesn't connect to anything and throws an exception. Server: -module(server). -export([startServer/0,loopServer/7,node/0,log/0,name/0]). -compile({no_auto_import,[node/0]}). -import(werkzeug, [get_config_value/2,lengthSL/1,logging/2,reset_timer/3,get_config_value/2]). -import(erlang, [append/2]). log() -> erlang:list_to_atom(lists:concat(["Server#", node(),".log"])). node() -> {ok,Config} = file:consult("configs/server.cfg"), {ok, Node} = werkzeug:get_config_value(node,Config), Node. name() -> {ok,Config} = file:consult("configs/server.cfg"), {ok, Name} = werkzeug:get_config_value(servername,Config), Name. %%Startet den Server und die darin enthaltene Schleife startServer() -> {ok,Config} = file:consult("configs/server.cfg"), {ok, Name} = get_config_value(servername,Config), %%CMEM initialisieren {ok, RemTime} = get_config_value(cmemtime,Config), CMEM = cmem:initCMEM(RemTime, log()), %%HBQ-Prozess erzeugen {ok,HBQName} = get_config_value(hbqname,Config), {ok,HBQNode} = get_config_value(node,Config), HBQ = {HBQName,HBQNode}, {ok,Serverzeit} = get_config_value(serverzeit,Config), %%Zeitpunkt des Timer übergeben {ok, Timer} = timer:send_after(round(RemTime * 1000),Name,delServer), %%Prozess registrieren, Serverschleife mit allen Infos starten, plus NNr 1 ServerPid = spawn(?MODULE, loopServer, [Name,CMEM,HBQ,Timer,Serverzeit,Config,1]), register(Name,ServerPid), %%HBQ initialisieren HBQ ! {ServerPid, {request,initHBQ}}, {Config,CMEM,HBQ,ServerPid}. loopServer(Name,CMEM,HBQ,Timer,Serverzeit,Config,NNr) -> receive %%Client fragt neue Nachrichten ab, dazu wird aus CMEM die aktuelle NNr für %%den Client angefordert und mit der ClientPID an die HBQ weitergegeben {ClientPID,getmessages} -> NewTimer = reset_timer(Timer,Serverzeit,delServer), ClientNNr = cmem:getClientNNr(CMEM, ClientPID), HBQ ! {self(), {request, deliverMSG, ClientNNr, ClientPID}}, logging(log(), lists:concat(["Server: Nachricht ", NNr, " wurde zugestellt.\n"])), loopServer(Name,CMEM,HBQ,NewTimer,Serverzeit,Config,NNr); %%Nachricht soll in HBQ verschoben werden {dropmessage,[INNr,Msg,TSclientout]} -> NewTimer = reset_timer(Timer,Serverzeit,delServer), HBQ ! {self(), {request,pushHBQ,[INNr,Msg,TSclientout]}}, receive {reply,ok} -> logging(log(), lists:concat(["Server: Nachricht ", INNr, " wurde in HBQ eingefuegt.\n"])) end, loopServer(Name,CMEM,HBQ,NewTimer,Serverzeit,Config,NNr); %%Client fragt naechste NNr ab, diese wird dem Zustand des Server entnommen {ClientPID,getmsgid} -> NewTimer = reset_timer(Timer,Serverzeit,delServer), ClientPID ! {nid, NNr}, NewNNr = NNr + 1, logging(log(), lists:concat(["Server: Nachrichtennumer ", NNr, " an ", erlang:pid_to_list(ClientPID), "gesendet.\n"])), loopServer(Name,CMEM,HBQ,NewTimer,Serverzeit,Config,NewNNr); %%Server beendet sich selbst und zugleich die HBQ delServer -> HBQ ! {self(),{request,delHBQ}}, receive {reply,ok} -> logging(log(), lists:concat([lists:concat(["Server: Downtime ", werkzeug:timeMilliSecond(), " von ", name() ,"\n"])])), ok end end. Client: -module(client). -export([startClients/0,loopClient/4,spawnC/1,forLoop/3,mitServerVerbinden/6,configLaden/0]). -import(werkzeug, [get_config_value/2]). -import(timer, [apply_after/4]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Client %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%initClient startClients() -> Config = configLaden(), {ok, ClientAnzahl} = werkzeug:get_config_value(clientanzahl, Config), {ok, ServerName} = werkzeug:get_config_value(servername, Config), {ok, ServerNode} = werkzeug:get_config_value(servernode, Config), ServerPid = {ServerName,ServerNode}, forLoop(ClientAnzahl, fun client:spawnC/1, ServerPid). %%Hilfsfunktion fuer for-Schleife: Zaehlt runter, %%ruft Funktion auf und gibt Ergebnisse als Liste zurueck forLoop(Clients, Spawn, SPid) -> forLoop(Clients, Spawn, SPid, []). forLoop(0, _Spawn, _SPid, ClientListe) -> ClientListe; forLoop(Clients, Spawn, SPid, ClientListe) -> ClientListeNew = ClientListe ++ [Spawn(SPid)], ClientsNew = Clients - 1, forLoop(ClientsNew, Spawn, SPid, ClientListeNew). %%Neuen ClientProzess erzeugen spawnC(ServerPid) -> Config = configLaden(), {ok, Lebenszeit} = werkzeug:get_config_value(lebenszeit, Config), {ok, Cookie} = werkzeug:get_config_value(cookie, Config), {ok, ServerNode} = werkzeug:get_config_value(servernode, Config), {ok, Wartezeit} = werkzeug:get_config_value(wartezeit, Config), ClientPid = erlang:spawn(?MODULE, mitServerVerbinden, [ServerPid, [], [], Wartezeit, ServerNode, Cookie]), timer:kill_after(Lebenszeit, ClientPid), ClientPid. %%mit Server Verbinden mitServerVerbinden(ServerPid,Datei,NNummern,Wartezeit,ServerNode,Cookie) -> erlang:set_cookie(ServerNode,Cookie), pong = net_adm:ping(ServerNode), loopClient(ServerPid,NNummern,Wartezeit,Datei). %%loopClient loopClient(ServerPid,NNummern,Wartezeit,Datei) -> %%Client wird zum Redakteur {NNummernNew, WartezeitNew, DateiNew} = nachrichtenSenden(5,ServerPid,NNummern,Wartezeit,Datei), %%Client wird zum Leser nachrichtenLesen(false, NNummernNew, ServerPid,DateiNew), %%Methode ruft sich selbst wieder auf loopClient(ServerPid, NNummernNew, WartezeitNew,DateiNew). configLaden() -> {ok, Config} = file:consult("configs/client.cfg"), Config. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Redakteur %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%Nachricht soll vergessen werden nachrichtenSenden(0,ServerPid,NNummern,Wartezeit,Datei) -> %%Naechste NNr beim Server anfragen ServerPid ! {self(),getmsgid}, receive %%Server sendet NNr {nid,NNr} -> %%Logeintrag werkzeug:logging(Datei,lists:concat([NNr, "te Nachricht um ", werkzeug:timeMilliSecond(), " vergessen zu senden. ******\n"])) end, WartezeitNew = wartezeitBerechnen(Wartezeit), %%Rückgabewerte: Liste mit Nachrichtennummern fuer leser, neue Wartezeit, Logfile {NNummern,WartezeitNew,Datei}; %%Nachrichtennummer anfragen und erhalten, Nachricht schreiben nachrichtenSenden(NachrichtenVorVergessen,ServerPid,NNummern,Wartezeit,Datei) -> Config = configLaden(), {ok, ServerNode} = werkzeug:get_config_value(servernode, Config), %%Naechste NNr beim Server anfragen ServerPid ! {self(),getmsgid}, receive %%Server sendet NNr {nid,NNr} -> %%Nachricht schreiben Nachricht = nachrichtSchreiben(NNr), %%NNr zur Liste hinzufuegen fuer Leser NNummernNew = NNummern ++[NNr], timer:sleep(Wartezeit), %%Nachricht an Server senden ServerPid ! {dropmessage,[NNr,Nachricht,erlang:now()]}, %%Logeintrag schreiben werkzeug:logging(Datei,lists:concat([Nachricht, " gesendet"])), %%Neue Wartezeit berechnen WartezeitNew = wartezeitBerechnen(Wartezeit), %%Zaehler dekrementieren NachrichtenVorVergessenNew = NachrichtenVorVergessen -1, %%Methode neu aufrufen nachrichtenSenden(ServerPid,NNummernNew,WartezeitNew,NachrichtenVorVergessenNew,Datei) end. %%nachrichtSchreiben nachrichtSchreiben(NNr) -> Config = configLaden(), {ok, Rechner} = werkzeug:get_config_value(rechner, Config), {ok, Praktikumsgruppe} = werkzeug:get_config_value(praktikumsgruppe, Config), {ok, Teamnummer} = werkzeug:get_config_value(teamnummer, Config), lists:concat(["client#",Rechner, "_", Praktikumsgruppe, "_", Teamnummer, ": ", integer_to_list(NNr), "_te Nachricht. Sendezeit: ", werkzeug:timeMilliSecond()]). %%Hilfsmethode: Intervall darf nicht kleiner als zwei Sekunden werden minimumTime() -> 2000. %%Berechnet das neue Zeitintervall, um die Haelfte groesser oder %%kleiner als die alte Zeit, solange sie groesser gleich 2 Sekunden ist wartezeitBerechnen(Wartezeit) -> GroesserKleiner = werkzeug:bool_rand(), HaelfteZeit = trunc(max(Wartezeit * 0.5, minimumTime())), if GroesserKleiner -> Wartezeit + HaelfteZeit; true -> max(Wartezeit - HaelfteZeit, minimumTime()) end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Leser %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nachrichtenLesen(true,NNummern,ServerPid,Datei) -> ok; nachrichtenLesen(false,NNummern,ServerPid,Datei) -> ServerPid ! {self(),getmessages}, receive {reply,Message,Terminated} -> nachrichtInLogSchreiben(Message,NNummern,Datei), nachrichtenLesen(Terminated,NNummern,ServerPid,Datei) end. nachrichtInLogSchreiben([NNr,Msg,TSclientout,TShbqin,TSdlqin,TSdlqout],NNummern,Datei) -> Now = erlang:timestamp(), DLQInTrue = werkzeug:validTS(TSdlqin), DLQOutTrue = werkzeug:validTS(TSdlqout), DLQInZukunft = werkzeug:lessTS(Now, TSdlqin), DLQOutZukunft = werkzeug:lessTS(Now, TSdlqout), MsgVonGleichemClient = msgVonGleichemClient(NNr, Msg, NNummern), if DLQInTrue and DLQInZukunft -> Zeitunterschied = werkzeug:now2stringD(werkzeug:diffTS(TSdlqin, Now)), MsgNew = MsgVonGleichemClient ++ ", Zeitunterschied: " ++ Zeitunterschied, werkzeug:logging(Datei, MsgNew ++ "\n"); DLQOutTrue and DLQOutZukunft -> Zeitunterschied = werkzeug:now2stringD(werkzeug:diffTS(TSdlqout, Now)), MsgNew = MsgVonGleichemClient ++ ", Zeitunterschied: " ++ Zeitunterschied, werkzeug:logging(Datei, MsgNew ++ "\n"); true -> werkzeug:logging(Datei, MsgVonGleichemClient ++ "\n") end. msgVonGleichemClient(NNr,Msg,NNummern) -> MsgVonGleichemClient = lists:member(NNr, NNummern), if MsgVonGleichemClient -> Msg ++ "*******"; true -> Msg end. Config file for server: {sizedlq,400}. {servername,'serverpa'}. {cmemtime,2000}. {hbqname,'hbqpa'}. {node,'hbqnode'}. {serverzeit,50}. Config file for client: {wartezeit,20}. {lebenszeit,240}. {pratikumsgruppe,'2'}. {teamnummer,'02'}. {servername,'serverpa'}. {clientanzahl,5}. {servernode,'servernode'}. {cookie,pa}. {rechner,'rechner'}. There are also distributed data strutures which are essentially queues and seem to be working fine: HBQ: -module(hbq). -export([startHBQ/0, checkTransfer/6,loophbq/4]). %% HBQ !{self(), {request,pushHBQ,[INNr,Msg,TSclientout]}} startHBQ() -> startHBQ("./configs/server.cfg"). %% Used for starting the HBQ with a custom config file startHBQ(Configfile) -> %%Config und Namen auslesen Config = loadConfig(Configfile), Config = loadConfig(Configfile), %%{ok,Config} = file:consult("./config/server.cfg"), {ok,HBQName} = werkzeug:get_config_value(hbqname,Config), %%Prozess der HBQ starten HBQPid = spawn(?MODULE,loophbq,[[],[],Config, 1]), %%Prozess registrieren register(HBQName,HBQPid), HBQPid. loophbq(HBQ,DLQ,Config,CurrNumber) -> receive %%initialisere HBQ und DLQ, sendet ok an Server {ServerPid,{request,initHBQ}} -> HBQList = [], Log = log(Config,["HBQ>>> initialisiert worden von ", ServerPid, ".\n"]), {ok,DLQSize} = werkzeug:get_config_file(sizedlq,Config), DLQ = dlq:initDLQ(DLQSize,Log), ServerPid ! {reply,ok}, loophbq(HBQList, DLQ ,Config, CurrNumber); %%fuegt der Msg einen Zeitstempel hinzu, fuegt sie in HBQ ein, sendet ok {ServerPid,{request,pushHBQ,[NNr,Msg,TSclientout]}} -> TShbqin = werkzeug:timeMillliSecond(), NewMessage = {NNr,lists:concat(Msg,["HBQ in: ",TShbqin])}, Log = log(Config,["HBQ>>> Nachricht ",NNr, "in HBQ eingefügt.\n"]), NewHBQ = [HBQ|NewMessage], lists:sort(fun({A,_},{B,_}) -> A=<B end), checkTransfer(NewHBQ, CurrNumber, Config, DLQ,TSclientout,TShbqin), ServerPid ! {reply,ok}, loophbq(NewHBQ, DLQ ,Config, CurrNumber); %%DLQ soll über HBQ Nachricht an Client senden {ServerPid,{request,deliverMSG,NNr,ToClient}} -> {ok, HBQName} = werkzeug:get_config_value(hbqname, Config), Log = lists:concat(["HB-DLQ#", HBQName, ".log"]), Datei = erlang:list_to_atom(Log), log(Config, ["HBQ>>> dlq:delivermsg", NNr, pid_to_list(ToClient), "\n"]), NNrDLQ = dlq:deliverMSG(NNr, ToClient, DLQ, Datei), ServerPid ! {reply, NNrDLQ}, loophbq(HBQ, DLQ ,Config, CurrNumber); %%Terminiert Prozess der DLQ {ServerPid,{request,delHBQ}} -> ServerPid ! {reply,ok}, ok end. %%CheckTransfer checkTransfer(HBQ, Number, Config, [DLQ,Size],TSclientout,TShbqin) -> Datei = log(Config, ["HBQ>>> Nachricht Nr ", Number, " wird in DLQ uebertragen\n"]), FoundMatch = lists:keyfind(Number, 1, HBQ), if FoundMatch =:= false -> if(length(HBQ)>Size*0.667) -> [{MinNNr,_}|_] = HBQ, %wegen sort ist immer die kleinste NNr vorne in der Liste NewMessage = {MinNNr-1,lists:concat(["Weiß noch nicht was hier reinsoll: ",werkzeug:timeMilliSecond()])}, NewHBQ = lists:append([{MinNNr-1,NewMessage}], HBQ), log(Config,["HBQ>>> Fehlernachricht fuer Nachrichten ",Number," bis",MinNNr-1, " generiert.\n"]), NewNumber = MinNNr-1, checkTransfer(NewHBQ, NewNumber, Config,[DLQ,Size],TSclientout,TShbqin); true -> ok end; true -> {MatchNr,Msg} = FoundMatch, dlq:push2DLQ([MatchNr, Msg, TSclientout, TShbqin], DLQ, Datei), lists:delete(FoundMatch, HBQ), checkTransfer(HBQ, Number+1, Config,[DLQ,Size],TSclientout,TShbqin) end. log(Config,Message) -> {ok,HBQNode} = werkzeug:get_config_value(node,Config), DateiName = lists:concat(["HB-DLQ#", HBQNode,".log"]), Datei = erlang:list_to_atom(DateiName), werkzeug:logging(Datei, lists:concat(Message)), Datei. %%Dummy-Nachrichten schreiben um Lücken in der HBQ zu füllen wenn sie kritische Größe erreicht %%Methode um zu prüfen, ob Nachrichten in DLQ geschoben werden können, das dann auch machen loadConfig(Configfile) -> {ok, Config} = file:consult(Configfile), Config. DLQ: -module(dlq). -export([initDLQ/2, delDLQ/1, expectedNr/1, push2DLQ/3, deliverMSG/4]). %%Initialisiert DLQ mit Kapazitaet Size, Log in Datei initDLQ(Size, Datei) -> werkzeug:logging(Datei,lists:concat(["DLQ>>> intitialisiert worden mit Groesse ",Size,".\n"])), [[],Size]. %%Loescht DLQ delDLQ(_Queue) -> ok. %%Liefert NNr die als naechstes in DLQ gespeichert werden kann %%expectedNr(Queue) expectedNr([[], _Size]) -> 1; expectedNr([[[NNr, _Msg, _TSclientout, _TShbqin, _TSdlqin] | _Rest], _Size]) -> NNr + 1. %%Speichert Nachricht in DLQ, fuegt Zeitstempel hinzu, Rueckgabe: Modifizierte DLQ %%push2DLQ([NNr, Msg, TSclientout, TShbqin], Queue, Datei) %%Fehlt noch: Abfrage, ob das die passende Nummer ist! push2DLQ([NNr, Msg, TSclientout, TShbqin], [DLQ,Size], Datei) -> if length(DLQ) < Size -> werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", NNr, " in DLQ eingefügt.\n"])), [[[NNr, Msg, TSclientout, TShbqin, erlang:now()] | DLQ], Size]; length(DLQ) =:= Size -> [LastNNr, _Msg, _TSclientout, _TShbqin, _TSdlqin] = lists:last(DLQ), werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", LastNNr, " aus DLQ entfernt.\n"])), werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", NNr, " in DLQ eingefügt.\n"])), [[[NNr, Msg, TSclientout, TShbqin, erlang:now()] | lists:droplast(DLQ)], Size] end. %%Sendet Nachricht an Leser-Client deliverMSG(MSGNr, ClientPID, Queue, Datei) -> %%Aendern: MSGNer = -1, flag am Ende der Reply (siehe zeile 42) [{NewestNr,Msg}|Rest] = Queue, if MSGNr > NewestNr -> DummyMessage = {-1,lists:concat(["DLQ in: ",werkzeug:timeMilliSecond()])}, %% -1 Flag werkzeug:logging(Datei, lists:concat(["DLQ>>> DummyNachricht fuer ",MSGNr," an Client ",ClientPID, " ausgeliefert.\n"])), ClientPID ! {reply,Msg,true} end, %%%%%%Ab hier noch aendern bzgl Flag FoundMatch = lists:keyfind(MSGNr, 1, Queue), if FoundMatch =:= false -> deliverMSG(MSGNr+1, ClientPID, Queue, Datei), if MSGNr =:= NewestNr -> {Number,Msg} = FoundMatch, NewMessage = {Number,lists:concat(Msg,["DLQ in: ",werkzeug:timeMilliSecond()],-1)}, werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", Number, " an Client ",ClientPID, " ausgeliefert.\n"])), ClientPID ! {reply,Msg,false}; true -> {Number,Msg} = FoundMatch, NewMessage = {Number,lists:concat(Msg,["DLQ in: ",werkzeug:timeMilliSecond()],0)}, werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", Number, " an Client ",ClientPID, " ausgeliefert.\n"])), ClientPID ! {reply,Msg,false} end; true -> ok end. CMEM: -module(cmem). -export([initCMEM/2, delCMEM/1, updateClient/4, getClientNNr/2]). -import(werkzeug, [get_config_value/2,lengthSL/1,logging/2,reset_timer/3,get_config_value/2,getUTC/0]). %%Initialisiert CMEM initCMEM(RemTime, Datei) -> werkzeug:logging(Datei, lists:concat(["CMEM>>> initialisiert mit ", RemTime, " Sekunden\n"])), [[], RemTime]. %%Loescht CMEM delCMEM(_CMEM) -> ok. %%Speichert/aktualisiert Client und NNr im CMEM, updateClient([CMEM, RemTime], ClientID, NNr, Datei) -> ClientTS = getUTC(), logging(Datei, lists:concat(["CMEM>>> Client ", ClientID, " wird aktualisiert.\n"])), [lists:keystore(ClientID, 1, CMEM, {ClientID, NNr, ClientTS}), RemTime]. %%Gibt naechste vom Client erwartete NNr zurueck %%Es wird geprueft ob Client in der Liste steht und dann %%mit diesem Wissen eine Hilfsfunktion aufgerufen getClientNNr([CMEM, RemTime], ClientID) -> ClientBekannt = lists:keymember(ClientID, 1, CMEM), isClientKnown([CMEM, RemTime], ClientID, ClientBekannt). %%Client ist nicht bekannt: Naechste NNr = 1 isClientKnown(_CMEM, _ClientID, false) -> 1; %% Der Client ist bekannt. %%Zeit noch nicht abgelaufen: Gibt naechste Nummer aus %%Zeit abgelaufen: Naechste NNr = 1 isClientKnown([CMEM, RemTime], ClientID, true) -> {ClientID, NNr, ClientTS} = lists:keyfind(ClientID, 1, CMEM), RemainingTime = ClientTS + RemTime, Now = getUTC(), if RemainingTime >= Now -> NNr + 1; true -> 1 end. The client is supposed to contact the server sending it a message, the server puts it in data structures which send it back to the client under the right circumstances. The problem is, when I compile them, the start the HBQ, then the server and then the client, I get =ERROR REPORT==== 18-Apr-2017::10:25:46 === Error in process <0.104.0> with exit value: {distribution_not_started,[{auth,set_cookie,2,[{file,"auth.erl"},{line,119}]},{client,mitServerVerbinden,6,[{file,"client.erl"},{line,42}]}]} So apparently there is an issue with the client not connecting to the server. This is my first time working with Erlang and distributed systems, so I have no idea what is going on. Is it not enough to put the nodes and cookie into the configs and tell the components of the system to look there?
The error distribution_not_started is returned by the auth module when the erlang VM calling it does not have a name. Ensure that a -sname or -name flag is passed when starting erlang e.g.: erl -sname test
decodingTCAP message - dialoguePortion
I'm writing an simulator (for learning purposes) for complete M3UA-SCCP-TCAP-MAP stack (over SCTP). So far M3UA+SCCP stacks are OK. M3UA Based on the RFC 4666 Sept 2006 SCCP Based on the ITU-T Q.711-Q716 TCAP Based on the ITU-T Q.771-Q775 But upon decoding TCAP part I got lost on dialoguePortion. TCAP is asn.1 encoded, so everything is tag+len+data. Wireshark decode it differently than my decoder. Message is: 62434804102f00676b1e281c060700118605010101a011600f80020780a1090607040000010005036c1ba1190201010201163011800590896734f283010086059062859107 Basically, my message is BER-decoded as Note: Format: hex(tag) + (BER splitted to CLS+PC+TAG in decimal) + hex(data) 62 ( 64 32 2 ) 48 ( 64 0 8 ) 102f0067 6b ( 64 32 11 ) 28 ( 0 32 8 ) 06 ( 0 0 6 ) 00118605010101 OID=0.0.17.773.1.1.1 a0 ( 128 32 0 ) 60 ( 64 32 0 ) 80 ( 128 0 0 ) 0780 a1 ( 128 32 1 ) 06 ( 0 0 6 ) 04000001000503 OID=0.4.0.0.1.0.5.3 6c ( 64 32 12 ) ... So I can see begin[2] message containing otid[8], dialogPortion[11] and componentPortion[12]. otid and ComponentPortion are decoded correctly. But not dialogPortion. ASN for dialogPortion does not mention any of these codes. Even more confusing, wireshark decode it differently (oid-as-dialogue is NOT in the dialoguePortion, but as a field after otid, which is NOT as described in ITU-T documentation - or not as I'm understanding it) Wireshark decoded Transaction Capabilities Application Part begin Source Transaction ID otid: 102f0067 oid: 0.0.17.773.1.1.1 (id-as-dialogue) dialogueRequest Padding: 7 protocol-version: 80 (version1) 1... .... = version1: True application-context-name: 0.4.0.0.1.0.5.3 (locationInfoRetrievalContext-v3) components: 1 item ... I can't find any reference for Padding in dialoguePDU ASN. Can someone point me in the right direction? I would like to know how to properly decode this message DialoguePDU format should be simple in this case: dialogue-as-id OBJECT IDENTIFIER ::= {itu-t recommendation q 773 as(1) dialogue-as(1) version1(1)} DialoguePDU ::= CHOICE { dialogueRequest AARQ-apdu, dialogueResponse AARE-apdu, dialogueAbort ABRT-apdu } AARQ-apdu ::= [APPLICATION 0] IMPLICIT SEQUENCE { protocol-version [0] IMPLICIT BIT STRING {version1(0)} DEFAULT {version1}, application-context-name [1] OBJECT IDENTIFIER, user-information [30] IMPLICIT SEQUENCE OF EXTERNAL OPTIONAL }
Wireshark is still wrong :-). But then... that is display. It displays values correctly - only in the wrong section. Probably some reason due to easier decoding. What I was missing was definition of EXTERNAL[8]. DialoguePortion is declared as EXTERNAL...so now everything makes sense.
For your message, my very own decoder says: begin [APPLICATION 2] (x67) otid [APPLICATION 8] (x4) =102f0067h dialoguePortion [APPLICATION 11] (x30) EXTERNAL (x28) direct-reference [OBJECT IDENTIFIER] (x7) =00118605010101h encoding:single-ASN1-type [0] (x17) dialogueRequest [APPLICATION 0] (x15) protocol-version [0] (x2) = 80 {version1 (0) } spare bits= 7 application-context-name [1] (x9) OBJECT IDENTIFIER (x7) =04000001000503h components [APPLICATION 12] (x27) invoke [1] (x25) invokeID [INTEGER] (x1) =1d (01h) operationCode [INTEGER] (x1) = (22) SendRoutingInfo parameter [SEQUENCE] (x17) msisdn [0] (x5) = 90896734f2h Nature of Address: international number (1) Numbering Plan Indicator: unknown (0) signal= 9876432 interrogationType [3] (x1) = (0) basicCall gmsc-Address [6] (x5) = 9062859107h Nature of Address: international number (1) Numbering Plan Indicator: unknown (0) signal= 26581970 Now, wireshark's padding 7 and my spare bits=7 both refer to the the protocol-version field, defined in Q.773 as: AARQ-apdu ::= [APPLICATION 0] IMPLICIT SEQUENCE { protocol-version [0] IMPLICIT BIT STRING { version1 (0) } DEFAULT { version1 }, application-context-name [1] OBJECT IDENTIFIER, user-information [30] IMPLICIT SEQUENCE OF EXTERNAL OPTIONAL } the BIT STRING definition, assigns name to just the leading bit (version1)... the rest (7 bits) are not given a name and wireshark consider them as padding