/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2005-2008 Jive Software. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ifsoft.websockets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.*;
import java.util.concurrent.*;
import java.io.*;
import java.net.*;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.*;
import javax.net.*;
import javax.net.ssl.*;
import javax.security.auth.callback.*;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
public class SipConnection
{
private static Logger Log = LoggerFactory.getLogger( "SipConnection" );
private boolean isSecure = false;
private XMPPServlet.SIPWebSocket socket;
private boolean connected = false;
private WebSocketClient client = null;
private SIPSocket sipSocket = null;
private String subprotocol = "sip";
public SipConnection(URI uri, String subprotocol, int connectTimeout)
{
Log.info("SipConnection " + uri + " " + subprotocol);
this.subprotocol = subprotocol;
SslContextFactory sec = new SslContextFactory();
if("wss".equals(uri.getScheme()))
{
sec.setValidateCerts(false);
Log.info("SipConnection - SSL");
getSSLContext();
isSecure = true;
}
client = new WebSocketClient(sec);
sipSocket = new SIPSocket(this);
try
{
client.start();
ClientUpgradeRequest request = new ClientUpgradeRequest();
if ("sip".equals(subprotocol))
{
request.setSubProtocols(subprotocol);
}
client.connect(sipSocket, uri, request);
Log.info("Connecting to : " + uri);
}
catch (Exception e)
{
Log.error("SipConnection", e);
}
finally
{
try
{
//client.stop();
}
catch (Exception e1)
{
Log.error("SipConnection", e1);
}
}
connected = true;
}
public void setSocket( XMPPServlet.SIPWebSocket socket ) {
this.socket = socket;
}
public void deliver(String text)
{
Log.info("SipConnection - deliver " + text);
String sendText = text;
if (sipSocket != null)
{
if ("sip".equals(subprotocol)) sendText = text.replaceAll("SIP/2.0/WSS", "SIP/2.0/WS");
sipSocket.deliver(sendText);
}
}
public void disconnect()
{
Log.info("SipConnection - disconnect");
if (sipSocket != null) sipSocket.disconnect();
}
public void onClose(int code, String reason)
{
Log.info("SipConnection - onClose " + reason + " " + code);
connected = false;
if (this.socket != null) this.socket.disconnect();
}
public void onMessage(String text) {
Log.info("SipConnection - onMessage " + text);
try {
this.socket.deliver(text);
}
catch (Exception e) {
Log.error("deliverRawText error", e);
}
}
public boolean isSecure() {
return isSecure;
}
public boolean isConnected() {
return connected;
}
public void setSecure(boolean isSecure) {
this.isSecure = isSecure;
}
private SSLContext getSSLContext()
{
SSLContext sc = null;
try {
Log.info("SipConnection SSL truster");
TrustManager[] trustAllCerts = new TrustManager[]
{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
public void checkServerTrusted(X509Certificate[] certs, String authType) { }
}
};
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier()
{
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (Exception e) {
Log.error("WireLynkComponent - getSSLContext SSL truster", e);
}
return sc;
}
@WebSocket(maxTextMessageSize = 64 * 1024) public class SIPSocket
{
private Session session;
private SipConnection sipConnection;
private String lastMessage = null;
public SIPSocket(SipConnection sipConnection)
{
this.sipConnection = sipConnection;
}
@OnWebSocketClose public void onClose(int statusCode, String reason)
{
Log.info("SIPSocket onClose " + statusCode + " " + reason);
this.session = null;
if (sipConnection != null) sipConnection.onClose(statusCode, reason);
}
@OnWebSocketConnect public void onConnect(Session session)
{
Log.info("SIPSocket onConnect: " + session);
this.session = session;
if (lastMessage != null) deliver(lastMessage);
}
@OnWebSocketMessage public void onMessage(String msg)
{
Log.info("SIPSocket onMessage \n" + msg);
if (sipConnection != null) sipConnection.onMessage(msg);
}
public void deliver(String text)
{
if (session != null)
{
try {
Log.info("SIPSocket deliver: \n" + text);
session.getRemote().sendStringByFuture(text);
lastMessage = null;
} catch (Exception e) {
Log.error("SIPSocket deliver", e);
}
} else lastMessage = text;
}
public void disconnect()
{
if (session != null) session.close(StatusCode.NORMAL,"I'm done");
}
}
}