Exemplo n.º 1
0
 /// <summary>
 /// 通用 API 请求方法
 /// </summary>
 /// <param name="apiName">API 名称</param>
 /// <param name="apiParams">API 参数</param>
 /// <returns>API 返回的数据</returns>
 public dynamic Request(string apiName, object apiParams)
 {
     using (SdkDebug.WriteLineAndIndent("> 请求鉴权服务 API"))
     {
         return(DoRequest(apiName, apiParams));
     }
 }
 /// <summary>
 /// 对信道服务器使用 POST 方法推送到业务服务器的报文进行处理
 /// </summary>
 /// <param name="handler">客户使用的信道服务处理实例,用于处理解析之后的包</param>
 private void HandlePost(ITunnelHandler handler, TunnelHandleOptions options)
 {
     using (SdkDebug.WriteLineAndIndent($"> 收到信道服务器 POST 过来的报文 (Time: {DateTime.Now.ToString("HH:mm:ss")})"))
     {
         DoHandlePost(handler);
     }
 }
Exemplo n.º 3
0
 /// <summary>
 /// 通用 API 请求方法
 /// </summary>
 /// <param name="api">API 名称</param>
 /// <param name="data">API 参数</param>
 /// <returns>API 返回的数据</returns>
 public dynamic Request(string path, object data, bool emitSkey = false)
 {
     using (SdkDebug.WriteLineAndIndent("> 请求信道服务 API"))
     {
         return(DoRequest(path, data, emitSkey));
     }
 }
Exemplo n.º 4
0
        private dynamic DoRequest(string apiName, object apiParams)
        {
            string responseContent;

            // 请求授权服务器,获取返回报文
            try
            {
                string requestContent = BuildRequestBody(apiName, apiParams);

                DateTime start = DateTime.Now;
                responseContent = Http.Post(APIEndpoint, BuildRequestBody(apiName, apiParams));
                DateTime end  = DateTime.Now;
                TimeSpan cost = end - start;

                using (SdkDebug.WriteLineAndIndent($"POST {APIEndpoint} (Time: {start.ToString("HH:mm:ss")}, Cost: {cost.TotalMilliseconds}ms)"))
                {
                    using (SdkDebug.WriteLineAndIndent("Requset:"))
                    {
                        SdkDebug.WriteLine(requestContent);
                    }
                    using (SdkDebug.WriteLineAndIndent("Response:"))
                    {
                        SdkDebug.WriteLine(responseContent);
                    }
                }
            }
            catch (Exception error)
            {
                using (SdkDebug.WriteLineAndIndent($"POST {APIEndpoint} (ERROR)"))
                {
                    SdkDebug.WriteLine(error);
                }
                throw new HttpRequestException($"请求鉴权 API 失败,网络异常或鉴权服务器错误:{error.Message}", error);
            }

            // 解析返回报文
            try
            {
                dynamic body = JsonConvert.DeserializeObject(responseContent);

                if (body.returnCode != 0)
                {
                    throw new AuthorizationAPIException($"鉴权服务调用失败:#{body.returnCode} - ${body.returnMessage}")
                          {
                              Code = body.returnCode
                          };
                }

                return(body.returnData);
            }
            catch (JsonException e)
            {
                throw new JsonException("鉴权服务器响应格式错误,无法解析 JSON 字符串", e);
            }
            catch (Exception e)
            {
                throw e;
            }
        }
Exemplo n.º 5
0
 public EmitResult EmitMessage(IEnumerable <string> tunnelIds, string messageType, object messageContent = null)
 {
     using (SdkDebug.WriteLineAndIndent("> 发送消息"))
     {
         SdkDebug.WriteLine($"> 消息类型:{messageType}");
         return(EmitPacket(tunnelIds, "message", new { type = messageType, content = messageContent }));
     }
 }
