@Override public boolean sendMeta(ServerSession session, Mutable message) { ServerMessage associated = message.getAssociated(); if (associated != null) { Map<String, Object> extIn = associated.getExt();
protected void resume(Context context, ServerMessage.Mutable message, Promise<Void> promise) { if (_logger.isDebugEnabled()) { _logger.debug("Resumed {}", message); } ServerMessage.Mutable reply = message.getAssociated(); ServerSessionImpl session = context.session; if (session != null) { Map<String, Object> advice = session.takeAdvice(this); if (advice != null) { reply.put(Message.ADVICE_FIELD, advice); } if (session.isDisconnected()) { reply.getAdvice(true).put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE); } } processReply(session, reply, Promise.from(r -> { if (r != null) { context.replies.add(r); } context.sendQueue = true; context.scheduleExpiration = true; promise.succeed(null); }, promise::fail)); }
private void handleMetaConnect(ServerSessionImpl session, Mutable message, Promise<Boolean> promise) { ServerMessage.Mutable reply = message.getAssociated(); if (session.connected()) { reply.setSuccessful(true); Map<String, Object> adviceIn = message.getAdvice(); if (adviceIn != null) { Number timeout = (Number)adviceIn.get("timeout"); session.updateTransientTimeout(timeout == null ? -1L : timeout.longValue()); Number interval = (Number)adviceIn.get("interval"); session.updateTransientInterval(interval == null ? -1L : interval.longValue()); // Force the server to send the advice, as the client may // have forgotten it (for example because of a reload) session.reAdvise(); } else { session.updateTransientTimeout(-1); session.updateTransientInterval(-1); } Map<String, Object> adviceOut = session.takeAdvice(message.getServerTransport()); if (adviceOut != null) { reply.put(Message.ADVICE_FIELD, adviceOut); } promise.succeed(true); } else { unknownSession(reply); promise.succeed(false); } }
private void handleMetaUnsubscribe(ServerSessionImpl session, Mutable message, Promise<Boolean> promise) { ServerMessage.Mutable reply = message.getAssociated(); Object subscriptionField = message.get(Message.SUBSCRIPTION_FIELD); if (subscriptionField == null) {
ServerMessage.Mutable reply = message.getAssociated(); if (session == null || session.isDisconnected() || (!session.getId().equals(message.getClientId()) && !Channel.META_HANDSHAKE.equals(message.getChannel()))) {
private void handleMetaSubscribe(ServerSessionImpl session, Mutable message, Promise<Boolean> promise) { ServerMessage.Mutable reply = message.getAssociated(); Object subscriptionField = message.get(Message.SUBSCRIPTION_FIELD); if (subscriptionField == null) {
private void publish2(ServerSessionImpl session, ServerChannelImpl channel, ServerMessage.Mutable message, boolean receiving, Promise<Boolean> promise) { if (channel.isBroadcast() || !receiving) { extendOutgoing(session, null, message, Promise.from(result -> { if (result) { // Exactly at this point, we convert the message to JSON and therefore // any further modification will be lost. // This is an optimization so that if the message is sent to a million // subscribers, we generate the JSON only once. // From now on, user code is passed a ServerMessage reference (and not // ServerMessage.Mutable), and we attempt to return immutable data // structures, even if it is not possible to guard against all cases. // For example, it is impossible to prevent things like // ((CustomObject)serverMessage.getData()).change() or // ((Map)serverMessage.getExt().get("map")).put(). freeze(message); publish3(session, channel, message, promise); } else { ServerMessage.Mutable reply = message.getAssociated(); error(reply, "404::message_deleted"); promise.succeed(false); } }, promise::fail)); } else { publish3(session, channel, message, promise); } }
protected void publish(ServerSessionImpl session, ServerChannelImpl channel, ServerMessage.Mutable message, boolean receiving, Promise<Boolean> promise) { if (_logger.isDebugEnabled()) { _logger.debug("< {} {}", message, session); } if (channel.isBroadcast()) { // Do not leak the clientId to other subscribers // as we are now "sending" this message. message.setClientId(null); // Reset the messageId to avoid clashes with message-based transports such // as websocket whose clients may rely on the messageId to match request/responses. message.setId(null); } notifyListeners(session, channel, message, Promise.from(proceed -> { if (proceed) { publish2(session, channel, message, receiving, promise); } else { ServerMessageImpl reply = (ServerMessageImpl)message.getAssociated(); if (reply != null && !reply.isHandled()) { error(reply, "404::message_deleted"); } promise.succeed(false); } }, promise::fail)); }
private void handleMetaHandshake(ServerSessionImpl session, Mutable message, Promise<Boolean> promise) { BayeuxContext context = message.getBayeuxContext(); if (context != null) { session.setUserAgent(context.getHeader("User-Agent")); } if (_policy != null) { _policy.canHandshake(this, session, message, Promise.from(can -> { if (can) { handleMetaHandshake2(session, message, promise); } else { ServerMessage.Mutable reply = message.getAssociated(); error(reply, "403::handshake_denied"); // The user's SecurityPolicy may have customized the response's advice Map<String, Object> advice = reply.getAdvice(true); if (!advice.containsKey(Message.RECONNECT_FIELD)) { advice.put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE); } promise.succeed(false); } }, promise::fail)); } else { handleMetaHandshake2(session, message, promise); } }
private void handleMetaSubscribe2(ServerSessionImpl session, Mutable message, ServerChannelImpl channel, Promise<Boolean> promise) { ServerMessage.Mutable reply = message.getAssociated(); isSubscribeAuthorized(channel, session, message, Promise.from(subscribeResult -> { if (subscribeResult instanceof Authorizer.Result.Denied) { String denyReason = ((Authorizer.Result.Denied)subscribeResult).getReason(); error(reply, "403:" + denyReason + ":subscribe_denied"); promise.succeed(false); } else { if (channel.subscribe(session, message)) { reply.setSuccessful(true); promise.succeed(true); } else { error(reply, "403::subscribe_failed"); promise.succeed(false); } } }, promise::fail)); }
private void handleMetaHandshake2(ServerSessionImpl session, Mutable message, Promise<Boolean> promise) { ServerMessage.Mutable reply = message.getAssociated(); if (session.handshake(message)) { addServerSession(session, message); reply.setSuccessful(true); reply.setClientId(session.getId()); reply.put(Message.VERSION_FIELD, "1.0"); reply.put(Message.MIN_VERSION_FIELD, "1.0"); reply.put(Message.SUPPORTED_CONNECTION_TYPES_FIELD, getAllowedTransports()); Map<String, Object> adviceOut = session.takeAdvice(message.getServerTransport()); reply.put(Message.ADVICE_FIELD, adviceOut); promise.succeed(true); } else { error(reply, "403::handshake_failed"); promise.succeed(false); } }
private void handle3(ServerSessionImpl session, ServerMessage.Mutable message, ServerChannelImpl channel, Promise<ServerMessage.Mutable> promise) { ServerMessage.Mutable reply = message.getAssociated(); if (channel.isMeta()) { publish(session, channel, message, true, Promise.from(published -> promise.succeed(reply), promise::fail)); } else { isPublishAuthorized(channel, session, message, Promise.from(result -> { if (result instanceof Authorizer.Result.Denied) { String denyReason = ((Authorizer.Result.Denied)result).getReason(); error(reply, "403:" + denyReason + ":publish denied"); promise.succeed(reply); } else { reply.setSuccessful(true); publish(session, channel, message, true, Promise.from(published -> promise.succeed(reply), promise::fail)); } }, promise::fail)); } }
private void handleMetaDisconnect(ServerSessionImpl session, Mutable message, Promise<Boolean> promise) { ServerMessage.Mutable reply = message.getAssociated(); reply.setSuccessful(true); removeServerSession(session, false); // Wake up the possibly pending /meta/connect session.flush(); promise.succeed(true); }