Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.yy.httpproxy.socketio.SocketIOProxyClient Maven / Gradle / Ivy
package com.yy.httpproxy.socketio;
import android.content.Context;
import android.os.Handler;
import android.util.Base64;
import android.util.Pair;
import com.yy.httpproxy.AndroidLoggingHandler;
import com.yy.httpproxy.requester.RequestInfo;
import com.yy.httpproxy.service.DnsHandler;
import com.yy.httpproxy.service.PushedNotification;
import com.yy.httpproxy.stats.Stats;
import com.yy.httpproxy.subscribe.CachedSharedPreference;
import com.yy.httpproxy.subscribe.PushCallback;
import com.yy.httpproxy.subscribe.PushSubscriber;
import com.yy.httpproxy.thirdparty.NotificationProvider;
import com.yy.httpproxy.thirdparty.UmengProvider;
import com.yy.httpproxy.util.JSONUtil;
import com.yy.httpproxy.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.net.URISyntaxException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Level;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import io.socket.engineio.client.transports.WebSocket;
public class SocketIOProxyClient implements PushSubscriber {
private static String TAG = "SocketIOProxyClient";
private final NotificationProvider notificationProvider;
private PushCallback pushCallback;
private String pushId;
private Callback socketCallback;
private CachedSharedPreference cachedSharedPreference;
private Map topics = new HashMap<>();
private Map topicToLastPacketId = new HashMap<>();
private boolean pushIdConnected = false;
private String uid;
private Stats stats = new Stats();
private String host = "";
private String packageName = "";
private Set tagsToSet = null;
private Set tagsFromServer = new HashSet<>();
private Socket socket;
private List cachedEvent = new ArrayList<>();
private String tokenFromServer = "";
public void unsubscribeBroadcast(String topic) {
topics.remove(topic);
topicToLastPacketId.remove(topic);
JSONObject data = new JSONObject();
try {
data.put("topic", topic);
sendObjectToServer("unsubscribeTopic", data);
} catch (JSONException e) {
}
}
public String getHost() {
return host;
}
public void setTags(Set tags) {
if (tags == null) {
tags = new HashSet<>();
}
if (tags.equals(this.tagsFromServer)) {
Log.i(TAG, "tags equal skip send to server");
return;
}
this.tagsToSet = tags;
if (pushIdConnected) {
JSONArray array = JSONUtil.toJSONArray(tags);
sendObjectToServer("setTags", array);
}
}
public interface Callback {
void onNotification(PushedNotification notification);
void onConnect();
void onDisconnect();
}
private final Emitter.Listener connectListener = new Emitter.Listener() {
@Override
public void call(Object... args) {
stats.onConnect();
sendPushIdAndTopicToServer();
}
};
private final Emitter.Listener disconnectListener = new Emitter.Listener() {
@Override
public void call(Object... args) {
pushIdConnected = false;
uid = null;
stats.onDisconnect();
if (socketCallback != null) {
socketCallback.onDisconnect();
}
}
};
public void unbindUid() {
sendObjectToServer("unbindUid", null);
}
private void sendPushIdAndTopicToServer() {
if (pushId != null) {
Log.i(TAG, "sendPushIdAndTopicToServer " + pushId);
JSONObject object = new JSONObject();
try {
object.put("id", pushId);
object.put("platform", "android");
if (topics.size() > 0) {
JSONArray array = new JSONArray();
object.put("topics", array);
for (String topic : topics.keySet()) {
array.put(topic);
}
JSONObject lastPacketIds = new JSONObject();
object.put("lastPacketIds", lastPacketIds);
for (Map.Entry entry : topicToLastPacketId.entrySet()) {
if (entry.getValue() != null && topics.containsKey(entry.getKey())) {
lastPacketIds.put(entry.getKey(), entry.getValue());
}
}
if (topics.containsKey("noti")) {
String lastNotiId = cachedSharedPreference.get("lastNotiId");
if (lastNotiId == null) {
lastNotiId = "0";
}
Log.i(TAG, "lastNotiId " + lastNotiId);
lastPacketIds.put("noti", lastNotiId);
}
}
String lastUniCastId = cachedSharedPreference.get("lastUnicastId");
if (lastUniCastId != null) {
object.put("lastUnicastId", lastUniCastId);
}
if (tagsToSet != null) {
object.put("tags", JSONUtil.toJSONArray(tagsToSet));
}
sendObjectToServer("pushId", object);
} catch (JSONException e) {
Log.e(TAG, "connectListener error ", e);
}
}
}
private final Emitter.Listener pushIdListener = new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
String pushId = data.optString("id");
uid = data.optString("uid", "");
tagsFromServer = JSONUtil.toStringSet(data.optJSONArray("tags"));
if (tagsFromServer.equals(tagsToSet)) {
tagsToSet = null;
}
Log.d(TAG, "on pushId " + pushId + " ,uid " + uid);
pushIdConnected = true;
if (socketCallback != null) {
socketCallback.onConnect();
}
tokenFromServer = data.optString("token", "");
sendTokenToServer();
handler.postDelayed(new Runnable() {
@Override
public void run() {
sendCachedObjectToServer();
}
}, 5000);
}
};
private JSONObject getTokenObject() {
if (notificationProvider != null && notificationProvider.getToken() != null) {
JSONObject object = new JSONObject();
try {
object.put("token", notificationProvider.getToken());
object.put("type", notificationProvider.getType());
object.put("package_name", packageName);
return object;
} catch (JSONException e) {
Log.e(TAG, "sendTokenToServer error ", e);
}
}
return null;
}
public void sendTokenToServer() {
if (pushIdConnected && notificationProvider != null) {
if (tokenFromServer.equals(notificationProvider.getToken())) {
Log.i(TAG, "token equal skip send to server");
return;
}
JSONObject object = getTokenObject();
if (object != null) {
sendObjectToServer("token", object);
}
}
}
public void sendUmengReply(String id) {
try {
JSONObject object = new JSONObject();
object.put("id", id);
Log.d(TAG, "sendUmengReply " + id);
sendObjectToServer("umengReply", object, true);
} catch (JSONException e) {
}
}
public void sendNotificationClick(String id) {
JSONObject object = new JSONObject();
try {
object.put("id", id);
if (notificationProvider != null) {
object.put("type", notificationProvider.getType());
}
Log.i(TAG, "notificationClick " + id);
sendObjectToServer("notificationClick", object, true);
} catch (JSONException e) {
Log.e(TAG, "sendNotificationClick error ", e);
}
}
public void bindUid(Map data) {
Log.i(TAG, "bindUid " + pushId);
JSONObject object = JSONUtil.toJSONObject(data);
sendObjectToServer("bindUid", object);
}
private final Emitter.Listener notificationListener = new Emitter.Listener() {
@Override
public void call(Object... args) {
try {
JSONObject data = (JSONObject) args[0];
JSONObject android = data.optJSONObject("android");
Log.i(TAG, "on notification topic " + android);
String id = data.optString("id", null);
updateLastPacketId(id, data.optString("ttl", null), data.optString("unicast", null), "noti");
long timestamp = data.optLong("timestamp", 0);
if (timestamp > 0 && id != null) {
JSONObject object = new JSONObject();
object.put("id", id);
object.put("timestamp", timestamp);
Log.d(TAG, "notificationReply " + id + " " + timestamp);
sendObjectToServer("notificationReply", object, true);
}
String title = android.optString("title");
if (socketCallback != null && title != null && !title.isEmpty()) {
socketCallback.onNotification(new PushedNotification(id, android));
}
} catch (Exception e) {
Log.e(TAG, "handle notification error ", e);
}
}
};
private void updateLastPacketId(String id, Object ttl, Object unicast, String topic) {
if (id != null && ttl != null) {
Log.d(TAG, "on push topic " + topic + " id " + id);
Boolean reciveTtl = topics.get(topic);
if (reciveTtl == null) {
reciveTtl = false;
}
if (unicast != null) {
cachedSharedPreference.save("lastUnicastId", id);
} else if (reciveTtl && topic != null) {
if (topic.equals("noti")) {
cachedSharedPreference.save("lastNotiId", id);
}
topicToLastPacketId.put(topic, id);
}
}
}
private final Emitter.Listener version2PushListener = new Emitter.Listener() {
@Override
public void call(Object... args) {
if (pushCallback != null) {
try {
String json = args[0].toString();
Log.i(TAG, "on push topic data: " + json);
pushCallback.onPush(json);
if (args.length > 1) {
JSONArray ttlData = (JSONArray) args[1];
String topic = ttlData.optString(0, null);
String id = ttlData.optString(1, null);
String ttl = "1";
int unicast = ttlData.optInt(2, 0);
String unicastObj = null;
if (unicast == 1) {
unicastObj = "1";
}
updateLastPacketId(id, ttl, unicastObj, topic);
}
} catch (Exception e) {
Log.e(TAG, "handle push error ", e);
}
}
}
};
private final Emitter.Listener pushListener = new Emitter.Listener() {
@Override
public void call(Object... args) {
if (pushCallback != null) {
try {
JSONObject data = (JSONObject) args[0];
String topic = data.optString("topic", null);
if (topic == null) {
topic = data.optString("t", null);
}
String dataBase64 = data.optString("data", null);
if (dataBase64 == null) {
dataBase64 = data.optString("d", null);
}
byte[] dataBytes;
if (dataBase64 == null) {
String json = data.optString("j");
pushCallback.onPush(json);
} else {
dataBytes = Base64.decode(dataBase64, Base64.DEFAULT);
pushCallback.onPush(new String(dataBytes, "UTF-8"));
}
String id = data.optString("id", null);
if (id == null) {
id = data.optString("i", null);
}
String ttl = data.optString("ttl", null);
if (ttl == null) {
ttl = data.optString("t", null);
}
String unicast = data.optString("unicast", null);
if (unicast == null) {
unicast = data.optString("u", null);
}
updateLastPacketId(id, ttl, unicast, topic);
} catch (Exception e) {
Log.e(TAG, "handle push error ", e);
}
}
}
};
private Handler handler = new Handler();
private Runnable statsTask = new Runnable() {
@Override
public void run() {
sendStats();
}
};
private void sendStats() {
try {
JSONArray requestStats = stats.getRequestJsonArray();
if (requestStats.length() > 0) {
JSONObject object = new JSONObject();
object.put("requestStats", requestStats);
sendObjectToServer("stats", object, true);
Log.d(TAG, "send stats " + requestStats.length());
}
} catch (JSONException e) {
Log.e(TAG, "sendStats error", e);
}
postStatsTask();
}
private void postStatsTask() {
handler.removeCallbacks(statsTask);
handler.postDelayed(statsTask, 10 * 60 * 1000L);
}
public void reportStats(String path, int successCount, int errorCount, int latency) {
stats.reportStats(path, successCount, errorCount, latency);
}
public SocketIOProxyClient(Context context, String host, String pushId, NotificationProvider provider, DnsHandler dnsHandler) {
this.packageName = context.getPackageName();
cachedSharedPreference = new CachedSharedPreference(context);
try {
AndroidLoggingHandler.reset(new AndroidLoggingHandler());
java.util.logging.Logger.getLogger("").setLevel(Level.FINEST);
} catch (Exception e) {
}
this.host = host;
this.notificationProvider = provider;
if (provider == null || notificationProvider instanceof UmengProvider) {
topics.put("noti", true);
}
if (pushId == null) {
pushId = cachedSharedPreference.get("pushId");
}
this.pushId = pushId;
try {
IO.Options opts = new IO.Options();
opts.transports = new String[]{WebSocket.NAME};
// opts.dnsHandler = dnsHandler;
if (host.startsWith("https")) {
try {
opts.sslContext = SSLContext.getInstance("TLS");
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
opts.sslContext.init(null, new TrustManager[]{tm}, null);
opts.hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
};
} catch (Exception e) {
Log.e(TAG, "ssl init error ", e);
}
}
Log.i(TAG, "connecting " + packageName + " " + host);
socket = IO.socket(host, opts);
socket.on(Socket.EVENT_CONNECT, connectListener);
socket.on("pushId", pushIdListener);
socket.on("push", pushListener);
socket.on("p", version2PushListener);
socket.on("noti", notificationListener);
socket.on("n", notificationListener);
socket.on(Socket.EVENT_DISCONNECT, disconnectListener);
socket.connect();
postStatsTask();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public void disconnect() {
socket.disconnect();
this.socketCallback = null;
this.pushCallback = null;
}
public void request(RequestInfo requestInfo) {
try {
Log.d(TAG, "request " + requestInfo.getPath());
requestInfo.setTimestamp();
JSONObject object = new JSONObject();
if (requestInfo.getBody() != null) {
object.put("data", Base64.encodeToString(requestInfo.getBody(), Base64.NO_WRAP));
}
object.put("path", requestInfo.getPath());
object.put("sequenceId", String.valueOf(requestInfo.getSequenceId()));
sendObjectToServer("packetProxy", object);
} catch (Exception e) {
}
}
@Override
public void subscribeBroadcast(String topic, boolean receiveTtlPackets) {
if (!topics.containsKey(topic)) {
topics.put(topic, receiveTtlPackets);
JSONObject data = new JSONObject();
try {
data.put("topic", topic);
String lastPacketId = topicToLastPacketId.get(topic);
if (lastPacketId != null && receiveTtlPackets) {
data.put("lastPacketId", lastPacketId);
}
sendObjectToServer("subscribeTopic", data);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void sendObjectToServer(String event, Object object) {
sendObjectToServer(event, object, false);
}
private void sendObjectToServer(String event, Object object, boolean cached) {
if (socket.connected()) {
if (object == null) {
socket.emit(event);
} else {
socket.emit(event, object);
}
} else if (cached) {
cachedEvent.add(new Pair<>(event, object));
}
}
private void sendCachedObjectToServer() {
List newList = new ArrayList<>(cachedEvent);
cachedEvent.clear();
for (Pair p : newList) {
sendObjectToServer(p.first, p.second);
}
}
public void setPushCallback(PushCallback pushCallback) {
this.pushCallback = pushCallback;
}
public void setSocketCallback(Callback socketCallback) {
this.socketCallback = socketCallback;
}
public String getUid() {
return uid;
}
public boolean isConnected() {
return pushIdConnected;
}
}