CAP Dialog not found for Dialog Id - mobicents

I am using SS7 Stack to receive IDP packets and forward to core using a new dialog.
I am able to successfully forward the request using following code:
#Override
public void onInitialDPRequest(InitialDPRequest arg0) {
try {
String refId = StringUtility.createRefId("sc");
logger.info("[" + refId + "] IDP Recieved");
String outgoingGTDigits = "92308985051";
int calledSSN = 146;
int remotePC = 3003;
SccpAddress remoteAddress = MapUtilities.getSccpAddress(RoutingIndicator.ROUTING_BASED_ON_GLOBAL_TITLE, outgoingGTDigits, calledSSN, remotePC);
arg0.getCAPDialog().setRemoteAddress(remoteAddress);
logger.debug("[" + refId + "] Forwading to Core with remoteAddress [" + remoteAddress + "]");
InitialDPRequestImpl initialDPRequestImpl = (InitialDPRequestImpl) arg0;
Invoke invoke = SCCPProxy.tcapStack_cap.getProvider().getComponentPrimitiveFactory()
.createTCInvokeRequest(InvokeClass.Class2);
invoke.setTimeout(_Timer_CircuitSwitchedCallControl_Short);
OperationCode oc = SCCPProxy.tcapStack_cap.getProvider().getComponentPrimitiveFactory().createOperationCode();
oc.setLocalOperationCode((long) CAPOperationCode.initialDP);
AsnOutputStream aos = new AsnOutputStream();
initialDPRequestImpl.encodeData(aos);
Parameter p = SCCPProxy.tcapStack_cap.getProvider().getComponentPrimitiveFactory().createParameter();
p.setTagClass(initialDPRequestImpl.getTagClass());
p.setPrimitive(initialDPRequestImpl.getIsPrimitive());
p.setTag(initialDPRequestImpl.getTag());
p.setData(aos.toByteArray());
invoke.setParameter(p);
invoke.setOperationCode(oc);
// Create a new dialog
Dialog clientDialog = SCCPProxy.tcapStack_cap.getProvider().getNewDialog(arg0.getCAPDialog().getLocalAddress(), remoteAddress);
invoke.setInvokeId(clientDialog.getLocalDialogId());
clientDialog.sendComponent(invoke);
logger.debug("[" + refId + "] set invoke id " + clientDialog.getLocalDialogId());
//long[] _ACN_ = new long[]{0, 4, 0, 0, 1, 0, 19, 2};
ApplicationContextName acn = SCCPProxy.tcapStack_cap.getProvider().getDialogPrimitiveFactory()
.createApplicationContextName(arg0.getCAPDialog().getApplicationContext().getOID());
// Create begin request
TCBeginRequest tcbr = SCCPProxy.tcapStack_cap.getProvider().getDialogPrimitiveFactory().createBegin(clientDialog);
tcbr.setApplicationContextName(acn);
clientDialog.send(tcbr);
logger.info("[" + refId + "] Forwaded to core with id: " + clientDialog.getLocalDialogId());
} catch (Exception ex) {
logger.error("Exception: ", ex);
}
}
TCPDump
Now when core node replies to this packet (packet #3) . I am getting CAP Dialog not found for Dialog Id n in sigtran logs.
Sigtran Logs
Am I forwarding packet correctly?

It's a little bit more complicated.
I may assume that you want to handle all in same Sbb..
When you create a new capDialog(clientDialog in your case), it created with new TCAP otid and dtid. So even when you receive a response in terms of new capDialog, you have to correlate it with original capDialog.
Sbb knows only about ActivityContext from initial event, as you didn't attach sbbLocalObject to new ActivityContext.
It's better to use Parent->Child architecture for such tasks. Parent Sbb handles all original dialog events. Child Sbb creates new dialog, attach sbbLocalObject to new ActivityContext and handles all related events for new dialog.

I was able to forward packet and get reply without any issue by doing following changes:
Have to create new dialog like this
CAPDialogCircuitSwitchedCall capDialog = capProvider.getCAPServiceCircuitSwitchedCall().createNewDialog(arg0
.getCAPDialog().getApplicationContext(), proxyOwnAddress, destinationAddress, arg0.getCAPDialog().getRemoteDialogId());
Copy payload from original dialog and put in new dialog
capDialog.addInitialDPRequest((int) arg0.getInvokeId(),
arg0.getServiceKey(), arg0.getCalledPartyNumber(),
arg0.getCallingPartyNumber(), arg0.getCallingPartysCategory(),
arg0.getCGEncountered(), arg0.getIPSSPCapabilities(),
arg0.getLocationNumber(), arg0.getOriginalCalledPartyID(),
arg0.getExtensions(), arg0 .getHighLayerCompatibility(),
arg0.getAdditionalCallingPartyNumber(), arg0.getBearerCapability(),
arg0.getEventTypeBCSM(), arg0 .getRedirectingPartyID(),
arg0.getRedirectionInformation(), arg0.getCause(),
arg0.getServiceInteractionIndicatorsTwo(),
arg0.getCarrier(),
arg0.getCugIndex(), arg0.getCugInterlock(),
arg0.getCugOutgoingAccess(), arg0.getIMSI(),
arg0.getSubscriberState(), arg0 .getLocationInformation(),
arg0.getExtBasicServiceCode(), arg0.getCallReferenceNumber(),
arg0.getMscAddress(), arg0 .getCalledPartyBCDNumber(),
arg0.getTimeAndTimezone(), arg0.getCallForwardingSSPending(),
arg0.getInitialDPArgExtension());
Save and Forward new dialog
dialogHashMap.put(capDialog.getLocalDialogId(), arg0.getCAPDialog());
capDialog.setReturnMessageOnError(true);
capDialog.send();
logger.info("[" + refId + "] Forwaded with id: " +
capDialog.getLocalDialogId());
Retrieve and reply
So now when I received the reply from core. I just needed to retrieve original dialog from dialogHashMap using local dialogId and reply back

Related

Unity Lobby/Relay - joining by code results in error 400 Bad Request

as a beginner I am trying to test new Unity Packages - Unity Lobby and Unity Relay to make multiplayer card game. Quick joining lobby and creating a lobby works fine but I have encountered a problem with joining lobby using Join Code. Here's the code:
public async void JoinByCode() {
string lobbyCode = InputField.text;
Debug.Log(lobbyCode);
Debug.Log("Searching for lobby with code " + lobbyCode + "...");
// UpdateState ?.Invoke("Searching for lobby with code " + lobbyCode + "...");
try {
JoinLobbyByCodeOptions options = new JoinLobbyByCodeOptions();
Lobby lobby = await Lobbies.Instance.JoinLobbyByCodeAsync(lobbyCode, options); //<--- results in error 400 - Bad Request
Debug.Log(lobby);
Debug.Log("Joined lobby: " + lobby.Id);
Debug.Log("Players in lobby: " + lobby.Players.Count);
//RelayCode
string joinCode = lobby.Data["joinCode"].Value;
Debug.Log("Kod dostępu: " + joinCode);
JoinAllocation allocation = await Relay.Instance.JoinAllocationAsync(joinCode);
//obiekt joindata
_joinData = new RelayJoinData {
Key = allocation.Key,
Port = (ushort) allocation.RelayServer.Port,
AllocationID = allocation.AllocationId,
AllocationIDBytes = allocation.AllocationIdBytes,
ConnectionData = allocation.ConnectionData,
HostConnectionData = allocation.HostConnectionData,
IPv4Address = allocation.RelayServer.IpV4
};
_joinData.JoinCode = await Relay.Instance.GetJoinCodeAsync(allocation.AllocationId);
NetworkManager.Singleton.GetComponent<UnityTransport>().SetClientRelayData(
_joinData.IPv4Address,
_joinData.Port,
_joinData.AllocationIDBytes,
_joinData.Key,
_joinData.ConnectionData,
_joinData.HostConnectionData
);
NetworkManager.Singleton.StartClient();
Debug.Log("Found lobby, code: " + joinCode);
UpdateState?.Invoke("Joining lobby, code: " + joinCode + ", players in lobby: " + lobby.Players.Count);
MatchFound?.Invoke();
} catch (LobbyServiceException e) {
Debug.Log("There's a problem finding lobby, try again. " + e);
}
}
In general: Join Code is passed from InputField, then to JoinLobbyByCodeAsync, then send player data to server. The problem is with variable lobby - when I am trying to test JoinByCode, it results with error:
There's a problem finding lobby, try again. Unity.Services.Lobbies.LobbyServiceException: request failed validation ---> Unity.Services.Lobbies.Http.HttpException`1[Unity.Services.Lobbies.Models.ErrorStatus]: HTTP/1.1 400 Bad Request
and I have no idea how to solve this problem. Yes, I was using Unity Documentation for Lobby and trying to find any info about error 400 in Lobby. I will be really grateful if someone could help me with this problem. Cheers!
I had a similar problem, in my case the input contained an extra character. Make sure that there are only 6 characters in your variable "lobbyCode" by checking it with lobbyCode.Length. Also make sure that you have activated the Lobby and Relay service in the dashboard.
My post to this problem:
https://forum.unity.com/threads/problem-joining-a-private-lobby-through-lobbycode-joinlobbybycodeasync.1287908/#post-8171102

UDP Server, Output doubles after each Loop

i have a UDP Server/Client Program wich works well.
I send the received Message from one Client back to all connected Clients, but the Output doubles after each Loop.
I think i have to reset the ListArray with the Clients, but then only the first Message will be Send.
Does somebody has any idea? Thanks!
UDP SERVER
//Listening on Port 12222
int servPort = 12222;
UdpClient client = null;
//Create a new ListArray for the connected Clients
ArrayList IPArray = new ArrayList();
try
{
//Create an instance of UdpClient
client = new UdpClient(servPort);
}
catch (SocketException se)
{
Console.WriteLine(se.ErrorCode + ": " + se.Message);
Environment.Exit(se.ErrorCode);
}
//Create an new IPEndPoint
IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
//Endless loop
for (; ; )
{
try
{
//Receive a byte array with contents
byte[] byteBuffer = client.Receive(ref remoteIPEndPoint);
//Message from Client
string returnData = Encoding.ASCII.GetString(byteBuffer);
//Add connected Client IPs to ListArray
IPArray.Add(remoteIPEndPoint);
//Send the received Message back to all Clients in the ArrayList
for (int i = 0; i < IPArray.Count; i++)
{
Console.WriteLine("Handling client at " + IPArray[i] + " - " + returnData + " arraylist.Length " + IPArray.Count + "\n");
Byte[] sendBytes = Encoding.ASCII.GetBytes("Clients Send " + returnData + "\n");
client.Send(sendBytes, sendBytes.Length, (IPEndPoint)IPArray[i]);
}
Console.WriteLine("echoed {0} bytes.", byteBuffer.Length);
}
catch (SocketException se)
{
Console.WriteLine(se.ErrorCode + ": " + se.Message);
}
}
}
UDP CLIENT
//Server name or IP address
static String server = "127.0.0.1";
//Port
static int servPort = 12222;
//Convert String to an array of bytes
static string message = "ICH";
static void Main(string[] args)
{
SendReceive();
}
static byte[] sendPacket = Encoding.ASCII.GetBytes(message);
//Create an instance of UdpClient
static UdpClient client = new UdpClient();
static void SendReceive()
{
try
{
//Send the string to the specified Server and Port
client.Send(sendPacket, sendPacket.Length, server, servPort);
Console.WriteLine("Sent {0} bytes to the server...", sendPacket.Length);
IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
//Attempt Message reply receive
byte[] rcvPacket = client.Receive(ref remoteIPEndPoint);
Console.WriteLine("Received {0} bytes from {1}: {2}",
rcvPacket.Length, remoteIPEndPoint,
Encoding.ASCII.GetString(rcvPacket, 0, rcvPacket.Length));
}
catch (SocketException se)
{
Console.WriteLine(se.ErrorCode + ": " + se.Message);
}
//Console.ReadKey();
//client.Close();
Thread.Sleep(500);
//Endless Loop
SendReceive();
}
UDP SERVER :
The Array with the iP Adresses grows with every Message from the
Client, but i want only the last Message that the Clients has send.
If that is the requirement, then there is no need of the loop. Also, without the help of arraylist, you can display the details of individual clients using the remoteIPEndPoint itself. That is the neater way to do what you want.
Remove the following lines from the UDP Server :
...
//Send the received Message back to all Clients in the ArrayList
for (int i = 0; i < IPArray.Count; i++)
{
Console.WriteLine("Handling client at " + IPArray[i] + " - " + returnData + " arraylist.Length " + IPArray.Count + "\n");
Byte[] sendBytes = Encoding.ASCII.GetBytes("Clients Send " + returnData + "\n");
client.Send(sendBytes, sendBytes.Length, (IPEndPoint)IPArray[i]);
}
...
You need to display the IP-Address and the port number of the client which sent the message. Instead, add the following lines :
//1. Now, you can show the count, but, you can get the indiviudal client detail
//using the remoteIPEndPoint, there is no need of iterating through the array.
Console.WriteLine("This message was sent from " + remoteIPEndPoint.Address.ToString() +
" on their port number " +
remoteIPEndPoint.Port.ToString() + " - " + returnData + "\n");
//2. Then send the data back to the individual client without using ArrayList,
// by passing the client's IPEndPoint in the Send() method.
Byte[] sendBytes = Encoding.ASCII.GetBytes("Clients Send " + returnData + "\n");
client.Send(sendBytes, sendBytes.Length, remoteIPEndPoint);
What it does is that it shows the IP-Address and the port number of the client which sent the message to the server.\
Also, the current way is not a better way for network/socket programming. You should always use separate threads(limit them in a pool using ConnectionQueue) for receving each client's message. Use a ConnectionQueue to maintain an order of threads (which can be reused for each new client-request).

