Package org.cometd.server

Examples of org.cometd.server.ServerSessionImpl


            // Remember if we start a batch
            boolean batch = false;

            // Don't know the session until first message or handshake response.
            ServerSessionImpl session = null;
            boolean connect = false;

            try {
                ServerMessage.Mutable[] messages = parseMessages(request);
                if (messages == null)
                    return;

                PrintWriter writer = null;
                for (ServerMessage.Mutable message : messages) {
                    // Is this a connect?
                    connect = Channel.META_CONNECT.equals(message.getChannel());

                    // Get the session from the message
                    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()) {
                            // start a batch to group all resulting messages into a single response.
                            batch = true;
                            session.startBatch();
                        }
                    } else if (!session.isHandshook()) {
                        batch = false;
                        session = null;
                    }

                    if (connect && session != null) {
                        // cancel previous scheduler to cancel any prior waiting long poll
                        // this should also dec the browser ID
                        session.setScheduler(null);
                    }

                    boolean wasConnected = session != null && session.isConnected();

                    // Forward handling of the message.
                    // The actual reply is return from the call, but other messages may
                    // also be queued on the session.
                    ServerMessage.Mutable reply = bayeuxServerHandle(session, message);

                    // Do we have a reply ?
                    if (reply != null) {
                        if (session == null) {
                            // This must be a handshake, extract a session from the reply
                            session = (ServerSessionImpl) getBayeux().getSession(reply.getClientId());

                            // Get the user agent while we are at it, and add the browser ID cookie
                            if (session != null) {
                                String userAgent = request.getHeader("User-Agent");
                                session.setUserAgent(userAgent);

                                String browserId = findBrowserId(request);
                                if (browserId == null)
                                    setBrowserId(request, response);
                            }
                        } else {
                            // Special handling for connect
                            if (connect) {
                                try {
                                    writer = sendQueue(request, response, session, writer);

                                    // If the writer is non null, we have already started sending a response, so we should not suspend
                                    if (writer == null && reply.isSuccessful() && session.isQueueEmpty()) {
                                        // Detect if we have multiple sessions from the same browser
                                        // Note that CORS requests do not send cookies, so we need to handle them specially
                                        // CORS requests always have the Origin header

                                        String browserId = findBrowserId(request);
                                        boolean allowSuspendConnect;
                                        if (browserId != null)
                                            allowSuspendConnect = incBrowserId(browserId);
                                        else
                                            allowSuspendConnect = _allowMultiSessionsNoBrowser;

                                        if (allowSuspendConnect) {
                                            long timeout = session.calculateTimeout(getTimeout());

                                            // Support old clients that do not send advice:{timeout:0} on the first connect
                                            if (timeout > 0 && wasConnected && session.isConnected()) {
                                                // Suspend and wait for messages
                                                Continuation continuation = ContinuationSupport.getContinuation(request);
                                                continuation.setTimeout(timeout);
                                                continuation.suspend(response);
                                                scheduler = new LongPollScheduler(session, continuation, reply, browserId);
                                                session.setScheduler(scheduler);
                                                request.setAttribute(LongPollScheduler.ATTRIBUTE, scheduler);
                                                reply = null;
                                                metaConnectSuspended(request, session, timeout);
                                            } else {
                                                decBrowserId(browserId);
                                            }
                                        } else {
                                            // There are multiple sessions from the same browser
                                            Map<String, Object> advice = reply.getAdvice(true);

                                            if (browserId != null)
                                                advice.put("multiple-clients", true);

                                            if (_multiSessionInterval > 0) {
                                                advice.put(Message.RECONNECT_FIELD, Message.RECONNECT_RETRY_VALUE);
                                                advice.put(Message.INTERVAL_FIELD, _multiSessionInterval);
                                            } else {
                                                advice.put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE);
                                                reply.setSuccessful(false);
                                            }
                                            session.reAdvise();
                                        }
                                    }
                                } finally {
                                    if (reply != null && session.isConnected())
                                        session.startIntervalTimeout(getInterval());
                                }
                            } else {
                                if (!isMetaConnectDeliveryOnly() && !session.isMetaConnectDeliveryOnly()) {
                                    writer = sendQueue(request, response, session, writer);
                                }
                            }
                        }

                        // If the reply has not been otherwise handled, send it
                        if (reply != null) {
                            if (connect && session != null && !session.isConnected())
                                reply.getAdvice(true).put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE);

                            reply = getBayeux().extendReply(session, session, reply);

                            if (reply != null) {
                                getBayeux().freeze(reply);
                                writer = send(request, response, writer, reply);
                            }
                        }
                    }

                    // Disassociate the reply
                    message.setAssociated(null);
                }
                if (writer != null)
                    complete(writer);
            } catch (ParseException x) {
                handleJSONParseException(request, response, x.getMessage(), x.getCause());
            } finally {
                // If we started a batch, end it now
                if (batch) {
                    boolean ended = session.endBatch();

                    // Flush session if not done by the batch, since some browser order <script> requests
                    if (!ended && isAlwaysFlushingAfterHandle())
                        session.flush();
                } else if (session != null && !connect && isAlwaysFlushingAfterHandle()) {
                    session.flush();
                }
            }
        } else {
            // Get the resumed session
            ServerSessionImpl session = scheduler.getSession();
            metaConnectResumed(request, session);

            PrintWriter writer;
            try {
                // Send the message queue
                writer = sendQueue(request, response, session, null);
            } finally {
                // We need to start the interval timeout before the connect reply
                // otherwise we open up a race condition where the client receives
                // the connect reply and sends a new connect request before we start
                // the interval timeout, which will be wrong.
                // We need to put this into a finally block in case sending the queue
                // throws an exception (for example because the client is gone), so that
                // we start the interval timeout that is important to sweep the session
                if (session.isConnected())
                    session.startIntervalTimeout(getInterval());
            }

            // Send the connect reply
            ServerMessage.Mutable reply = scheduler.getReply();

            if (!session.isConnected())
                reply.getAdvice(true).put(Message.RECONNECT_FIELD, Message.RECONNECT_NONE_VALUE);

            reply = getBayeux().extendReply(session, session, reply);

            if (reply != null) {
View Full Code Here


            Map<String, Object> rcvExt = rcv.getExt();
            boolean clientRequestedAcks = rcvExt != null && rcvExt.get("ack") == Boolean.TRUE;

            if (clientRequestedAcks && remote != null)
            {
                ServerSessionImpl session = (ServerSessionImpl)remote;
                if (_logger.isDebugEnabled())
                    _logger.debug("Enabled message acknowledgement for session {}", session);

                AcknowledgedMessagesSessionExtension extension = new AcknowledgedMessagesSessionExtension(session);

                // Make sure that adding the extension and importing the queue is atomic.
                synchronized (session.getLock())
                {
                    session.addExtension(extension);
                    extension.importMessages(session);
                }
            }

            Map<String, Object> sndExt = message.getExt(true);
View Full Code Here

    protected abstract void write(HttpServletRequest request, HttpServletResponse response, ServerSessionImpl session, boolean startInterval, List<ServerMessage> messages, ServerMessage.Mutable[] replies);

    protected void processMessages(HttpServletRequest request, HttpServletResponse response, ServerMessage.Mutable[] messages) throws IOException
    {
        boolean autoBatch = isAutoBatch();
        ServerSessionImpl session = null;
        boolean batch = false;
        boolean sendQueue = true;
        boolean sendReplies = true;
        boolean startInterval = false;
        boolean disconnected = false;
        try
        {
            for (int i = 0; i < messages.length; ++i)
            {
                ServerMessage.Mutable message = messages[i];
                if (_logger.isDebugEnabled())
                    _logger.debug("Processing {}", message);

                if (session == null && !disconnected)
                    session = (ServerSessionImpl)getBayeux().getSession(message.getClientId());

                if (session != null)
                {
                    disconnected = !session.isHandshook();
                    if (disconnected)
                    {
                        if (batch)
                        {
                            batch = false;
                            session.endBatch();
                        }
                        session = null;
                    }
                    else
                    {
                        if (autoBatch && !batch)
                        {
                            batch = true;
                            session.startBatch();
                        }
                    }
                }

                switch (message.getChannel())
                {
                    case Channel.META_HANDSHAKE:
                    {
                        if (messages.length > 1)
                            throw new IOException();
                        ServerMessage.Mutable reply = processMetaHandshake(request, response, session, message);
                        if (reply != null)
                            session = (ServerSessionImpl)getBayeux().getSession(reply.getClientId());
                        messages[i] = processReply(session, reply);
                        sendQueue = false;
                        break;
                    }
                    case Channel.META_CONNECT:
                    {
                        ServerMessage.Mutable reply = processMetaConnect(request, response, session, message);
                        messages[i] = processReply(session, reply);
                        startInterval = sendQueue = sendReplies = reply != null;
                        break;
                    }
                    default:
                    {
                        ServerMessage.Mutable reply = bayeuxServerHandle(session, message);
                        messages[i] = processReply(session, reply);
                        break;
                    }
                }
            }

            if (sendReplies || sendQueue)
                flush(request, response, session, sendQueue, startInterval, messages);
        }
        finally
        {
            if (batch)
                session.endBatch();
        }
    }
View Full Code Here

            AbstractWebSocketTransport.this.send(wsSession, _session, builder.toString(), callback);
        }

        protected void onClose(int code, String reason)
        {
            final ServerSessionImpl session = _session;
            if (session != null)
            {
                // There is no need to call BayeuxServerImpl.removeServerSession(),
                // because the connection may have been closed for a reload, so
                // just null out the current session to have it retrieved again
                _session = null;
                session.startIntervalTimeout(getInterval());
                cancelMetaConnectTask(session);
            }
            if (_logger.isDebugEnabled())
                _logger.debug("Closing {}/{} - {}", code, reason, session);
            AbstractWebSocketTransport.this.onClose(code, reason);
View Full Code Here

            }
        }

        private void processMessages(S wsSession, ServerMessage.Mutable[] messages) throws IOException
        {
            ServerSessionImpl session = _session;

            boolean startInterval = false;
            boolean send = true;
            List<ServerMessage> queue = Collections.emptyList();
            List<ServerMessage> replies = new ArrayList<>(messages.length);
            for (int i = 0; i < messages.length; i++)
            {
                ServerMessage.Mutable message = messages[i];
                if (_logger.isDebugEnabled())
                    _logger.debug("Processing {}", message);

                // Get the session from the message
                String clientId = message.getClientId();
                if (session == null || !session.getId().equals(clientId))
                    _session = session = (ServerSessionImpl)getBayeux().getSession(message.getClientId());

                // Session expired concurrently ?
                if (session != null && !session.isHandshook())
                    _session = session = null;

                switch (message.getChannel())
                {
                    case Channel.META_HANDSHAKE:
                    {
                        if (messages.length > 1)
                            throw new IOException();
                        ServerMessage.Mutable reply = processMetaHandshake(session, message);
                        if (reply != null)
                            session = (ServerSessionImpl)getBayeux().getSession(reply.getClientId());
                        replies.add(processReply(session, reply));
                        break;
                    }
                    case Channel.META_CONNECT:
                    {
                        ServerMessage.Mutable reply = processMetaConnect(session, message);
                        replies.add(processReply(session, reply));
                        send = startInterval = reply != null;
                        if (send && session != null)
                        {
                            if (isMetaConnectDeliveryOnly() || session.isMetaConnectDeliveryOnly())
                                queue = session.takeQueue();
                        }
                        break;
                    }
                    default:
                    {
View Full Code Here

        protected abstract void close(int code, String reason);

        @Override
        public void cancel()
        {
            final ServerSessionImpl session = _session;
            if (session != null)
            {
                if (cancelMetaConnectTask(session))
                    close(1000, "Cancel");
            }
View Full Code Here

        protected void schedule(S wsSession, boolean timeout, ServerMessage.Mutable expiredConnectReply)
        {
            // This method may be executed concurrently by threads triggered by
            // schedule() and by the timeout thread that replies to the meta connect.

            ServerSessionImpl session = _session;
            try
            {
                if (session == null)
                {
                    if (_logger.isDebugEnabled())
                        _logger.debug("No session, skipping reply {}", expiredConnectReply);
                    return;
                }

                boolean metaConnectDelivery = isMetaConnectDeliveryOnly() || session.isMetaConnectDeliveryOnly();
                if (_logger.isDebugEnabled())
                    _logger.debug("Flushing {} timeout={} metaConnectDelivery={}", session, timeout, metaConnectDelivery);

                // Decide atomically if we have to reply to the meta connect
                // We need to guarantee the metaConnectDeliverOnly semantic
                // and allow only one thread to reply to the meta connect
                // otherwise we may have out of order delivery.
                boolean reply = false;
                ServerMessage.Mutable connectReply;
                synchronized (session.getLock())
                {
                    connectReply = _connectReply;

                    if (timeout && connectReply != expiredConnectReply)
                    {
                        // We had a second meta connect arrived while we were expiring the first:
                        // just ignore to reply to the first connect as if we were able to cancel it
                        if (_logger.isDebugEnabled())
                            _logger.debug("Flushing skipped replies that do not match: {} != {}", connectReply, expiredConnectReply);
                        return;
                    }

                    if (connectReply == null)
                    {
                        if (metaConnectDelivery)
                        {
                            // If we need to deliver only via meta connect, but we
                            // do not have one outstanding, wait until it arrives
                            if (_logger.isDebugEnabled())
                                _logger.debug("Flushing skipped since metaConnectDelivery={}, metaConnectReply={}", metaConnectDelivery, connectReply);
                            return;
                        }
                    }
                    else
                    {
                        if (timeout || metaConnectDelivery || !session.isConnected())
                        {
                            // We will reply to the meta connect, so cancel the timeout task
                            cancelMetaConnectTask(session);
                            _connectReply = null;
                            reply = true;
View Full Code Here

                // Start the interval timeout after writing the messages
                // since they may take time to be written, even in case
                // of exceptions to make sure the session can be swept.
                if (entry._startInterval)
                {
                    ServerSessionImpl session = entry._session;
                    if (session != null)
                        session.startIntervalTimeout(getInterval());
                }

                List<ServerMessage> replies = entry._replies;
                if (_logger.isDebugEnabled())
                    _logger.debug("Processing replies {}", replies);
View Full Code Here

TOP

Related Classes of org.cometd.server.ServerSessionImpl

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.