if (Channel.META_HANDSHAKE.equals(reply.getChannel())) { if (allowMessageDeliveryDuringHandshake(session) && !messages.isEmpty()) { reply.put("x-messages", messages.size());
@Override public void run() { for (SystemTopics topic : SystemTopics.values()) { String topicData; switch (topic) { case Time: topicData = logDateFormat.format(new Date()); break; default: topicData = "unknown topic: " + topic.toString(); } ServerMessage.Mutable message = bayeuxServer.newMessage(); message.setChannel(channels.get(topic.ordinal()).getId()); message.setData(topicData); channels.get(topic.ordinal()).publish(session, message); } } }
private void messageFailure(ServerMessage message, Throwable cause) { ServerMessage.Mutable failed = newMessage(); failed.setId(message.getId()); failed.setSuccessful(false); failed.setChannel(message.getChannel()); if (message.containsKey(Message.SUBSCRIPTION_FIELD)) { failed.put(Message.SUBSCRIPTION_FIELD, message.get(Message.SUBSCRIPTION_FIELD)); } Map<String, Object> failure = new HashMap<>(); failed.put("failure", failure); failure.put("message", message); failure.put("exception", cause); receive(failed, Promise.noop()); }
for (ServerMessage.Mutable message : messages) { connect = Channel.META_CONNECT.equals(message.getChannel()); String client_id = message.getClientId(); if (session == null || client_id != null && !client_id.equals(session.getId())) { session = (ServerSessionImpl) getBayeux().getSession(client_id); if (_autoBatch && !batch && session != null && !connect && !message.isMeta()) { if (session == null) { session = (ServerSessionImpl) getBayeux().getSession(reply.getClientId()); if (writer == null && reply.isSuccessful() && session.isQueueEmpty()) { Map<String, Object> advice = reply.getAdvice(true); } else { advice.put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE); reply.setSuccessful(false); reply.getAdvice(true).put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE); message.setAssociated(null); reply.getAdvice(true).put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE);
if (session != null) { boolean maySuspend = !session.shouldSchedule(); if (canSuspend && maySuspend && reply.isSuccessful()) { HttpServletRequest request = context.request; Map<String, Object> advice = reply.getAdvice(true); advice.put("multiple-clients", true); } else { advice.put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE); reply.setSuccessful(false); reply.getAdvice(true).put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE);
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) { error(reply, "403::subscription_missing"); promise.succeed(false); } else { reply.put(Message.SUBSCRIPTION_FIELD, subscriptionField); AsyncFoldLeft.run(subscriptions, true, (result, subscription, loop) -> { ServerChannelImpl channel = getServerChannel(subscription); } else { if (channel.unsubscribe(session, message)) { reply.setSuccessful(true); loop.proceed(true); } else {
private void processMetaHandshake(Context context, ServerMessage.Mutable message, Promise<Void> promise) { handleMessage(context, message, Promise.from(reply -> { ServerSessionImpl session = context.session; if (reply.isSuccessful()) { HttpServletRequest request = context.request; context.replies.add(r); context.sendQueue = r != null && r.isSuccessful() && allowMessageDeliveryDuringHandshake(session); context.scheduleExpiration = true; promise.succeed(null);
ServerMessage.Mutable reply = message.getAssociated(); if (session == null || session.isDisconnected() || (!session.getId().equals(message.getClientId()) && !Channel.META_HANDSHAKE.equals(message.getChannel()))) { unknownSession(reply); promise.succeed(reply); } else { String channelName = message.getChannel(); session.cancelExpiration(Channel.META_CONNECT.equals(channelName));
RemoteCall.Caller caller = new CallerImpl(bayeuxServer, localSession, from, message.getId(), message.getChannel()); args[0] = caller; args[1] = message.getData(); for (int i = 0; i < paramNames.size(); ++i) { args[2 + i] = matches.get(paramNames.get(i));
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); } }
@Override public boolean sendMeta(ServerSession to, Mutable message) { String channel = message.getChannel(); Map<String, Object> ext = message.getExt(true); if (channel.equals(Channel.META_HANDSHAKE)) { if (_session.isAllowMessageDeliveryDuringHandshake()) { long batch = closeBatch(message); Map<String, Object> ack = new HashMap<>(3); ack.put("enabled", true); ack.put("batch", batch); ext.put("ack", ack); if (_logger.isDebugEnabled()) { _logger.debug("Sending batch {} for {}", batch, _session); } } else { ext.put("ack", Boolean.TRUE); } } else if (channel.equals(Channel.META_CONNECT)) { long batch = closeBatch(message); ext.put("ack", batch); if (_logger.isDebugEnabled()) { _logger.debug("Sending batch {} for {}", batch, _session); } } return true; }
@Override public void handshake(Map<String, Object> template, ClientSession.MessageListener callback) { if (_session != null) { throw new IllegalStateException(); } ServerSessionImpl session = new ServerSessionImpl(_bayeux, this, _idHint); ServerMessage.Mutable hsMessage = newMessage(); if (template != null) { hsMessage.putAll(template); } String messageId = newMessageId(); hsMessage.setId(messageId); hsMessage.setChannel(Channel.META_HANDSHAKE); registerCallback(messageId, callback); doSend(session, hsMessage, Promise.from(hsReply -> { if (hsReply != null && hsReply.isSuccessful()) { _session = session; ServerMessage.Mutable cnMessage = newMessage(); cnMessage.setId(newMessageId()); cnMessage.setChannel(Channel.META_CONNECT); cnMessage.getAdvice(true).put(Message.INTERVAL_FIELD, -1L); cnMessage.setClientId(session.getId()); doSend(session, cnMessage, Promise.from(cnReply -> { // Nothing more to do. }, failure -> messageFailure(cnMessage, failure))); } }, failure -> messageFailure(hsMessage, failure))); }
@Override public ServerMessage send(ServerSession session, ServerMessage message) { Object data = message.getData(); if (data instanceof BinaryData) { ServerMessage.Mutable result = bayeuxServer.newMessage(); result.putAll(message); BinaryData binaryData = (BinaryData)data; Object binary = binaryData.get(BinaryData.DATA); String encoded; if (binary instanceof byte[]) { encoded = Z85.encoder.encodeBytes(binaryData.asBytes()); } else if (binary instanceof ByteBuffer) { encoded = Z85.encoder.encodeByteBuffer(binaryData.asByteBuffer()); } else { throw new IllegalArgumentException("Cannot Z85 encode " + binary); } Map<String, Object> newData = new HashMap<>(binaryData); newData.put(BinaryData.DATA, encoded); result.setData(newData); Map<String, Object> ext = result.getExt(true); ext.put(BinaryData.EXT_NAME, new HashMap<>(0)); return result; } else { return message; } } }
protected void processMessages(Context context, ServerMessage.Mutable[] messages, Promise<Void> promise) { if (messages.length == 0) { promise.fail(new IOException("protocol violation")); } else { Collection<ServerSessionImpl> sessions = findCurrentSessions(context.request); ServerMessage.Mutable message = messages[0]; ServerSessionImpl session = findSession(sessions, message); if (_logger.isDebugEnabled()) { _logger.debug("Processing {} messages for session {}", messages.length, session); } boolean batch = session != null && !Channel.META_CONNECT.equals(message.getChannel()); if (batch) { session.startBatch(); } context.messages = messages; context.session = session; AsyncFoldLeft.run(messages, null, (result, item, loop) -> processMessage(context, (ServerMessageImpl)item, Promise.from(loop::proceed, loop::fail)), Promise.from(y -> { flush(context, promise); if (batch) { session.endBatch(); } }, promise::fail)); } }
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)); }
@Override public boolean send(ServerSession from, ServerSession to, ServerMessage.Mutable message) { Object data = message.getData(); if (data instanceof BinaryData) { BinaryData binaryData = (BinaryData)data; Object binary = binaryData.get(BinaryData.DATA); String encoded; if (binary instanceof byte[]) { encoded = Z85.encoder.encodeBytes(binaryData.asBytes()); } else if (binary instanceof ByteBuffer) { encoded = Z85.encoder.encodeByteBuffer(binaryData.asByteBuffer()); } else { throw new IllegalArgumentException("Cannot Z85 encode " + binary); } Map<String, Object> newData = new HashMap<>(binaryData); newData.put(BinaryData.DATA, encoded); message.setData(newData); Map<String, Object> ext = message.getExt(true); ext.put(BinaryData.EXT_NAME, new HashMap<>(0)); } return true; } }
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); } }
protected ServerSessionImpl findSession(Collection<ServerSessionImpl> sessions, ServerMessage.Mutable message) { if (Channel.META_HANDSHAKE.equals(message.getChannel())) { ServerSessionImpl session = getBayeux().newServerSession(); session.setAllowMessageDeliveryDuringHandshake(isAllowMessageDeliveryDuringHandshake()); return session; } // Is there an existing, trusted, session ? String clientId = message.getClientId(); if (sessions != null) { if (clientId != null) { for (ServerSessionImpl session : sessions) { if (session.getId().equals(clientId)) { return session; } } } } if (_trustClientSession) { return (ServerSessionImpl)getBayeux().getSession(clientId); } return null; }
@Override public boolean onMessage(ServerSession from, ServerChannel channel, Mutable message) { try { Object data = message.getData(); final Object orig = data; for (DataFilter filter : _filters) { data = filter.filter(from, channel, data); if (data == null) { return false; } } if (data != orig) { message.setData(data); } return true; } catch (DataFilter.AbortException a) { if (_logger.isDebugEnabled()) { _logger.debug("", a); } return false; } } }
private void doSend(ServerSessionImpl session, ServerMessage.Mutable message, Promise<ServerMessage.Mutable> promise) { String messageId = message.getId(); message.setClientId(session.getId()); extendOutgoing(message, Promise.from(result -> { // Extensions may have changed the messageId. message.setId(messageId); if (result) { _bayeux.handle(session, message, Promise.from(r -> _bayeux.extendReply(session, _session, r, Promise.from(reply -> { if (reply != null) { receive(reply, Promise.from(y -> promise.succeed(reply), promise::fail)); } else { promise.succeed(null); } }, promise::fail)), promise::fail)); } else { ServerMessage.Mutable reply = _bayeux.createReply(message); _bayeux.error(reply, "404::message_deleted"); receive(reply, Promise.from(y -> promise.succeed(reply), promise::fail)); } }, promise::fail)); }