return_url 和 notify_url 的区分

本文详细介绍了支付宝通知系统的两大类型:服务器通知与页面跳转通知,解释了它们的区别、实现方式及注意事项,帮助开发者正确配置支付宝通知。
现支付宝的通知有两类。
A服务器通知,对应的参数为notify_url,支付宝通知使用POST方式
B页面跳转通知,对应的参数为return_url,支付宝通知使用GET方式 (通知地址不需要像以前一样去账户内设置,而是由客户在支付的时候通过参数传递给我地址。例如 notify_url=http://www.xxx.com/notify_alipay.asp 注意:www.XXX.com是您网站的域名,也可以用ip地址代替。对于服务器通知,ip地址一定是公网的,私有地址(例如10.2.1.1或者192.168.1.1)支付宝无法通知到客户端
def wait_for_vehicle_upgrade_new(task_name, taskid,timeout_seconds=120, check_interval=60):# 300改为60,3600改为120调试 """等待车辆升级完成""" logger.info(f"等待车辆升级完成,任务: {task_name},超时时间: {timeout_seconds/60}分钟") wait_start_time = time.time() success_status = "车辆安装成功" failure_status = ["检测失败", "匹配失败", "车辆下载失败", "车辆安装失败", "车辆下载暂停"] while True: result = get_vehicle_upgrade_status(task_name) print(result) OTA_taskid = taskid item_list = result.get('list', []) # 计算返回字典里list中的字典个数 if not isinstance(item_list, list): print("字段不存在或不是列表类型") return False dict_count = len(item_list) # 只有一个升级车辆时 if dict_count == 1: item1 = result['list'][0] # 取出 list 的第一个字典 upgrade_status1 = item1['vehicleUpgradeStatus'] start_time1 = item1["statusUpdateTime"] carID1 = item1['carId'] if upgrade_status1 == success_status: logger.info(f"测试通过:车辆升级状态已变为'{success_status}'") return True elif upgrade_status1 in failure_status: reason1 = item1["reason"] vehicleFailReason1 = item1["vehicleFailReason"] logger.info(f"车辆ID: {carID1} 开始时间: {start_time1} 失败原因: {reason1}") logger.error(f"测试失败:车辆升级状态已变为'{upgrade_status1}'") # 发送测试失败通知 info = ["OTA测试失败", f"任务名称: {task_name}", f"任务编号: {OTA_taskid}", f"车辆名称: {carID1}", f"车辆升级状态: {upgrade_status1}", f"任务开始时间: {start_time1}", f"任务失败原因: {reason1}", f"错误码: {vehicleFailReason1}"] send_test_result_information(info, _notifier_info, _dc_notify_url) return False # 当升级车辆有多个时 elif dict_count == 2: item1 = result['list'][0] # 取出 list 的第1个字典 item2 = result['list'][1] # 取出 list 的第2个字典 upgrade_status1 = item1['vehicleUpgradeStatus'] upgrade_status2 = item2['vehicleUpgradeStatus'] start_time1 = item1["statusUpdateTime"] start_time2 = item2["statusUpdateTime"] carID1 = item1['carId'] carID2 = item2['carId'] # 都成功 if upgrade_status1 == success_status and upgrade_status2 == success_status: logger.info(f"测试通过:车辆升级状态都已变为'{success_status}'") return True # 都失败 elif upgrade_status1 in failure_status and upgrade_status2 in failure_status: reason1 = item1["reason"] reason2 = item2["reason"] vehicleFailReason1 = item1["vehicleFailReason"] vehicleFailReason2 = item2["vehicleFailReason"] logger.info(f"车辆ID: {carID1} 开始时间: {start_time1} 失败原因: {reason1}") logger.info(f"车辆ID: {carID2} 开始时间: {start_time2} 失败原因: {reason2}") logger.error(f"测试失败:车辆升级状态已变为'{upgrade_status1}'") # 发送测试失败通知 info1 = ["OTA测试失败", f"任务名称: {task_name}", f"任务编号: {OTA_taskid}", f"车辆名称: {carID1}", f"车辆升级状态: {upgrade_status1}", f"任务开始时间: {start_time1}", f"任务失败原因: {reason1}", f"错误码: {vehicleFailReason1}"] info2 = ["OTA测试失败", f"任务名称: {task_name}", f"任务编号: {OTA_taskid}", f"车辆名称: {carID2}", f"车辆升级状态: {upgrade_status2}", f"任务开始时间: {start_time2}", f"任务失败原因: {reason2}", f"错误码: {vehicleFailReason2}"] # send_test_result_information(info1, _notifier_info, _dc_notify_url) # 调试先注释 # send_test_result_information(info2, _notifier_info, _dc_notify_url) return False # 第1个失败第2个成功 elif upgrade_status1 in failure_status and upgrade_status2 == success_status: reason1 = item1["reason"] reason2 = item2["reason"] vehicleFailReason1 = item1["vehicleFailReason"] vehicleFailReason2 = item2["vehicleFailReason"] logger.info(f"车辆ID: {carID1} 开始时间: {start_time1} 失败原因: {reason1}") logger.error(f"测试失败:车辆升级状态已变为'{upgrade_status1}'") # 发送测试失败通知 info1 = ["OTA测试失败", f"任务名称: {task_name}", f"任务编号: {OTA_taskid}", f"车辆名称: {carID1}", f"车辆升级状态: {upgrade_status1}", f"任务开始时间: {start_time1}", f"任务失败原因: {reason1}", f"错误码: {vehicleFailReason1}"] info2 = ["OTA测试成功", f"任务名称: {task_name}", f"任务编号: {OTA_taskid}", f"车辆名称: {carID2}", f"车辆升级状态: {upgrade_status2}", f"任务开始时间: {start_time2}", f"任务失败原因: {reason2}", f"错误码: {vehicleFailReason2}"] # send_test_result_information(info1, _notifier_info, _dc_notify_url) # send_test_result_information(info2, _notifier_info, _dc_notify_url) return True # 第1个成功第2个失败 elif upgrade_status2 in failure_status and upgrade_status1 == success_status: reason1 = item1["reason"] reason2 = item2["reason"] vehicleFailReason1 = item1["vehicleFailReason"] vehicleFailReason2 = item2["vehicleFailReason"] logger.info(f"车辆ID: {carID1} 开始时间: {start_time1} 失败原因: {reason1}") logger.info(f"车辆ID: {carID2} 开始时间: {start_time2} 失败原因: {reason2}") logger.error(f"测试失败:车辆升级状态已变为'{upgrade_status1}'") # 发送测试失败通知 info1 = ["OTA测试成功", f"任务名称: {task_name}", f"任务编号: {OTA_taskid}", f"车辆名称: {carID1}", f"车辆升级状态: {upgrade_status1}", f"任务开始时间: {start_time1}", f"任务失败原因: {reason1}", f"错误码: {vehicleFailReason1}"] info2 = ["OTA测试失败", f"任务名称: {task_name}", f"任务编号: {OTA_taskid}", f"车辆名称: {carID2}", f"车辆升级状态: {upgrade_status2}", f"任务开始时间: {start_time2}", f"任务失败原因: {reason2}", f"错误码: {vehicleFailReason2}"] # send_test_result_information(info1, _notifier_info, _dc_notify_url) # send_test_result_information(info2, _notifier_info, _dc_notify_url) return True elif dict_count >= 3: pass # 循环 elapsed_time = time.time() - wait_start_time if elapsed_time > timeout_seconds: # download_ota_logs() logger.error(f"测试失败:车辆升级在 {timeout_seconds/60} 分钟内未能完成,当前状态: {upgrade_status1} {upgrade_status2}") # 发送测试超时通知 info = ["OTA测试失败, 超时未完成", f"任务名称: {task_name}", f"车辆升级状态: {upgrade_status1} {upgrade_status2}, 超时时间: {timeout_seconds/60}分钟"] send_test_result_information(info, _notifier_info, _dc_notify_url) # time.sleep(3600) # 等待1小时后重新检测任务状态 assert False, f"车辆升级失败,超时 {timeout_seconds/60} 分钟,当前状态: {upgrade_status1} {upgrade_status2}" next_check_time = min(check_interval, timeout_seconds - elapsed_time) if next_check_time > 0: logger.info(f"当前车辆升级状态为 {upgrade_status1} {upgrade_status2},将在 {int(next_check_time/60)} 分钟后重新检查...") time.sleep(next_check_time)优化一下这个方法,代码尽量精简一点然后在添加一个逻辑判断当elif dict_count >= 3:时将list返回的字典内容提取出来并且依次赋值然后判断比如有三个字典时取出的状态值都安装成功upgrade_status1 == success_status and upgrade_status2 == success_status and upgrade_status3 == success_status:,如果全部都不是安装成功则发送相应的失败信息,第三种情况就是有一个或者多个安装成功就将成功信息返回然后等所有的结果都出来之后再返回True或者false。
最新发布
11-21
using CY_PUBLIC_LIBRARY; using CY_PUBLIC_LIBRARY.AppConfigurtaion; using CY_PUBLIC_LIBRARY.BaseModels; using CY_PUBLIC_LIBRARY.Extension; using CY_PUBLIC_LIBRARY.Middleware; using CY_PUBLIC_LIBRARY.WebRequestHelp; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Drawing.Imaging; using DoMain; using Org.BouncyCastle.Asn1.X509; using System.Diagnostics; using Newtonsoft.Json; using Model.cxbd; using Model.sys_model; using Model.hospital_model; namespace APP_API.Controllers.wechatControllers { /// <summary> /// 微信支付 /// </summary> [Route("api/[controller]")] [ApiController] [Authorize] [ApiExplorerSettings(GroupName = "base_data")] public class wechat_payController : BaseApiController { public wechat_payController(IFreeSql fsql) : base(fsql) { } /// <summary> /// 微信支付下单 /// </summary> /// <param name="payItem"></param> /// <returns></returns> [HttpPost("pay")] [Authorize] public ActionResult<retObject<payRetModel>> Pay([FromBody] payOrderModel payItem) { var app_user = _fsql.Select<app_user>(_jwt.user_info.user_id).ToOne(); var order = _fsql.Select<sys_order>(payItem.order_id).ToOne(); if (order == null) { throw new ServiceException("订单不存在"); } if (order.status != (int)wechat_refund_status.待付款) { throw new ServiceException("订单状态有误"); } order.guid = Guid.NewGuid().ToString("N"); //order.status = (int)wechat_refund_status.待接单; _fsql.Update<sys_order>(order.order_id).Set(x=>x.guid,order.guid).ExecuteAffrows(); var domain = new orderDomain(_fsql); var payfee = Convert.ToInt32(payItem.pay * 100); var order_pay = new order_pay() { amount = payItem.pay, rl = false, pay_type_id = 2, is_app = true, order_id = payItem.order_id }; var pay_id = _fsql.Insert(order_pay).ExecuteIdentity(); var name = app_user.name; if (name.Length > 40) { name = name.Substring(0, 40) + "..."; } name = name.Replace("<", "").Replace(">", ""); var nonStr = CommandHelp.GetGuid(); var PayNotifyUrl = AppConfigurtaionServices.Configuration["Wechat:PayNotifyUrl"]; var appid = AppConfigurtaionServices.Configuration["Wechat:AppId"]; var mch_id = AppConfigurtaionServices.Configuration["Wechat:MchId"]; var ipStr = AppConfigurtaionServices.Configuration["Wechat:Ip"]; var key = AppConfigurtaionServices.Configuration["Wechat:Key"]; var postData = "appid=" + appid + "&attach=" + pay_id + "&body=" + name + "&mch_id=" + mch_id + "&nonce_str=" + nonStr + "&notify_url=" + PayNotifyUrl + "&openid=" + app_user.open_id + "&out_trade_no=" + pay_id + "&spbill_create_ip=" + ipStr + "&total_fee=" + payfee + "&trade_type=JSAPI"; postData += "&key=" + key; CyLogHelp.WriteLog(postData, "微信下单"); var md5 = MD5.Create(); var bs2 = md5.ComputeHash(Encoding.UTF8.GetBytes(postData)); var sb2 = new StringBuilder(); foreach (byte bb in bs2) { sb2.Append(bb.ToString("x2")); } postData = sb2.ToString().ToUpper(); var orderXml = "<xml>" + "<appid>" + appid + "</appid>" + "<attach>" + pay_id + "</attach>" + "<body>" + name + "</body>" + "<mch_id>" + mch_id + "</mch_id>" + "<nonce_str>" + nonStr + "</nonce_str>" + "<notify_url>" + PayNotifyUrl + "</notify_url>" + "<openid>" + app_user.open_id + "</openid>" + "<out_trade_no>" + pay_id + "</out_trade_no>" + "<spbill_create_ip>" + ipStr + "</spbill_create_ip>" + "<total_fee>" + payfee + "</total_fee>" + "<trade_type>JSAPI</trade_type>" + "<sign>" + postData + "</sign>" + "</xml>"; var retStr = WebRequsetHelp.PostRequestData("https://api.mch.weixin.qq.com/pay/unifiedorder", orderXml, WebRequsetContentType.Form表单); if (retStr != "" && retStr.IndexOf("prepay_id") > 0) { XmlDocument doc = new XmlDocument(); doc.LoadXml(retStr); XmlNodeList list = doc.GetElementsByTagName("xml"); XmlNode xn = list[0]; var prepay_id = xn.SelectSingleNode("//prepay_id").InnerText; if (!string.IsNullOrEmpty(prepay_id)) { var timeSpanStr = DateTime.Now.ConvertShortDateTimeInt().ToString(); var postStr = "appId=" + appid + "&nonceStr=" + nonStr + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeSpanStr; postStr += "&key=" + key; var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(postStr)); var sb = new StringBuilder(); foreach (byte bb in bs) { sb.Append(bb.ToString("x2")); } var signStr = sb.ToString().ToUpper(); var ret = new payRetModel() { appId = appid, nonceStr = nonStr, package = "prepay_id=" + prepay_id, paySign = signStr, signType = "MD5", timeStamp = timeSpanStr }; return Ok(ret.GetRetObject()); } else { CyLogHelp.WriteLog(retStr + "\r\n" + orderXml, "微信下单失败"); throw new ServiceException("微信下单失败", 201); } } else { CyLogHelp.WriteLog(retStr + "\r\n" + orderXml, "微信下单失败"); throw new ServiceException("微信下单失败", 201); } } /// <summary> /// 微信支付回调 /// </summary> /// <returns></returns> [HttpPost("gspayback")] public ActionResult<string> PayNotify() { var successStr = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; var failStr = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数错误]]></return_msg></xml>"; var postStr = ""; Request.Body.Seek(0,SeekOrigin.Begin); using (var reader = new StreamReader(Request.Body, Encoding.UTF8)) { postStr = reader.ReadToEndAsync().Result; } _fsql.Insert(new wechat_request() { content = postStr }).ExecuteAffrows(); if (!string.IsNullOrEmpty(postStr)) { XmlDocument doc = new XmlDocument(); doc.XmlResolver = null; doc.LoadXml(postStr); XmlNodeList list = doc.GetElementsByTagName("xml"); XmlNode xn = list[0]; string ret = xn.SelectSingleNode("//result_code").InnerText; string attach = xn.SelectSingleNode("//attach").InnerText; string mch_id = xn.SelectSingleNode("//mch_id").InnerText; string out_trade_no = xn.SelectSingleNode("//out_trade_no").InnerText; string transaction_id = xn.SelectSingleNode("//transaction_id").InnerText; string totalFee = xn.SelectSingleNode("//total_fee").InnerText; string openid = xn.SelectSingleNode("//openid").InnerText; decimal price = 0; if (decimal.TryParse(totalFee, out price)) { price = price / 100; } if (_fsql.Select<wechat_pay_log>().Where(x => x.transaction_id == transaction_id && x.result_code == "SUCCESS").Count() > 0) return Ok(successStr); //再去判断是否收到订单 var nonStr = CommandHelp.GetGuid(); var appid = AppConfigurtaionServices.Configuration["Wechat:AppId"]; var mymch_id = AppConfigurtaionServices.Configuration["Wechat:MchId"]; var key = AppConfigurtaionServices.Configuration["Wechat:Key"]; var postData = "appid=" + appid + "&mch_id=" + mymch_id + "&nonce_str=" + nonStr + "&out_trade_no=" + out_trade_no; postData += "&key=" + key; var md5 = MD5.Create(); var bs2 = md5.ComputeHash(Encoding.UTF8.GetBytes(postData)); var sb2 = new StringBuilder(); foreach (byte bb in bs2) { sb2.Append(bb.ToString("x2")); } postData = sb2.ToString().ToUpper(); var orderXml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>" + mymch_id + "</mch_id>" + "<nonce_str>" + nonStr + "</nonce_str>" + "<out_trade_no>" + out_trade_no + "</out_trade_no>" + "<sign>" + postData + "</sign>" + "</xml>"; var retStr = WebRequsetHelp.PostRequestData("https://api.mch.weixin.qq.com/pay/orderquery", orderXml, WebRequsetContentType.Form表单); if (!retStr.Contains("支付成功")) { CyLogHelp.WriteLog(retStr + "\r\n" + orderXml, "微信支付回调请求失败"); throw new ServiceException("订单未支付", 201); }; _fsql.Transaction(() => { var order = _fsql.Select<sys_order>().Where(e => e.guid == out_trade_no).ToOne(); //添加支付记录 var _paylog = new wechat_pay_log() { openid = openid, order_id = order.order_id, out_trade_no = out_trade_no, postStr = postStr, result_code = ret, total_fee = Convert.ToDecimal(totalFee), transaction_id = transaction_id, }; if (_fsql.Insert(_paylog).ExecuteAffrows() <= 0) throw new ServiceException("添加支付记录失败", 201); if (_paylog.result_code == "SUCCESS") { //支付逻辑 var domain = new orderDomain(_fsql); domain.order_pay(order.order_id); } }); return Ok(successStr); } return Ok(failStr); } /// <summary> /// 微信退款回调 /// </summary> /// <returns></returns> [HttpPost("refundnotify")] public ActionResult<string> RefundNotify() { string WechatDecrypt(string decryptStr, string key) { byte[] keyArray = Encoding.UTF8.GetBytes(key); byte[] toEncryptArray = Convert.FromBase64String(decryptStr); RijndaelManaged rDel = new RijndaelManaged(); rDel.Key = keyArray; rDel.Mode = CipherMode.ECB; rDel.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = rDel.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); return Encoding.UTF8.GetString(resultArray); } var successStr = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; var failStr = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数错误]]></return_msg></xml>"; var postStr = ""; Request.Body.Seek(0, SeekOrigin.Begin); using (var reader = new StreamReader(Request.Body, Encoding.UTF8)) { postStr = reader.ReadToEndAsync().Result; } _fsql.Insert(new wechat_request_refund() { content = postStr }).ExecuteAffrows(); if (string.IsNullOrEmpty(postStr)) return Ok(failStr); try { XmlDocument doc = new XmlDocument(); doc.XmlResolver = null; doc.LoadXml(postStr); XmlNodeList list = doc.GetElementsByTagName("xml"); XmlNode xn = list[0]; var retcode = xn.SelectSingleNode("//return_code").InnerText; var req_info = xn.SelectSingleNode("//req_info").InnerText; if (!string.IsNullOrEmpty(req_info)) { //解密 var key = AppConfigurtaionServices.Configuration["Wechat:Key"]; var md5 = MD5.Create(); var bs2 = md5.ComputeHash(Encoding.UTF8.GetBytes(key)); var sb2 = new StringBuilder(); foreach (byte bb in bs2) { sb2.Append(bb.ToString("x2")); } var temp_key = sb2.ToString().ToLower(); var refund_info = WechatDecrypt(req_info, temp_key); if (!string.IsNullOrEmpty(refund_info)) { doc.LoadXml(refund_info); if (doc != null) { list = doc.GetElementsByTagName("root"); xn = list[0]; string transaction_id = xn.SelectSingleNode("//transaction_id").InnerText; string out_trade_no = xn.SelectSingleNode("//out_trade_no").InnerText; string refund_id = xn.SelectSingleNode("//refund_id").InnerText; string out_refund_no = xn.SelectSingleNode("//out_refund_no").InnerText; string refund_fee = xn.SelectSingleNode("//refund_fee").InnerText; string refund_status = xn.SelectSingleNode("//refund_status").InnerText; string totalFee = xn.SelectSingleNode("//total_fee").InnerText; decimal price = 0; if (decimal.TryParse(refund_fee, out price)) { price = price / 100; } if (_fsql.Select<wechat_refund_log>().Where(x => x.refund_id == refund_id && x.refund_status == "SUCCESS").Count() > 0) return Ok(successStr); _fsql.Transaction(() => { var _refundlog = new wechat_refund_log() { out_refund_no = out_refund_no, out_trade_no = out_trade_no, postStr = postStr, refund_fee = Convert.ToDecimal(price), refund_status = refund_status, refund_id = refund_id, transaction_id = transaction_id }; var _r = _fsql.Insert(_refundlog).ExecuteAffrows(); if (_r <= 0) throw new ServiceException("添加退款日志失败", 201); if (_refundlog.refund_status == "SUCCESS") { var _order = _fsql.Select<sys_order>().Where(x => x.guid == _refundlog.out_trade_no).ToOne(); if (_order == null) { throw new ServiceException("订单不存在", 201); } //找到退款记录 var refund_id = Convert.ToInt32(out_refund_no); _fsql.Update<sys_order>(refund_id).Set(e => e.status, (int)DoMain.Enum.wechat_refund_status.已取消).ExecuteAffrows(); } }); return Ok(successStr); } } } } catch { } return Ok(failStr); } } public class payRetModel { public string appId { get; set; } public string timeStamp { get; set; } public string nonceStr { get; set; } public string package { get; set; } public string signType { get; set; } public string paySign { get; set; } } public class payOrderModel { /// <summary> /// 订单ID/购物车订单id /// </summary> [Required] public int order_id { get; set; } = 0; /// <summary> /// 支付金额 /// </summary> [Required] public decimal pay { get; set; } [Required] public bool from_cart { get; set; } } } 我这个为啥状态不修改而且支付也报Object reference not set to an instance of an object.(在小程序上支付)怎么解决
08-17
这两份代码呈现的,/****************************************************************************** * Copyright (c) 2020-2020 TP-Link Technologies CO.,LTD. * * Filename: diagnose_main.h * Version: 1.0 * Description: 自动诊断头文件 * Author: 赖滨绍<laibinshao@tp-link.com.cn> * Date: 2020-12-10 ******************************************************************************/ #ifndef _H_DIAGNOSE_MAIN #define _H_DIAGNSOE_MAIN #include "diagnose_commom.h" typedef enum { DIAGNOSE_WIRELESS=0, /*无线诊断*/ DIAGNOSE_GATEWAY, /*网关诊断*/ DIAGNOSE_ADDR1, /*外网1诊断*/ DIAGNOSE_ADDR2, /*外网2诊断*/ DIAGNOSE_BASE_CLOUD, /*基础云诊断*/ #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT DIAGNOSE_LTE_DNS1, /* LTE检测的DNS地址1 */ DIAGNOSE_LTE_DNS2, /* LTE检测的DNS地址2 */ DIAGNOSE_USER_ADDR1, /* 用户自定义地址1 */ DIAGNOSE_USER_ADDR2, /* 用户自定义地址2 */ #endif DIAGNOSE_STORAGE, /*存储诊断*/ DIAGNOSE_FIRMWARE, /*固件诊断*/ DIAGNOSE_SAFETY, /*安全诊断(视频加密)*/ DIAGNOSE_MAX } DIAGNOSE_PARA; /*标记诊断项对应的位*/ typedef enum { NET_GATEWAY = 0, /*网关*/ NET_INTERNET1, /*外网1*/ NET_INTERNET2, /*外网2*/ NET_BASE_CLOUD, /*基础云*/ /* 由于外销基础云域名不让ping, 暂改成官网域名 “www.tp-link.com” */ #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT NET_4G_DET_DNS1, /* 4G网络检测的DNS地址1 */ NET_4G_DET_DNS2, /* 4G网络检测的DNS地址2 */ NET_USER_DEFINED1, /* 用户自定义地址1 */ NET_USER_DEFINED2, /* 用户自定义地址2 */ #endif NET_MAX }NETWORK_PARA; /*网络诊断参数,表示在g_ping_array数组中的位置*/ typedef enum { CSTG_OFFLINE = 0, /*云掉线*/ CSTG_ONLINE /*云在线*/ } CSTG_STAT; /*云状态*/ #endif /****************************************************************************** * Copyright (c) 2020-2020 TP-Link Technologies CO.,LTD. * * Filename: diagnose_main.c * Version: 1.0 * Description: 自动诊断部分 * Author: 赖滨绍<laibinshao@tp-link.com.cn> * Date: 2020-12-10 ******************************************************************************/ #include <sys/types.h> #include <arpa/inet.h> #include <errno.h> #include "diagnose_main.h" #include "msg_utils.h" #include "telnet.h" #define ITEMS_TIMEOUT_VAL 15 /*网络诊断超时时间*/ #define MAX_CLIENTS_NUM 10 /*接受客户端请求诊断数量*/ #define CLIENT_GET_TIMEOUT 30 /*客户端get请求最大次数*/ #define CLIENT_RECLAIM_INTERVAL 50 /*客户端诊断实例资源回收超时*/ DIAG_ADDR g_default_address; /*网络诊断地址*/ LOCAL S32 g_diagnose_timerid = ERROR; /*网络诊断超时定时器*/ LOCAL S8 g_is_auto_diagnose = 0; /*是否收到自诊断消息*/ PHY_STATUS g_phy_stat; /*物理链路状态*/ TASK_STRUCT g_client_array[MAX_CLIENTS_NUM]; /*记录客户端信息*/ NETWORK_STRUCT g_network_array[ADDR_COUNTS]; /*网络地址诊断信息*/ CONNECT_INFO g_connect_info; STORAGE_INFO g_storage_info; FIRMWARE_STRUCT g_firmware_info; VIDEO_ENCRYPTION g_video_encryption; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT #define NET_DETECTION_DEFAULT_DNS1 "8.8.8.8" #define NET_DETECTION_DEFAULT_DNS2 "www.google.com" LOCAL S8 g_is_lte_diagnose = 0; /* 是否是lte模块发起的自诊断信息 */ LOCAL S8 g_is_other_model_diagnose = 0; /* 其他模块发起的自诊断信息 */ #endif LOCAL S8 g_task_running = 0; /*当前是否进行了除网络诊断外的其他诊断*/ /*********************************************************************************************** *函数: *描述:加载数据模型中的诊断地址 *参数: *返回值: ***********************************************************************************************/ S32 load_network_address() { int index = 0; DIAG_ADDR target_addr; memset(&target_addr, 0, sizeof(DIAG_ADDR)); if (0 == ds_read(DIAGNOSE_ADDR_PATH, (void*)(&target_addr), sizeof(DIAG_ADDR))) { DIAGNOSE_WARNING("diagnose read address error."); return ERROR; } /*第0位保留为网关地址*/ for(index = 1; index < ADDR_COUNTS; index++) { strncpy(g_default_address.diag_addr[index], target_addr.diag_addr[index], ADDR_LEN); } DIAGNOSE_DEBUG("internet1:%s internet2:%s basecloud:%s", g_default_address.diag_addr[1], g_default_address.diag_addr[2], g_default_address.diag_addr[3]); return OK; } /*********************************************************************************************** *函数: *描述:关注数据据块,加载网关地址 *参数: *返回值: ***********************************************************************************************/ void load_gateway_address() { LINK_STATUS link_status = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; LTE_DHCP_IP lte_dhcp_ip = {0}; ds_read(LTE_INFO_DATA_PATH, (U8*)&lte_config, sizeof(LTE_CONFIG_INFO_DATA)); if(lte_config.internet_wired_enable == 0 || (lte_config.internet_wired_enable == 2 && lte_config.auto_switch_wired == 0)) { ds_read(LTE_DHCP_IP_PATH, (U8*)&lte_dhcp_ip, sizeof(LTE_DHCP_IP)); ip_to_str(lte_dhcp_ip.gateway, g_default_address.diag_addr[0]); }else #endif { ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS)); ip_to_str(link_status.gateway, g_default_address.diag_addr[0]); } DIAGNOSE_DEBUG("gateway:%s, internet1:%s,internet2:%s,cloud:%s",g_default_address.diag_addr[0], g_default_address.diag_addr[1],g_default_address.diag_addr[2],g_default_address.diag_addr[3]); } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT /*********************************************************************************************** *函数: *描述:关注lte模块net_det数据块,加载用户自定义地址 *参数: *返回值: ***********************************************************************************************/ void load_user_defined_address() { LTE_CONFIG_NET_DETECTION net_det = {0}; if(0 == ds_read(LTE_NET_DET_PATH, (U8*)&net_det, sizeof(LTE_CONFIG_NET_DETECTION))) { DIAGNOSE_ERROR("read path: %s\n failed.", LTE_NET_DET_PATH); return; } DIAGNOSE_ERROR("[LTE] add default dns address:%s", NET_DETECTION_DEFAULT_DNS1); strncpy(g_default_address.diag_addr[NET_4G_DET_DNS1], NET_DETECTION_DEFAULT_DNS1, ADDR_LEN); DIAGNOSE_ERROR("[LTE] add default dns address:%s", NET_DETECTION_DEFAULT_DNS2); strncpy(g_default_address.diag_addr[NET_4G_DET_DNS2], NET_DETECTION_DEFAULT_DNS2, ADDR_LEN); if(strlen(net_det.hostname_1) != 0) { DIAGNOSE_ERROR("add user defined address:%s.", net_det.hostname_1); strncpy(g_default_address.diag_addr[NET_USER_DEFINED1], net_det.hostname_1, ADDR_LEN); }else { memset(g_default_address.diag_addr[NET_USER_DEFINED1], 0, ADDR_LEN); } if(strlen(net_det.hostname_2) != 0) { DIAGNOSE_ERROR("add user defined address:%s.", net_det.hostname_2); strncpy(g_default_address.diag_addr[NET_USER_DEFINED2], net_det.hostname_2, ADDR_LEN); }else { memset(g_default_address.diag_addr[NET_USER_DEFINED2], 0, ADDR_LEN); } DIAGNOSE_ERROR("user defined addrees1:%s, user define address2:%s.", g_default_address.diag_addr[NET_USER_DEFINED1], g_default_address.diag_addr[NET_USER_DEFINED2]); } #endif /*********************************************************************************************** *函数:ip_to_str *描述:将网络字节序IP转成字符形式 *参数: *返回值: ***********************************************************************************************/ S32 ip_to_str(U32 ip_addr, char* str_ip) { struct in_addr dst; if (NULL == str_ip) { return ERROR; } memset(str_ip, 0, IP_LEN); dst.s_addr = ip_addr; if (NULL == inet_ntop(AF_INET, (void*)&dst, str_ip, IP_LEN)) { return ERROR; } return OK; } void diagnose_stop(void) { int index =0; g_task_running = 0; if (g_is_auto_diagnose) { #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(g_is_lte_diagnose) { lte_diagnose_reply_result(); g_is_lte_diagnose = 0; }else #endif { diagnose_reply_result(); /*诊断完成后发送诊断消息*/ } g_is_auto_diagnose = 0; } DIAGNOSE_DEBUG("diagnose stop, save diagnose result to network config\n"); diagnose_result_save_config(); if (ERROR != g_diagnose_timerid) { inet_del_timer(g_diagnose_timerid); g_diagnose_timerid = ERROR; } for (index = 0; index < ADDR_COUNTS; index++) { if (TESTED != g_network_array[index].status) { g_network_array[index].status = TESTED; g_network_array[index].res = DIAGNOSE_FAILED; } if (g_network_array[index].do_telnet) { if (g_network_array[index].tel_state != TESTED) { g_network_array[index].tel_res = DIAGNOSE_FAILED; } telnet_stop(&g_network_array[index]); } } } /*********************************************************************************************** *函数:check_signal_quality *描述:获取无线信号强度 *参数: *返回值: ***********************************************************************************************/ S32 check_signal_quality(CONNECT_INFO* ptr_wireless) { DS_HANDLE_CONTEXT ds_context; JSON_OBJPTR data_obj = NULL; const char* ptr_value = NULL; int error_code = OK; PHY_STATUS phy_status = {0}; if (NULL == ptr_wireless) { return ERROR; } ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS)); if (1 == phy_status.ether || 0 == phy_status.wlan) { strncpy(ptr_wireless->link_type, "ethernet", LINK_TYPE_LEN); return OK; } /*构造jason请求sd信息*/ memset(&ds_context, 0, sizeof(DS_HANDLE_CONTEXT)); if (NULL == (ds_context.req_obj = jso_new_obj())) { return ERROR; } if (NULL == (data_obj = jso_new_obj())) { error_code = ERROR; goto out; } jso_obj_add(ds_context.req_obj, "network", data_obj); jso_add_string(data_obj, "get_connection_type", ""); jso_add_string(ds_context.req_obj, "method", "do"); ds_context.group_mask = ROOT_MASK; ds_context.method = METHOD_DO; ds_handle(&ds_context); if (NULL == ds_context.res_obj) { error_code = ERROR; goto out; } if (NULL == (ptr_value = jso_obj_get_string_origin(ds_context.res_obj, "link_type"))) { error_code = ERROR; goto out; } strncpy(ptr_wireless->link_type, ptr_value, LINK_TYPE_LEN); if (0 == strcmp(ptr_value, "ethernet")) { /*有线连接*/ error_code = OK; goto out; } /*无线连接*/ if (NULL == (ptr_value = jso_obj_get_string_origin(ds_context.res_obj, "ssid"))) { error_code = ERROR; goto out; } strncpy(ptr_wireless->ssid, ptr_value, WIFI_SSID_MAX_LEN); jso_obj_get_int(ds_context.res_obj, "rssi", &(ptr_wireless->rssi)); error_code = OK; DIAGNOSE_INFO("ssid:%s rssi:%d", ptr_wireless->ssid, ptr_wireless->rssi); out: if (NULL != ds_context.req_obj) { jso_free_obj(ds_context.req_obj); ds_context.req_obj = NULL; } if (NULL != ds_context.res_obj) { jso_free_obj(ds_context.res_obj); ds_context.res_obj = NULL; } return error_code; } /*********************************************************************************************** *函数: *描述:网络诊断数组初始化 *参数: *返回值: ***********************************************************************************************/ void address_array_init() { /*数组第0位放网关地址*/ memset(&g_network_array[NET_GATEWAY], 0, sizeof(NETWORK_STRUCT)); strncpy(g_network_array[NET_GATEWAY].para_name, "gateway", PARA_NAME_LEN); g_network_array[NET_GATEWAY].params_code = DIAGNOSE_GATEWAY; g_network_array[NET_GATEWAY].test = 1; /*数组第1位放外网地址1*/ memset(&g_network_array[NET_INTERNET1], 0, sizeof(NETWORK_STRUCT)); strncpy(g_network_array[NET_INTERNET1].para_name, "internet1", PARA_NAME_LEN); g_network_array[NET_INTERNET1].params_code = DIAGNOSE_ADDR1; g_network_array[NET_INTERNET1].test = 1; /*数组第2位放外网地址2*/ memset(&g_network_array[NET_INTERNET2], 0, sizeof(NETWORK_STRUCT)); strncpy(g_network_array[NET_INTERNET2].para_name, "internet2", PARA_NAME_LEN); g_network_array[NET_INTERNET2].params_code = DIAGNOSE_ADDR2; g_network_array[NET_INTERNET2].test = 1; /*数组第3位放云服务器地址*/ memset(&g_network_array[NET_BASE_CLOUD], 0, sizeof(NETWORK_STRUCT)); strncpy(g_network_array[NET_BASE_CLOUD].para_name, "cloud", PARA_NAME_LEN); g_network_array[NET_BASE_CLOUD].params_code = DIAGNOSE_BASE_CLOUD; g_network_array[NET_BASE_CLOUD].test = 1; g_network_array[NET_BASE_CLOUD].do_telnet = 1; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT memset(&g_network_array[NET_4G_DET_DNS1], 0, sizeof(NETWORK_STRUCT)); memset(&g_network_array[NET_4G_DET_DNS2], 0, sizeof(NETWORK_STRUCT)); memset(&g_network_array[NET_USER_DEFINED1], 0, sizeof(NETWORK_STRUCT)); memset(&g_network_array[NET_USER_DEFINED2], 0, sizeof(NETWORK_STRUCT)); LTE_CONFIG_NET_DETECTION net_det = {0}; if(0 == ds_read(LTE_NET_DET_PATH, (U8*)&net_det, sizeof(LTE_CONFIG_NET_DETECTION))) { DIAGNOSE_ERROR("read path %s failed.", LTE_NET_DET_PATH); return; } if(net_det.ping_enable == 1 && g_is_lte_diagnose == 1 && g_is_other_model_diagnose == 0) { /* 如果是LTE模块发起的ping检测只检测dns1 dns2用户自定义地址 */ g_network_array[NET_INTERNET1].test = 0; g_network_array[NET_INTERNET2].test = 0; /* 如果是LTE模块发起的ping检测暂时不检测网关地址 */ g_network_array[NET_GATEWAY].test = 0; /* 如果是LTE模块发起的ping检测不对bata云进行telnet */ g_network_array[NET_BASE_CLOUD].do_telnet = 0; g_network_array[NET_BASE_CLOUD].test = 0; /* 数组第4位放LTE检测的DNS地址1 */ strncpy(g_network_array[NET_4G_DET_DNS1].para_name, "dns1", PARA_NAME_LEN); g_network_array[NET_4G_DET_DNS1].params_code = DIAGNOSE_LTE_DNS1; g_network_array[NET_4G_DET_DNS1].test = 1; /* 数组第5位放LTE检测的DNS地址2 */ strncpy(g_network_array[NET_4G_DET_DNS2].para_name, "dns2", PARA_NAME_LEN); g_network_array[NET_4G_DET_DNS2].params_code = DIAGNOSE_LTE_DNS2; g_network_array[NET_4G_DET_DNS2].test = 1; /* 数组第6位放用户自定义地址1(如果有配置的话) */ if(strlen(net_det.hostname_1) != 0) { strncpy(g_network_array[NET_USER_DEFINED1].para_name, "hostname_1", PARA_NAME_LEN); g_network_array[NET_USER_DEFINED1].params_code = DIAGNOSE_USER_ADDR1; g_network_array[NET_USER_DEFINED1].test = 1; } /* 数组第7位放用户自定义地址2(如果有配置的话) */ if(strlen(net_det.hostname_2) != 0) { strncpy(g_network_array[NET_USER_DEFINED2].para_name, "hostname_2", PARA_NAME_LEN); g_network_array[NET_USER_DEFINED2].params_code = DIAGNOSE_USER_ADDR2; g_network_array[NET_USER_DEFINED2].test = 1; } } #endif return; } /*********************************************************************************************** *函数: *描述:ping结束时,保存错误码,保存ip、域名及ping结果,设置相应标志 *参数: *返回值: ***********************************************************************************************/ void save_result_callback(struct _DIAGNOSE_CONTEXT* context) { int index = 0; if (NULL == context) { return; } g_network_array[context->index].status = TESTED; /*设置诊断状态为结束*/ if (NULL != context->dnsData) { strncpy(g_network_array[context->index].str_domain, context->dnsData->url, ADDR_LEN); /*保存域名*/ } if (0 == context->ipAddr && NULL != context->dnsData) /*dns解析失败*/ { g_network_array[context->index].res = DIAGNOSE_FAILED; goto exit; } ip_to_str(context->ipAddr, g_network_array[context->index].str_ip);/*保存ip地址*/ if (PING_SUCCESS != context->status) { g_network_array[context->index].res = DIAGNOSE_FAILED; /*设置诊断结果为失败*/ goto exit; } g_network_array[context->index].res = DIAGNOSE_SUCCESS; /*设置诊断结果为成功*/ DIAGNOSE_DEBUG("save %s OK", g_network_array[context->index].para_name); exit: /*是否所有诊断结束*/ for (index = 0; index < ADDR_COUNTS; index++) { if (0 == g_network_array[index].test) { continue; } if (g_network_array[index].do_telnet && TESTED != g_network_array[index].tel_state) { break; } if (TESTED != g_network_array[index].status) { break; } } if (ADDR_COUNTS == index) { diagnose_stop(); } return; } /*********************************************************************************************** *函数: *描述:发起ping请求 *参数: *返回值:ERROR:ping失败 OK:ping 发起成功 ***********************************************************************************************/ S32 ping_start(char* addr, U32 index, U32* context_id) { U32 icmpid = 0; IP_ADDR ip_addr = {0}; DIAGNOSE_DNS_DATA* dns_data = NULL; if (NULL == addr || NULL == context_id) { return ERROR; } /*ip合法检查*/ if (0 == inet_pton(AF_INET, addr, (void*)&ip_addr)) { if (FALSE == valid_domain(addr)) { DIAGNOSE_WARNING("Invalid target domain name format."); return ERROR; } dns_data = (DIAGNOSE_DNS_DATA *)DIAGNOSE_MALLOC(sizeof(DIAGNOSE_DNS_DATA)); if (NULL == dns_data) { DIAGNOSE_WARNING("Failed to alloc memory, size=%d.", sizeof(DIAGNOSE_DNS_DATA)); return ERROR; } memset(dns_data, 0, sizeof(DIAGNOSE_DNS_DATA)); strncpy(dns_data->url, addr, ADDR_LEN); } else { if (FALSE == valid_ip_addr(ip_addr.ipAddr)) { DIAGNOSE_DEBUG("Invalid target ip format."); return ERROR; } } /*发起ping请求*/ DIAGNOSE_ERROR("start ping:%s", (NULL == dns_data) ? addr : dns_data->url); icmpid = diagnose_ping(dns_data, ip_addr.ipAddr, DEFAULT_PING_SIZE, DEFAULT_PING_TIMES, DEFAULT_PING_TIMEOUT, index, save_result_callback); if (CONTEXT_IDLE == icmpid) { DIAGNOSE_FREE(dns_data); return ERROR; } *context_id = icmpid; return OK; } /*********************************************************************************************** *函数:network_diagnose *描述:基础网络诊断 *参数: *返回值: ***********************************************************************************************/ S32 network_diagnose() { int index = 0; U32 context_id = 0; int ping_stat = 0; address_array_init(); for (index = 0; index < ADDR_COUNTS; index++) { if (0 == g_network_array[index].test) { continue; } ping_stat = ping_start(g_default_address.diag_addr[index], index, &context_id); if (OK != ping_stat) { DIAGNOSE_DEBUG("ping start failed"); g_network_array[index].res = DIAGNOSE_FAILED; g_network_array[index].status = TESTED; } else { g_network_array[index].status = TESTING; } if (g_network_array[index].do_telnet) { if (OK == telnet_start(g_default_address.diag_addr[index], &g_network_array[index])) { g_network_array[index].tel_state = TESTING; } else { g_network_array[index].tel_state = TESTED; g_network_array[index].tel_res = DIAGNOSE_FAILED; } } } g_diagnose_timerid = inet_add_timer(diagnose_timer_handle, 0, ITEMS_TIMEOUT_VAL, EXECUTE_SINGLE); if (ERROR == g_diagnose_timerid) { return ERROR; } return OK; } /*********************************************************************************************** *函数:get_sd_info *描述:通过ds_handle获得sd卡信息 *参数: *返回值: ***********************************************************************************************/ LOCAL S32 get_sd_info(STORAGE_INFO* ptr_storage) { const char* ptr = NULL; int error_code = OK; JSON_OBJPTR data_obj = NULL; JSON_OBJPTR data_array = NULL; JSON_OBJPTR array_obj = NULL; JSON_OBJPTR json_harddisk_manage = NULL; JSON_OBJPTR json_harddisk_info = NULL; JSON_OBJPTR json_harddisk_NO = NULL; JSON_OBJPTR json_harddisk_parse = NULL; DS_HANDLE_CONTEXT ds_context; if (NULL == ptr_storage) { return ERROR; } /*构造jason请求sd信息*/ memset(&ds_context, 0, sizeof(DS_HANDLE_CONTEXT)); if (NULL == (ds_context.req_obj = jso_new_obj())) { DIAGNOSE_WARNING("jso_new_obj failed."); return ERROR; } if (NULL == (data_obj = jso_new_obj())) { error_code = ERROR; goto out; } jso_obj_add(ds_context.req_obj, "harddisk_manage", data_obj); jso_add_string(ds_context.req_obj, "method", "get"); if (NULL == (data_array = jso_new_array())) { error_code = ERROR; goto out; } jso_obj_add(data_obj, "name", data_array); if (NULL == (array_obj = jso_new_string("harddisk"))) { error_code = ERROR; goto out; } jso_array_add(data_array, array_obj); if (NULL == (array_obj = jso_new_string("video"))) { error_code = ERROR; goto out; } jso_array_add(data_array, array_obj); if (NULL == (array_obj = jso_new_string("picture"))) { error_code = ERROR; goto out; } jso_array_add(data_array, array_obj); if (NULL == (data_array = jso_new_array())) { error_code = ERROR; goto out; } jso_obj_add(data_obj, "table", data_array); if (NULL == (array_obj = jso_new_string("hd_info"))) { error_code = ERROR; goto out; } jso_array_add(data_array, array_obj); /*发送请求*/ ds_context.group_mask = ROOT_MASK; ds_context.method = METHOD_GET; ds_handle(&ds_context); if(NULL == ds_context.res_obj) { error_code = ERROR; goto out; } /*读取返回值*/ if (NULL == (json_harddisk_manage = jso_obj_get(ds_context.res_obj, "harddisk_manage"))) { error_code = ERROR; goto out; } if (NULL == (json_harddisk_info = jso_obj_get(json_harddisk_manage, "hd_info"))) { error_code = ERROR; goto out; } if (NULL == (json_harddisk_NO = jso_array_get_idx(json_harddisk_info, 0))) { error_code = ERROR; goto out; } if (NULL == (json_harddisk_parse = jso_obj_get(json_harddisk_NO, "hd_info_1"))) { error_code = ERROR; goto out; } if (NULL != (ptr= jso_obj_get_string_origin(json_harddisk_parse, "total_space"))) /*sd总大小*/ { strncpy(ptr_storage->size.total, ptr, SD_SIZE_LEN); } if (NULL != (ptr = jso_obj_get_string_origin(json_harddisk_parse, "free_space"))) /*sd剩余空间*/ { strncpy(ptr_storage->size.free, ptr, SD_SIZE_LEN); } if (NULL != (ptr = jso_obj_get_string_origin(json_harddisk_parse,"record_duration")))/*sd已录时长*/ { strncpy(ptr_storage->recorded_time, ptr, SD_SIZE_LEN); } if (NULL != (ptr = jso_obj_get_string_origin(json_harddisk_parse, "status"))) /*sd状态*/ { strncpy(ptr_storage->available, ptr, SD_STATUS_LEN); } error_code = OK; out: if (NULL != ds_context.req_obj) { jso_free_obj(ds_context.req_obj); ds_context.req_obj = NULL; } if (NULL != ds_context.res_obj) { jso_free_obj(ds_context.res_obj); ds_context.res_obj = NULL; } return error_code; } /*********************************************************************************************** *函数:storage_diagnose *描述:存储诊断 *参数: *返回值: ***********************************************************************************************/ LOCAL S32 storage_diagnose(STORAGE_INFO* ptr_storage) { if (NULL == ptr_storage) { return ERROR; } DIAGNOSE_DEBUG("start storage diagnose"); /*云存储*/ ds_read(CSTG_UPLOAD_ENABLE_PATH, &(ptr_storage->upload_enable), sizeof(CSTG_UPLOAD_ENABLE)); ds_read(CSTG_IS_UPLOADING_PATH, &(ptr_storage->uploading), sizeof(CSTG_IS_UPLOADING)); /*本地存储*/ ds_read(PLAN_ADVANCE_PATH, &(ptr_storage->plan_advance), sizeof(PLAN_ADVANCE));/*预录延录时间*/ get_sd_info(ptr_storage); /*请求sd 状态、总大小、剩余空间、已录时长*/ return OK; } /*********************************************************************************************** *函数: *描述:获取固件是否有更新 *参数: *返回值: ***********************************************************************************************/ S32 request_fw_status() { DS_HANDLE_CONTEXT ds_context = {0}; JSON_OBJPTR data_obj = NULL; if (NULL == (ds_context.req_obj = jso_new_obj())) { return ERROR; } if (NULL == (data_obj = jso_new_obj())) { return ERROR; } jso_obj_add(ds_context.req_obj, "cloud_status", data_obj); jso_add_string(ds_context.req_obj, "method", "get"); jso_add_string(data_obj, "name", "check_fw_ver"); ds_context.group_mask = ROOT_MASK; ds_context.method = METHOD_GET; ds_handle(&ds_context); if(NULL == ds_context.res_obj) { return ERROR; } return OK; } /*********************************************************************************************** *函数:firmware_diagnose *描述:固件诊断 *参数: *返回值: ***********************************************************************************************/ LOCAL S32 firmware_diagnose(FIRMWARE_STRUCT* ptr_firmware) { NEW_FIRMWARE new_firm; if (NULL == ptr_firmware) { return ERROR; } DIAGNOSE_DEBUG("start firmware diagnose"); memset(&new_firm, 0, sizeof(NEW_FIRMWARE)); if (0 == ds_read(CLOUD_CONFIG_NEWFW_PATH, &new_firm, sizeof(NEW_FIRMWARE))) { return ERROR; } ptr_firmware->fw_new_notify = new_firm.fw_new_notify; return OK; } /*********************************************************************************************** *函数:safety_diagnose *描述:安全诊断 *参数: *返回值: ***********************************************************************************************/ void safety_diagnose(VIDEO_ENCRYPTION* ptr_videoencryption) { if (NULL == ptr_videoencryption) { return; } DIAGNOSE_DEBUG("start safety diagnose"); ptr_videoencryption->is_encryption = 1; return; } S32 diagnose_msg_send(int res) { #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(g_is_lte_diagnose) { LTE_NETWORK_DIAGNOSE_RPL_MSG msg = {0}; DIAGNOSE_ERROR("send lte model diagnose msg out id:%d", res); msg.res = res; return msg_send(LTE_NETWORK_DIAGNOSE_RPL_MID, (U8 *)&msg, sizeof(msg)); }else #endif { NETWORK_DIAGNOSE_RPL_MSG msg = {0}; DIAGNOSE_DEBUG("send diagnose msg out id:%d", res); msg.res = res; return msg_send(NETWORK_DIAGNOSE_RPL_MID, (U8 *)&msg, sizeof(msg)); } } S32 diagnose_reply_result(void) { int res = 0; if (LINK_DOWN == g_phy_stat.ether && LINK_DOWN == g_phy_stat.wlan) { res = NETWORK_PHY_DOWN; goto out; } if (DIAGNOSE_FAILED == g_network_array[NET_GATEWAY].res) { res = NETWORK_GATEWAY_FAILED; goto out; } if (DIAGNOSE_FAILED == g_network_array[NET_INTERNET1].res && DIAGNOSE_FAILED == g_network_array[NET_INTERNET2].res) { if (DIAGNOSE_FAILED == g_network_array[NET_BASE_CLOUD].res && DIAGNOSE_FAILED == g_network_array[NET_BASE_CLOUD].tel_res) { res = NETWORK_FAILED; goto out; } res = NETWORK_OK; goto out; } if (DIAGNOSE_FAILED == g_network_array[NET_BASE_CLOUD].res && DIAGNOSE_FAILED == g_network_array[NET_BASE_CLOUD].tel_res) { res = NETWORK_CLOUD_FAILED; goto out; } res = NETWORK_OK; out: return diagnose_msg_send(res); } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT S32 lte_diagnose_reply_result(void) { int res = 0; LTE_CONFIG_NET_DETECTION lte_net_detection; memset(&lte_net_detection, 0, sizeof(LTE_CONFIG_NET_DETECTION)); ds_read(LTE_NET_DET_PATH, &lte_net_detection, sizeof(LTE_CONFIG_NET_DETECTION)); INFO_INTERNET info_internet; memset(&info_internet, 0, sizeof(INFO_INTERNET)); ds_read(INFO_INTERNET_PATH, &info_internet, sizeof(INFO_INTERNET)); if (INTERNET_4G_CONNECTED != info_internet.link_status) { res = NETWORK_4G_DOWN; goto out; } if(strlen(lte_net_detection.hostname_1) != 0 || strlen(lte_net_detection.hostname_2) != 0) { if(DIAGNOSE_FAILED == g_network_array[NET_4G_DET_DNS1].res && DIAGNOSE_FAILED == g_network_array[NET_4G_DET_DNS2].res) { if(g_network_array[NET_USER_DEFINED1].test == 1 && g_network_array[NET_USER_DEFINED2].test == 1) { if(g_network_array[NET_USER_DEFINED1] .res == DIAGNOSE_FAILED && g_network_array[NET_USER_DEFINED2] .res == DIAGNOSE_FAILED) { res = NETWORK_DETECTION_FAILED; goto out; } }else { if((g_network_array[NET_USER_DEFINED1].test == 1 && g_network_array[NET_USER_DEFINED1] .res == DIAGNOSE_FAILED) || (g_network_array[NET_USER_DEFINED2].test == 1 && g_network_array[NET_USER_DEFINED2] .res == DIAGNOSE_FAILED)) { res = NETWORK_DETECTION_FAILED; goto out; } } } res = NETWORK_DETECTION_OK; goto out; }else { if (DIAGNOSE_FAILED == g_network_array[NET_4G_DET_DNS1].res && DIAGNOSE_FAILED == g_network_array[NET_4G_DET_DNS2].res) { res = NETWORK_DETECTION_FAILED; goto out; } } res = NETWORK_DETECTION_OK; out: return diagnose_msg_send(res); } #endif S32 diagnose_result_save_config(void) { int res = 0; LINK_STATUS link_status = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; ds_read(LTE_INFO_DATA_PATH, (U8*)&lte_config, sizeof(LTE_CONFIG_INFO_DATA)); if(lte_config.internet_wired_enable == 0 || (lte_config.internet_wired_enable == 2 && lte_config.auto_switch_wired == 0)) { INFO_INTERNET info_internet = {0}; ds_read(INFO_INTERNET_PATH, (U8*)&info_internet, sizeof(INFO_INTERNET)); if(INTERNET_4G_CONNECTED != info_internet.link_status) { res = NETWORK_PHY_DOWN; goto out; } if(DIAGNOSE_FAILED == g_network_array[NET_4G_DET_DNS1].res && DIAGNOSE_FAILED == g_network_array[NET_4G_DET_DNS2].res) { if(g_network_array[NET_USER_DEFINED1].test == 1 && g_network_array[NET_USER_DEFINED2].test == 1) { if(g_network_array[NET_USER_DEFINED1] .res == DIAGNOSE_FAILED && g_network_array[NET_USER_DEFINED2] .res == DIAGNOSE_FAILED) { res = NETWORK_DETECTION_FAILED; goto out; } }else if(g_network_array[NET_USER_DEFINED1].test == 0 && g_network_array[NET_USER_DEFINED2].test == 0) { res = NETWORK_DETECTION_FAILED; goto out; }else { if(g_network_array[NET_USER_DEFINED1] .res == DIAGNOSE_FAILED || g_network_array[NET_USER_DEFINED2] .res == DIAGNOSE_FAILED) { res = NETWORK_DETECTION_FAILED; goto out; } } } res = NETWORK_OK; }else #endif { if (LINK_DOWN == g_phy_stat.ether && LINK_DOWN == g_phy_stat.wlan) { res = NETWORK_PHY_DOWN; goto out; } if (DIAGNOSE_FAILED == g_network_array[NET_GATEWAY].res) { res = NETWORK_GATEWAY_FAILED; goto out; } if (DIAGNOSE_FAILED == g_network_array[NET_INTERNET1].res && DIAGNOSE_FAILED == g_network_array[NET_INTERNET2].res) { if (DIAGNOSE_FAILED == g_network_array[NET_BASE_CLOUD].res && DIAGNOSE_FAILED == g_network_array[NET_BASE_CLOUD].tel_res) { res = NETWORK_FAILED; goto out; } res = NETWORK_OK; goto out; } if (DIAGNOSE_FAILED == g_network_array[NET_BASE_CLOUD].res && DIAGNOSE_FAILED == g_network_array[NET_BASE_CLOUD].tel_res) { res = NETWORK_CLOUD_FAILED; goto out; } res = NETWORK_OK; } out: ds_read(LINK_STATUS_PATH, (U8 *)&link_status, sizeof(link_status)); if (link_status.internet_status != res) { DIAGNOSE_ERROR("internet status has changed: [%d] ===> [%d]", link_status.internet_status, res); link_status.internet_status = res; } ds_write(LINK_STATUS_PATH, (U8 *)&link_status, sizeof(link_status)); return OK; } /*********************************************************************************************** *函数:get_result *描述:web轮询诊断结果 *参数: type:本次诊断的参数,每一位代表一个诊断项 *返回值: ***********************************************************************************************/ LOCAL S32 get_result(JSON_OBJPTR jso_result, char* type, int cli_index) { JSON_OBJPTR data_obj = NULL; JSON_OBJPTR data_array = NULL; int index = 0; int finish = 0; char buffer[PARSE_BUFFER_LEN] = {'\0'}; char item_status[DIAGNOSE_BIT_LEN + 1] = {'\0'}; if (NULL == type || NULL == jso_result) { return SLP_EINVARG; } memset(item_status, '0', DIAGNOSE_BIT_LEN); if (NULL == (data_array = jso_new_array())) { DIAGNOSE_WARNING("Lookup failed, jso_new_array failed."); return SLP_ENOMEMORY; } /*无线信号*/ if (SET_TEST == type[DIAGNOSE_WIRELESS] && NULL != (data_obj = jso_new_obj())) { memset(buffer, 0, PARSE_BUFFER_LEN); snprintf(buffer, PARSE_BUFFER_LEN, "%d", g_connect_info.rssi); jso_add_string(data_obj, "link_type", g_connect_info.link_type); jso_add_string(data_obj, "rssi", buffer); jso_add_string(data_obj, "ssid", g_connect_info.ssid); jso_obj_add(jso_result, "wireless", data_obj); if (TESTED == g_connect_info.status) { item_status[DIAGNOSE_WIRELESS] = ITEM_FINISH; } else if (TESTING == g_connect_info.status) { item_status[DIAGNOSE_WIRELESS] = ITEM_TESTING; } } /*网络诊断*/ for (index = 0; index < ADDR_COUNTS; index++) { if (SET_TEST == type[g_network_array[index].params_code] && NULL != (data_obj = jso_new_obj())) { memset(buffer, 0, PARSE_BUFFER_LEN); snprintf(buffer, PARSE_BUFFER_LEN, "%d", g_network_array[index].res); jso_add_string(data_obj, "ip", g_network_array[index].str_ip); jso_add_string(data_obj, "domain", g_network_array[index].str_domain); jso_add_string(data_obj, "res", buffer); if (1 == g_network_array[index].do_telnet) { memset(buffer, 0, PARSE_BUFFER_LEN); snprintf(buffer, PARSE_BUFFER_LEN, "%d", g_network_array[index].tel_res); jso_add_string(data_obj, "telnet", buffer); } jso_obj_add(jso_result, g_network_array[index].para_name, data_obj); if (TESTED == g_network_array[index].status) { item_status[g_network_array[index].params_code] = ITEM_FINISH; } } } /*存储诊断*/ if(SET_TEST == type[DIAGNOSE_STORAGE] && NULL != (data_obj = jso_new_obj())) { memset(buffer, 0, PARSE_BUFFER_LEN); snprintf(buffer, PARSE_BUFFER_LEN, "%d", g_storage_info.upload_enable.enable); jso_add_string(data_obj, "cstg_enable", buffer); memset(buffer, 0, PARSE_BUFFER_LEN); snprintf(buffer, PARSE_BUFFER_LEN, "%d", g_storage_info.uploading.is_uploading); jso_add_string(data_obj, "cstg_uploading", buffer); jso_add_string(data_obj, "hd_status", g_storage_info.available); jso_add_string(data_obj, "total", g_storage_info.size.total); jso_add_string(data_obj, "free", g_storage_info.size.free); memset(buffer, 0, PARSE_BUFFER_LEN); snprintf(buffer, PARSE_BUFFER_LEN, "%d", 3); jso_add_string(data_obj, "record_type", buffer); jso_add_string(data_obj, "record_duration", g_storage_info.recorded_time); jso_add_string(data_obj, "hd_lifespan", g_storage_info.sd_lifespan); jso_obj_add(jso_result, "storage", data_obj); if (TESTED == g_storage_info.status) { item_status[DIAGNOSE_STORAGE] = ITEM_FINISH; } } /*固件诊断*/ if(SET_TEST == type[DIAGNOSE_FIRMWARE] && NULL != (data_obj = jso_new_obj())) { firmware_diagnose(&g_firmware_info); memset(buffer, 0, PARSE_BUFFER_LEN); snprintf(buffer, PARSE_BUFFER_LEN, "%d", g_firmware_info.fw_new_notify); jso_add_string(data_obj, "new_fw", buffer); jso_obj_add(jso_result, "firmware", data_obj); if (TESTED == g_firmware_info.status) { item_status[DIAGNOSE_FIRMWARE] = ITEM_FINISH; } } /*安全诊断*/ if(SET_TEST == type[DIAGNOSE_SAFETY] && NULL != (data_obj = jso_new_obj())) { memset(buffer, 0, PARSE_BUFFER_LEN); snprintf(buffer, PARSE_BUFFER_LEN, "%d", g_video_encryption.is_encryption); jso_add_string(data_obj, "is_encrypted", buffer); jso_obj_add(jso_result, "encrypted", data_obj); if (TESTED == g_video_encryption.status) { item_status[DIAGNOSE_SAFETY] = ITEM_FINISH; } } for (index = 0; index < DIAGNOSE_BIT_LEN; index++) { if (SET_TEST == type[index] && ITEM_FINISH != item_status[index]) { break; } } if (DIAGNOSE_BIT_LEN == index || AUTO_STOP == g_client_array[cli_index].is_stop) { finish = 1; goto exit; } g_client_array[cli_index].time_out++; if (g_client_array[cli_index].time_out > CLIENT_GET_TIMEOUT) { finish = 1; inet_del_timer(g_client_array[cli_index].timerid); memset(&g_client_array[cli_index], 0, sizeof(TASK_STRUCT)); } exit: jso_add_string(jso_result, "status", item_status); jso_add_string(jso_result, "finish", finish == 1 ? "1" : "0"); return SLP_ENONE; } void diagnose_timer_handle(S32 param) { DIAGNOSE_INFO("Ping test timeout!"); diagnose_stop(); } void init_global_var() { memset(&g_connect_info, 0, sizeof(g_connect_info)); memset(&g_storage_info, 0, sizeof(g_storage_info)); memset(&g_firmware_info, 0, sizeof(g_firmware_info)); memset(&g_video_encryption, 0, sizeof(g_video_encryption)); memset(g_network_array, 0, sizeof(NETWORK_STRUCT) * ADDR_COUNTS); memset(g_client_array, 0, sizeof(TASK_STRUCT) * MAX_CLIENTS_NUM); memset(&g_phy_stat, 0, sizeof(PHY_STATUS)); } /*********************************************************************************************** *函数: *描述:来自客户端的诊断,如web、App *参数: *返回值: ***********************************************************************************************/ LOCAL S32 client_diagnose() { if (0 == g_task_running) { memset(&g_connect_info, 0, sizeof(g_connect_info)); memset(&g_storage_info, 0, sizeof(g_storage_info)); memset(&g_firmware_info, 0, sizeof(g_firmware_info)); memset(&g_video_encryption, 0, sizeof(g_video_encryption)); request_fw_status(); check_signal_quality(&g_connect_info); g_connect_info.status = TESTED; storage_diagnose(&g_storage_info); g_storage_info.status = TESTED; firmware_diagnose(&g_firmware_info); g_firmware_info.status = TESTED; safety_diagnose(&g_video_encryption); g_video_encryption.status = TESTED; g_task_running = 1; } if (ERROR == g_diagnose_timerid) { network_diagnose(); } return OK; } void phy_status_change(void) { #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; ds_read(LTE_INFO_DATA_PATH, (U8*)&lte_config, sizeof(LTE_CONFIG_INFO_DATA)); #endif ds_read(PHY_STATUS_PATH, &g_phy_stat, sizeof(PHY_STATUS)); if (LINK_DOWN == g_phy_stat.ether && LINK_DOWN == g_phy_stat.wlan) { DIAGNOSE_DEBUG("catch phy link down"); #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(lte_config.internet_wired_enable == 1 || (lte_config.internet_wired_enable == 2 && lte_config.auto_switch_wired == 1)) #endif { diagnose_stop(); } } } /*开启自诊断*/ S32 diagnose_operation_handle(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { /*开启网络诊断*/ g_is_auto_diagnose = 1; if (ERROR == g_diagnose_timerid) { #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT NET_DIAGNOSE_MSG *msg = NULL; if(mbuf != NULL && mlen == sizeof(NET_DIAGNOSE_MSG)) { msg = (NET_DIAGNOSE_MSG*)mbuf; if(msg->model == MODEL_LTE) { g_is_lte_diagnose = 1; g_is_other_model_diagnose = 0; }else { g_is_other_model_diagnose = 1; } }else { g_is_other_model_diagnose = 1; } #endif network_diagnose(); } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT else if(ERROR != g_diagnose_timerid) { NET_DIAGNOSE_MSG *msg = NULL; if(mbuf != NULL && mlen == sizeof(NET_DIAGNOSE_MSG)) { msg = (NET_DIAGNOSE_MSG*)mbuf; if(msg->model == MODEL_LTE) { LTE_NETWORK_DIAGNOSE_RPL_MSG msg_sendto_lte = {0}; int res = TIMER_NOT_OVER; DIAGNOSE_ERROR("send lte model diagnose msg out id:%d", res); msg_sendto_lte.res = res; msg_send(LTE_NETWORK_DIAGNOSE_RPL_MID, (U8 *)&msg_sendto_lte, sizeof(msg)); } } } #endif return OK; } void client_array_reclaim_handle(S32 param) { if (param >= 0 && param < MAX_CLIENTS_NUM) { inet_del_timer(g_client_array[param].timerid); memset(&g_client_array[param], 0, sizeof(TASK_STRUCT)); } } S32 get_empty_client_ctx(int* client_index) { int index = 0; if (NULL == client_index) { return ERROR; } for (index = 0; index < MAX_CLIENTS_NUM; index++) { if (0 == strlen(g_client_array[index].instance_id)) { g_client_array[index].timerid = inet_add_timer(client_array_reclaim_handle, index, CLIENT_RECLAIM_INTERVAL, EXECUTE_SINGLE); if (ERROR == g_client_array[index].timerid) { return ERROR; } *client_index = index; return OK; } } return ERROR; } S32 get_client_instance_by_id(const char* instance_id, int* cli_index) { int index = 0; if (NULL == instance_id || NULL == cli_index) { return ERROR; } for (index = 0; index < MAX_CLIENTS_NUM; index++) { if (0 == strlen(g_client_array[index].instance_id)) { continue; } if (0 == strcmp(g_client_array[index].instance_id, instance_id)) { *cli_index = index; return OK; } } return ERROR; } S32 valid_param(const char* type) { int type_len = 0; int index = 0; if (NULL == type) { return SLP_EINVARG; } type_len = strlen(type); if (0 == type_len || type_len > DIAGNOSE_BIT_LEN) { return SLP_EINVARG; } for (index = 0; index < type_len; index++) { if (type[index] != '0' && type[index] != '1') { return IPC_DIAGNOSE_TYPE_NOT_SUPPORT; } if (index > DIAGNOSE_MAX && SET_TEST == type[index]) { return IPC_DIAGNOSE_TYPE_NOT_SUPPORT; } } return SLP_ENONE; } /*********************************************************************************************** *函数:start_oneclick_diagnose_callback *描述:快速诊断 *参数:读取诊断id,执行对应诊断内容 *返回值: ***********************************************************************************************/ S32 start_oneclick_diagnose_callback(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { const char* ptr = NULL; char instance_id[DIAGNOSE_ID_LEN + 1] = {'\0'}; U64 time_stamp = 0; int rand_num = 0; int error_code = SLP_ENONE; int client_index = 0; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; LTE_CONFIG_NET_DETECTION net_det = {0}; #endif if (!context || !context->res_obj || !context->req_obj) { error_code = SLP_ESYSTEM; goto out; } ptr = jso_obj_get_string_origin(param, "type"); if (NULL == ptr) { error_code = IPC_DIAGNOSE_PARAMS_INVALID; goto out; } error_code = valid_param(ptr); if (SLP_ENONE != error_code) { goto out; } if (ERROR == get_empty_client_ctx(&client_index)) { error_code = IPC_DIAGNOSE_TASK_BUSY; goto out; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(0 == ds_read(LTE_INFO_DATA_PATH, (U8*)&lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DIAGNOSE_ERROR("read config path %s fail.", LTE_INFO_DATA_PATH); error_code = IPC_DIAGNOSE_INTERNAL_ERROR; goto out; } if(0 == ds_read(LTE_NET_DET_PATH, (U8*)&net_det, sizeof(LTE_CONFIG_NET_DETECTION))) { DIAGNOSE_ERROR("read config path %s fail.", LTE_NET_DET_PATH); error_code = IPC_DIAGNOSE_INTERNAL_ERROR; goto out; } if((lte_config.internet_wired_enable == 0 || (lte_config.internet_wired_enable == 2 && lte_config.auto_switch_wired == 0)) && net_det.ping_enable == 1) { goto out; }else #endif { if (ERROR == client_diagnose()) { goto out; } } /*返回诊断id*/ srand((U32)time(NULL)); time_stamp = nvmp_get_us(); rand_num = rand() % 10000; snprintf(instance_id, DIAGNOSE_ID_LEN, "%llu-%u", time_stamp, rand_num); g_client_array[client_index].time_out = 0; g_client_array[client_index].is_stop = 0; strncpy(g_client_array[client_index].instance_id, instance_id, DIAGNOSE_ID_LEN); jso_add_string(context->res_obj, "diagnose_id", instance_id); return SLP_ENONE; out: snprintf(instance_id, DIAGNOSE_ID_LEN, "%d", 0); jso_add_string(context->res_obj, "diagnose_id", instance_id); return error_code; } S32 diagnose_result_callback(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { const char* ptr = NULL; char str_type[DIAGNOSE_BIT_LEN + 1] = {'\0'}; /*诊断内容*/ char instance_id[DIAGNOSE_ID_LEN + 1] = {'\0'}; /*诊断实例id*/ int error_code = SLP_ENONE; int cli_index = 0; if (!context || !context->res_obj || !context->req_obj) { return SLP_ESYSTEM; } if (NULL == (ptr = jso_obj_get_string_origin(param, "diagnose_id"))) { return IPC_DIAGNOSE_PARAMS_INVALID; } strncpy(instance_id, ptr, DIAGNOSE_ID_LEN); if (ERROR == get_client_instance_by_id(instance_id, &cli_index)) { return IPC_DIAGNOSE_ID_NOT_FOUND; } if (NULL == (ptr = jso_obj_get_string_origin(param, "type"))) { return IPC_DIAGNOSE_PARAMS_INVALID; } error_code = valid_param(ptr); if (SLP_ENONE != error_code) { return error_code; } strncpy(str_type, ptr, DIAGNOSE_BIT_LEN); return get_result(context->res_obj, str_type, cli_index); } S32 stop_oneclick_diagnose_callback(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { char instance_id[DIAGNOSE_ID_LEN + 1] = {'\0'}; const char* ptr = NULL; int cli_index = 0; if (!context || !context->res_obj || !context->req_obj) { return SLP_ESYSTEM; } ptr = jso_obj_get_string_origin(param, "diagnose_id"); if (NULL == ptr) { return IPC_DIAGNOSE_PARAMS_INVALID; } strncpy(instance_id, ptr, DIAGNOSE_ID_LEN); if (ERROR == get_client_instance_by_id(instance_id, &cli_index)) { return IPC_DIAGNOSE_ID_NOT_FOUND; } g_client_array[cli_index].is_stop = AUTO_STOP; if (g_client_array[cli_index].timerid > 0) { inet_del_timer(g_client_array[cli_index].timerid); } memset(&g_client_array[cli_index], 0, sizeof(TASK_STRUCT)); DIAGNOSE_DEBUG("stop get result ......."); return SLP_ENONE; } 重点去关注,这函数是不是填充地址,第一位地址留给了网关,然后他怎么去获取的网关?我主要关注在有线部分, 234位的外网都正常,现在我要修改功能是,读取网关时,我的ip是在4G那边的,他会默认读到4G的网关,首先找到具体读网关的操作在哪里,然后,能否指定读eth0的网关?
10-23
#include <stdio.h> #include "chm_default.h" #include "ubus_test.h" #include "chm_dbg.h" #include "chm_ubus.h" extern struct ubus_context *ctx; extern struct blob_buf b; enum { TEST_CHANNEL, __TEST_MAX }; static void leak_mem() { /* 故意分配内存但不释放 - 内存泄漏 */ int *leak_memory = malloc(1024 * sizeof(int)); if (leak_memory) { // 入数据避免编译器优化 for (int i = 0; i < 1024; i++) { leak_memory[i] = i; } } } static void null_pointer() { // 故意创建空指针并解引用 - 空指针访问 int *null_pointer = NULL; *null_pointer = 0xDEADBEEF; // 触发SIGSEGV } // 用于消息解析,指明key为channel字符串的时候,它的值是一个INT32类型的值,可以单纯的理解为"channel" : 20 static const struct blobmsg_policy test_policy[__TEST_MAX] = { [TEST_CHANNEL] = {.name = "channel", .type = BLOBMSG_TYPE_INT32}}; // 方法函数 static int32 test_problem_handler(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { int32 ret = ERROR; int32 test_channel; struct blob_attr *tb[__TEST_MAX]; // 根据policy从解析出blobmsg blobmsg在blob_attr的data区 /* blobmsg用于二进制对象网络序列化。嵌套在blob数据结构(blob_attr)的data区。 因此形成:blob_buff <- blob_attr -< blobmsg,blob_buff可存储管理多个blob_attr,每个blob_attr又可存储管理一个blogmsg。且可存储在线性数据区,不需要链表指针。 blobmsg_policy用于解析缓存blobmsg列表,一般声明为一个静态数组,用于指导消息解析。 blobmsg默认使用id为table。array类似C语言的数组,table类似C的结构。 */ blobmsg_parse(test_policy, __TEST_MAX, tb, blob_data(msg), blob_len(msg)); /* 这里是一系列函数,因为上面的.type = BLOBMSG_TYPE_INT32 所以这里用blobmsg_get_u32来解析 */ if (tb[TEST_CHANNEL] != NULL) { test_channel = blobmsg_get_u32(tb[TEST_CHANNEL]); if (0 == test_channel) { /* 触发内存泄漏 */ leak_mem(); ret = 0; } else if (1 == test_channel) { /* 访问空指针 */ null_pointer(); ret = 1; } // ret = notify_cloud_connect_status(connect_status); } // 因为blob_buff // blob_buf一般声明为本地静态变量,id一般使用0(BLOBMSG_TYPE_UNSPEC)来初始化。 blob_buf_init(&b, 0); // 将ret的值添加到buf中,然后调用发送函数 blobmsg_add_u32(&b, "result", ret); // ubus发送函数,执行完成方法调用后发送响应 ubus_send_reply(ctx, req, b.head); return 0; } static struct ubus_method test_leakmem_methods[] = { /* 触发通知 */ UBUS_METHOD("test_problem", test_problem_handler, test_policy), }; static struct ubus_object_type test_ubus_obj_type = UBUS_OBJECT_TYPE("leakmem_test", test_leakmem_methods); static struct ubus_object test_ubus_obj = { .name = "leakmem_test", .type = &test_ubus_obj_type, .methods = test_leakmem_methods, .n_methods = ARRAY_SIZE(test_leakmem_methods), }; /****************************************************************************** * 函数名称: test_ubus_init * 函数描述: 初始化ubus处理模块,注册ubus对象 * 输 入: path: unix socket path * 输 出: N/A * 返 回 值: -1: 失败。该函数正常情况下不会返回 ******************************************************************************/ CHM_STATUS test_ubus_init() { int32 ret = CHM_STATUS_OK; ret = ubus_add_object(ctx, &test_ubus_obj); if (ret) { CHM_DPRINTF(MSG_FATAL, "ubus problem test add obj failed\n"); return CHM_STATUS_ERROR; } return CHM_STATUS_OK; } 这是一个测试模块注册的ubus程序,此外我需要用TDCP接口调用上面的ubus方法,应该是可以用ubus_simple_call函数去调用ubus方法,/****************************************************************************** * 函数名称: ubus_simple_call * 函数描述: 调用无需传参的ubus方法 * 输 入: module: 模块名 method: 方法名 * 输 出: err_code: 错误码 * 返 回 值: ******************************************************************************/ int ubus_simple_call(const char *module, const char *method, const char *msg, int *err_code) 下面是我的TDCP接口的代码,我需要一下S32 test_leakmem_problem(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param)这个函数,你学习别人的函数实现,帮我重新一下这个函数的内容,我的题目是这样的3. 该进程实现ubus方法,根据传入参数触发内存泄漏及访问空指针问题4. 在dsd中添加接口,可用postman通过TDCP接口调用上述ubus 方法 帮我重新一下函数代码,完成上面的要求: /* 处理IPC osd多语言字符,生成字库文件并上传给ipc */ S32 do_multi_language_osd_process(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { S32 ret = SLP_ENONE; int chn_id; int port; int retry_count = 2; int err_code; const char* osd_str = NULL; const char* upload_uri = NULL; const char* stok = NULL; const char* ip = NULL; char http_port[PORT_STR_LEN] = {0}; char recv_buf[RECV_BUF_SIZE] = {0}; char stok_buf[STOK_BUF_SIZE] = {0}; char upload_uri_decode[HTTP_URL_MAX_SIZE] = {0}; JSON_OBJPTR json_header = NULL; JSON_OBJPTR resp_obj = NULL; if (!context || !param || !jso_is_obj(param)) { DSD_LOG(DSD_LOG_ERROR, "Invalid params."); ret = SLP_EINVARG; goto finish; } jso_obj_get_int(param, "chn_id", &chn_id); jso_obj_get_int(param, "http_port", &port); osd_str = jso_obj_get_string_origin(param, "osd_str"); upload_uri = jso_obj_get_string_origin(param, "url"); stok = jso_obj_get_string_origin(param, "stok"); ip = jso_obj_get_string_origin(param, "ip"); if (!osd_str || !upload_uri || !stok || !ip) { ret = SLP_EINVARG; goto finish; } strcpy(stok_buf, stok); ret = generate_ttf_file(osd_str); if (ret < 0) { goto finish; } DSD_LOG(DSD_LOG_ERROR, "chn:%d, %s, %d", chn_id, osd_str, ret); if (chn_id < 0 || !osd_str || !upload_uri || !stok) { DSD_LOG(DSD_LOG_ERROR, "Invalid params."); ret = SLP_EINVARG; goto finish; } snprintf(http_port, sizeof(http_port), "%d", port); uh_urldecode(upload_uri_decode, sizeof(upload_uri_decode), upload_uri, strlen(upload_uri)); DSD_LOG(DSD_LOG_DEBUG, "upload_uri_decode : %s", upload_uri_decode); retry: //上传文件 memset(recv_buf, 0, RECV_BUF_SIZE); ret = https_mutipartform_post_upload_file(ip, http_port, stok_buf, URL_WITH_STOK, upload_uri_decode, (char *)NEW_OSD_FILE_PATH, recv_buf); DSD_LOG(DSD_LOG_DEBUG, "http_mutipartform_post_upload_file recv_buf: %s, ret = %d", recv_buf, ret); resp_obj = json_tokener_parse(recv_buf); if (NULL == resp_obj || is_error(resp_obj)) { DSD_LOG(DSD_LOG_ERROR, "parse json data failed"); resp_obj = NULL; ret = ECPARSEJSON; goto finish; } err_code = json_object_get_int(json_object_object_get(resp_obj, "error_code")); if (err_code == SLP_EUNAUTH && retry_count-- > 0) { get_new_token(context, chn_id + 1, stok_buf); goto retry; } if (NULL != context->res_obj) { jso_free_obj(context->res_obj); context->res_obj = NULL; } context->res_obj = resp_obj; finish: if (NULL == context->res_obj) { context->res_obj = jso_new_obj(); } return ret; } S32 check_ip_conflict(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { UBUS_CONN *conn = NULL; UBUS_CALL_ATTR attr = {0}; JSON_OBJPTR result = NULL; int ret = 0; int error_code; int i; JSON_OBJPTR code_list = NULL; JSON_OBJPTR temp = NULL; JSON_OBJPTR ret_list = NULL; if (!context || !param || (FALSE == jso_is_obj(param))) { DSD_LOG(DSD_LOG_ERROR, "Invalid params."); return SLP_EINVARG; } conn = ubus_create_connection(); if (NULL == conn) { goto finish; } if (ERROR == jso_to_string(param, context->buffer, context->buf_len)) { DSD_LOG(DSD_LOG_ERROR, "jso_to_string error."); ret = NVR_UBUS_CONN_ERR; goto finish; } attr.module = "chm_dev_manager"; attr.method = "chm_ubus_check_ip_conflict"; attr.msg = context->buffer; if (NULL != context->res_obj) { jso_free_obj(context->res_obj); context->res_obj = NULL; context->res_obj = jso_new_obj(); } ret = ubus_call(conn, &attr, &result); if (ret < 0) { DSD_LOG(DSD_LOG_ERROR, "ubus call error."); ret = EPROCESSERR; goto finish; } if (FALSE == jso_is_obj(result)) { DSD_LOG(DSD_LOG_ERROR, "result is not a json object."); ret = EPROCESSERR; goto finish; } code_list = jso_obj_get(result, "result"); if (FALSE == jso_is_array(code_list)) { DSD_LOG(DSD_LOG_ERROR, "result is not a json array."); ret = NVR_CHM_UNK_ERR; goto finish; } ret_list = jso_new_array(); for (i = 0; i < jso_array_length(code_list); i++) { temp = jso_array_get_idx(code_list, i); error_code = json_object_get_int(temp); if (error_code < MAP_TABLE_LEN && error_code >= 0) { jso_array_add(ret_list, json_object_new_int(MAP_TABLE[error_code])); } else { jso_array_add(ret_list, json_object_new_int(NVR_CHM_UNK_ERR)); } } jso_obj_add(context->res_obj, "result", ret_list); finish: if (NULL != conn) { ubus_close_connection(conn); } jso_free_obj(result); return SLP_ENONE; } S32 test_leakmem_problem(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { const char *action = NULL; JSON_OBJPTR channels = NULL; JSON_OBJPTR jso_channel = NULL; S32 err_code = 0; U8 params[MAX_JSON_STR_LEN] = {0}; U8 channel_param[MAX_JSON_STR_LEN] = {0}; if (!context || !jso_is_obj(param)) { return SLP_EINVARG; } action = jso_obj_get_string_origin(param, "action"); if ((NULL == action) || (0 == strlen(action))) { return SLP_EINVARG; } if (!strcmp(action, ACTION_CHANGE_UPLOAD_STATE)) { DSD_LOG(DSD_LOG_DEBUG, "!!!change upload state"); /* parse channels */ channels = jso_obj_get(param, "channel"); if (!channels || !jso_is_array(channels)) { return SLP_EINVARG; } jso_to_string(channels, channel_param, MAX_JSON_STR_LEN); if (MAX_JSON_STR_LEN <= snprintf(params, MAX_JSON_STR_LEN, "{\"channel\": %s}", channel_param)) { DSD_LOG(DSD_LOG_ERROR, "Buf not large enough!"); } DSD_LOG(DSD_LOG_DEBUG, "Msg: %s", params); if ((OK != ubus_simple_call(CLOUD_STORAGE_UBUS_OBJ, CS_METHOD_CHANGE_UPLOAD_STATE, params, &err_code)) || (SLP_ENONE != err_code)) { DSD_LOG(DSD_LOG_ERROR, "Ubus call " CLOUD_STORAGE_UBUS_OBJ " " CS_METHOD_CHANGE_UPLOAD_STATE " failed: %d.", err_code); err_code = EPROCESSERR; } else { err_code = SLP_ENONE; } } else if (!strcmp(action, ACTION_CHANGE_ENCRYPT_KEY)) { DSD_LOG(DSD_LOG_DEBUG, "!!!change encrypt key"); /* no other arguments */ if ((OK != ubus_simple_call(CLOUD_STORAGE_UBUS_OBJ, CS_METHOD_CHANGE_ENCRYPT_KEY, NULL, &err_code)) || (SLP_ENONE != err_code)) { DSD_LOG(DSD_LOG_ERROR, "Ubus call " CLOUD_STORAGE_UBUS_OBJ " " CS_METHOD_CHANGE_ENCRYPT_KEY " failed."); err_code = EPROCESSERR; } else { err_code = SLP_ENONE; } } else { DSD_LOG(DSD_LOG_ERROR, "Unsupported action: %s", action); return SLP_EINVARG; } return err_code; }
09-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值