/**
         * <summary>
         * Wraps protocol message into a results bean.</summary>
         *
         * <param name="data">Protocol message that need to be wrapped.</param>
         * <returns>Wrapped message.</returns>
         */
        private static GridClientResponse WrapResponse(ProtoResponse data)
        {
            GridClientResponse bean = new GridClientResponse();

            //bean.RequestId = data.RequestId;
            //bean.ClientId = WrapGuid(data.ClientId);
            bean.Status = GridClientResponse.FindByCode(data.Status);

            if (data.HasErrorMessage)
            {
                bean.ErrorMessage = data.ErrorMessage;
            }

            if (data.HasResultBean)
            {
                bean.Result = WrapObject(data.ResultBean);
            }

            if (data.HasSessionToken)
            {
                bean.SessionToken = data.SessionToken.ToByteArray();
            }

            return(bean);
        }
Пример #2
0
        /**
         * <summary>
         * Handles incoming response message.</summary>
         *
         * <param name="msg">Incoming response message.</param>
         */
        private void handleResponse(GridClientResponse msg)
        {
            Dbg.Assert(Thread.CurrentThread.Equals(rdr));

            GridClientTcpRequestFuture fut;

            lock (pendingReqs) {
                if (!pendingReqs.TryGetValue(msg.RequestId, out fut))
                {
                    return;
                }
            }

            // Update authentication session token.
            if (msg.SessionToken != null)
            {
                sesTok = msg.SessionToken;
            }

            if (fut.State == GridClientTcpRequestFuture.INITIAL)
            {
                // If request initially failed due to authentication - try to re-authenticate session.
                if (msg.Status == GridClientResponseStatus.AuthFailure)
                {
                    fut.State = GridClientTcpRequestFuture.AUTHORISING;

                    sendCredentials(msg.RequestId);
                }
                else
                {
                    finishRequest(fut, msg);
                }
            }
            else if (fut.State == GridClientTcpRequestFuture.AUTHORISING)
            {
                if (msg.Status == GridClientResponseStatus.Success)
                {
                    // Send the original message under authorised session.
                    fut.State = GridClientTcpRequestFuture.RETRY;

                    fut.Message.SessionToken = sesTok;

                    sendPacket(fut.Message);
                }
                else
                {
                    // Let the request fail straight way.
                    finishRequest(fut, msg);
                }
            }
            else   // State == RETRY
                   // Finish request with whatever server responded.
            {
                finishRequest(fut, msg);
            }
        }
Пример #3
0
        /**
         * <summary>
         * Finishes user request to the grid.</summary>
         *
         * <param name="fut">Future used to pass result to the user.</param>
         * <param name="resp">Incoming response message.</param>
         */
        private void finishRequest(GridClientFuture fut, GridClientResponse resp)
        {
            switch (resp.Status)
            {
            case GridClientResponseStatus.Success:
                fut.Done(resp.Result);

                break;

            case GridClientResponseStatus.Failed:
                var error = resp.ErrorMessage;

                if (error == null)
                {
                    error = "Unknown server error";
                }

                fut.Fail(() => {
                    throw new GridClientException(error);
                });

                break;

            case GridClientResponseStatus.AuthFailure:
                fut.Fail(() => {
                    throw new GridClientAuthenticationException("Authentication failed (session expired?)" +
                                                                " errMsg=" + resp.ErrorMessage + ", [srv=" + ServerAddress + "]");
                });

                U.Async(() => Close(false));

                break;

            case GridClientResponseStatus.AuthorizationFailure:
                fut.Fail(() => {
                    throw new GridClientException("Client authorization failed: " + resp.ErrorMessage);
                });

                break;

            default:
                fut.Fail(() => {
                    throw new GridClientException("Unknown server response status code: " + resp.Status);
                });

                break;
            }

            pendingReqs.Remove(resp.RequestId);
        }
        /**
         * <summary>
         * Wraps results bean into a protocol message.</summary>
         *
         * <param name="bean">Results bean that need to be wrapped.</param>
         * <returns>Wrapped message.</returns>
         */
        private static ProtoResponse WrapResultBean(GridClientResponse bean)
        {
            ProtoResponse.Builder builder = ProtoResponse.CreateBuilder()
                                            //.SetRequestId(bean.RequestId)
                                            //.SetClientId(WrapGuid(bean.ClientId))
                                            .SetStatus((int)bean.Status);

            if (bean.ErrorMessage != null)
            {
                builder.SetErrorMessage(bean.ErrorMessage);
            }

            if (bean.Result != null)
            {
                builder.SetResultBean(WrapObject(bean.Result));
            }

            if (bean.SessionToken != null)
            {
                builder.SetSessionToken(ByteString.CopyFrom(bean.SessionToken));
            }

            return(builder.Build());
        }
