How can connect to SSL in JAVA with websocket and socket.io? - android

How can access to wss:// protocol in java ?
i use benkay / java-socket.io.client
but it's not support wss protocol.
i tried use SSLEngine. but it's very hard work.
how can connect to ssl in java ?
I tried change SocketChannel by SSLEngine. but it is not worked.
ssl channel is ok. but i can't wire this original websocket part.
this is source code.
client = SocketChannel.open(remote);
client.configureBlocking(false);
//client.connect(remote);
selector = Selector.open();
this.conn = new WebSocket(client, new LinkedBlockingQueue<ByteBuffer>(), this);
client.register(selector, SelectionKey.OP_READ);
try {
sslClient = new SSLClient(keyStore, storepass.toCharArray(), client);
sslClient.beginHandShake();
startClient()
} catch (Exception e) {
e.printStackTrace();
}
this point uncorret ?? i don't know .. not same the original websocket code.. may problem is this point. how can fix it ??
public void startClient()
{
try
{
while(true)
{
if(selector.select() <= 0)
{
continue;
}
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while(it.hasNext())
{
SelectionKey key = (SelectionKey)it.next();
Log.e("key","key");
if(key.isReadable())
{
read(key);
}
it.remove();
}
}
}
catch(Exception e)
{
}
}
and SSLClient is http://rapidant.tistory.com/attachment/cfile25.uf#121346414D45B0960BD01B.zip
key store : change JKS to BKS, not problem.
how can wrap the SocketChannel ?
(Web browser it worked.)

You could check out my fork of the Autobahn WebSocket Library.
Secure WebSockets based upon Autobahn
You don't want to use SSLEngine on Android because it is broken.

Related

File transfer using Smack 4.2.3 gives service-unavailable error

