├── .htaccess
├── README.md
├── callback
└── tape_callback.php
├── common
├── AbstractInterface.php
├── Common.php
├── ConfFactory.php
├── ErrorCode.php
├── GlobalDefine.php
├── GlobalFunctions.php
├── Ini.php
├── MiniLog.php
├── Param.php
├── ParamChecker.php
└── TLSSigAPIv2.php
├── conf
├── OutDefine.php
├── cdn.inc.ini
└── cdn.route.ini
├── createDB.sh
├── dao
├── dao_base
│ ├── dao.class.php
│ └── simple_mysql_session.class.php
├── dao_live
│ └── dao_live.class.php
└── redis_cache.php
├── doc
└── protocol.md
├── fastcgi.conf
├── index.php
├── interface.php
├── interface
├── get_cos_sign.php
├── get_user_info.php
├── get_vod_list.php
├── login.php
├── refresh.php
├── register.php
├── upload_room.php
└── upload_user_info.php
└── liteav_demo.nginx
/.htaccess:
--------------------------------------------------------------------------------
1 | RewriteEngine on #rewriteengine???????on???off???
2 | RewriteRule ^([a-zA-Z0-9_]){5,100}/?$ interface.php/$0
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 小直播解决方案服务端
2 |
3 | 为观众端提供直播间列表和回放列表,以及账号注册、登录、个人信息维护等功能。
4 |
5 |
6 | ### 开通直播服务
7 |
8 | #### step 1.1 开通视频直播服务
9 |
10 | 登录腾讯云官网,进入 [云直播管理控制台](https://console.cloud.tencent.com/live),如果服务还没有开通,单击【申请开通】。
11 |
12 | #### step 1.2 绑定直播域名
13 | 按照相关政策要求,您需要添加自有的**已备案域名**才能使用腾讯云的 CDN 播放功能,请参见 [域名管理](https://cloud.tencent.com/document/product/267/20381) 和 [CNAME 配置](https://cloud.tencent.com/document/product/267/30560) 进行配置。
14 |
15 |
16 | #### step 1.3 获取 SDK 的测试 License
17 | “小直播”是基于腾讯云 LiteAVSDK 实现推流和播放功能的,但您需要提前绑定 License 才能使用其提供的推流功能,您可以先按照如下步骤获取“小直播”所需要的测试 License:
18 |
19 | 1. 在 [云直播管理控制台](https://console.cloud.tencent.com/live) 中点击进入 [移动直播 License](https://console.cloud.tencent.com/live/license) 页面。
20 | 2. 填写【Package Name】为 Android 的包名,【Bundle Id】为 iOS 的 Bundle Id。
21 | 3. 单击【免费创建】,创建成功后,页面会显示生成的 License 信息。请记录 Key 和 LicenseUrl,便于在 SDK 初始化时使用。
22 |
23 | 
24 |
25 |
26 | #### step 1.4 在应用管理中添加一个新的应用
27 | “小直播”是基于腾讯云 TIMSDK 实现文字聊天室和弹幕消息等互动功能的,但您需要先创建一个 IM 应用才能使用其提供的聊天室功能,您可以先按照如下步骤获取“小直播”所需要的 SDKAppID 和 SecretKey 两个重要信息:
28 |
29 | 1. 进入【云直播控制台】>【直播SDK】>【[应用管理](https://console.cloud.tencent.com/live/license/appmanage)】,单击【创建应用】,待应用创建完成后,记录其 SDKAppID 信息。
30 | 2. 单击目标应用的 SDKAppID,进入应用详情页面。
31 | 3. 选择【应用管理】页签,单击【编辑】,输入一个管理员名称(例如“admin”),单击【添加】按钮,之后再单击【确定】按钮。
32 | 4. 单击【查看密钥】,复制保存密钥信息 SecretKey。
33 |
34 | 
35 |
36 | ### 开通对象存储服务
37 |
step 2.1 申请开通对象存储服务
38 |
39 | 进入 [对象存储服务控制台](https://console.cloud.tencent.com/cos5),如果还没有服务,直接单击【创建存储桶】即可。
40 |
41 | step 2.2 创建存储桶并获取基本信息
42 |
43 | 1. 填写名称,选择所属地域,设置访问权限为【公有读私有写】。单击【确定】创建存储桶。
44 | 
45 |
46 | 2. 单击【基础配置】,记录`存储空间名称`、`所属地域`,分别对应于后文 [修改云服务器配置信息](#STEP4_1) 中的 `COSKEY_BUCKET` 和 `COSKEY_BUCKET_REGION`。
47 | 
48 |
49 | step 2.3 获取密钥信息
50 |
51 | 进入[【对象存储控制台】>【密钥管理】>【云API密钥】](https://console.cloud.tencent.com/cam/capi) 获取 `APPID`、`SecretId` 和 `SecretKey`,分别对应下文 [修改云服务器配置信息](#STEP4_1) 中的 `COSKEY_APPID`、`COSKEY_SECRETID` 和 `COSKEY_SECRETKEY`。
52 | 
53 |
54 |
55 | ### 腾讯云CVM镜像部署
56 |
57 | step 3.1 创建虚拟主机
58 |
59 | 进入 [CVM 控制台](https://console.cloud.tencent.com/cvm) ,单击【新建】开始创建云服务器。
60 |
61 | 选择【自定义配置】选择符合您需求的虚拟主机,在镜像提供栏选择【镜像市场】,并单击【从镜像市场选择】进服务市场选取镜像。选中图中的【小直播镜像】,您可以直接在搜索栏中搜索。
62 | 
63 |
64 | step 3.2 设置云服务器
65 | 配置云服务器的访问密码,设置安全组。
66 |
67 | >!安全组一定要放开80、443服务端口
68 | >请**妥善保管 root 密码**,该密码将用于后续 [修改云服务器配置信息](#STEP4_1) 操作。
69 |
70 | 
71 |
72 | step 3.3 查看云服务器信息
73 |
74 | 付款后生成云服务器。请记录外网 IP 地址,将用于后续 [配置录制回调](#STEP3_2) 和 [终端集成](#STEP5) 操作。
75 | 
76 |
77 |
78 | #### step 3.4 准备配置文件
79 | 将以下内容粘贴到文本编辑器(如记事本),按照下方脚本中的注释填写各项内容,其中`xxxx`的部分在本文前半部分均能找到对应的值。
80 |
81 | ```bash
82 | #!/bin/bash
83 |
84 | echo " /data/live_demo_service/conf/OutDefine.php;
98 | ```
99 |
100 | #### step 3.5 登录云服务器
101 |
102 | 1. 进入 [CVM 控制台](https://console.cloud.tencent.com/cvm) ,单击目标主机所在行【登录】。
103 | 
104 |
105 | 2. 选择【标准登录方式】区域的【立即登录】,输入配置主机时设置的密码,单击【确认】。
106 |
107 | #### step 3.6 修改配置
108 | 登录成功后会进入一个网页版的控制台界面,您只需要直接将 [准备配置文件](#STEP3_4) 中准备好的文本粘贴过来,按 `Enter` 键确认即可。
109 | 
110 |
111 | **至此业务后台部署完成**
112 |
113 |
114 | ### 终端集成及回调设置
115 |
116 | 终端集成主要是小直播源码集成,主要是以下简单几步:
117 |
118 | #### 小直播源码下载
119 | 小直播 App 的源码位于 Github/Github 仓库中,可以在`Android/XiaoZhiBo`和`iOS/XiaoZhiBo`分别获取到 Android 和 iOS 的源码。
120 |
121 |
122 |
123 | ZIP 包
124 | | Github
125 | | Gitee
126 | |
127 |
128 | DOWNLOAD |
129 | Github |
130 | Gitee |
131 |
132 |
133 |
134 | #### 替换“小直播” 中的 License 配置
135 |
136 | 我们在 step 1.3 中拿到的 LiteAVSDK 的测试版 License 在这一步可以发挥作用了,参照如下的说明替换源代码中的两行字符串(License URL 和 Key) 即可:
137 |
138 | - **iOS 版替换方案**:
139 | 打开`iOS/XiaoZhiBo/XiaoZhiBoApp/Classes/App/`目录下的 `TCGlobalConfig.h` 文件,将文件里的 `LICENCE_URL` 和 `LICENCE_KEY` 分别替换为[ step 1.3:获取 SDK 的测试 License ](#get_lvb_license)中记录的 License URL 和 Key。
140 |
141 | - **Android 版替换方案**:
142 | 打开`Android/XiaoZhiBo/app/src/main/java/com/tencent/qcloud/xiaozhibo`目录下的 `TCGlobalConfig.java` 文件,将文件里的 `LICENCE_URL` 和 `LICENCE_KEY` 分别替换为[ step 1.3:获取 SDK 的测试 License ](#get_lvb_license)中记录的 License URL 和 Key。
143 |
144 | #### 替换小直播后台服务器地址
145 | 小直播后台服务的地址为`http://云服务器公网 IP 地址`。例如`http://134.175.197.138`:
146 | - iOS:
147 | 打开`iOS/XiaoZhiBo/XiaoZhiBoApp/Classes/App/`目录下的 **TCGlobalConfig.h** 文件,将文件里的`kHttpServerAddr`改为您的小直播后台服务的地址。
148 | - Android:
149 | 打开`Android/XiaoZhiBo/app/src/main/java/com/tencent/qcloud/xiaozhibo`目录下的 **TCGlobalConfig.java** 文件,将文件里的`APP_SVR_URL`改为您的小直播后台服务的地址。
150 |
151 | `注意:如果服务器没有配置证书,这里的云主机服务器地址需要用http,而不能用https。`
152 |
153 | ### 在直播控制台配置录制回调地址
154 |
155 | 小直播 App 中的“精彩回放”功能依托于云直播的录制功能。
156 | #### step 4.1 配制录制参数
157 | 1. 在云直播菜单栏内选择【功能模板】>【[录制配置](https://console.cloud.tencent.com/live/config/record)】,单击 "+" 进行设置。
158 | 
159 |
160 | 2. 设置基本信息,填写【模板名称】,并选择录制文件类型(HLS、MP4 或者 FLV),单击【保存】。
161 |
162 |
163 | #### step 4.2 配置录制回调
164 | 1. 在云直播菜单栏内选择【功能模板】>【[回调配置](https://console.cloud.tencent.com/live/config/callback)】,单击 "+" 创建回调模板。
165 | 
166 |
167 | 2. 填写并记录【回调密钥】,填写【录制回调】为 `http://您的云服务器公网 IP 地址/callback/tape_callback.php`,单击【保存】。
168 | 
169 |
170 | #### step 4.3 应用配置到域名
171 | 1. 进入云直播控制台 [域名管理](https://console.cloud.tencent.com/live/domainmanage),单击推流域名后的【管理】。
172 | 
173 |
174 | 2. 单击【模板配置】,分别将【回调配置】和【录制配置】设置为上述步骤中新建的模板。
175 | 
176 |
177 |
178 |
179 | ## 后台源码目录结构说明
180 | ```
181 | xiaozhibo_server_php
182 | ├── callback
183 | │ └── tape_callback.php //录制回调的处理
184 | ├── common
185 | │ ├── AbstractInterface.php //所有接口类的抽象父类,输入输出的统一处理
186 | │ ├── Common.php
187 | │ ├── ConfFactory.php //用于读取数据库配置文件
188 | │ ├── ErrorCode.php //错误码定义
189 | │ ├── GlobalDefine.php //一些全局定义
190 | │ ├── GlobalFunctions.php //通用函数,一些无用的函数清理掉
191 | │ ├── Ini.php //ini配置文件读取
192 | │ ├── MiniLog.php //日志
193 | │ ├── Param.php //输入参数检查
194 | │ ├── ParamChecker.php //输入参数检查
195 | │ └── TLSSigAPIv2.php //UserSig计算
196 | ├── conf
197 | │ ├── OutDefine.php //腾讯云账号信息配置文件
198 | │ ├── cdn.inc.ini //总配置文件
199 | │ └── cdn.route.ini //数据库配置文件
200 | ├── dao //数据库相关
201 | │ ├── dao_base
202 | │ │ └── dao.class.php //数据库对外的类
203 | │ ├── dao_live
204 | │ │ └── dao_live.class.php //数据库对外的实现类,各种sql语句在这里
205 | │ └── redis_cache.php //redis本地缓存
206 | ├── fastcgi.conf //nginx配置文件
207 | ├── index.php
208 | ├── interface
209 | │ ├── get_cos_sign.php //上传头像、封面图片用
210 | │ ├── get_user_info.php //获取用户信息,用于漫游个人信息
211 | │ ├── get_vod_list.php //获取回放列表
212 | │ ├── login.php //登录,获取token
213 | │ ├── refresh.php //刷新token
214 | │ ├── register.php //注册
215 | │ └── upload_user_info.php //更新个人信息
216 | ├── interface.php //接口处理入口
217 | └── liteav_demo.nginx //nginx配置文件
218 | ```
219 |
--------------------------------------------------------------------------------
/callback/tape_callback.php:
--------------------------------------------------------------------------------
1 | data = json_decode($request, true);
24 | if (!$this->data) {
25 | component_log(ERROR, EC_OK, " request para EC_SYSTEM_INVALID_JSON_FORMAT");
26 | return EC_SYSTEM_INVALID_JSON_FORMAT;
27 | }
28 |
29 | if (array_key_exists("t", $this->data)
30 | && array_key_exists("sign", $this->data)
31 | && array_key_exists("event_type", $this->data)
32 | && array_key_exists("stream_id", $this->data)) {
33 | $check_t = $this->data['t'];
34 | $check_sign = $this->data['sign'];
35 | $this->event_type = $this->data['event_type'];
36 | $this->stream_id = $this->data['stream_id'];
37 | } else {
38 | component_log(ERROR, EC_OK, " request para EC_SYSTEM_INVALID_PARA");
39 | return EC_SYSTEM_INVALID_PARA;
40 | }
41 | $md5_sign = GetCallBackSign($check_t);
42 | if (!($check_sign == $md5_sign)) {
43 | component_log(ERROR, EC_OK, " check_sign error:" . $check_sign . ":" . $md5_sign);
44 | return EC_SYSTEM_INVALID_SIGN;
45 | }
46 | if ($this->event_type == 100) {
47 | if (array_key_exists("video_id", $this->data) &&
48 | array_key_exists("video_url", $this->data) &&
49 | array_key_exists("start_time", $this->data) &&
50 | array_key_exists("end_time", $this->data) &&
51 | array_key_exists("file_format", $this->data)) {
52 | $this->video_id = $this->data['video_id'];
53 | $this->video_url = $this->data['video_url'];
54 | $this->start_time = $this->data['start_time'];
55 | $this->end_time = $this->data['end_time'];
56 | $this->format_type = $this->data['file_format'];
57 |
58 | if (!is_numeric($this->start_time) || !is_numeric($this->end_time)) {
59 | component_log(ERROR, EC_OK, " EC_SYSTEM_INVALID_PARA error");
60 | return EC_SYSTEM_INVALID_PARA;
61 | }
62 | } else {
63 | component_log(ERROR, EC_OK, " EC_SYSTEM_INVALID_PARA error");
64 | return EC_SYSTEM_INVALID_PARA;
65 | }
66 | }
67 |
68 | $config = getConf('ROUTE.DB');
69 | $this->dao_live = new dao_live($config['HOST'], $config['PORT'], $config['USER'], $config['PASSWD'], $config['DBNAME']);
70 | return 0;
71 | }
72 |
73 | public function process()
74 | {
75 | component_log(INFO, EC_OK, "callback args=" . var_export($this->data, true));
76 | $ret = $this->init();
77 | if ($ret == 0) {
78 | $stream_id = $this->stream_id;
79 | if ($this->event_type == 100) {
80 | $duration = $this->end_time - $this->start_time;
81 | if ($duration > TAPE_DURATION_TIME) {
82 | $ret = $this->dao_live->addTapeFile($stream_id,
83 | $this->video_id,
84 | $this->video_url,
85 | $this->start_time,
86 | $this->end_time,
87 | $this->format_type);
88 | } else {
89 | $ret = 0;
90 | component_log(ERROR, EC_OK, "tape duration too short:" . strval($duration) . "|" . $stream_id . "|" . $this->video_id);
91 | }
92 |
93 | }
94 | }
95 |
96 | $result = array(
97 | 'code' => $ret,
98 | );
99 | $json_result = json_encode($result);
100 | header("Content-Length:" . strlen($json_result));
101 | echo $json_result;
102 |
103 | component_log(INFO, EC_OK, "process result:" . $ret);
104 | }
105 | }
106 |
107 | //process
108 | $tapecallback = new tape_callback();
109 | $tapecallback->process();
110 | exit(0);
111 |
--------------------------------------------------------------------------------
/common/AbstractInterface.php:
--------------------------------------------------------------------------------
1 | _interfaceName;
26 | }
27 |
28 | /**
29 | * @return the $_retValue
30 | */
31 | public function getRetValue()
32 | {
33 | return $this->_retValue;
34 | }
35 |
36 | /**
37 | * @return the $_retMsg
38 | */
39 | public function getRetMsg()
40 | {
41 | return $this->_retMsg;
42 | }
43 |
44 | /**
45 | * @return the $_data
46 | */
47 | public function getData()
48 | {
49 | return $this->_data;
50 | }
51 |
52 | /**
53 | * @param field_type $_interfaceName
54 | */
55 | public function setInterfaceName($_interfaceName)
56 | {
57 | $this->_interfaceName = $_interfaceName;
58 | }
59 |
60 | /**
61 | * @param field_type $_retValue
62 | */
63 | public function setRetValue($_retValue)
64 | {
65 | $this->_retValue = $_retValue;
66 | }
67 |
68 | /**
69 | * @param field_type $_retMsg
70 | */
71 | public function setRetMsg($_retMsg)
72 | {
73 | $this->_retMsg = $_retMsg;
74 | }
75 |
76 | /**
77 | * @param field_type $_data
78 | */
79 | public function setData($_data)
80 | {
81 | $this->_data = $_data;
82 | }
83 |
84 | /**
85 | *
86 | * 加载需要用到的对象
87 | */
88 | abstract public function initialize();
89 | /**
90 | *
91 | * 输入校验
92 | * @param array $args 输入参数
93 | */
94 | abstract public function verifyInput(&$args);
95 |
96 | /**
97 | *
98 | * 输入校验
99 | * @param array $args 输入参数
100 | * @param String $Sign 签名
101 | */
102 | abstract public function verifySign(&$args, $Sign);
103 |
104 | /**
105 | *
106 | * 请求处理
107 | */
108 | abstract public function process();
109 |
110 | public function renderOutput()
111 | {
112 | return json_encode(
113 | array(
114 | "code" => $this->_retValue,
115 | "message" => genErrMsg($this->_retValue, $this->_retMsg),
116 | "data" => (object) $this->_data,
117 | )
118 | );
119 | }
120 |
121 | public function setLogAppIdAndChannelId($app_id, $channel_id = "")
122 | {
123 | MiniLog::instance(ROOT_PATH . "/log/")->setAppIdAndChannelId($app_id, $channel_id);
124 | }
125 |
126 | public function _verifyInput(&$args, $rules)
127 | {
128 | if ($args == null && $rules == null) {
129 | return true;
130 | }
131 | $req = $args;
132 | $result = ParamChecker::getInstance()->checkParam($rules, $req);
133 | if (!$result['result']) {
134 | $this->_retValue = EC_INVALID_PARAM;
135 | $this->_retMsg = ParaStrFilter($result['msg']);
136 | return false;
137 | }
138 | $keys = array_keys($rules);
139 | extract($req);
140 | $this->_args = compact($keys);
141 |
142 | return true;
143 | }
144 |
145 | public function _verifySign(&$args, $Sign)
146 | {
147 | //return true;
148 | $data = json_decode($args, true);
149 | $userid = "";
150 | if (isset($data['userid'])) {
151 | $userid = $data['userid'];
152 | }
153 |
154 | $session = redis_cache::instance()->get($userid);
155 |
156 | if ($session && isset($session['token'])) {
157 | $token = $session['token'];
158 | $localsign = md5($token . md5($args));
159 | if (strcmp($Sign, $localsign) == 0) {
160 | return true;
161 | }
162 | }
163 | return false;
164 | }
165 |
166 | }
167 |
--------------------------------------------------------------------------------
/common/Common.php:
--------------------------------------------------------------------------------
1 | loadInc(CONFIG_FILE);
23 | return ConfFactory::$conf;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/common/ErrorCode.php:
--------------------------------------------------------------------------------
1 | "OK",
24 | EC_BAD_REQUEST => "Bad Request",
25 | EC_SIGN_ERROR => "Invalid Token",
26 | EC_INVALID_PARAM => "Invalid Param",
27 | EC_DATABASE_ERROR => "Internal Server Error(db operate error)",
28 | EC_UPDATE_ERROR => "update error",
29 | EC_USER_EXIST => "user exist",
30 | EC_USER_NOT_EXIST => "user not exist",
31 | EC_USER_PWD_ERROR => "password error",
32 | EC_SYSTEM_INVALID_JSON_FORMAT => "http post body is empty or invalid json format in post body from client!",
33 | EC_SYSTEM_INVALID_PARA => "request para error",
34 | EC_SYSTEM_FREQUECY => "frequency control",
35 |
36 | );
37 |
38 | if ($errorMsg == "") {
39 | return $errMsg[$errCode];
40 | }
41 |
42 | return $errMsg[$errCode] . " | " . $errorMsg;
43 | }
44 |
--------------------------------------------------------------------------------
/common/GlobalDefine.php:
--------------------------------------------------------------------------------
1 | checkParam($rules, $args);
11 | }
12 |
13 | define("DEBUG", "DEBUG");
14 | define("INFO", "INFO");
15 | define("ERROR", "ERROR");
16 | define("STAT", "STAT");
17 |
18 | function instance($interfaceName)
19 | {
20 | //$tmp = explode("_", $interfaceName);
21 | $dir = '';
22 | //for($i = 0; $i < count($tmp) -1; $i++) {
23 | // $dir = $dir.'/'.strtolower($tmp[$i]);
24 | //}
25 |
26 | $file_name = dirname(__FILE__) . '/../interface/' . $dir . '/' . $interfaceName . '.php';
27 | if (file_exists($file_name)) {
28 | require_once $file_name;
29 | if (!class_exists($interfaceName)) {
30 | interface_log(ERROR, 0, "invalid interfaceName of " . $interfaceName);
31 | return null;
32 | } else {
33 | return new $interfaceName();
34 | }
35 | } else {
36 | interface_log(ERROR, 0, "invalid fileName of $file_name");
37 | return null;
38 | }
39 | }
40 |
41 | function isLogLevelOff($logLevel)
42 | {
43 | $swithFile = ROOT_PATH . '/log/' . 'NO_' . $logLevel;
44 | if (file_exists($swithFile)) {
45 | return true;
46 | } else {
47 | return false;
48 | }
49 | }
50 |
51 | function _log($confName, $logLevel, $errorCode, $logMessage = "no error msg")
52 | {
53 | if (isLogLevelOff($logLevel)) {
54 | return;
55 | }
56 |
57 | $st = debug_backtrace();
58 |
59 | $function = ''; //璋冪敤interface_log/web_log鐨勫嚱鏁板悕
60 | $file = ''; //璋冪敤interface_log/web_log鐨勬枃浠跺悕
61 | $line = ''; //璋冪敤interface_log/web_log鐨勮鍙�
62 | foreach ($st as $item) {
63 | if ($file) {
64 | $function = $item['function'];
65 | break;
66 | }
67 | if (substr($item['function'], -4) == '_log' && strlen($item['function']) > 4) {
68 | $file = $item['file'];
69 | $line = $item['line'];
70 | }
71 | }
72 |
73 | $function = $function ? $function : 'main';
74 |
75 | $file = explode("/", rtrim($file, '/'));
76 | $file = $file[count($file) - 1];
77 | $prefix = "[$file][$function][$line][$logLevel][$errorCode] ";
78 | //if($logLevel == INFO || $logLevel == STAT) {
79 | // $prefix = "[$logLevel]" ;
80 | //}
81 | if ($errorCode) {
82 | $logMessage = genErrMsg($errorCode, $logMessage);
83 | }
84 |
85 | $logFileName = $confName . "_" . strtolower($logLevel);
86 | MiniLog::instance(ROOT_PATH . "/log/")->log($logFileName, $prefix . $logMessage);
87 | if (isLogLevelOff("DEBUG") || $logLevel == "DEBUG") {
88 | return;
89 | } else {
90 | MiniLog::instance(ROOT_PATH . "/log/")->log($confName . "_" . "debug", $prefix . $logMessage);
91 | }
92 | }
93 |
94 | function interface_log($logLevel, $errorCode, $logMessage = "no error msg")
95 | {
96 | _log('interface', $logLevel, $errorCode, $logMessage);
97 | }
98 |
99 | function component_log($logLevel, $errorCode, $logMessage = "no error msg")
100 | {
101 | _log('component', $logLevel, $errorCode, $logMessage);
102 | }
103 |
104 | function mysql_log($logLevel, $errorCode, $logMessage = "no error msg")
105 | {
106 | _log('mysql', $logLevel, $errorCode, $logMessage);
107 | }
108 |
109 | function init_log($args)
110 | {
111 | if (array_key_exists("eventId", $args) && array_key_exists("timestamp", $args)) {
112 | MiniLog::instance(ROOT_PATH . "/log/")->setRequestInfo($args["eventId"], $args["timestamp"], $args["interface"]["interfaceName"]);
113 | }
114 | }
115 |
116 | function parseInterfaceName($args)
117 | {
118 | if (array_key_exists("Action", $args)) {
119 | return $args["Action"];
120 | }
121 |
122 | return null;
123 | }
124 |
125 | function getConf($key)
126 | {
127 | $conf = ConfFactory::getInstance();
128 | $keyArr = explode('.', $key);
129 | if (false === $keyArr) {
130 | return '';
131 | } else {
132 | $keyStr = '';
133 | foreach ($keyArr as $k => $v) {
134 | if ($k >= 2) {
135 | unset($keyArr[0]);
136 | unset($keyArr[1]);
137 | $keyStr .= "['" . implode(".", $keyArr) . "']";
138 | break;
139 | }
140 | $keyStr .= "['" . $v . "']";
141 | }
142 | eval("\$keyStr = \$conf$keyStr ;");
143 | if (isset($keyStr)) {
144 | return $keyStr;
145 | }
146 | }
147 | return '';
148 | }
149 |
150 | function genErrorResult(
151 | $retValue, $retMsg, $retData = array()) {
152 | return json_encode(
153 | array(
154 | "code" => $retValue,
155 | "message" => $retMsg,
156 | "data" => $retData,
157 | )
158 | );
159 | }
160 |
161 | function getCurrentTime()
162 | {
163 | date_default_timezone_set('PRC');
164 | $secondTime = time();
165 | return date('Y-m-d H:i:s', $secondTime);
166 | }
167 |
168 | function getMillisecond($startTime = false)
169 | {
170 | $endTime = microtime(true) * 1000;
171 |
172 | if ($startTime !== false) {
173 | $consumed = $endTime - $startTime;
174 | return round($consumed);
175 | }
176 |
177 | return $endTime;
178 | }
179 |
180 | function getTimeSpan($startDateTime, $endDateTime)
181 | {
182 | $startTime = strtotime($startDateTime);
183 |
184 | $endTime = strtotime($endDateTime);
185 |
186 | return $endTime - $startTime;
187 | }
188 |
189 | function createTxTime($now_time)
190 | {
191 | // $now_time = time();
192 | $now_time += 3 * 60 * 60;
193 | return dechex($now_time);
194 | }
195 |
196 | function GetCallBackSign($txTime)
197 | {
198 | $md5_val = md5(API_KEY . strval($txTime));
199 | return $md5_val;
200 | }
201 |
202 | function ParaStrFilter($str)
203 | {
204 | $str = str_replace('<', '', $str);
205 | $str = str_replace('>', '', $str);
206 | $str = str_replace('"', '', $str);
207 | $str = str_replace('&', '', $str);
208 | return trim($str);
209 | }
210 |
211 | /*
212 | * @author christbao
213 | * @param monitor_id string .....monitor_id
214 | * @param value int ...monitor.
215 | * @param type int ...............:1 ...:2
216 | */
217 | function report_fc($monitor_id, $value, $type, $interface, $app_id, $service)
218 | {
219 | $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
220 | socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 5000));
221 | socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 0, "usec" => 5000));
222 | if ($type == 1) {
223 | $arr = array('method' => 'Attr_API', 'id' => $monitor_id, 'value' => $value, 'fc' => array
224 | (
225 | 'service' => $service, 'appid' => $app_id, 'interface' => $interface,
226 | ),
227 | );
228 | } else {
229 | $arr = array('method' => 'Attr_API_Set', 'id' => $monitor_id, 'value' => $value, 'fc' => array
230 | (
231 | 'service' => $service, 'appid' => $app_id, 'interface' => $interface,
232 | ),
233 | );
234 | }
235 | $msg = json_encode($arr);
236 | $len = strlen($msg);
237 | socket_sendto($sock, $msg, $len, 0, '127.0.0.1', 14000);
238 | $buf = '';
239 | if (false !== ($bytes = socket_recv($sock, $buf, 2048, MSG_WAITALL))) {
240 | component_log(ERROR, $ret, "Read $bytes bytes from socket_recv(). Closing socket...");
241 | } else {
242 | component_log(ERROR, $ret, "socket_recv() failed; reason: " . socket_strerror(socket_last_error($sock)) . "\n");
243 | }
244 | socket_close($sock);
245 | $data = json_decode($buf, true);
246 | if (!$data) {
247 | component_log(ERROR, $ret, "json decode fail,bypass");
248 | return true;
249 | }
250 |
251 | if ($data['fc']['errcode'] == 0) {
252 | return true;
253 | } else {
254 | return false;
255 | }
256 |
257 | }
258 |
--------------------------------------------------------------------------------
/common/Ini.php:
--------------------------------------------------------------------------------
1 | _conf = array();
37 | $this->_confInc = $this->loadFile($file);
38 |
39 | $this->_conf['PROJECT'] = $this->_confInc;
40 |
41 | if (isset($this->_confInc['COMMON']) && isset($this->_confInc['COMMON']['INC'])) {
42 | $inc = $this->_confInc['COMMON']['INC'];
43 | } else {
44 | $inc = '';
45 | }
46 |
47 | $conf = array();
48 | if (!empty($this->_confInc)) {
49 | if (isset($this->_confInc[$inc]) && !empty($this->_confInc[$inc])) {
50 | foreach ($this->_confInc[$inc] as $k => $v) {
51 | $pattern = "%(#|;|(//)).*%";
52 | $v = preg_replace($pattern, "", $v);
53 | $v = trim($v);
54 | $k = trim($k);
55 | $this->_confFile[$k] = $v; //后者会覆盖前者
56 | $this->_conf[$k] = $this->loadFile(ROOT_PATH . '/' . $v, $process_sections);
57 | }
58 | }
59 | }
60 | return $this->_conf;
61 | }
62 |
63 | /**
64 | * 获取配置项
65 | *
66 | * @params string $key key字符串,规则是k1.k2.k3,则表示引用配置$conf中的$conf[inc中的key][section作为key][真正的key]
67 | * @return mix 根据配置的具体情况,可能返回字符串,也可能返回数组
68 | */
69 | public function get($key)
70 | {
71 | $keyArr = explode('.', $key);
72 | if (false === $keyArr) {
73 | return '';
74 | } else {
75 | $keyStr = '';
76 | foreach ($keyArr as $k => $v) {
77 | if ($k >= 2) {
78 | unset($keyArr[0]);
79 | unset($keyArr[1]);
80 | $keyStr .= "['" . implode(".", $keyArr) . "']";
81 | break;
82 | }
83 | $keyStr .= "['" . $v . "']";
84 | }
85 | eval("\$keyStr = \$this->_conf$keyStr ;");
86 | if (isset($keyStr)) {
87 | return $keyStr;
88 | }
89 | }
90 | return '';
91 | }
92 |
93 | /**
94 | * 清空配置
95 | * -- 清空已经加载的配置
96 | */
97 | public function cleanUp()
98 | {
99 | $this->_confFile = array();
100 | $this->_conf = array();
101 | }
102 | };
103 |
104 | //end of script
105 |
--------------------------------------------------------------------------------
/common/MiniLog.php:
--------------------------------------------------------------------------------
1 | _path = $path;
20 | $this->_pid = getmypid();
21 | $this->_eventId = rand();
22 | $this->_timestamp = time();
23 | $this->_appid = -1;
24 | $this->_channelId = "";
25 | $this->_interfaceName = "";
26 | }
27 |
28 | private function __clone()
29 | {
30 |
31 | }
32 |
33 | public static function instance($path = '/tmp/')
34 | {
35 | if (!(self::$_instance instanceof self)) {
36 | self::$_instance = new self($path);
37 | }
38 |
39 | return self::$_instance;
40 | }
41 |
42 | public function setRequestInfo($eventId, $timestamp, $interfaceName)
43 | {
44 | $this->_eventId = $eventId;
45 | $this->_timestamp = $timestamp;
46 | $this->_interfaceName = $interfaceName;
47 | }
48 |
49 | public function setAppIdAndChannelId($app_id, $channel_id)
50 | {
51 | $this->_appid = $app_id;
52 | $this->_channelId = $channel_id;
53 | }
54 |
55 | private function getHandle($channelName)
56 | {
57 | if ($this->_handleArr[$channelName]) {
58 | return $this->_handleArr[$channelName];
59 | }
60 | date_default_timezone_set('PRC');
61 | $nowTime = time();
62 | $logSuffix = date('Ymd', $nowTime);
63 | $fileName = $this->_path . '/' . $channelName . $logSuffix . ".log.php"; // saxongao added
64 | $dirName = dirname($fileName);
65 | if (!is_dir($dirName)) {
66 | mkdir($dirName, 0777);
67 | chmod($dirName, 0777);
68 | }
69 | $str = urldecode("%E5%87%BA%E4%BA%8E%E5%AE%89%E5%85%A8%E8%80%83%E8%99%91%EF%BC%8C%E8%AF%B7%E7%94%A8%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91%E5%99%A8%E6%89%93%E5%BC%80%E6%9F%A5%E7%9C%8B%EF%BC%9B%");
70 | $safeString = file_exists($fileName) ? false : "\n