Пример #5
0
        /** <summary>Reader thread.</summary> */
        private void readPackets()
        {
            try {
                bool running = true;

                while (running)
                {
                    // Note that only this thread removes futures from map.
                    // So if we see closed condition, it is safe to check map size since no more futures
                    // will be added to the map.
                    if (closed)
                    {
                        // Exit if either all requests processed or we do not wait for completion.
                        if (!waitCompletion)
                        {
                            break;
                        }

                        lock (pendingReqs) {
                            if (pendingReqs.Count == 0)
                            {
                                break;
                            }
                        }
                    }

                    // Header.
                    int symbol;

                    try {
                        symbol = readByte();
                    }
                    catch (TimeoutException) {
                        checkPing();

                        continue;
                    }

                    // Connection closed.
                    if (symbol == -1)
                    {
                        Dbg.WriteLine("Connection closed by remote host " +
                                      "[srvAddr=" + ServerAddress + ", symbol=" + symbol + "]");

                        break;
                    }

                    // Check for correct header.
                    if ((byte)symbol != (byte)0x90)
                    {
                        Dbg.WriteLine("Failed to parse incoming message (unexpected header received, will close) " +
                                      "[srvAddr=" + ServerAddress + ", symbol=" + symbol + "]");

                        break;
                    }

                    // Packet.
                    MemoryStream buf = new MemoryStream();

                    int len = 0;

                    while (true)
                    {
                        try {
                            symbol = readByte();
                        }
                        catch (TimeoutException) {
                            checkPing();

                            continue;
                        }

                        if (symbol == -1)
                        {
                            running = false;

                            break;
                        }

                        byte b = (byte)symbol;

                        buf.WriteByte(b);

                        if (len == 0)
                        {
                            if (buf.Length == 4)
                            {
                                len = U.BytesToInt32(buf.ToArray(), 0);

                                // Reset buffer.
                                buf.SetLength(0);

                                if (len == 0)
                                {
                                    // Ping received.
                                    lastPingRcvTime = U.Now;

                                    break;
                                }
                            }
                        }
                        else
                        {
                            if (buf.Length == len)
                            {
                                if (len < 40)
                                {
                                    Dbg.WriteLine("Invalid packet received [len=" + len + ", buf=" + buf + "]");

                                    break;
                                }

                                buf.Position = 0; // Rewind buffer.

                                byte[] head   = new byte[40];
                                byte[] packet = new byte[len - head.Length];

                                buf.Read(head, 0, head.Length);
                                buf.Read(packet, 0, packet.Length);

                                GridClientResponse msg = marshaller.Unmarshal <GridClientResponse>(packet);

                                msg.RequestId  = U.BytesToInt64(head, 0);
                                msg.ClientId   = U.BytesToGuid(head, 8);
                                msg.DestNodeId = U.BytesToGuid(head, 24);

                                // Reset buffer.
                                buf.SetLength(0);

                                len = 0;

                                lastPacketRcvTime = U.Now;

                                handleResponse(msg);

                                break;
                            }
                        }
                    }
                }
            }
            catch (IOException e) {
                if (!closed)
                {
                    Dbg.WriteLine("Failed to read data from remote host (will close connection)" +
                                  " [addr=" + ServerAddress + ", e=" + e.Message + "]");
                }
            }
            catch (Exception e) {
                Dbg.WriteLine("Unexpected throwable in connection reader thread (will close connection)" +
                              " [addr={0}, e={1}]", ServerAddress, e);
            }
            finally {
                U.Async(() => Close(false));
            }
        }
        /**
         * <summary>
         * Handle server response.</summary>
         *
         * <param name="args">Parameters map.</param>
         * <param name="fut">Future to use.</param>
         * <param name="str">Downloaded string response.</param>
         */
        private void OnResponse(IDictionary <String, Object> args, GridClientFuture fut, String str)
        {
            try {
                JavaScriptSerializer s = new JavaScriptSerializer();

                // Parse json response.
                var json = (IDictionary <String, Object>)s.Deserialize(str, typeof(Object));

                // Recover status.
                GridClientResponseStatus statusCode = GridClientResponse.FindByCode((int)json["successStatus"]);

                // Retry with credentials, if authentication failed.
                if (statusCode == GridClientResponseStatus.AuthFailure)
                {
                    // Reset session token.
                    sessionToken = null;

                    // Re-send request with credentials and without session token.
                    str = LoadString(args, null);

                    // Parse json response.
                    json = (IDictionary <String, Object>)s.Deserialize(str, typeof(IDictionary <String, Object>));

                    // Recover status.
                    statusCode = GridClientResponse.FindByCode((int)json["successStatus"]);
                }

                Object o;
                String errorMsg = null;

                if (json.TryGetValue("error", out o))
                {
                    errorMsg = (String)o;
                }

                if (String.IsNullOrEmpty(errorMsg))
                {
                    errorMsg = "Unknown server error";
                }

                if (statusCode == GridClientResponseStatus.AuthFailure)
                {
                    // Close this connection.
                    Close(false);

                    throw new GridClientAuthenticationException("Client authentication failed " +
                                                                "[clientId=" + ClientId + ", srvAddr=" + ServerAddress + ", errMsg=" + errorMsg + ']');
                }

                if (statusCode == GridClientResponseStatus.Failed)
                {
                    throw new GridClientException(errorMsg);
                }

                if (statusCode == GridClientResponseStatus.AuthorizationFailure)
                {
                    throw new GridClientException("Client authorization failed: " + errorMsg);
                }

                if (statusCode != GridClientResponseStatus.Success)
                {
                    throw new GridClientException("Unsupported response status code: " + statusCode);
                }

                // Update session token only on success and auth-failed responses.
                if (json.TryGetValue("sessionToken", out o))
                {
                    sessionToken = o == null ? null : o.ToString();
                }

                fut.Done(json["response"]);
            }
            catch (Exception e) {
                fut.Fail(() => {
                    throw new GridClientException(e.Message, e);
                });
            }
            finally {
                lock (pendingReqs) {
                    pendingReqs.Remove(fut);
                }
            }
        }