I’m developing XMPP client using smack 4.2.3. Using ejabberd as an XMPP server on linux platform.
Using following code to send file:
public static void sendFile(String path, String description){
String sFqdn = currentUser.getFqdn();
if(sFqdn.equals(null)) return;
String node = XmppStringUtils.parseLocalpart(sFqdn);
String domain = XmppStringUtils.parseDomain(sFqdn);
String resource = XmppStringUtils.parseResource(sFqdn);
try {
EntityFullJid fqdn = entityFullFrom(node, domain, resource);
OutgoingFileTransfer transfer = FileTransferManager.getInstanceFor(connection).createOutgoingFileTransfer(fqdn);
transfer.sendFile(new File(path), description);
} catch (SmackException e) {
e.printStackTrace();
} catch (XmppStringprepException e) {
e.printStackTrace();
}
}
and to receive:
if(fileTransferManager == null){
fileTransferManager = FileTransferManager.getInstanceFor(connection);
fileTransferManager.addFileTransferListener(new FileTransferListener() {
#Override
public void fileTransferRequest(final FileTransferRequest request) {
// Accept it
IncomingFileTransfer transfer = request.accept();
try {
transfer.recieveFile(new File(dir_path+request.getFileName()));
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
});
}
sometimes it successfully sends a file between users, but most of the time i get this XMPP error:
D/SMACK: RECV (1): <iq xml:lang=‘en’ to=‘bob#domain/122573506394002920791746’ from=‘tom#domain/126676407739368221821682’ type=‘set’ id=‘VdzEA-77’><si xmlns=‘http: //jabber .org/protocol/si’ id=‘jsi_8874207690796615693’ mime-type=‘image/png’ profile=‘http ://jabber .org/protocol/si/profile/file-transfer’><desc>test file</desc></file><feature xmlns=‘http ://jabber .org/protocol/feature-neg’><x xmlns=‘jabber:x:data’ type=‘form’><field var=‘stream-method’ type=‘list-single’><option><value>http ://jabber .org/protocol/bytestreams</value></option><option><value>http ://jabber .org/protocol/ibb</value></option></field></x></feature></iq><r xmlns=‘urn:xmpp:sm:3’/>
D/SMACK: SENT (1): <iq to=‘tom#domain/126676407739368221821682’ id=‘VdzEA-77’ type=‘error’><error type=‘cancel’><service-unavailable xmlns=‘urn:ietf:params:xml:ns:xmpp-stanzas’/></error></iq>
In ejabberd config file I’ve successfully enabled the module “mod_proxy65”
One reason I can think of is that it might happening due to continuous presence changed by the receiver, that changes its resource.
Although I’m keeping the track of presence in Roster’s presenceChanged() method but still no success. I’m wondering if there is any way in smack to connect to server with a static resource?
One more thing, is there any example for HTTP_FILE_UPLOAD (XEP-0363), I can’t find any in smacks official documentation.
After discussion at ignite realtime's forum, I found out that I was hitting a bug.
A work around to this bug is forced in-band byte stream.
Setting FileTransferNegotiator.IBB_ONLY to true did the trick for me.
Please take a look at line 76 in FileTransferNegotiator class as well.

Apps did not download after vpn is connected

I am making an application that block certain webs and application but problem is on Some devices manufacture Like Motorola and HTC (android OS nougat and oreo) apps did not download and update after VPN is Connected But Internet Work perfectly.I am using Local VPN to monitor Network Trafic. Please Help i am stuck on this stage.
I tried all methods mention on the google
https://www.androidpit.com/google-play-not-working
http://appslova.com/android-fix-error-495-in-google-play-store/
http://techknowzone.com/how-to-solve-fix-error-code-495-in-google-play-store/
Below is the Snipped of local VPN Code
private void connect() {
int i;
isRunning=true;
Builder builder = new Builder();
StringBuilder stringBuilder = new StringBuilder("10.0.0.");
if (lastInt == 254) {
i = 0;
lastInt = 0;
} else {
i = lastInt;
lastInt = i + 1;
}
this.localAddress = stringBuilder.append(i).toString();
try {
if (this.parcelFileDescriptor != null) {
this.parcelFileDescriptor.close();
}
} catch (Exception e) {
}
try {
builder.addAddress(this.localAddress, 24);
builder.addDnsServer(dns1);
builder.addDnsServer(dns2);
this.parcelFileDescriptor = builder.setSession(getString(R.string.app_name)).setConfigureIntent(this.pendingIntent).establish();
Intent intent = new Intent("STARTEDDNSCHANGER");
intent.setAction(getPackageName() + ".STARTED_DNS_CHANGER");
sendBroadcast(intent);
} catch (Throwable e2) {
throw new IllegalArgumentException(e2);
}
}
Play downloads apps over HTTPS. If you are getting error 495 it suggests that the VPN is interfering with the HTTPS / TLS handshaking, and so Play won't download the apps. Possibly you don't support the cipher algorithm negotiation properly.

Socket.IO connect with Params Android

We are developing an App on iOS and Android that includes implementation of socket.io for quick messaging.
For iOS we are using Socket Connection with params, where we send the 'user_id' in configuration and the server receives it.
We are unable to find, the Android implementation of the same scheme.
Following is the iOS code.
// creating dictionary/json to be sent on connection
var dic = NSMutableDictionary()
dic.setValue(["user_id": Profile().getProfile(atr: "_id") as! String], forKey: "connectParams")
// creating socket.io object and passing dictionary into config
socket = SocketIOClient(socketURL: NSURL(string: "http://something.com")!, config: dic as! NSDictionary )
socket!.connect() // works perfectly
I think you have to do like this. Please try it and let me know is it working for you.
Socket socket = null;
try {
IO.Options mOptions = new IO.Options();
mOptions.query = "userId=" + mUserId;
socket = IO.socket(url, mOptions);
} catch (URISyntaxException e) {
return Observable.error(e);
}
socket.connect();

Is the usage of TcpClients in unity3d for android possible?

I am trying to make an andorid app that commuicates with my server via Unity 5.4. The Devices need to be in the same network to do so.
For that i am using System.Net.Sockets and a TcpClient to connect to my server. Everything works well when i run it out of the Editor, or build it as a Windows standalone.The communication between a pc hosting the service and a diffrent pc running the standalone is possible and working as intended. As soon as i build it as an .apk and install it on my smartphone i will get a SocketException. Also my phone is stuck loading for quite some time
Is using a TcpClient, is that possible on android with unity3d ?
The Exception i get is:
System.Net.Sockets.SocketException: Connection timed out
I made sure that both devices are in the same network, e.g. the Ip for my Pc hosting the server is 192.168.178.24 and the ip for my smartphone is 192.168.178.113.
The ports required are open and the firewall lets data through.
I am runnig this code in Unity:
private TcpClient client;
private StreamWriter writer;
void Start()
{
try
{
client = new TcpClient(AddressFamily.InterNetwork);
IPAddress ipAddress = IPAddress.Parse(PlayerPrefs.GetString(MenuManager.IpPlayerPrefKey));
Debug.Log(ipAddress.ToString());
client.Connect(ipAddress, 11000);
writer = new StreamWriter(client.GetStream());
Debug.Log("connected");
}
catch (ArgumentNullException ane)
{
Debug.Log(string.Format("ArgumentNullException : {0}", ane.ToString()));
}
catch (SocketException se)
{
Debug.Log(string.Format("SocketException : {0}", se.ToString()));
}
catch (Exception e)
{
Debug.Log(string.Format("Unexpected exception : {0}", e.ToString()));
}
}
i double checked if the Ip adress recieved from the player prefs is correct, it is.
Has someone an idea what causes it to not even establish a connection ? I tried Wireshark on my pc, it didn't show any incoming packages, so my guess is the mistake is sometimes during establishing the connection.
Here is an image for my Log output from the smartphone:
LogCat Output
Edit: Server Code
public class ServiceListener
{
public TcpListener Listener;
public void StartListening()
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = Array.Find<IPAddress>(ipHostInfo.AddressList, ipMatch => ipMatch.AddressFamily == AddressFamily.InterNetwork);
Listener = new TcpListener(ipAddress, 11000);
Listener.Start();
}
public void StopListening()
{
Listener.Stop();
}
}
static void Main()
{
ServiceListener currentListener = new ServiceListener();
currentListener.StartListening();
TcpClient currentClient = currentListener.Listener.AcceptTcpClient();
StreamReader reader = new StreamReader(currentClient.GetStream());
Console.WriteLine("Connected");
while (true)
{
byte[] messageBytes = new byte[1024];
if (!reader.EndOfStream)
{
string message = reader.ReadLine();
string[] messageParts = message.Split('|');
int xOffset = int.Parse(messageParts[0]);
int yOffset = int.Parse(messageParts[1]);
bool leftClick = bool.Parse(messageParts[2]);
bool rightClick = bool.Parse(messageParts[3]);
Console.WriteLine(string.Format("x:{0},y:{1},left:{2},right:{3}", xOffset, yOffset, leftClick, rightClick));
}
else
{
currentClient = currentListener.Listener.AcceptTcpClient();
reader = new StreamReader(currentClient.GetStream());
}
}
}
Is using a TcpClient, is that possible on android with unity3d ?
Yes, it is. It is very possible and should work.
Your problem is very likely to come from this line of code:
IPAddress ipAddress = IPAddress.Parse(PlayerPrefs.GetString(MenuManager.IpPlayerPrefKey));
Since your hosting server IP is 192.168.178.24. Hardcode the value for testing purposes to see if PlayerPrefs.GetString(MenuManager.IpPlayerPrefKey) is returning an invalid IP Address.
Maybe something like:
IPAddress ipAddress = IPAddress.Parse("192.168.178.24");
Another thing to do in your server code is to put Application.runInBackground = true; in your Start() function. This will make sure that your server is running even when the Applciation is not on focus.
Finally, you are currently using synchronous server socket. When connecting, receiving data from the server, Unity will block/freeze until that operation completes. You should use asynchronous socket or run your server and client code in another Thread. This does not look like the current problem but you will run into it later on.

Android Socket.io Websocket Transport does not works in SSL

I'm using gottox socket.io java client for an Android chat application. I could connect to both web-socket and Xhr transport in HTTP mode. But when i switch to HTTPS only Xhr mode is working. i used the default SSL Context as below
SocketIO.setDefaultSSLSocketFactory(SSLContext.getInstance("Default"));
This works fine in Xhr mode. But in websocket transport there are no responses or errors.
Update
It might be that with new versions IO.setDefaultSSLContext and IO. setDefaultHostnameVerifier methods are not available. Instead now we can create our own OkHttpClient and set the hostname verifier and ssl socket factory etc on it as mentioned on socket.io-client-java usage. Here is the sniplet from there:
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.hostnameVerifier(myHostnameVerifier)
.sslSocketFactory(mySSLContext.getSocketFactory(), myX509TrustManager)
.build(); // default settings for all sockets
IO.setDefaultOkHttpWebSocketFactory(okHttpClient);
IO.setDefaultOkHttpCallFactory(okHttpClient);
Initial Answer:
I had the same issue with io.socket:socket.io-client:0.7.0 version of socket.io library on Android for long. It used to work fine for http protocol, however for https protocol it had trouble establishing connection giving xhr poll errors.
Following solution works for me without modifying the library itself:
// Socket connection
private Socket mSocket;
// Configure options
IO.Options options = new IO.Options();
// ... add more options
// End point https
String yourEndpoint = "https://whatever.yoururl.com"
String yourHostName = "yoururl.com"
// If https, explicitly tell set the sslContext.
if (yourEndpoint.startsWith("https://")) {
try {
// Default settings for all sockets
// Set default ssl context
IO.setDefaultSSLContext(SSLContext.getDefault());
// Set default hostname
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
return hv.verify(yourHostName, session);
}
};
IO.setDefaultHostnameVerifier(hostnameVerifier);
// set as an option
options.sslContext = SSLContext.getDefault();
options.hostnameVerifier = hostnameVerifier;
options.secure = true;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
// Instantiate the socket
mSocket = IO.socket(mEndpoint, options);
Hope this helps.
It works but you have to do some modifications on io.socket library.
Instead of using the socketio.jar, import into src folder the io.socket library (You'll find inside socket.io-java-client package). There, you have to edit the WebsocketTransport class.
Here you have the solution
https://github.com/Gottox/socket.io-java-client/issues/60
public WebsocketTransport(URI uri, IOConnection connection) {
super(uri);
this.connection = connection;
SSLContext context = null;
try {
context = SSLContext.getInstance("TLS", "HarmonyJSSE");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
try {
context.init(null, null, null);
} catch (KeyManagementException e) {
e.printStackTrace();
}
if("wss".equals(uri.getScheme()) && context != null) {
this.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(context));
}
}
And remember to call the setDefaultSSLSocketFactory like this:
socket = new SocketIO();
socket.setDefaultSSLSocketFactory(SSLContext.getDefault());
socket.connect("https://www.myHttpsServer.com:443/");
Hope it helps someone ;)
Websocket with SSL working in AndroidAsync. Using that for now.

Categories

Resources