001/**
002 *
003 * Copyright 2020 Aditya Borikar, 2020-2021 Florian Schmaus
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smack.websocket.okhttp;
018
019import java.util.logging.Level;
020
021import javax.net.ssl.SSLSession;
022
023import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
024import org.jivesoftware.smack.websocket.impl.AbstractWebSocket;
025import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint;
026
027import okhttp3.OkHttpClient;
028import okhttp3.Request;
029import okhttp3.Response;
030import okhttp3.WebSocket;
031import okhttp3.WebSocketListener;
032
033public final class OkHttpWebSocket extends AbstractWebSocket {
034
035    private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient();
036
037    private final WebSocket okHttpWebSocket;
038
039    OkHttpWebSocket(WebSocketRemoteConnectionEndpoint endpoint,
040                    ModularXmppClientToServerConnectionInternal connectionInternal) {
041        super(endpoint, connectionInternal);
042
043        final String url = endpoint.getRawString();
044        Request request = new Request.Builder()
045                              .url(url)
046                              .header(SEC_WEBSOCKET_PROTOCOL_HEADER_FILED_NAME, SEC_WEBSOCKET_PROTOCOL_HEADER_FILED_VALUE_XMPP)
047                              .build();
048
049        okHttpWebSocket = OK_HTTP_CLIENT.newWebSocket(request, listener);
050    }
051
052    private final WebSocketListener listener = new WebSocketListener() {
053
054        @Override
055        public void onOpen(WebSocket webSocket, Response response) {
056            LOGGER.log(Level.FINER, "OkHttp invoked onOpen() for {0}. Response: {1}",
057                            new Object[] { webSocket, response });
058            future.setResult(OkHttpWebSocket.this);
059        }
060
061        @Override
062        public void onMessage(WebSocket webSocket, String text) {
063            onIncomingWebSocketElement(text);
064        }
065
066        @Override
067        public void onFailure(WebSocket webSocket, Throwable throwable, Response response) {
068            LOGGER.log(Level.FINER, "OkHttp invoked onFailure() for " + webSocket + ". Response: " + response, throwable);
069            onWebSocketFailure(throwable);
070        }
071
072        @Override
073        public void onClosing(WebSocket webSocket, int code, String reason) {
074            LOGGER.log(Level.FINER, "OkHttp invoked onClosing() for " + webSocket + ". Code: " + code + ". Reason: " + reason);
075        }
076
077        @Override
078        public void onClosed(WebSocket webSocket, int code, String reason) {
079            LOGGER.log(Level.FINER, "OkHttp invoked onClosed() for " + webSocket + ". Code: " + code + ". Reason: " + reason);
080        }
081
082    };
083
084    @Override
085    public void send(String element) {
086        okHttpWebSocket.send(element);
087    }
088
089    @Override
090    public void disconnect(int code, String message) {
091        LOGGER.log(Level.INFO, "WebSocket closing with code: " + code + " and message: " + message);
092        okHttpWebSocket.close(code, message);
093    }
094
095    @Override
096    public SSLSession getSSLSession() {
097        // TODO: What shall we do about this method, as it appears that OkHttp does not provide access to the used SSLSession?
098        return null;
099    }
100}