Fix message parser

The parser didn't take into accoun, that the arriving string can
contain several messages
This commit is contained in:
0xboobface 2018-10-24 23:40:53 +02:00
parent ff0d1b5eae
commit 0bcea4e753
1 changed files with 98 additions and 100 deletions

View File

@ -58,7 +58,7 @@ public class MyFreeCamsClient {
private String chatToken; private String chatToken;
private int sessionId; private int sessionId;
private EvictingQueue<String> receivedTextHistory = EvictingQueue.create(100); private EvictingQueue<String> receivedTextHistory = EvictingQueue.create(10000);
private MyFreeCamsClient() { private MyFreeCamsClient() {
moshi = new Moshi.Builder().build(); moshi = new Moshi.Builder().build();
@ -168,98 +168,95 @@ public class MyFreeCamsClient {
msgBuffer.append(text); msgBuffer.append(text);
Message message; Message message;
try { try {
message = parseMessage(msgBuffer); while( (message = parseMessage(msgBuffer)) != null) {
if (message != null) { switch (message.getType()) {
msgBuffer.setLength(0); case NULL:
} break;
case LOGIN:
switch (message.getType()) { LOG.debug("LOGIN: {}", message);
case NULL: sessionId = message.getReceiver();
break; break;
case LOGIN: case DETAILS:
LOG.debug("LOGIN: {}", message); case ROOMHELPER:
sessionId = message.getReceiver(); case ADDFRIEND:
break; case ADDIGNORE:
case DETAILS: case CMESG:
case ROOMHELPER: case PMESG:
case ADDFRIEND: case TXPROFILE:
case ADDIGNORE: case USERNAMELOOKUP:
case CMESG: case MYCAMSTATE:
case PMESG: case MYWEBCAM:
case TXPROFILE: case JOINCHAN:
case USERNAMELOOKUP: case SESSIONSTATE:
case MYCAMSTATE: if(!message.getMessage().isEmpty()) {
case MYWEBCAM: //LOG.debug("SessionState: {}", message.getMessage());
case JOINCHAN: JsonAdapter<SessionState> adapter = moshi.adapter(SessionState.class);
case SESSIONSTATE: try {
if(!message.getMessage().isEmpty()) { SessionState sessionState = adapter.fromJson(message.getMessage());
//LOG.debug("SessionState: {}", message.getMessage()); updateSessionState(sessionState);
JsonAdapter<SessionState> adapter = moshi.adapter(SessionState.class); } catch (IOException e) {
try { LOG.error("Couldn't parse session state message {}", message, e);
SessionState sessionState = adapter.fromJson(message.getMessage()); }
updateSessionState(sessionState);
} catch (IOException e) {
LOG.error("Couldn't parse session state message {}", message, e);
} }
} break;
break; case TAGS:
case TAGS: JSONObject json = new JSONObject(message.getMessage());
JSONObject json = new JSONObject(message.getMessage()); String[] names = JSONObject.getNames(json);
String[] names = JSONObject.getNames(json); Integer uid = Integer.parseInt(names[0]);
Integer uid = Integer.parseInt(names[0]); SessionState sessionState = sessionStates.get(uid);
SessionState sessionState = sessionStates.get(uid); if (sessionState != null) {
if (sessionState != null) { JSONArray tags = json.getJSONArray(names[0]);
JSONArray tags = json.getJSONArray(names[0]); for (Object obj : tags) {
for (Object obj : tags) { sessionState.getM().getTags().add((String) obj);
sessionState.getM().getTags().add((String) obj); }
} }
} break;
break; case EXTDATA:
case EXTDATA: if(message.getArg1() == MessageTypes.LOGIN) {
if(message.getArg1() == MessageTypes.LOGIN) { chatToken = message.getMessage();
chatToken = message.getMessage(); String username = Config.getInstance().getSettings().username;
String username = Config.getInstance().getSettings().username; if(StringUtil.isNotBlank(username)) {
if(StringUtil.isNotBlank(username)) { boolean login = mfc.getHttpClient().login();
boolean login = mfc.getHttpClient().login(); if (login) {
if (login) { Cookie passcode = mfc.getHttpClient().getCookie("passcode");
Cookie passcode = mfc.getHttpClient().getCookie("passcode"); webSocket.send("1 0 0 20071025 0 " + chatToken + "@1/" + username + ":" + passcode.value() + "\n");
webSocket.send("1 0 0 20071025 0 " + chatToken + "@1/" + username + ":" + passcode.value() + "\n"); } else {
LOG.error("Login failed");
webSocket.send("1 0 0 20080909 0 guest:guest\n");
}
} else { } else {
LOG.error("Login failed");
webSocket.send("1 0 0 20080909 0 guest:guest\n"); webSocket.send("1 0 0 20080909 0 guest:guest\n");
} }
} else if(message.getArg1() == MessageTypes.MANAGELIST) {
requestExtData(message.getMessage());
} else { } else {
webSocket.send("1 0 0 20080909 0 guest:guest\n"); LOG.debug("EXTDATA: {}", message);
} }
} else if(message.getArg1() == MessageTypes.MANAGELIST) { break;
requestExtData(message.getMessage()); case ROOMDATA:
} else { LOG.debug("ROOMDATA: {}", message);
LOG.debug("EXTDATA: {}", message); case UEOPT:
LOG.debug("UEOPT: {}", message);
break;
case SLAVEVSHARE:
// LOG.debug("SLAVEVSHARE {}", message);
// LOG.debug("SLAVEVSHARE MSG [{}]", message.getMessage());
break;
case TKX:
json = new JSONObject(message.getMessage());
tkx = json.getString("tkx");
cxid = json.getInt("cxid");
ctxenc = URLDecoder.decode(json.getString("ctxenc"), "utf-8");
JSONArray ctxArray = json.getJSONArray("ctx");
ctx = new int[ctxArray.length()];
for (int i = 0; i < ctxArray.length(); i++) {
ctx[i] = ctxArray.getInt(i);
}
break;
default:
LOG.debug("Unknown message {}", message);
break;
} }
break;
case ROOMDATA:
LOG.debug("ROOMDATA: {}", message);
case UEOPT:
LOG.debug("UEOPT: {}", message);
break;
case SLAVEVSHARE:
// LOG.debug("SLAVEVSHARE {}", message);
// LOG.debug("SLAVEVSHARE MSG [{}]", message.getMessage());
break;
case TKX:
json = new JSONObject(message.getMessage());
tkx = json.getString("tkx");
cxid = json.getInt("cxid");
ctxenc = URLDecoder.decode(json.getString("ctxenc"), "utf-8");
JSONArray ctxArray = json.getJSONArray("ctx");
ctx = new int[ctxArray.length()];
for (int i = 0; i < ctxArray.length(); i++) {
ctx[i] = ctxArray.getInt(i);
}
break;
default:
LOG.debug("Unknown message {}", message);
break;
} }
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
e.printStackTrace(); e.printStackTrace();
@ -391,27 +388,30 @@ public class MyFreeCamsClient {
model.update(state, getStreamUrl(state)); model.update(state, getStreamUrl(state));
} }
private Message parseMessage(StringBuilder msg) throws UnsupportedEncodingException { private Message parseMessage(StringBuilder msgBuffer) throws UnsupportedEncodingException {
if (msg.length() < 4) { if (msgBuffer.length() < 4) {
// packet size not transmitted completely // packet size not transmitted completely
return null; return null;
} else { } else {
try { try {
int packetLength = Integer.parseInt(msg.substring(0, 4)); int packetLength = Integer.parseInt(msgBuffer.substring(0, 4));
if (packetLength > msg.length() - 4) { if (packetLength > msgBuffer.length() - 4) {
// packet not complete // packet not complete
return null; return null;
} else { } else {
msg.delete(0, 4); msgBuffer.delete(0, 4);
int type = parseNextInt(msg); StringBuilder rawMessage = new StringBuilder(msgBuffer.substring(0, packetLength));
int sender = parseNextInt(msg); int type = parseNextInt(rawMessage);
int receiver = parseNextInt(msg); int sender = parseNextInt(rawMessage);
int arg1 = parseNextInt(msg); int receiver = parseNextInt(rawMessage);
int arg2 = parseNextInt(msg); int arg1 = parseNextInt(rawMessage);
return new Message(type, sender, receiver, arg1, arg2, URLDecoder.decode(msg.toString(), "utf-8")); int arg2 = parseNextInt(rawMessage);
Message message = new Message(type, sender, receiver, arg1, arg2, URLDecoder.decode(rawMessage.toString(), "utf-8"));
msgBuffer.delete(0, packetLength);
return message;
} }
} catch(Exception e) { } catch(Exception e) {
LOG.error("StringBuilder contains invalid data {}", msg.toString(), e); LOG.error("StringBuilder contains invalid data {}", msgBuffer.toString(), e);
String logfile = "mfc_messages.log"; String logfile = "mfc_messages.log";
try(FileOutputStream fout = new FileOutputStream(logfile)) { try(FileOutputStream fout = new FileOutputStream(logfile)) {
for (String string : receivedTextHistory) { for (String string : receivedTextHistory) {
@ -423,7 +423,7 @@ public class MyFreeCamsClient {
LOG.error("Couldn't write mfc message history to " + logfile); LOG.error("Couldn't write mfc message history to " + logfile);
e1.printStackTrace(); e1.printStackTrace();
} }
msg.setLength(0); msgBuffer.setLength(0);
return null; return null;
} }
} }
@ -501,11 +501,9 @@ public class MyFreeCamsClient {
if(serverConfig.isOnNgServer(state)) { if(serverConfig.isOnNgServer(state)) {
String server = serverConfig.ngVideoServers.get(camserv.toString()); String server = serverConfig.ngVideoServers.get(camserv.toString());
streamUrl = "https://" + server + ".myfreecams.com:8444/x-hls/" + cxid + '/' + userChannel + '/' + ctxenc + "/mfc_" + phase + '_' + userChannel + ".m3u8"; streamUrl = "https://" + server + ".myfreecams.com:8444/x-hls/" + cxid + '/' + userChannel + '/' + ctxenc + "/mfc_" + phase + '_' + userChannel + ".m3u8";
//LOG.debug("{} {}", state.getNm(), streamUrl);
} else if(serverConfig.isOnWzObsVideoServer(state)) { } else if(serverConfig.isOnWzObsVideoServer(state)) {
String server = serverConfig.wzobsServers.get(camserv.toString()); String server = serverConfig.wzobsServers.get(camserv.toString());
streamUrl = "https://"+ server + ".myfreecams.com/NxServer/ngrp:mfc_" + phase + '_' + userChannel + ".f4v_mobile/playlist.m3u8"; streamUrl = "https://"+ server + ".myfreecams.com/NxServer/ngrp:mfc_" + phase + '_' + userChannel + ".f4v_mobile/playlist.m3u8";
LOG.debug("{} isOnWzObsvideo: {}", state.getNm(), streamUrl);
} else if(serverConfig.isOnHtml5VideoServer(state)) { } else if(serverConfig.isOnHtml5VideoServer(state)) {
String server = serverConfig.h5Servers.get(camserv.toString()); String server = serverConfig.h5Servers.get(camserv.toString());
streamUrl = "https://"+ server + ".myfreecams.com/NxServer/ngrp:mfc_" + userChannel + ".f4v_mobile/playlist.m3u8"; streamUrl = "https://"+ server + ".myfreecams.com/NxServer/ngrp:mfc_" + userChannel + ".f4v_mobile/playlist.m3u8";