Secure WebSocket server in Android - java

I am using the AndroidAsync library from GitHub that is provided by koush. I need this library to create a WebSocket server and I was able to create it.
private static List<WebSocket> webSockets = new ArrayList<WebSocket>();
private static AsyncHttpServer httpServer = new AsyncHttpServer();
Here's the implementation:
public static void createWebSocket() {
httpServer.websocket("/", new AsyncHttpServer.WebSocketRequestCallback() {
#Override
public void onConnected(final WebSocket webSocket, AsyncHttpServerRequest request) {
webSockets.add(webSocket);
webSocket.setClosedCallback(new CompletedCallback() {
#Override
public void onCompleted(Exception ex) {
Log.d(TAG, "onCompleted");
}
});
webSocket.setStringCallback(new WebSocket.StringCallback() {
#Override
public void onStringAvailable(String s) {
Log.d(TAG, "onStringAvailable");
}
});
}
});
httpServer.listen(8080);
}
This implementation works completely fine.
But I want to use the wss protocol where I can use a JKS (Java KeyStore) certificate for the websocket.
Is there any way to do this? If not with this library, is there any other library I can use? Any example would be really appreciated.
Thank you!!

try this one. I haven't used it. However, it says it supports Java servers and Android clients with support for wss. Good luck!

Honestly, I don't know that I am right. I just happened into this.
Do you think you could do it with NanoHTTPD for java?
I imagine the basic structure is:
MyHTTPDTask
import java.io.IOException;
import java.util.Map;
import fi.iki.elonen.NanoHTTPD;
class MyHTTPDTask extends AsyncTask {
private MyServer mHTTPD;
#Override
protected Object doInBackground(Object... params) {
mHTTPD = new MyServer();
mHTTPD.makeSecure(NanoHTTPD.makeSSLSocketFactory(R.string.keystore.jks, "password".toCharArray()), null);
}
}
MyServer
import java.io.IOException;
import fi.iki.elonen.NanoHTTPD;
public class MyServer extends NanoHTTPD {
private final static int PORT = 8080;
public MyServer() throws IOException {
super(PORT);
start();
System.out.println( "\nRunning! Point your browers to http://localhost:8080/ \n" );
}
#Override
public Response serve(IHTTPSession session) {
String msg = "<html><body><h1>Hello server</h1>\n";
msg += "<p>We serve " + session.getUri() + " !</p>";
return newFixedLengthResponse( msg + "</body></html>\n" );
}
}

For the server side, why don't you use the standard API, javax.websocket? It's a part of Java EE.
For the Android side, see "Which WebSocket library to use in Android app?".

Related

Java create/overwrite http server

I'm creating a plugin on a certain platform (the details are irrelevant) and need to create a HTTP endpoint. In normal circumstances you'd create a http server and stop it whenever you're done using it or when the application stops, however, in my case I can't detect when the plugin is being uninstalled/reinstalled.
The problem
When someone installs my plugin twice, the second time it will throw an error because I'm trying to create a http server on a port which is already in use. Since it's being reinstalled, I can't save the http server on some static variable either. In other words, I need to be able to stop a previously created http server without having any reference to it.
My attempt
I figured the only way to interact with the original reference to the http server would be to create a thread whenever the http server starts, and then overwrite the interrupt() method to stop the server, but somehow I'm still receiving the 'port is already in use' error. I'm using Undertow as my http server library, but this problem applies to any http server implementation.
import io.undertow.Undertow;
import io.undertow.util.Headers;
public class SomeServlet extends Thread {
private static final String THREAD_NAME = "some-servlet-container-5391301";
private static final int PORT = 5839;
private Undertow server;
public static void listen() { // this method is called whenever my plugin is installed
deleteExistingServer();
new SomeServlet().start();
}
private static void deleteExistingServer() {
for (Thread t : Thread.getAllStackTraces().keySet()) {
if (t.getName().equals(THREAD_NAME)) {
t.interrupt();
}
}
}
#Override
public void run() {
createServer();
}
#Override
public void interrupt() {
try {
System.out.println("INTERRUPT");
this.server.stop();
} finally {
super.interrupt();
}
}
private void createServer() {
this.server = Undertow.builder()
.addHttpListener(PORT, "localhost")
.setHandler(exchange -> {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello World!");
})
.build();
this.server.start();
}
}
Desired behaviour
Whenever listen() is called, it will remove any previously existing http server and create a new one, without relying on storing the server on a static variable.
You could try com.sun.net.httpserver.HttpServer. Use http://localhost:8765/stop to stop and 'http://localhost:8765/test' for test request:
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
public class TestHttpServer {
public static void main(String[] args) throws IOException {
final HttpServer server = HttpServer.create();
server.bind(new InetSocketAddress(8765), 0);
server.createContext("/test", httpExchange -> {
String response = "<html>TEST!!!</html>";
httpExchange.sendResponseHeaders(200, response.length());
OutputStream os = httpExchange.getResponseBody();
os.write(response.getBytes());
os.close();
});
server.createContext("/stop", httpExchange -> server.stop(1));
server.start();
}
}