Пример #7
0
        /** <summary>Reader thread.</summary> */
        private void readPackets()
        {
            try {
                bool   running = true;
                byte[] lenByte = new byte[4];
                byte[] head    = new byte[40];

                while (running)
                {
                    // Note that only this thread removes futures from map.
                    // So if we see closed condition, it is safe to check map size since no more futures
                    // will be added to the map.
                    if (closed)
                    {
                        // Exit if either all requests processed or we do not wait for completion.
                        if (!waitCompletion)
                        {
                            break;
                        }

                        if (pendingReqs.Count == 0)
                        {
                            break;
                        }
                    }

                    // Header.
                    int symbol;

                    try {
                        if (lastReadTimedOut)
                        {
                            lastReadTimedOut = false;

                            if (isSslStream)
                            {
                                // Recover SSL stream state after socket exception.
                                skipSslDataRecordHeader();
                            }
                        }

                        symbol = inStream.ReadByte();
                    }
                    catch (Exception e) {
                        if (e.InnerException is SocketException)
                        {
                            e = e.InnerException;
                        }

                        var sockEx = e as SocketException;

                        if (sockEx != null && sockEx.ErrorCode == 10060)
                        {
                            checkPing();

                            lastReadTimedOut = true;

                            continue;
                        }

                        // All other exceptions are interpreted as stream ends.
                        throw;
                    }

                    // Connection closed.
                    if (symbol == -1)
                    {
                        Dbg.WriteLine("Connection closed by remote host " +
                                      "[srvAddr=" + ServerAddress + ", symbol=" + symbol + "]");

                        break;
                    }

                    // Check for correct header.
                    if ((byte)symbol != (byte)0x90)
                    {
                        Dbg.WriteLine("Failed to parse incoming message (unexpected header received, will close) " +
                                      "[srvAddr=" + ServerAddress + ", symbol=" + symbol + "]");

                        break;
                    }

                    U.ReadFully(inStream, lenByte, 0, 4);

                    int len = U.BytesToInt32(lenByte, 0);

                    if (len == 0)
                    {
                        // Ping received.
                        lastPingRcvTime = U.Now;

                        continue;
                    }

                    if (len < 40)
                    {
                        Dbg.WriteLine("Invalid packet received [len=" + len + "]");

                        break;
                    }

                    U.ReadFully(inStream, head, 0, 40);

                    long reqId      = U.BytesToInt64(head, 0);
                    Guid clientId   = U.BytesToGuid(head, 8);
                    Guid destNodeId = U.BytesToGuid(head, 24);

                    byte[] msgBytes = new byte[len - 40];

                    U.ReadFully(inStream, msgBytes, 0, msgBytes.Length);

                    GridClientResponse msg = marshaller.Unmarshal <GridClientResponse>(msgBytes);

                    msg.RequestId  = reqId;
                    msg.ClientId   = clientId;
                    msg.DestNodeId = destNodeId;

                    lastPacketRcvTime = U.Now;

                    handleResponse(msg);
                }
            }
            catch (IOException e) {
                if (!closed)
                {
                    Dbg.WriteLine("Failed to read data from remote host (will close connection)" +
                                  " [addr=" + ServerAddress + ", e=" + e.Message + "]");
                }
            }
            catch (Exception e) {
                Dbg.WriteLine("Unexpected throwable in connection reader thread (will close connection)" +
                              " [addr={0}, e={1}]", ServerAddress, e);
            }
            finally {
                U.Async(() => Close(false));
            }
        }