Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
01c69a63
T
TDengine
项目概览
taosdata
/
TDengine
1 年多 前同步成功
通知
1185
Star
22016
Fork
4786
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
01c69a63
编写于
9月 12, 2020
作者:
S
Shengliang Guan
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
TD-1225 rename files
上级
11aed420
变更
24
隐藏空白更改
内联
并排
Showing
24 changed file
with
60 addition
and
250 deletion
+60
-250
src/plugins/http/inc/ehttp_util_string.h
src/plugins/http/inc/ehttp_util_string.h
+0
-13
src/plugins/http/inc/httpGcHandle.h
src/plugins/http/inc/httpGcHandle.h
+0
-0
src/plugins/http/inc/httpGcJson.h
src/plugins/http/inc/httpGcJson.h
+0
-0
src/plugins/http/inc/httpGzip.h
src/plugins/http/inc/httpGzip.h
+0
-0
src/plugins/http/inc/httpInt.h
src/plugins/http/inc/httpInt.h
+1
-2
src/plugins/http/inc/httpParser.h
src/plugins/http/inc/httpParser.h
+12
-3
src/plugins/http/inc/httpRestHandle.h
src/plugins/http/inc/httpRestHandle.h
+0
-0
src/plugins/http/inc/httpRestJson.h
src/plugins/http/inc/httpRestJson.h
+0
-0
src/plugins/http/inc/httpTgHandle.h
src/plugins/http/inc/httpTgHandle.h
+0
-0
src/plugins/http/inc/httpTgJson.h
src/plugins/http/inc/httpTgJson.h
+0
-0
src/plugins/http/src/ehttp_util_string.c
src/plugins/http/src/ehttp_util_string.c
+0
-27
src/plugins/http/src/httpContext.c
src/plugins/http/src/httpContext.c
+2
-3
src/plugins/http/src/httpGcHandle.c
src/plugins/http/src/httpGcHandle.c
+3
-3
src/plugins/http/src/httpGcJson.c
src/plugins/http/src/httpGcJson.c
+2
-2
src/plugins/http/src/httpGzip.c
src/plugins/http/src/httpGzip.c
+1
-4
src/plugins/http/src/httpParser.c
src/plugins/http/src/httpParser.c
+27
-13
src/plugins/http/src/httpRestHandle.c
src/plugins/http/src/httpRestHandle.c
+2
-2
src/plugins/http/src/httpRestJson.c
src/plugins/http/src/httpRestJson.c
+2
-2
src/plugins/http/src/httpServer.c
src/plugins/http/src/httpServer.c
+1
-3
src/plugins/http/src/httpSystem.c
src/plugins/http/src/httpSystem.c
+3
-3
src/plugins/http/src/httpTgHandle.c
src/plugins/http/src/httpTgHandle.c
+2
-2
src/plugins/http/src/httpTgJson.c
src/plugins/http/src/httpTgJson.c
+2
-2
src/util/inc/elog.h
src/util/inc/elog.h
+0
-71
src/util/src/elog.c
src/util/src/elog.c
+0
-95
未找到文件。
src/plugins/http/inc/ehttp_util_string.h
已删除
100644 → 0
浏览文件 @
11aed420
#ifndef HTTP_UTIL_STRING
#define HTTP_UTIL_STRING
typedef
struct
HttpUtilString
{
char
*
str
;
size_t
len
;
}
HttpUtilString
;
void
httpParserCleanupString
(
HttpUtilString
*
str
);
int32_t
httpParserAppendString
(
HttpUtilString
*
str
,
const
char
*
s
,
int32_t
len
);
void
httpParserClearString
(
HttpUtilString
*
str
);
#endif
src/plugins/http/inc/
g
cHandle.h
→
src/plugins/http/inc/
httpG
cHandle.h
浏览文件 @
01c69a63
文件已移动
src/plugins/http/inc/
g
cJson.h
→
src/plugins/http/inc/
httpG
cJson.h
浏览文件 @
01c69a63
文件已移动
src/plugins/http/inc/
ehttp_g
zip.h
→
src/plugins/http/inc/
httpG
zip.h
浏览文件 @
01c69a63
文件已移动
src/plugins/http/inc/httpInt.h
浏览文件 @
01c69a63
...
...
@@ -27,8 +27,7 @@
#include "httpCode.h"
#include "httpLog.h"
#include "httpJson.h"
#include "ehttp_parser.h"
#include "httpParser.h"
#define HTTP_MAX_CMD_SIZE 1024
#define HTTP_MAX_BUFFER_SIZE 1024*1024
...
...
src/plugins/http/inc/
ehttp_p
arser.h
→
src/plugins/http/inc/
httpP
arser.h
浏览文件 @
01c69a63
#ifndef HTTP_PARSER_H
#define HTTP_PARSER_H
#include "ehttp_util_string.h"
#include "ehttp_gzip.h"
#include "httpGzip.h"
struct
HttpContext
;
...
...
@@ -25,6 +24,11 @@ typedef enum HTTP_PARSER_STATE {
HTTP_PARSER_ERROR
,
}
HTTP_PARSER_STATE
;
typedef
struct
HttpParserString
{
char
*
str
;
size_t
len
;
}
HttpParserString
;
typedef
struct
HttpParserStatusObj
{
int32_t
status_code
;
const
char
*
status_desc
;
...
...
@@ -77,11 +81,16 @@ typedef struct HttpParserObj {
size_t
received_chunk_size
;
size_t
received_size
;
ehttp_gzip_t
*
gzip
;
Http
Util
String
str
;
Http
Parser
String
str
;
HTTP_PARSER_STATE
*
stacks
;
size_t
stacks_count
;
}
HttpParserObj
;
void
httpParserCleanupString
(
HttpParserString
*
str
);
int32_t
httpParserAppendString
(
HttpParserString
*
str
,
const
char
*
s
,
int32_t
len
);
void
httpParserClearString
(
HttpParserString
*
str
);
HttpParserObj
*
httpParserCreate
(
HttpParserCallbackObj
callbacks
,
HttpParserConfObj
conf
,
void
*
arg
);
void
httpParserDestroy
(
HttpParserObj
*
parser
);
int32_t
httpParserBuf
(
struct
HttpContext
*
pContext
,
HttpParserObj
*
parser
,
const
char
*
buf
,
int32_t
len
);
...
...
src/plugins/http/inc/
r
estHandle.h
→
src/plugins/http/inc/
httpR
estHandle.h
浏览文件 @
01c69a63
文件已移动
src/plugins/http/inc/
r
estJson.h
→
src/plugins/http/inc/
httpR
estJson.h
浏览文件 @
01c69a63
文件已移动
src/plugins/http/inc/
t
gHandle.h
→
src/plugins/http/inc/
httpT
gHandle.h
浏览文件 @
01c69a63
文件已移动
src/plugins/http/inc/
t
gJson.h
→
src/plugins/http/inc/
httpT
gJson.h
浏览文件 @
01c69a63
文件已移动
src/plugins/http/src/ehttp_util_string.c
已删除
100644 → 0
浏览文件 @
11aed420
#include "os.h"
#include "ehttp_util_string.h"
void
httpParserCleanupString
(
HttpUtilString
*
str
)
{
free
(
str
->
str
);
str
->
str
=
NULL
;
str
->
len
=
0
;
}
int32_t
httpParserAppendString
(
HttpUtilString
*
str
,
const
char
*
s
,
int32_t
len
)
{
int32_t
n
=
str
->
len
;
char
*
p
=
(
char
*
)
realloc
(
str
->
str
,
n
+
len
+
1
);
if
(
!
p
)
return
-
1
;
strncpy
(
p
+
n
,
s
,
len
);
p
[
n
+
len
]
=
'\0'
;
str
->
str
=
p
;
str
->
len
=
n
+
len
;
return
0
;
}
void
httpParserClearString
(
HttpUtilString
*
str
)
{
if
(
str
->
str
)
{
str
->
str
[
0
]
=
'\0'
;
str
->
len
=
0
;
}
}
src/plugins/http/src/httpContext.c
浏览文件 @
01c69a63
...
...
@@ -27,7 +27,6 @@
#include "httpSql.h"
#include "httpSession.h"
#include "httpContext.h"
#include "elog.h"
extern
bool
httpGetHttpMethod
(
HttpContext
*
pContext
);
extern
bool
httpParseURL
(
HttpContext
*
pContext
);
...
...
@@ -144,8 +143,8 @@ HttpContext *httpCreateContext(int32_t fd) {
HttpContext
*
httpGetContext
(
void
*
ptr
)
{
uint64_t
handleVal
=
(
uint64_t
)
ptr
;
HttpContext
**
ppContext
=
taosCacheAcquireByKey
(
tsHttpServer
.
contextCache
,
&
handleVal
,
sizeof
(
HttpContext
*
));
EQ_
ASSERT
(
ppContext
);
EQ_
ASSERT
(
*
ppContext
);
ASSERT
(
ppContext
);
ASSERT
(
*
ppContext
);
if
(
ppContext
)
{
HttpContext
*
pContext
=
*
ppContext
;
...
...
src/plugins/http/src/
g
cHandle.c
→
src/plugins/http/src/
httpG
cHandle.c
浏览文件 @
01c69a63
...
...
@@ -15,11 +15,11 @@
#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "cJSON.h"
#include "httpLog.h"
#include "gcHandle.h"
#include "gcJson.h"
#include "taosdef.h"
#include "httpGcHandle.h"
#include "httpGcJson.h"
static
HttpDecodeMethod
gcDecodeMethod
=
{
"grafana"
,
gcProcessRequest
};
static
HttpEncodeMethod
gcHeartBeatMethod
=
{
...
...
src/plugins/http/src/
g
cJson.c
→
src/plugins/http/src/
httpG
cJson.c
浏览文件 @
01c69a63
...
...
@@ -15,8 +15,8 @@
#define _DEFAULT_SOURCE
#include "os.h"
#include "
g
cHandle.h"
#include "
g
cJson.h"
#include "
httpG
cHandle.h"
#include "
httpG
cJson.h"
#include "httpJson.h"
#include "httpResp.h"
...
...
src/plugins/http/src/
ehttp_g
zip.c
→
src/plugins/http/src/
httpG
zip.c
浏览文件 @
01c69a63
#include "ehttp_gzip.h"
#include "os.h"
#include "zlib.h"
#include <stdlib.h>
#include "httpGzip.h"
typedef
enum
{
EHTTP_GZIP_INITING
,
...
...
src/plugins/http/src/
ehttp_p
arser.c
→
src/plugins/http/src/
httpP
arser.c
浏览文件 @
01c69a63
#include "os.h"
#include "httpLog.h"
#include "httpContext.h"
#include "ehttp_util_string.h"
#include "ehttp_parser.h"
#include "ehttp_gzip.h"
#include "ehttp_util_string.h"
#include "elog.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "httpParser.h"
#include "httpGzip.h"
static
HttpParserStatusObj
status_codes
[]
=
{
{
100
,
"Continue"
},
...
...
@@ -213,7 +203,7 @@ void httpParserDestroy(HttpParserObj *parser) {
char
*
ehttp_parser_urldecode
(
const
char
*
enc
)
{
int
ok
=
1
;
Http
Util
String
str
=
{
0
};
Http
Parser
String
str
=
{
0
};
while
(
*
enc
)
{
char
*
p
=
strchr
(
enc
,
'%'
);
if
(
!
p
)
break
;
...
...
@@ -916,3 +906,27 @@ int32_t httpParserBuf(HttpContext *pContext, HttpParserObj *parser, const char *
return
ret
;
}
void
httpParserCleanupString
(
HttpParserString
*
str
)
{
free
(
str
->
str
);
str
->
str
=
NULL
;
str
->
len
=
0
;
}
int32_t
httpParserAppendString
(
HttpParserString
*
str
,
const
char
*
s
,
int32_t
len
)
{
int32_t
n
=
str
->
len
;
char
*
p
=
(
char
*
)
realloc
(
str
->
str
,
n
+
len
+
1
);
if
(
!
p
)
return
-
1
;
strncpy
(
p
+
n
,
s
,
len
);
p
[
n
+
len
]
=
'\0'
;
str
->
str
=
p
;
str
->
len
=
n
+
len
;
return
0
;
}
void
httpParserClearString
(
HttpParserString
*
str
)
{
if
(
str
->
str
)
{
str
->
str
[
0
]
=
'\0'
;
str
->
len
=
0
;
}
}
src/plugins/http/src/
r
estHandle.c
→
src/plugins/http/src/
httpR
estHandle.c
浏览文件 @
01c69a63
...
...
@@ -16,8 +16,8 @@
#define _DEFAULT_SOURCE
#include "os.h"
#include "httpLog.h"
#include "
r
estHandle.h"
#include "
r
estJson.h"
#include "
httpR
estHandle.h"
#include "
httpR
estJson.h"
static
HttpDecodeMethod
restDecodeMethod
=
{
"rest"
,
restProcessRequest
};
static
HttpDecodeMethod
restDecodeMethod2
=
{
"restful"
,
restProcessRequest
};
...
...
src/plugins/http/src/
r
estJson.c
→
src/plugins/http/src/
httpR
estJson.c
浏览文件 @
01c69a63
...
...
@@ -18,8 +18,8 @@
#include "tglobal.h"
#include "httpLog.h"
#include "httpJson.h"
#include "
r
estHandle.h"
#include "
r
estJson.h"
#include "
httpR
estHandle.h"
#include "
httpR
estJson.h"
void
restBuildSqlAffectRowsJson
(
HttpContext
*
pContext
,
HttpSqlCmd
*
cmd
,
int
affect_rows
)
{
JsonBuf
*
jsonBuf
=
httpMallocJsonBuf
(
pContext
);
...
...
src/plugins/http/src/httpServer.c
浏览文件 @
01c69a63
...
...
@@ -25,8 +25,6 @@
#include "httpResp.h"
#include "httpUtil.h"
#include "elog.h"
#ifndef EPOLLWAKEUP
#define EPOLLWAKEUP (1u << 29)
#endif
...
...
@@ -334,7 +332,7 @@ bool httpInitConnect() {
static
bool
httpReadData
(
HttpContext
*
pContext
)
{
HttpParser
*
pParser
=
&
pContext
->
parser
;
EQ_
ASSERT
(
!
pContext
->
parsed
);
ASSERT
(
!
pContext
->
parsed
);
if
(
!
pParser
->
parser
)
{
if
(
!
pParser
->
inited
)
{
...
...
src/plugins/http/src/httpSystem.c
浏览文件 @
01c69a63
...
...
@@ -27,9 +27,9 @@
#include "httpResp.h"
#include "httpHandle.h"
#include "httpQueue.h"
#include "
g
cHandle.h"
#include "
r
estHandle.h"
#include "
t
gHandle.h"
#include "
httpG
cHandle.h"
#include "
httpR
estHandle.h"
#include "
httpT
gHandle.h"
#ifndef _ADMIN
void
adminInitHandle
(
HttpServer
*
pServer
)
{}
...
...
src/plugins/http/src/
t
gHandle.c
→
src/plugins/http/src/
httpT
gHandle.c
浏览文件 @
01c69a63
...
...
@@ -19,8 +19,8 @@
#include "taosdef.h"
#include "taosmsg.h"
#include "httpInt.h"
#include "
t
gHandle.h"
#include "
t
gJson.h"
#include "
httpT
gHandle.h"
#include "
httpT
gJson.h"
#include "cJSON.h"
/*
...
...
src/plugins/http/src/
t
gJson.c
→
src/plugins/http/src/
httpT
gJson.c
浏览文件 @
01c69a63
...
...
@@ -19,8 +19,8 @@
#include "httpLog.h"
#include "httpJson.h"
#include "httpResp.h"
#include "
t
gHandle.h"
#include "
t
gJson.h"
#include "
httpT
gHandle.h"
#include "
httpT
gJson.h"
void
tgInitQueryJson
(
HttpContext
*
pContext
)
{
JsonBuf
*
jsonBuf
=
httpMallocJsonBuf
(
pContext
);
...
...
src/util/inc/elog.h
已删除
100644 → 0
浏览文件 @
11aed420
#ifndef _elog_h_8897be44_dda8_45b6_9d37_8d8691cb05fb_
#define _elog_h_8897be44_dda8_45b6_9d37_8d8691cb05fb_
#include <stdio.h>
typedef
enum
{
ELOG_DEBUG
,
ELOG_INFO
,
ELOG_WARN
,
ELOG_ERROR
,
ELOG_CRITICAL
,
ELOG_VERBOSE
,
ELOG_ABORT
,
}
ELOG_LEVEL
;
void
elog_set_level
(
ELOG_LEVEL
base
);
// only log those not less than base
void
elog_set_thread_name
(
const
char
*
name
);
void
elog
(
ELOG_LEVEL
level
,
int
fd
,
const
char
*
file
,
int
line
,
const
char
*
func
,
const
char
*
fmt
,
...)
#ifdef __GNUC__
__attribute__
((
format
(
printf
,
6
,
7
)))
#endif
;
#define DLOG(fd, fmt, ...) elog(ELOG_DEBUG, fd, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define ILOG(fd, fmt, ...) elog(ELOG_INFO, fd, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define WLOG(fd, fmt, ...) elog(ELOG_WARN, fd, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define ELOG(fd, fmt, ...) elog(ELOG_ERROR, fd, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define CLOG(fd, fmt, ...) elog(ELOG_CRITICAL, fd, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define VLOG(fd, fmt, ...) elog(ELOG_VERBOSE, fd, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define ALOG(fd, fmt, ...) elog(ELOG_ABORT, fd, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define D(fmt, ...) elog(ELOG_DEBUG, fileno(stdout), __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define I(fmt, ...) elog(ELOG_INFO, fileno(stdout), __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define W(fmt, ...) elog(ELOG_WARN, fileno(stdout), __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define E(fmt, ...) elog(ELOG_ERROR, fileno(stdout), __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define C(fmt, ...) elog(ELOG_CRITICAL, fileno(stdout), __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define V(fmt, ...) elog(ELOG_VERBOSE, fileno(stdout), __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define A(fmt, ...) elog(ELOG_ABORT, fileno(stdout), __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
// NOTE: https://en.wikipedia.org/wiki/Fail-fast
// for the sake of simplicity, both implementation and usage,
// we'll follow `fail-fast` or `let-it-crash` philosophy.
// assertion in both debug/release build
#define EQ_ABORT(fmt, ...) A("Assertion failure: "fmt, ##__VA_ARGS__)
#define EQ_ASSERT(statement) do { \
if (statement) break; \
A("Assertion failure: %s", #statement); \
} while (0)
#define EQ_ASSERT_EXT(statement, fmt, ...) do { \
if (statement) break; \
A("Assertion failure: %s: "fmt, #statement, ##__VA_ARGS__); \
} while (0)
#define EQ_ASSERT_API0(statement) do { \
if (statement) break; \
A("Assertion failure: %s failed: [%d]%s", #statement, errno, strerror(errno)); \
} while (0)
#define EQ_ASSERT_API(api) do { \
A("Assertion failure: %s failed: [%d]%s", #api, errno, strerror(errno)); \
} while (0)
#endif // _elog_h_8897be44_dda8_45b6_9d37_8d8691cb05fb_
src/util/src/elog.c
已删除
100644 → 0
浏览文件 @
11aed420
#include "elog.h"
#include <libgen.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
#define gettid() syscall(__NR_gettid)
static
ELOG_LEVEL
elog_level_base
=
ELOG_DEBUG
;
static
__thread
long
elog_thread_id
;
static
__thread
char
elog_thread_name
[
24
]
=
{
0
};
void
elog_set_level
(
ELOG_LEVEL
base
)
{
elog_level_base
=
base
;
}
void
elog_set_thread_name
(
const
char
*
name
)
{
elog_thread_id
=
gettid
();
snprintf
(
elog_thread_name
,
sizeof
(
elog_thread_name
),
"%s"
,
name
);
}
void
elog
(
ELOG_LEVEL
level
,
int
fd
,
const
char
*
file
,
int
line
,
const
char
*
func
,
const
char
*
fmt
,
...)
{
if
(
level
<
elog_level_base
)
return
;
if
(
fd
==
-
1
)
return
;
if
(
elog_thread_name
[
0
]
==
'\0'
)
{
elog_set_thread_name
(
"unknown"
);
}
char
*
p
;
int
n
;
size_t
bytes
;
char
buf
[
4096
];
snprintf
(
buf
,
sizeof
(
buf
),
"%s"
,
file
);
char
fn
[
1024
];
snprintf
(
fn
,
sizeof
(
fn
),
"%s"
,
basename
(
buf
));
char
C
;
switch
(
level
)
{
case
ELOG_DEBUG
:
C
=
'D'
;
break
;
case
ELOG_INFO
:
C
=
'I'
;
break
;
case
ELOG_WARN
:
C
=
'W'
;
break
;
case
ELOG_ERROR
:
C
=
'E'
;
break
;
case
ELOG_CRITICAL
:
C
=
'C'
;
break
;
case
ELOG_VERBOSE
:
C
=
'V'
;
break
;
case
ELOG_ABORT
:
C
=
'A'
;
break
;
default:
return
;
}
struct
tm
t
;
struct
timeval
tv
;
if
(
gettimeofday
(
&
tv
,
NULL
))
return
;
if
(
!
localtime_r
(
&
tv
.
tv_sec
,
&
t
))
return
;
p
=
buf
;
bytes
=
sizeof
(
buf
);
n
=
snprintf
(
p
,
bytes
,
"%c[%02d/%02d %02d:%02d:%02d.%06ld][%06ld]: =="
,
C
,
t
.
tm_mon
+
1
,
t
.
tm_mday
,
t
.
tm_hour
,
t
.
tm_min
,
t
.
tm_sec
,
tv
.
tv_usec
,
elog_thread_id
);
p
+=
n
;
bytes
-=
n
;
va_list
arg
;
va_start
(
arg
,
fmt
);
if
(
bytes
>
0
)
{
n
=
vsnprintf
(
p
,
bytes
,
fmt
,
arg
);
p
+=
n
;
bytes
-=
n
;
}
va_end
(
arg
);
if
(
bytes
>
0
)
{
n
=
snprintf
(
p
,
bytes
,
"== t:%s#%s[%d]#%s()"
,
elog_thread_name
,
fn
,
line
,
func
);
}
dprintf
(
fd
,
"%s
\n
"
,
buf
);
if
(
level
==
ELOG_ABORT
)
{
abort
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录