Sending message does not work in XMPP with Smack library

Problem Description
I'm writing chat application using XMPP and Smack Android library. I'm sending messages using code below and everything is working fine.
final ChatManager chatManager = ChatManager.getInstanceFor(connection);
chatManager.addChatListener(this);
....
#Override
public void chatCreated(Chat chat, boolean createdLocally) {
chat.addMessageListener(this);
}
#Override
public void processMessage(Chat chat, Message message) {
// Do something here.
}
Chat chat = ChatManager.getInstanceFor(connection).createChat(jid);
chat.sendMessage("message");
Question
Unfortunately the API above is deprecated org.jivesoftware.smack.chat.Chat and instead I should use org.jivesoftware.smack.chat2.Chat, so I am changing implementation as follows
final ChatManager chatManager = ChatManager.getInstanceFor(connection);
chatManager.addOutgoingListener(this);
chatManager.addIncomingListener(this);
....
Chat chat = ChatManager.getInstanceFor(connection).chatWith(jid);
chat.send("message");
In this case I can still get Incoming messages, but when I am trying to send message with chat.send("message"); server does not get anything and addOutgoingListener callback is not called.
Any ideas why?
There is an example with an older version of smack:
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
public class Test {
public static void main(String args[]) throws XMPPException {
ConnectionConfiguration config = new ConnectionConfiguration("127.0.0.1", 5222);
XMPPConnection connection = new XMPPConnection(config);
connection.connect();
connection.login("userx", "123456");
ChatManager cm = connection.getChatManager();
Chat chat = cm.createChat("tongqian#tsw-PC", null);
/*
* add listener
*/
cm.addChatListener(new ChatManagerListener() {
#Override
public void chatCreated(Chat chat, boolean create) {
chat.addMessageListener(new MessageListener() {
#Override
public void processMessage(Chat chat, Message msg) {
System.out.println(chat.getParticipant() + ":" + msg.getBody());
}
});
}
});
chat.sendMessage("hello");
while(true);
//connection.disconnect();
}
}
Answer
Digging a bit deeper I found the answer, the code below will help to send a message
Sending Message Code
final Chat chat = ChatManager.getInstanceFor(connection).chatWith(jid);
Message newMessage = new Message(jid, Message.Type.chat);
newMessage.setBody(message);
chat.send(newMessage);
Conclusion
So instead of sending a string message, you need to create a Message object and I think what is more important is to specify Message.Type.chat in the constructor and also jid and then call chat.send(...)
You can refer to this code snippet:
public void sendMessage(String to, Message newMessage) {
if(chatManager!=null) {
Chat newChat = chatManager.createChat(to);
try {
if (connection.isConnected() && connection.isAuthenticated()) {
newChat.sendMessage(newMessage);
}
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
}
else
{
Log.d(TAG,”chatmanager is null”);
}
}
And the link is https://ramzandroidarchive.wordpress.com/2016/03/13/send-messages-over-xmpp-using-smack-4-1/ .

httpClient connection not closing

Version
vert.x core: 3.3.0
Context
Am just trying to run http client in core examples io.vertx.example.core.http.simple.Client.
While running this example its found that the established connection not closing after completion of request.
Server side I didnt see any issue. Since while trying with jmeter and server its working fine. So I think that the problem is in the HttpClient.
Anyone can help me on this?
Thanks in advance.
Steps to reproduce
running io.vertx.example.core.http.simple.Server code
running io.vertx.example.core.http.simple.Client code
Extra
The following shown even after the request and response is ended. while giving
LINUX
lsof -i -P
java 32551 USER 223u IPv4 16264097 0t0 TCP localhost:8080->localhost:26980 (ESTABLISHED)
java 32634 USER 218u IPv4 16264087 0t0 TCP localhost:26980->localhost:8080 (ESTABLISHED)
WINDOWS
TCP 127.0.0.1:8080 FSSCHND12957:56893 ESTABLISHED
TCP 127.0.0.1:56893 FSSCHND12957:8080 ESTABLISHED
Tried in both LINUX and WINDOWS system.
Client Code
package io.vertx.example.core.http.simple;
import io.vertx.core.AbstractVerticle;
import io.vertx.example.util.Runner;
/*
#author Tim Fox
*/
public class Client extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(Client.class);
}
#Override
public void start() throws Exception {
vertx.createHttpClient().getNow(8080, "localhost", "/", resp -> {
System.out.println("Got response " + resp.statusCode());
resp.bodyHandler(body -> {
System.out.println("Got data " + body.toString("ISO-8859-1"));
});
});
}
}
Server Code
package io.vertx.example.core.http.simple;
import io.vertx.core.AbstractVerticle;
import io.vertx.example.util.Runner;
/*
#author Tim Fox
*/
public class Server extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(Server.class);
}
#Override
public void start() throws Exception {
vertx.createHttpServer().requestHandler(req -> {
req.response().putHeader("content-type", "text/html").end("
Hello from vert.x!
");
}).listen(8080);
}
}
We have to close the httpClient which we normally do in java. Only end() is not closing the connection. httpClient.close() is required.... This solved my issue..
Modified code:
public class Client extends AbstractVerticle {
// Convenience method so you can run it in your IDE
public static void main(String[] args) {
Runner.runExample(Client.class);
}
#Override
public void start() throws Exception {
HttpClient httpClient = vertx.createHttpClient().getNow(8080, "localhost", "/", resp -> {
System.out.println("Got response " + resp.statusCode());
resp.bodyHandler(body -> {
System.out.println("Got data " + body.toString("ISO-8859-1"));
httpClient.close();
});
});
}
}

