/** * finds the corresponding callback object to an incoming message. Returns a dummy callback if no * corresponding callback can be found * * @param message the message * @return the iO callback * @throws SocketIOException */ private IOCallback findCallback(IOMessage message) throws SocketIOException { if ("".equals(message.getEndpoint())) { return this; } SocketIO socket = sockets.get(message.getEndpoint()); if (socket == null) { throw new SocketIOException("Cannot find socket for '" + message.getEndpoint() + "'"); } return socket.getCallback(); }
/** * Creates a new {@link IOAcknowledge} instance which sends its arguments back to the server. * * @param message the message * @return an {@link IOAcknowledge} instance, may be <code>null</code> if server doesn't request * one. */ private IOAcknowledge remoteAcknowledge(IOMessage message) { String _id = message.getId(); if (_id.equals("")) { return null; } else if (!_id.endsWith("+")) { _id = _id + "+"; } final String id = _id; final String endPoint = message.getEndpoint(); return new IOAcknowledge() { @Override public void ack(Object... args) { String jsonString = null; try { jsonString = objectMapper.writeValueAsString(args); } catch (Exception e) { error( new SocketIOException( "You can only put values in IOAcknowledge.ack() which can be serialized", e)); } IOMessage ackMsg = new IOMessage(IOMessage.TYPE_ACK, endPoint, id + jsonString); sendPlain(ackMsg.toString()); } }; }
/** * Transport message. {@link IOTransport} calls this, when a message has been received. * * @param text the text */ public void transportMessage(String text) { log.debug("< " + text); IOMessage message; try { message = new IOMessage(text); } catch (Exception e) { error(new SocketIOException("Garbage from server: " + text, e)); return; } resetTimeout(); switch (message.getType()) { case IOMessage.TYPE_DISCONNECT: try { findCallback(message).onDisconnect(); } catch (Exception e) { error(new SocketIOException("Exception was thrown in onDisconnect()", e)); } break; case IOMessage.TYPE_CONNECT: try { if (firstSocket != null && "".equals(message.getEndpoint())) { if (firstSocket.getNamespace().equals("")) { firstSocket.getCallback().onConnect(); } else { IOMessage connect = new IOMessage(IOMessage.TYPE_CONNECT, firstSocket.getNamespace(), ""); sendPlain(connect.toString()); } } else { findCallback(message).onConnect(); } firstSocket = null; } catch (Exception e) { error(new SocketIOException("Exception was thrown in onConnect()", e)); } break; case IOMessage.TYPE_HEARTBEAT: sendPlain("2::"); break; case IOMessage.TYPE_MESSAGE: try { findCallback(message).onMessage(message.getData(), remoteAcknowledge(message)); } catch (Exception e) { error( new SocketIOException( "Exception was thrown in onMessage(String).\n" + "Message was: " + message.toString(), e)); } break; case IOMessage.TYPE_JSON_MESSAGE: try { // test if JSON is valid by catching a parse Exception objectMapper.readValue(message.getData(), new TypeReference<Map<String, Object>>() {}); // JSONUtils.getJsonGenericMap(message.getData(), objectMapper); findCallback(message).onMessage(message.getData(), remoteAcknowledge(message)); } catch (JsonParseException e) { log.warn("Malformated JSON received: " + message.getData()); } catch (Exception e) { error( new SocketIOException( "Exception was thrown in onMessage(JSON).\n" + "Message was: " + message.toString(), e)); } break; case IOMessage.TYPE_EVENT: try { Map<String, Object> map = objectMapper.readValue( message.getData(), new TypeReference<Map<String, Object>>() {}); Object[] argsArray; if (map.containsKey("args")) { Object argsString = map.get("args"); List<Object> argObjects = objectMapper.readValue(argsString.toString(), new TypeReference<List<Object>>() {}); argsArray = new Object[argObjects.size()]; for (int i = 0; i < argObjects.size(); i++) { if (argObjects.get(i) != null) { argsArray[i] = argObjects.get(i); } } } else { argsArray = new Object[0]; } String eventName = map.get("name").toString(); try { findCallback(message).on(eventName, remoteAcknowledge(message), argsArray); } catch (Exception e) { error( new SocketIOException( "Exception was thrown in on(String, JSON[]).\n" + "Message was: " + message.toString(), e)); } } catch (JsonParseException e) { log.warn("Malformated JSON received: " + message.getData()); } catch (JsonMappingException e) { log.warn("Mapping JSON received: " + message.getData()); } catch (IOException e) { log.warn("IO Exception: " + message.getData()); } break; case IOMessage.TYPE_ACK: String[] data = message.getData().split("\\+", 2); if (data.length == 2) { try { int id = Integer.parseInt(data[0]); IOAcknowledge ack = acknowledge.get(id); if (ack == null) { log.warn("Received unknown ack packet"); } else { List<Object> argObjects = objectMapper.readValue(data[1].toString(), new TypeReference<List<Object>>() {}); Object[] argsArray = new Object[argObjects.size()]; for (int i = 0; i < argObjects.size(); i++) { if (argObjects.get(i) != null) { argsArray[i] = argObjects.get(i); } } ack.ack(argsArray); } } catch (NumberFormatException e) { log.warn( "Received malformated Acknowledge! This is potentially filling up the acknowledges!"); } catch (JsonParseException e) { log.warn("Malformated JSON received: " + message.getData()); } catch (JsonMappingException e) { log.warn("Mapping JSON received: " + message.getData()); } catch (IOException e) { log.warn("IO Exception: " + message.getData()); } } else if (data.length == 1) { sendPlain("6:::" + data[0]); } break; case IOMessage.TYPE_ERROR: try { findCallback(message).onError(new SocketIOException(message.getData())); } catch (SocketIOException e) { error(e); } if (message.getData().endsWith("+0")) { // We are advised to disconnect cleanup(); } break; case IOMessage.TYPE_NOOP: break; default: log.warn("Unkown type received" + message.getType()); break; } }