Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Turbo码先生
redis
提交
a7780f71
R
redis
项目概览
Turbo码先生
/
redis
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
redis
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a7780f71
编写于
2月 25, 2019
作者:
A
antirez
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'gopher' into unstable
上级
21f92e9e
40a01a94
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
174 addition
and
1 deletion
+174
-1
redis.conf
redis.conf
+55
-0
src/Makefile
src/Makefile
+1
-1
src/config.c
src/config.c
+8
-0
src/gopher.c
src/gopher.c
+97
-0
src/networking.c
src/networking.c
+8
-0
src/server.c
src/server.c
+1
-0
src/server.h
src/server.h
+4
-0
未找到文件。
redis.conf
浏览文件 @
a7780f71
...
...
@@ -1183,6 +1183,61 @@ latency-monitor-threshold 0
# specify at least one of K or E, no events will be delivered.
notify
-
keyspace
-
events
""
############################### GOPHER SERVER #################################
# Redis contains an implementation of the Gopher protocol, as specified in
# the RFC 1436 (https://www.ietf.org/rfc/rfc1436.txt).
#
# The Gopher protocol was very popular in the late '90s. It is an alternative
# to the web, and the implementation both server and client side is so simple
# that the Redis server has just 100 lines of code in order to implement this
# support.
#
# What do you do with Gopher nowadays? Well Gopher never *really* died, and
# lately there is a movement in order for the Gopher more hierarchical content
# composed of just plain text documents to be resurrected. Some want a simpler
# internet, others believe that the mainstream internet became too much
# controlled, and it's cool to create an alternative space for people that
# want a bit of fresh air.
#
# Anyway for the 10nth birthday of the Redis, we gave it the Gopher protocol
# as a gift.
#
# --- HOW IT WORKS? ---
#
# The Redis Gopher support uses the inline protocol of Redis, and specifically
# two kind of inline requests that were anyway illegal: an empty request
# or any request that starts with "/" (there are no Redis commands starting
# with such a slash). Normal RESP2/RESP3 requests are completely out of the
# path of the Gopher protocol implementation and are served as usually as well.
#
# If you open a connection to Redis when Gopher is enabled and send it
# a string like "/foo", if there is a key named "/foo" it is served via the
# Gopher protocol.
#
# In order to create a real Gopher "hole" (the name of a Gopher site in Gopher
# talking), you likely need a script like the following:
#
# https://github.com/antirez/gopher2redis
#
# --- SECURITY WARNING ---
#
# If you plan to put Redis on the internet in a publicly accessible address
# to server Gopher pages MAKE SURE TO SET A PASSWORD to the instance.
# Once a password is set:
#
# 1. The Gopher server (when enabled, not by default) will kill serve
# content via Gopher.
# 2. However other commands cannot be called before the client will
# authenticate.
#
# So use the 'requirepass' option to protect your instance.
#
# To enable Gopher support uncomment the following line and set
# the option from no (the default) to yes.
#
# gopher-enabled no
############################### ADVANCED CONFIG ###############################
# Hashes are encoded using a memory efficient data structure when they have a
...
...
src/Makefile
浏览文件 @
a7780f71
...
...
@@ -164,7 +164,7 @@ endif
REDIS_SERVER_NAME
=
redis-server
REDIS_SENTINEL_NAME
=
redis-sentinel
REDIS_SERVER_OBJ
=
adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o acl.o
REDIS_SERVER_OBJ
=
adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o acl.o
gopher.o
REDIS_CLI_NAME
=
redis-cli
REDIS_CLI_OBJ
=
anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o
REDIS_BENCHMARK_NAME
=
redis-benchmark
...
...
src/config.c
浏览文件 @
a7780f71
...
...
@@ -216,6 +216,10 @@ void loadServerConfigFromString(char *config) {
if
((
server
.
protected_mode
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"gopher-enabled"
)
&&
argc
==
2
)
{
if
((
server
.
gopher_enabled
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"port"
)
&&
argc
==
2
)
{
server
.
port
=
atoi
(
argv
[
1
]);
if
(
server
.
port
<
0
||
server
.
port
>
65535
)
{
...
...
@@ -1141,6 +1145,8 @@ void configSetCommand(client *c) {
#endif
}
config_set_bool_field
(
"protected-mode"
,
server
.
protected_mode
)
{
}
config_set_bool_field
(
"gopher-enabled"
,
server
.
gopher_enabled
)
{
}
config_set_bool_field
(
"stop-writes-on-bgsave-error"
,
server
.
stop_writes_on_bgsave_err
)
{
}
config_set_bool_field
(
...
...
@@ -1472,6 +1478,7 @@ void configGetCommand(client *c) {
config_get_bool_field
(
"activerehashing"
,
server
.
activerehashing
);
config_get_bool_field
(
"activedefrag"
,
server
.
active_defrag_enabled
);
config_get_bool_field
(
"protected-mode"
,
server
.
protected_mode
);
config_get_bool_field
(
"gopher-enabled"
,
server
.
gopher_enabled
);
config_get_bool_field
(
"repl-disable-tcp-nodelay"
,
server
.
repl_disable_tcp_nodelay
);
config_get_bool_field
(
"repl-diskless-sync"
,
...
...
@@ -2301,6 +2308,7 @@ int rewriteConfig(char *path) {
rewriteConfigYesNoOption
(
state
,
"activerehashing"
,
server
.
activerehashing
,
CONFIG_DEFAULT_ACTIVE_REHASHING
);
rewriteConfigYesNoOption
(
state
,
"activedefrag"
,
server
.
active_defrag_enabled
,
CONFIG_DEFAULT_ACTIVE_DEFRAG
);
rewriteConfigYesNoOption
(
state
,
"protected-mode"
,
server
.
protected_mode
,
CONFIG_DEFAULT_PROTECTED_MODE
);
rewriteConfigYesNoOption
(
state
,
"gopher-enabled"
,
server
.
gopher_enabled
,
CONFIG_DEFAULT_GOPHER_ENABLED
);
rewriteConfigClientoutputbufferlimitOption
(
state
);
rewriteConfigNumericalOption
(
state
,
"hz"
,
server
.
config_hz
,
CONFIG_DEFAULT_HZ
);
rewriteConfigYesNoOption
(
state
,
"aof-rewrite-incremental-fsync"
,
server
.
aof_rewrite_incremental_fsync
,
CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC
);
...
...
src/gopher.c
0 → 100644
浏览文件 @
a7780f71
/*
* Copyright (c) 2019, Salvatore Sanfilippo <antirez at gmail dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "server.h"
/* Emit an item in Gopher directory listing format:
* <type><descr><TAB><selector><TAB><hostname><TAB><port>
* If descr or selector are NULL, then the "(NULL)" string is used instead. */
void
addReplyGopherItem
(
client
*
c
,
const
char
*
type
,
const
char
*
descr
,
const
char
*
selector
,
const
char
*
hostname
,
int
port
)
{
sds
item
=
sdscatfmt
(
sdsempty
(),
"%s%s
\t
%s
\t
%s
\t
%i
\r\n
"
,
type
,
descr
,
selector
?
selector
:
"(NULL)"
,
hostname
?
hostname
:
"(NULL)"
,
port
);
addReplyProto
(
c
,
item
,
sdslen
(
item
));
sdsfree
(
item
);
}
/* This is called by processInputBuffer() when an inline request is processed
* with Gopher mode enabled, and the request happens to have zero or just one
* argument. In such case we get the relevant key and reply using the Gopher
* protocol. */
void
processGopherRequest
(
client
*
c
)
{
robj
*
keyname
=
c
->
argc
==
0
?
createStringObject
(
"/"
,
1
)
:
c
->
argv
[
0
];
robj
*
o
=
lookupKeyRead
(
c
->
db
,
keyname
);
/* If there is no such key, return with a Gopher error. */
if
(
o
==
NULL
||
o
->
type
!=
OBJ_STRING
)
{
char
*
errstr
;
if
(
o
==
NULL
)
errstr
=
"Error: no content at the specified key"
;
else
errstr
=
"Error: selected key type is invalid "
"for Gopher output"
;
addReplyGopherItem
(
c
,
"i"
,
errstr
,
NULL
,
NULL
,
0
);
addReplyGopherItem
(
c
,
"i"
,
"Redis Gopher server"
,
NULL
,
NULL
,
0
);
}
else
{
addReply
(
c
,
o
);
}
/* Cleanup, also make sure to emit the final ".CRLF" line. Note that
* the connection will be closed immediately after this because the client
* will be flagged with CLIENT_CLOSE_AFTER_REPLY, in accordance with the
* Gopher protocol. */
if
(
c
->
argc
==
0
)
decrRefCount
(
keyname
);
/* Note that in theory we should terminate the Gopher request with
* ".<CR><LF>" (called Lastline in the RFC) like that:
*
* addReplyProto(c,".\r\n",3);
*
* However after examining the current clients landscape, it's probably
* going to do more harm than good for several reasons:
*
* 1. Clients should not have any issue with missing .<CR><LF> as for
* specification, and in the real world indeed certain servers
* implementations never used to send the terminator.
*
* 2. Redis does not know if it's serving a text file or a binary file:
* at the same time clients will not remove the ".<CR><LF>" bytes at
* tne end when downloading a binary file from the server, so adding
* the "Lastline" terminator without knowing the content is just
* dangerous.
*
* 3. The utility gopher2redis.rb that we provide for Redis, and any
* other similar tool you may use as Gopher authoring system for
* Redis, can just add the "Lastline" when needed.
*/
}
src/networking.c
浏览文件 @
a7780f71
...
...
@@ -1548,6 +1548,14 @@ void processInputBuffer(client *c) {
if
(
c
->
reqtype
==
PROTO_REQ_INLINE
)
{
if
(
processInlineBuffer
(
c
)
!=
C_OK
)
break
;
/* If the Gopher mode and we got zero or one argument, process
* the request in Gopher mode. */
if
(
server
.
gopher_enabled
&&
(
c
->
argc
==
1
||
c
->
argc
==
0
))
{
processGopherRequest
(
c
);
resetClient
(
c
);
c
->
flags
|=
CLIENT_CLOSE_AFTER_REPLY
;
break
;
}
}
else
if
(
c
->
reqtype
==
PROTO_REQ_MULTIBULK
)
{
if
(
processMultibulkBuffer
(
c
)
!=
C_OK
)
break
;
}
else
{
...
...
src/server.c
浏览文件 @
a7780f71
...
...
@@ -2222,6 +2222,7 @@ void initServerConfig(void) {
server
.
ipfd_count
=
0
;
server
.
sofd
=
-
1
;
server
.
protected_mode
=
CONFIG_DEFAULT_PROTECTED_MODE
;
server
.
gopher_enabled
=
CONFIG_DEFAULT_GOPHER_ENABLED
;
server
.
dbnum
=
CONFIG_DEFAULT_DBNUM
;
server
.
verbosity
=
CONFIG_DEFAULT_VERBOSITY
;
server
.
maxidletime
=
CONFIG_DEFAULT_CLIENT_TIMEOUT
;
...
...
src/server.h
浏览文件 @
a7780f71
...
...
@@ -121,6 +121,7 @@ typedef long long mstime_t; /* millisecond time type. */
#define CONFIG_DEFAULT_UNIX_SOCKET_PERM 0
#define CONFIG_DEFAULT_TCP_KEEPALIVE 300
#define CONFIG_DEFAULT_PROTECTED_MODE 1
#define CONFIG_DEFAULT_GOPHER_ENABLED 0
#define CONFIG_DEFAULT_LOGFILE ""
#define CONFIG_DEFAULT_SYSLOG_ENABLED 0
#define CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR 1
...
...
@@ -1054,6 +1055,8 @@ struct redisServer {
dict
*
migrate_cached_sockets
;
/* MIGRATE cached sockets */
uint64_t
next_client_id
;
/* Next client unique ID. Incremental. */
int
protected_mode
;
/* Don't accept external connections. */
int
gopher_enabled
;
/* If true the server will reply to gopher
queries. Will still serve RESP2 queries. */
/* RDB / AOF loading information */
int
loading
;
/* We are loading data from disk if true */
off_t
loading_total_bytes
;
...
...
@@ -1511,6 +1514,7 @@ void setDeferredAttributeLen(client *c, void *node, long length);
void
setDeferredPushLen
(
client
*
c
,
void
*
node
,
long
length
);
void
processInputBuffer
(
client
*
c
);
void
processInputBufferAndReplicate
(
client
*
c
);
void
processGopherRequest
(
client
*
c
);
void
acceptHandler
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
void
acceptTcpHandler
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
void
acceptUnixHandler
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录