How to import the Gottox/socket.io-java-client api in current Eclipse Android Project?

I'm trying to write a JavaScript server running on node.js using Socket.io that communicates with the client which is my android app (java class). Since I need a combination of a JS server and java client that utilizes the Socket.io (or any other efficient websockets) framework, I found the Gottox/socket-io.-java-client implementation that seemed like it might do the job.
Problem: I'm very new to socket programming and working with Github projects. I tried following the simplistic approach mentioned on the project but ran into build errors with Eclipse, specifically relating to Archiving issues with WebSocket.jar and json-org.jar.
Unable to solve this, I tried importing the project into Android Studio when I ran into a whole different bug, which I'm very unfamiliar with.
I just want to make sure I'm working with this project right in the first place. This is what my client class looks like:
package com.example.culami;
import io.socket.IOAcknowledge;
import io.socket.IOCallback;
import io.socket.SocketIO;
import io.socket.SocketIOException;
import org.json.JSONException;
import org.json.JSONObject;
public class AcknowledgeExample implements IOCallback {
private SocketIO socket;
/**
* #param args
*/
/*public static void main(String[] args) {
try {
new AcknowledgeExample();
} catch (Exception e) {
e.printStackTrace();
}
}*/
public AcknowledgeExample() throws Exception
{
socket = new SocketIO();
socket.connect("http://192.168.0.108:3000/", this);
// Sends a string to the server.
socket.send("Hello Server");
// Sends a JSON object to the server.
socket.send(new JSONObject().put("key", "value").put("key2",
"another value"));
// Emits an event to the server.
socket.emit("event", "argument1", "argument2", 13.37);
}
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
}
I imported the socketio.jar and even WebSocket.jar and json-org.jar because it seemed these were needed as well. Any feedback on what I'm doing wrong or how I should incorporate this library in my android project will be highly appreciated since I've already spent countless hours trying to debug the build issue.
Note: I'm using Android L, API 21 and jdk1.7 to run this project.
Instead you can add
socket.io-client-0.1.0.jar
The link for his http://mvnrepository.com/artifact/com.github.nkzawa/socket.io-client/0.1.0