Exemplo n.º 6
0
        /// <summary>
        /// 发送数据包到信道服务器
        /// </summary>
        /// <param name="tunnelIds">指定数据包需要送到的信道 ID 列表</param>
        /// <param name="packetType">指定数据包的类型(message/close)</param>
        /// <param name="packetContent">指定数据包的内容</param>
        /// <returns>返回数据包发送结果,可能会包含不可用信道的列表</returns>
        /// <exception cref="EmitException">网络不可用或者信道服务器不可用</exception>
        public EmitResult EmitPacket(IEnumerable <string> tunnelIds, string packetType, object packetContent)
        {
            if (tunnelIds.Count() == 0)
            {
                return new EmitResult()
                       {
                           TunnelIvalidInfos = new List <TunnelInvalidInfo>()
                       }
            }
            ;
            var data = new object[] {
                new {
                    type = packetType,
                    tunnelIds,
                    content = packetContent == null ? null : JsonConvert.SerializeObject(packetContent)
                }
            };

            using (SdkDebug.WriteLineAndIndent("> 发送数据包"))
            {
                SdkDebug.WriteLine($"> 信道 ID 列表:[{tunnelIds}]");

                SdkDebug.WriteLine($"> 包类型: {packetType}");
                try
                {
                    var emitResult = Request("/ws/push", data);
                    IEnumerable <string> invalidTunnels;
                    if (emitResult?.invalidTunnelIds == null)
                    {
                        invalidTunnels = new List <string>();
                    }
                    else
                    {
                        invalidTunnels = (emitResult?.invalidTunnelIds as JArray).ToList().Select(x => x.Value <string>());
                    }
                    return(new EmitResult()
                    {
                        TunnelIvalidInfos = invalidTunnels.Select(tunnelId => new TunnelInvalidInfo()
                        {
                            TunnelId = tunnelId,
                            Type = TunnelInvalidType.TunnelHasClosed
                        })
                    });
                }
                catch (Exception error)
                {
                    throw new EmitException($"网络不可用或者信道服务器不可用:{error.Message}", error);
                }
            }
        }
        /// <remarks>
        /// 对于推送过来的报文,我们这样进行处理:
        ///     1. 读取报文内容
        ///     2. 解析报文内容成 JSON
        ///     3. 检查报文签名,如果失败,则忽略报文
        ///     4. 解析报文所携带包数据(解析成功直接响应)
        ///     5. 根据包类型(connect/message/close)给到客户指定的处理实例进行处理
        /// </remarks>
        private void DoHandlePost(ITunnelHandler handler)
        {
            #region 1. 读取报文内容
            string requestContent = null;
            try
            {
                using (Stream stream = Request.Body)
                {
                    using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                    {
                        requestContent = reader.ReadToEnd();
                    }
                }
                using (SdkDebug.WriteLineAndIndent("> 读取报文内容:成功"))
                {
                    SdkDebug.WriteLine(requestContent);
                }
            }
            catch (Exception error)
            {
                using (SdkDebug.WriteLineAndIndent("> 读取报文内容:失败"))
                {
                    SdkDebug.WriteLine(error);
                }
                throw new Exception("读取报文失败", error);
            }
            #endregion

            #region 2. 读取报文内容成 JSON 并保存在 body 变量中
            var body = new
            {
                data       = "{encode data}",
                dataEncode = "json",
                signature  = string.Empty
            };
            try
            {
                body = JsonConvert.DeserializeAnonymousType(requestContent, body);
                SdkDebug.WriteLine("> 解析报文内容:成功");
            }
            catch (JsonException ex)
            {
                using (SdkDebug.WriteLineAndIndent("> 解析报文内容:失败"))
                {
                    SdkDebug.WriteLine(ex);
                }
                Response.WriteJson(new
                {
                    code    = 9001,
                    message = "Cant not parse the request body: invalid json"
                });
                return;
            }
            #endregion

            #region 3. 检查报文签名
            string data              = body.data;
            string signature         = body.signature;
            string computedSignature = (data + TunnelClient.Key).HashSha1();
            if (computedSignature != signature)
            {
                using (SdkDebug.WriteLineAndIndent("> 检查签名:失败"))
                {
                    SdkDebug.WriteLine($"报文签名:{signature},计算结果:{computedSignature},tcKey: {TunnelClient.Key}");
                }
                Response.WriteJson(new
                {
                    code    = 9003,
                    message = "Bad Request - 签名错误"
                });
                return;
            }
            using (SdkDebug.WriteLineAndIndent("> 检查签名:成功"))
            {
                SdkDebug.WriteLine(signature);
            }
            #endregion

            #region 4. 解析报文中携带的包数据
            var packet = new
            {
                tunnelId = string.Empty,
                type     = string.Empty,
                content  = string.Empty
            };
            try
            {
                packet = JsonConvert.DeserializeAnonymousType(data, packet);
            }
            catch (JsonException ex)
            {
                using (SdkDebug.WriteLineAndIndent("> 解析包数据:失败"))
                {
                    SdkDebug.WriteLine(ex);
                }
                Response.WriteJson(new
                {
                    code    = 9004,
                    message = "Bad Request - 无法解析的数据包"
                });
                return;
            }
            using (SdkDebug.WriteLineAndIndent("> 解析包数据:成功"))
            {
                SdkDebug.WriteLine($"tunnelId = {packet.tunnelId}");
                SdkDebug.WriteLine($"type = {packet.type}");
                SdkDebug.WriteLine($"content = {packet.content}");
            }
            Response.WriteJson(new
            {
                code    = 0,
                message = "OK"
            });
            #endregion

            #region 5. 交给客户处理实例处理报文
            var tunnel = Tunnel.GetById(packet.tunnelId);
            try
            {
                using (SdkDebug.WriteLineAndIndent("> 处理数据包:开始"))
                {
                    switch (packet.type)
                    {
                    case "connect":
                        handler.OnTunnelConnect(tunnel);
                        break;

                    case "message":
                        handler.OnTunnelMessage(tunnel, new TunnelMessage(packet.content));
                        break;

                    case "close":
                        handler.OnTunnelClose(tunnel);
                        break;
                    }
                }
                SdkDebug.WriteLine("> 处理数据包:完成");
            }
            catch (Exception ex)
            {
                using (SdkDebug.WriteLineAndIndent("> 处理数据包:发生异常"))
                {
                    SdkDebug.WriteLine(ex);
                }
            }
            #endregion
        }