Error emailing outgoing sms

Is there anyway to listen for an outbound sms without having to import javax.wireless.messaging?
I'm trying to write an app that listens for an sms sent from the device then emails the message of the sms, but I get the error:
reference to Message is ambiguous, both class
javax.wireless.messaging.Message in javax.wireless.messaging and class
net.rim.blackberry.api.mail.Message in net.rim.blackberry.api.mail
match
I need to import net.rim.blackberry.api.mail.Message in order to sent an email.
Is there a way to get around this as it seems that the two packages are clashing.
My code:
public void notifyIncomingMessage(MessageConnection messageconnection) {}
public void notifyOutgoingMessage(javax.wireless.messaging.Message message) {
try {
String address = message.getAddress();
String msg = null;
if ( message instanceof TextMessage ) {
TextMessage tm = (TextMessage)message;
msg = tm.getPayloadText();
} else if (message instanceof BinaryMessage) {
StringBuffer buf = new StringBuffer();
byte[] data = ((BinaryMessage) message).getPayloadData();
msg = new String(data, "UTF-8");
Store store = Session.getDefaultInstance().getStore();
Folder[] folders = store.list(Folder.SENT);
Folder sentfolder = folders[0];
Message in = new Message(sentfolder);
Address recipients[] = new Address[1];
recipients[0]= new Address("me#us.com", "user");
in.addRecipients(Message.RecipientType.TO, recipients);
in.setSubject("Outgoing sms");
in.setContent("You have just sent an sms to: " + address + "\n" + "Message: " + msg);
in.setPriority(Message.Priority.HIGH);
Transport.send(in);
in.setFlag(Message.Flag.OPENED, true);
Folder folder = in.getFolder();
folder.deleteMessage(in);
}
} catch (IOException me) {
System.out.println(me);
}
}
}
You never should need to import anything in Java. Importing a package is just a shortcut, so that you don't have to fully type out the whole package name. If you have a class named Message that you want to use, and it exists in two packages (both of which you need), then I wouldn't import either of them.
Simply, always refer to each of them by their fully-qualified name:
net.rim.blackberry.api.mail.Message
and
javax.wireless.messaging.Message
It's just a little more typing.