[Californium/CoAP/LWM2M]: Reusing message send endpoint for server not possible?

I am building a tool that can send CoAP messages to another peer (different implementation), but I am having difficulties. I am using the CoAP library called "Californium" and am developing the tool in java/eclipse. Here's the deal: I send a message over californium's "default endpoint", which allows the system to make up a source-port for the UDP "connection". I want to listen on this same source-port using californium's Server object, but I am getting the following error:
SEVERE: Could not start endpoint
java.net.BindException: Address already in use
So my question is: how do I first send a CoAP message and start listening for other CoAP messages on the same socket using Californium?
Below is the java code for the client. What it does is "register" using a certain protocol layered on top of CoAP. After registering I want it to re-use the UDP socket for listening for subsequent messages of the entity I registered with earlier.
NOTE: The server part of the client works when I explicitly tell it to listen to a certain port (e.g. 5683), leave out the register part and test it with the Firefox Addon "Copper" (i.e. Copper can get to the /1 /1/1 /1/1/0 resources).
package com.example.l2mwm.client;
import java.net.InetSocketAddress;
import ch.ethz.inf.vs.californium.coap.CoAP.Code;
import ch.ethz.inf.vs.californium.coap.CoAP.ResponseCode;
import ch.ethz.inf.vs.californium.coap.CoAP;
import ch.ethz.inf.vs.californium.coap.Request;
import ch.ethz.inf.vs.californium.coap.Response;
import ch.ethz.inf.vs.californium.network.Endpoint;
import ch.ethz.inf.vs.californium.network.EndpointManager;
import ch.ethz.inf.vs.californium.server.Server;
import ch.ethz.inf.vs.californium.server.resources.CoapExchange;
import ch.ethz.inf.vs.californium.server.resources.Resource;
import ch.ethz.inf.vs.californium.server.resources.ResourceBase;
public class Main {
public static void main(String[] args) {
Endpoint endpoint;
if ((endpoint = register()) != null) {
listen(endpoint);
} else {
System.out.println("Couldn't register!");
}
}
private static void listen(Endpoint endpoint) {
InetSocketAddress sockAddress = endpoint.getAddress();
int port = sockAddress.getPort();
Server server = new Server(port);
Resource topResource = new ResourceBase("1") {
#Override
public void handleGET(CoapExchange exchange) {
exchange.respond(ResponseCode.CONTENT, "this is /1's value!");
}
#Override
public String getPath() {
return "/";
}
};
Resource instanceResource = new ResourceBase("1") {
#Override
public void handleGET(CoapExchange exchange) {
exchange.respond(ResponseCode.CONTENT, "this is /1/1's value!");
}
#Override
public String getPath() {
return "/1/";
}
};
topResource.add(instanceResource);
instanceResource.add(new ResourceBase("0") {
#Override
public void handleGET(CoapExchange exchange) {
exchange.respond(ResponseCode.CONTENT, "this is /1/1/0's value!");
}
#Override
public String getPath() {
return "/1/1/";
}
});
server.add(topResource);
server.start();
}
private static Endpoint register() {
Request request = new Request(Code.POST);
request.setURI("localhost:5684/rd?ep=coapclient&lt=86400&b=U");
request.setPayload("</1/1/0>");
Endpoint endpoint = EndpointManager.getEndpointManager().getDefaultEndpoint();
request.send(endpoint);
Response response;
ResponseCode responseCode = null;
try {
response = request.waitForResponse();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
return null;
}
responseCode = response.getCode();
if (responseCode != CoAP.ResponseCode.CREATED) {
return null;
}
return endpoint;
}
}
You need to first bind your UDP socket and then start your LWM2M register.
Because what you do: create CoAP Endpoint (bind a udp server) and than you bind again in your listen method.
// list to the UDP post 5555
coapServer = new Server();
Endpoint endpoint = new CoAPEndpoint(new InetSocketAddress("localhost",5555);
coapServer.addEndpoint(endpoint);
// send a message to a LWM2M server:
request request = new Request(Code.POST);
request.setURI("iot.eclipse.org:5683/rd?ep=coapclient&lt=86400&b=U");
request.setPayload("</1/1/0>");
Endpoint endpoint = EndpointManager.getEndpointManager().getDefaultEndpoint();
request.send(endpoint);
You can still access to your client using copper on coap://localhost:5555

Categories