Exemplo n.º 8
0
        private dynamic DoRequest(string path, object data, bool emitSkey)
        {
            string url = TunnelServerUrl + path;
            string responseContent;

            // 请求信道服务器,获取返回报文
            try
            {
                string   requestContent = BuildRequestContent(data, emitSkey);
                DateTime start          = DateTime.Now;

                responseContent = Http.Post(url, requestContent);
                DateTime end  = DateTime.Now;
                TimeSpan cost = end - start;

                using (SdkDebug.WriteLineAndIndent($"POST {url} (Time: {start.ToString("HH:mm:ss")}, Cost: {cost.TotalMilliseconds}ms)"))
                {
                    using (SdkDebug.WriteLineAndIndent("Requset:"))
                    {
                        SdkDebug.WriteLine(requestContent);
                    }
                    using (SdkDebug.WriteLineAndIndent("Response:"))
                    {
                        SdkDebug.WriteLine(responseContent);
                    }
                }
            }
            catch (Exception error)
            {
                using (SdkDebug.WriteLineAndIndent($"POST {url} (ERROR)"))
                {
                    SdkDebug.WriteLine(error);
                }
                throw new HttpRequestException("请求信道 API 失败,网络异常或鉴权服务器错误", error);
            }

            // 解析返回报文
            try
            {
                var bodyShape = new
                {
                    code    = 0,
                    message = "OK",
                    data    = "{}"
                };
                var body = JsonConvert.DeserializeAnonymousType(responseContent, bodyShape, new JsonSerializerSettings()
                {
                    NullValueHandling = NullValueHandling.Include
                });

                if (body.code != 0)
                {
                    throw new Exception($"信道服务调用失败:#{body.code} - ${body.message}");
                }
                return(body.data == null ? null : JsonConvert.DeserializeObject(body.data));
            }
            catch (JsonException e)
            {
                throw new JsonException("信道服务器响应格式错误,无法解析 JSON 字符串", e);
            }
            catch (Exception e)
            {
                throw e;
            }
        }