Socket connection gets closed for no apparent reason

I am trying to implement Facebook X_FACEBOOK_PLATFORM SASL mechanism so I could integrate Facebook Chat to my application over XMPP.
Here is the code:
var ak = "my app id";
var sk = "access token";
var aps = "my app secret";
using (var client = new TcpClient())
{
client.Connect("chat.facebook.com", 5222);
using (var writer = new StreamWriter(client.GetStream())) using (var reader = new StreamReader(client.GetStream()))
{
// Write for the first time
writer.Write("<stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" to=\"chat.facebook.com\"><auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-FACEBOOK-PLATFORM\" /></stream:stream>");
writer.Flush();
Thread.Sleep(500);
// I am pretty sure following works or at least it's not what causes the error
var challenge = Encoding.UTF8.GetString(Convert.FromBase64String(XElement.Parse(reader.ReadToEnd()).Elements().Last().Value)).Split('&').Select(s => s.Split('=')).ToDictionary(s => s[0], s => s[1]);
var response = new SortedDictionary<string, string>() { { "api_key", ak }, { "call_id", DateTime.Now.Ticks.ToString() }, { "method", challenge["method"] }, { "nonce", challenge["nonce"] }, { "session_key", sk }, { "v", "1.0" } };
var responseString1 = string.Format("{0}{1}", string.Join(string.Empty, response.Select(p => string.Format("{0}={1}", p.Key, p.Value)).ToArray()), aps);
byte[] hashedResponse1 = null;
using (var prov = new MD5CryptoServiceProvider()) hashedResponse1 = prov.ComputeHash(Encoding.UTF8.GetBytes(responseString1));
var builder = new StringBuilder();
foreach (var item in hashedResponse1) builder.Append(item.ToString("x2"));
var responseString2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}&sig={1}", string.Join("&", response.Select(p => string.Format("{0}={1}", p.Key, p.Value)).ToArray()), builder.ToString().ToLower()))); ;
// Write for the second time
writer.Write(string.Format("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">{0}</response>", responseString2));
writer.Flush();
Thread.Sleep(500);
MessageBox.Show(reader.ReadToEnd());
}
}
I shortened and shrunk the code as much as possible, because I think my SASL implementation (whether it works or not, I haven't had a chance to test it yet) is not what causes the error.
I get the following exception thrown at my face: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
10053
System.Net.Sockets.SocketError.ConnectionAborted
It happens every time I try to read from client's stream for the second time. As you can see i pause a thread here so Facebook server has enough time to answer me, but I used asynchronous approach before and I encountered the exact same thing, so I decided to try it synchronously first. Anyway actual SASL mechanism implementation really shouldn't cause this because if I don't try to authenticate right away, but I send the request to see what mechanisms server uses and select that mechanism in another round of reading and writing, it fails, but when I send mechanism selection XML right away, it works and fails on whatever second I send.
So the conclusion is following: I open the socket connection, write to it, read from it (first read works both sync and async), write to it for the second time and try to read from it for the second time and here it always fails. Clearly then, problem is with socket connection itself. I tried to use new StreamReader for second read but to no avail. This is rather unpleasant since I would really like to implement facade over NetworkStream with "Received" event or something like Send(string data, Action<string> responseProcessor) to get some comfort working with that stream, and I already had the implementation, but it also failed on second read.
Thanks for your suggestions.
Edit: Here is the code of facade over NetworkStream. Same thing happens when using this asynchronous approach, but couple of hours ago it worked, but for second response returned same string as for first. I can't figute out what I changed in a meantime and how.
public void Send(XElement fragment)
{
if (Sent != null) Sent(this, new XmppEventArgs(fragment));
byte[] buffer = new byte[1024];
AsyncCallback callback = null;
callback = (a) =>
{
var available = NetworkStream.EndRead(a);
if (available > 0)
{
StringBuilder.Append(Encoding.UTF8.GetString(buffer, 0, available));
NetworkStream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
}
else
{
var args = new XmppEventArgs(XElement.Parse(StringBuilder.ToString()));
if (Received != null) Received(this, args);
StringBuilder = new StringBuilder();
// NetworkStream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
}
};
NetworkStream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
NetworkStreamWriter.Write(fragment);
NetworkStreamWriter.Flush();
}
The reader.ReadToEnd() call consumes everything until end-of-stream, i.e. until TCP connection is closed.

File transfer using Smack doesn't work

I'm trying to use Smack to transfer a file between two PCs connected on the same XMPP server, but I get a weird error.
To summarize, the destination PC has a FileTransferListener registered, like so:
ftm.addFileTransferListener(new FileTransferListener() {
#Override
public void fileTransferRequest(FileTransferRequest request) {
System.out.println("Request received");
if (true) // Check to see if the request should be accepted
{
// Accept it
System.out.println("Entering FTListener because of FTRequest");
IncomingFileTransfer transfer = request.accept();
String id = request.getDescription();
String path = savePoint + System.getProperty("file.separator") + request.getFileName();
try
{
System.out.println("Receiving...");
transfer.recieveFile(new File(path));
// Information put in HashMap for later retrieval
System.out.println("IM - putting in path (" + id + "," + path + ")");
paths.put(id, path);
} catch (XMPPException e) {
logger.error("Error getting the VM file: " + e.getMessage());
}
}
else
{
// Reject it
request.reject();
logger.info("VM file transfer rejected");
}
}
});
The source PC uses an OutgoingFileTransfer like so:
try
{
String nick = destHost + "#" + this.conn.getServer() + "/Smack";
//destHost = destination host name, conn = XMPP connection
System.out.println("OFT to " + nick);
OutgoingFileTransfer.setResponseTimeout(10000);
OutgoingFileTransfer oft = ftm.createOutgoingFileTransfer(nick);
oft.sendFile(f, name); //f = file to send, name = a message
while (!oft.isDone())
{
if (oft.getStatus().equals(Status.error))
{
System.out.println("ERROR!!! " + oft.getError());
oft.cancel();
return false;
}
System.out.println(oft.getStatus());
System.out.println(oft.getProgress());
System.out.println("5 sec sleep");
Thread.sleep(5000);
}
if (oft.getStatus().equals(Status.complete))
{
System.out.println("Transfer done");
return true;
}
if (oft.getStatus().equals(Status.error))
System.out.println("Transfer failed: " + oft.getError());
return false;
} catch (XMPPException e) {
System.out.println("Error sending VM image file with the FTM : " + e.getMessage());
return false;
} catch (InterruptedException e) {
System.err.println("Error sleeping during OFT : " + e.getMessage());
return false;
}
When I try to send a file, the outgoing file transfer begins, and the destination PC receives the request, but the source PC cannot go further then the transfer negotiation.
This is seen in the source PC output...
Initial
0.0
2 sec sleep
Negotiating Transfer
0.0
2 sec sleep
Negotiating Stream
0.0
2 sec sleep
Transfer failed: null
I'm really annoyed because I don't even get a proper error message, so I don't really know what went wrong.
Has this ever happened to anyone else?
Looks like you are running into a known issue in Smack that will hopefully be fixed in the next release.
Update: This is now fixed and will be in version 3.2.1.
XMPP bytestreams are well specified, but are a rather complex topic, because there is more than one way to establish such a stream.
Your code looks right on a quick review. Now the next step would be to analyze the XMPP stanzas send between both clients and the server. This should give you a hint about the error cause. Also make sure to use smack 3.2.0 which has IBB support, which should increase the chance of a successful file transfer via XMPP.