Updating server dependancies. (#7538)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8b9dbb8613
Коммит
b84736e9b6
4
Makefile
4
Makefile
@@ -80,7 +80,7 @@ endif
|
|||||||
# Prepares the enterprise build if exists. The IGNORE stuff is a hack to get the Makefile to execute the commands outside a target
|
# Prepares the enterprise build if exists. The IGNORE stuff is a hack to get the Makefile to execute the commands outside a target
|
||||||
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
||||||
IGNORE:=$(shell echo Enterprise build selected, preparing)
|
IGNORE:=$(shell echo Enterprise build selected, preparing)
|
||||||
IGNORE:=$(shell mkdir -p imports/)
|
IGNORE:=$(shell rm -f imports/imports.go)
|
||||||
IGNORE:=$(shell cp $(BUILD_ENTERPRISE_DIR)/imports/imports.go imports/)
|
IGNORE:=$(shell cp $(BUILD_ENTERPRISE_DIR)/imports/imports.go imports/)
|
||||||
IGNORE:=$(shell rm -f enterprise)
|
IGNORE:=$(shell rm -f enterprise)
|
||||||
IGNORE:=$(shell ln -s $(BUILD_ENTERPRISE_DIR) enterprise)
|
IGNORE:=$(shell ln -s $(BUILD_ENTERPRISE_DIR) enterprise)
|
||||||
@@ -465,7 +465,7 @@ clean: stop-docker
|
|||||||
rm -f ecover.out
|
rm -f ecover.out
|
||||||
rm -f *.out
|
rm -f *.out
|
||||||
rm -f *.test
|
rm -f *.test
|
||||||
rm -f imports.go
|
rm -f imports/imports.go
|
||||||
|
|
||||||
nuke: clean clean-docker
|
nuke: clean clean-docker
|
||||||
@echo BOOM
|
@echo BOOM
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/mattermost/platform/app"
|
|
||||||
"github.com/mattermost/platform/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestParseChannelArg(t *testing.T) {
|
|
||||||
if team, channel := parseChannelArg("channel"); team != "" {
|
|
||||||
t.Fatal("got incorrect team", team)
|
|
||||||
} else if channel != "channel" {
|
|
||||||
t.Fatal("got incorrect channel", channel)
|
|
||||||
}
|
|
||||||
|
|
||||||
if team, channel := parseChannelArg("team:channel"); team != "team" {
|
|
||||||
t.Fatal("got incorrect team", team)
|
|
||||||
} else if channel != "channel" {
|
|
||||||
t.Fatal("got incorrect channel", channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetChannelFromChannelArg(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
team := th.BasicTeam
|
|
||||||
channel := th.BasicChannel
|
|
||||||
|
|
||||||
if found := getChannelFromChannelArg(""); found != nil {
|
|
||||||
t.Fatal("shoudn't have gotten a channel", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelFromChannelArg(channel.Id); found == nil || found.Id != channel.Id {
|
|
||||||
t.Fatal("got incorrect channel", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelFromChannelArg(model.NewId()); found != nil {
|
|
||||||
t.Fatal("shouldn't have gotten a channel that doesn't exist", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelFromChannelArg(channel.Name); found != nil {
|
|
||||||
t.Fatal("shouldn't have gotten a channel by name without team", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelFromChannelArg(team.Id + ":" + channel.Name); found == nil || found.Id != channel.Id {
|
|
||||||
t.Fatal("got incorrect channel", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelFromChannelArg(team.Name + ":" + channel.Name); found == nil || found.Id != channel.Id {
|
|
||||||
t.Fatal("got incorrect channel", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelFromChannelArg(team.Name + ":" + channel.Id); found == nil || found.Id != channel.Id {
|
|
||||||
t.Fatal("got incorrect channel", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelFromChannelArg("notateam" + ":" + channel.Name); found != nil {
|
|
||||||
t.Fatal("shouldn't have gotten a channel by name on incorrect team", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelFromChannelArg(team.Name + ":" + "notachannel"); found != nil {
|
|
||||||
t.Fatal("shouldn't have gotten a channel that doesn't exist", found)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetChannelsFromChannelArg(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
team := th.BasicTeam
|
|
||||||
channel := th.BasicChannel
|
|
||||||
channel2 := th.CreateChannel(team)
|
|
||||||
|
|
||||||
if found := getChannelsFromChannelArgs([]string{}); len(found) != 0 {
|
|
||||||
t.Fatal("shoudn't have gotten any channels", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelsFromChannelArgs([]string{channel.Id}); len(found) == 1 && found[0].Id != channel.Id {
|
|
||||||
t.Fatal("got incorrect channel", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelsFromChannelArgs([]string{team.Name + ":" + channel2.Name}); len(found) == 1 && found[0].Id != channel2.Id {
|
|
||||||
t.Fatal("got incorrect channel", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelsFromChannelArgs([]string{team.Name + ":" + channel.Name, team.Name + ":" + channel2.Name}); len(found) != 2 {
|
|
||||||
t.Fatal("got incorrect number of channels", found)
|
|
||||||
} else if !(found[0].Id == channel.Id && found[1].Id == channel2.Id) && !(found[1].Id == channel.Id && found[0].Id == channel2.Id) {
|
|
||||||
t.Fatal("got incorrect channels", found[0], found[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelsFromChannelArgs([]string{channel.Id, channel2.Id}); len(found) != 2 {
|
|
||||||
t.Fatal("got incorrect number of channels", found)
|
|
||||||
} else if !(found[0].Id == channel.Id && found[1].Id == channel2.Id) && !(found[1].Id == channel.Id && found[0].Id == channel2.Id) {
|
|
||||||
t.Fatal("got incorrect channels", found[0], found[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getChannelsFromChannelArgs([]string{channel.Id, team.Name + ":" + channel2.Name}); len(found) != 2 {
|
|
||||||
t.Fatal("got incorrect number of channels", found)
|
|
||||||
} else if !(found[0].Id == channel.Id && found[1].Id == channel2.Id) && !(found[1].Id == channel.Id && found[0].Id == channel2.Id) {
|
|
||||||
t.Fatal("got incorrect channels", found[0], found[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/mattermost/platform/app"
|
|
||||||
"github.com/mattermost/platform/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetTeamFromTeamArg(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
team := th.BasicTeam
|
|
||||||
|
|
||||||
if found := getTeamFromTeamArg(""); found != nil {
|
|
||||||
t.Fatal("shoudn't have gotten a team", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getTeamFromTeamArg(model.NewId()); found != nil {
|
|
||||||
t.Fatal("shoudn't have gotten a team", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getTeamFromTeamArg(team.Id); found == nil || found.Id != team.Id {
|
|
||||||
t.Fatal("got incorrect team", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getTeamFromTeamArg(team.Name); found == nil || found.Id != team.Id {
|
|
||||||
t.Fatal("got incorrect team", found)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetTeamsFromTeamArg(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
team := th.BasicTeam
|
|
||||||
team2 := th.CreateTeam()
|
|
||||||
|
|
||||||
if found := getTeamsFromTeamArgs([]string{}); len(found) != 0 {
|
|
||||||
t.Fatal("shoudn't have gotten any teams", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getTeamsFromTeamArgs([]string{team.Id}); len(found) == 1 && found[0].Id != team.Id {
|
|
||||||
t.Fatal("got incorrect team", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getTeamsFromTeamArgs([]string{team2.Name}); len(found) == 1 && found[0].Id != team2.Id {
|
|
||||||
t.Fatal("got incorrect team", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getTeamsFromTeamArgs([]string{team.Name, team2.Id}); len(found) != 2 {
|
|
||||||
t.Fatal("got incorrect number of teams", found)
|
|
||||||
} else if !(found[0].Id == team.Id && found[1].Id == team2.Id) && !(found[1].Id == team.Id && found[0].Id == team2.Id) {
|
|
||||||
t.Fatal("got incorrect teams", found[0], found[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,212 +0,0 @@
|
|||||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/mattermost/platform/app"
|
|
||||||
"github.com/mattermost/platform/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestChangeUserActiveStatus(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
user := th.BasicUser
|
|
||||||
|
|
||||||
if err := changeUserActiveStatus(nil, "user", false); err == nil {
|
|
||||||
t.Fatal("should've returned error when user doesn't exist")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := changeUserActiveStatus(user, user.Username, false); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if user, _ = app.GetUser(user.Id); user.DeleteAt == 0 {
|
|
||||||
t.Fatal("should've deactivated user")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := changeUserActiveStatus(user, user.Username, true); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if user, _ := app.GetUser(user.Id); user.DeleteAt != 0 {
|
|
||||||
t.Fatal("should've activated user")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChangeUsersActiveStatus(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
user := th.BasicUser
|
|
||||||
user2 := th.CreateUser()
|
|
||||||
|
|
||||||
changeUsersActiveStatus([]string{user.Username, user2.Id}, false)
|
|
||||||
|
|
||||||
if user, _ = app.GetUser(user.Id); user.DeleteAt == 0 {
|
|
||||||
t.Fatal("should've deactivated user")
|
|
||||||
} else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt == 0 {
|
|
||||||
t.Fatal("should've deactivated user")
|
|
||||||
}
|
|
||||||
|
|
||||||
changeUsersActiveStatus([]string{user.Username, user2.Id}, true)
|
|
||||||
|
|
||||||
if user, _ = app.GetUser(user.Id); user.DeleteAt != 0 {
|
|
||||||
t.Fatal("should've activated user")
|
|
||||||
} else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt != 0 {
|
|
||||||
t.Fatal("should've activated user")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUserActivateDeactivateCmdF(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
user := th.BasicUser
|
|
||||||
user2 := th.CreateUser()
|
|
||||||
|
|
||||||
userDeactivateCmdF(userDeactivateCmd, []string{user.Username, user2.Id})
|
|
||||||
|
|
||||||
if user, _ = app.GetUser(user.Id); user.DeleteAt == 0 {
|
|
||||||
t.Fatal("should've deactivated user")
|
|
||||||
} else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt == 0 {
|
|
||||||
t.Fatal("should've deactivated user")
|
|
||||||
}
|
|
||||||
|
|
||||||
userActivateCmdF(userActivateCmd, []string{user.Username, user2.Id})
|
|
||||||
|
|
||||||
if user, _ = app.GetUser(user.Id); user.DeleteAt != 0 {
|
|
||||||
t.Fatal("should've activated user")
|
|
||||||
} else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt != 0 {
|
|
||||||
t.Fatal("should've activated user")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUserActivateDeactivateCmd(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
user := th.BasicUser
|
|
||||||
user2 := th.CreateUser()
|
|
||||||
|
|
||||||
if err := runCommand("user deactivate " + user.Username + " " + user2.Id); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if user, _ = app.GetUser(user.Id); user.DeleteAt == 0 {
|
|
||||||
t.Fatal("should've deactivated user")
|
|
||||||
} else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt == 0 {
|
|
||||||
t.Fatal("should've deactivated user")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runCommand("user activate " + user.Id + " " + user2.Username); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if user, _ = app.GetUser(user.Id); user.DeleteAt != 0 {
|
|
||||||
t.Fatal("should've activated user")
|
|
||||||
} else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt != 0 {
|
|
||||||
t.Fatal("should've activated user")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUserCreateCmd(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
if err := runCommand("user create"); err == nil {
|
|
||||||
t.Fatal("should've failed without any arguments")
|
|
||||||
}
|
|
||||||
|
|
||||||
username := th.MakeUsername()
|
|
||||||
email := th.MakeEmail()
|
|
||||||
if err := runCommand("user create --username " + username + " --email " + email + " --password " + model.NewId()); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if user, err := app.GetUserByUsername(username); err != nil {
|
|
||||||
t.Fatal(err.Message)
|
|
||||||
} else if user.Username != username {
|
|
||||||
t.Fatal("should've set correct username")
|
|
||||||
} else if user.Email != email {
|
|
||||||
t.Fatal("should've set correct email")
|
|
||||||
}
|
|
||||||
|
|
||||||
username = th.MakeUsername()
|
|
||||||
nickname := model.NewId()
|
|
||||||
firstName := model.NewId()
|
|
||||||
lastName := model.NewId()
|
|
||||||
locale := "fr"
|
|
||||||
if err := runCommand("user create --username " + username + " --email " + th.MakeEmail() + " --password " + model.NewId() +
|
|
||||||
" --nickname " + nickname + " --firstname " + firstName + " --lastname " + lastName + " --locale " + locale); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if user, err := app.GetUserByUsername(username); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if user.Nickname != nickname {
|
|
||||||
t.Fatal("should've set correct nickname")
|
|
||||||
} else if user.FirstName != firstName {
|
|
||||||
t.Fatal("should've set correct first name")
|
|
||||||
} else if user.LastName != lastName {
|
|
||||||
t.Fatal("should've set correct last name")
|
|
||||||
} else if user.Locale != locale {
|
|
||||||
t.Fatal("should've set correct locale", user.Locale)
|
|
||||||
} else if user.Roles != "system_user" {
|
|
||||||
t.Fatal("should've set correct roles for user")
|
|
||||||
}
|
|
||||||
|
|
||||||
username = th.MakeUsername()
|
|
||||||
if err := runCommand("user create --username " + username + " --email " + th.MakeEmail() + " --password " + model.NewId() + " --system_admin"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if user, err := app.GetUserByUsername(username); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if user.Roles != "system_user system_admin" {
|
|
||||||
t.Fatal("should've set correct roles for system admin")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runCommand("user create --email " + th.MakeEmail() + " --password " + model.NewId()); err == nil {
|
|
||||||
t.Fatal("should've failed without username")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runCommand("user create --username " + th.MakeUsername() + " --email " + th.MakeEmail()); err == nil {
|
|
||||||
t.Fatal("should've failed without password")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runCommand("user create --username " + th.MakeUsername() + " --password " + model.NewId()); err == nil {
|
|
||||||
t.Fatal("should've failed without email")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInviteUser(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
team := th.CreateTeam()
|
|
||||||
|
|
||||||
if err := inviteUser(th.MakeEmail(), nil, "faketeam"); err == nil {
|
|
||||||
t.Fatal("should've failed with nonexistent team")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := inviteUser(th.MakeEmail(), team, team.Name); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing else to test here since this just fires off an email
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUserInviteCmd(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
team := th.BasicTeam
|
|
||||||
team2 := th.CreateTeam()
|
|
||||||
|
|
||||||
if err := runCommand("user invite"); err == nil {
|
|
||||||
t.Fatal("should've failed without any arguments")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runCommand("user invite " + th.MakeEmail()); err == nil {
|
|
||||||
t.Fatal("should've failed with 1 argument")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runCommand("user invite " + th.MakeEmail() + " " + team.Id); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runCommand("user invite " + th.MakeEmail() + " " + team.Name); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runCommand("user invite " + th.MakeEmail() + " " + team.Id + " " + team2.Name); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runCommand("user invite " + th.MakeEmail() + " " + team.Id + " " + team2.Name + " " + "faketeam"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/mattermost/platform/app"
|
|
||||||
"github.com/mattermost/platform/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetUserFromUserArg(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
user := th.BasicUser
|
|
||||||
|
|
||||||
if found := getUserFromUserArg(""); found != nil {
|
|
||||||
t.Fatal("shoudn't have gotten a user", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getUserFromUserArg(model.NewId()); found != nil {
|
|
||||||
t.Fatal("shoudn't have gotten a user", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getUserFromUserArg(user.Id); found == nil || found.Id != user.Id {
|
|
||||||
t.Fatal("got incorrect user", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getUserFromUserArg(user.Username); found == nil || found.Id != user.Id {
|
|
||||||
t.Fatal("got incorrect user", found)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetUsersFromUserArg(t *testing.T) {
|
|
||||||
th := app.Setup().InitBasic()
|
|
||||||
|
|
||||||
user := th.BasicUser
|
|
||||||
user2 := th.CreateUser()
|
|
||||||
|
|
||||||
if found := getUsersFromUserArgs([]string{}); len(found) != 0 {
|
|
||||||
t.Fatal("shoudn't have gotten any users", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getUsersFromUserArgs([]string{user.Id}); len(found) == 1 && found[0].Id != user.Id {
|
|
||||||
t.Fatal("got incorrect user", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getUsersFromUserArgs([]string{user2.Username}); len(found) == 1 && found[0].Id != user2.Id {
|
|
||||||
t.Fatal("got incorrect user", found)
|
|
||||||
}
|
|
||||||
|
|
||||||
if found := getUsersFromUserArgs([]string{user.Username, user2.Id}); len(found) != 2 {
|
|
||||||
t.Fatal("got incorrect number of users", found)
|
|
||||||
} else if !(found[0].Id == user.Id && found[1].Id == user2.Id) && !(found[1].Id == user.Id && found[0].Id == user2.Id) {
|
|
||||||
t.Fatal("got incorrect users", found[0], found[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
67
glide.lock
сгенерированный
67
glide.lock
сгенерированный
@@ -1,17 +1,17 @@
|
|||||||
hash: c8c28a291e4ef606837d38252852246fa634c9eebac12ceaae37103caed16883
|
hash: a63bdc06107e9917f943ab3af7d55d64702bc745e3a5dd0affa2c012a8d8e07f
|
||||||
updated: 2017-08-17T09:43:52.281308245-07:00
|
updated: 2017-09-29T08:20:31.615625246-07:00
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/alecthomas/log4go
|
- name: github.com/alecthomas/log4go
|
||||||
version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c
|
version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c
|
||||||
repo: https://github.com/mattermost/log4go.git
|
repo: https://github.com/mattermost/log4go.git
|
||||||
- name: github.com/armon/go-metrics
|
- name: github.com/armon/go-metrics
|
||||||
version: 023a4bbe4bb9bfb23ee7e1afc8d0abad217641f3
|
version: 0a12dc6f6b9da6da644031a1b9b5a85478c5ee27
|
||||||
- name: github.com/beorn7/perks
|
- name: github.com/beorn7/perks
|
||||||
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||||
subpackages:
|
subpackages:
|
||||||
- quantile
|
- quantile
|
||||||
- name: github.com/cpanato/html2text
|
- name: github.com/cpanato/html2text
|
||||||
version: d788b7d6dc58bea298b318059332a25442583880
|
version: d47a5532a7bc36ad7b2b8ec3eebe24e975154f94
|
||||||
- name: github.com/davecgh/go-spew
|
- name: github.com/davecgh/go-spew
|
||||||
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
||||||
subpackages:
|
subpackages:
|
||||||
@@ -21,7 +21,7 @@ imports:
|
|||||||
- name: github.com/dimchansky/utfbom
|
- name: github.com/dimchansky/utfbom
|
||||||
version: 6c6132ff69f0f6c088739067407b5d32c52e1d0f
|
version: 6c6132ff69f0f6c088739067407b5d32c52e1d0f
|
||||||
- name: github.com/disintegration/imaging
|
- name: github.com/disintegration/imaging
|
||||||
version: a5858022df0e1734a59f973fffe3f87b51c087ed
|
version: c3956f26e8f5f2370428d573648fedc717fbe51e
|
||||||
- name: github.com/dyatlov/go-opengraph
|
- name: github.com/dyatlov/go-opengraph
|
||||||
version: 41a3523719dfbe7e8f853fbd4061867543db5270
|
version: 41a3523719dfbe7e8f853fbd4061867543db5270
|
||||||
subpackages:
|
subpackages:
|
||||||
@@ -33,7 +33,7 @@ imports:
|
|||||||
- name: github.com/go-ldap/ldap
|
- name: github.com/go-ldap/ldap
|
||||||
version: 8168ee085ee43257585e50c6441aadf54ecb2c9f
|
version: 8168ee085ee43257585e50c6441aadf54ecb2c9f
|
||||||
- name: github.com/go-redis/redis
|
- name: github.com/go-redis/redis
|
||||||
version: 19c1c2272e00c1aaa903cf574c746cd449f9cd3c
|
version: 8e6b51ec3a92ec095dcbd2439c7a3eec6b6cb586
|
||||||
subpackages:
|
subpackages:
|
||||||
- internal
|
- internal
|
||||||
- internal/consistenthash
|
- internal/consistenthash
|
||||||
@@ -48,7 +48,7 @@ imports:
|
|||||||
- raster
|
- raster
|
||||||
- truetype
|
- truetype
|
||||||
- name: github.com/golang/protobuf
|
- name: github.com/golang/protobuf
|
||||||
version: ab9f9a6dab164b7d1246e0e688b0ab7b94d8553e
|
version: 130e6b02ab059e7b717a096f397c5b60111cae74
|
||||||
subpackages:
|
subpackages:
|
||||||
- proto
|
- proto
|
||||||
- name: github.com/gorilla/context
|
- name: github.com/gorilla/context
|
||||||
@@ -56,7 +56,7 @@ imports:
|
|||||||
- name: github.com/gorilla/handlers
|
- name: github.com/gorilla/handlers
|
||||||
version: a4043c62cc2329bacda331d33fc908ab11ef0ec3
|
version: a4043c62cc2329bacda331d33fc908ab11ef0ec3
|
||||||
- name: github.com/gorilla/mux
|
- name: github.com/gorilla/mux
|
||||||
version: bcd8bc72b08df0f70df986b97f95590779502d31
|
version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7
|
||||||
- name: github.com/gorilla/websocket
|
- name: github.com/gorilla/websocket
|
||||||
version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b
|
version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b
|
||||||
- name: github.com/hashicorp/errwrap
|
- name: github.com/hashicorp/errwrap
|
||||||
@@ -76,7 +76,7 @@ imports:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- simplelru
|
- simplelru
|
||||||
- name: github.com/hashicorp/hcl
|
- name: github.com/hashicorp/hcl
|
||||||
version: 392dba7d905ed5d04a5794ba89f558b27e2ba1ca
|
version: 68e816d1c783414e79bc65b3994d9ab6b0a722ab
|
||||||
subpackages:
|
subpackages:
|
||||||
- hcl/ast
|
- hcl/ast
|
||||||
- hcl/parser
|
- hcl/parser
|
||||||
@@ -87,21 +87,21 @@ imports:
|
|||||||
- json/scanner
|
- json/scanner
|
||||||
- json/token
|
- json/token
|
||||||
- name: github.com/hashicorp/memberlist
|
- name: github.com/hashicorp/memberlist
|
||||||
version: d6c1fb0b99c33d0a8e22acea9da9709b369b5d39
|
version: 687988a0b5daaf7ed5051e5e374aef27f8254822
|
||||||
- name: github.com/inconshreveable/mousetrap
|
- name: github.com/inconshreveable/mousetrap
|
||||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||||
- name: github.com/jehiah/go-strftime
|
- name: github.com/jehiah/go-strftime
|
||||||
version: 834e15c05a45371503440cc195bbd05c9a0968d9
|
version: 834e15c05a45371503440cc195bbd05c9a0968d9
|
||||||
- name: github.com/lib/pq
|
- name: github.com/lib/pq
|
||||||
version: e42267488fe361b9dc034be7a6bffef5b195bceb
|
version: b77235e3890a962fe8a6f8c4c7198679ca7814e7
|
||||||
subpackages:
|
subpackages:
|
||||||
- oid
|
- oid
|
||||||
- name: github.com/magiconair/properties
|
- name: github.com/magiconair/properties
|
||||||
version: be5ece7dd465ab0765a9682137865547526d1dfb
|
version: 8d7837e64d3c1ee4e54a880c5a920ab4316fc90a
|
||||||
- name: github.com/mattermost/gorp
|
- name: github.com/mattermost/gorp
|
||||||
version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a
|
version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a
|
||||||
- name: github.com/mattermost/html2text
|
- name: github.com/mattermost/html2text
|
||||||
version: d788b7d6dc58bea298b318059332a25442583880
|
version: d47a5532a7bc36ad7b2b8ec3eebe24e975154f94
|
||||||
- name: github.com/mattermost/rsc
|
- name: github.com/mattermost/rsc
|
||||||
version: bbaefb05eaa0389ea712340066837c8ce4d287f9
|
version: bbaefb05eaa0389ea712340066837c8ce4d287f9
|
||||||
subpackages:
|
subpackages:
|
||||||
@@ -113,11 +113,13 @@ imports:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- pbutil
|
- pbutil
|
||||||
- name: github.com/miekg/dns
|
- name: github.com/miekg/dns
|
||||||
version: 0598bd43cf51d0375c5bcd3a42e807cc19b3b7d9
|
version: aade52d68e0bf400ae55afd3adadffce3b027043
|
||||||
|
subpackages:
|
||||||
|
- internal/socket
|
||||||
- name: github.com/minio/go-homedir
|
- name: github.com/minio/go-homedir
|
||||||
version: 21304a94172ae3a09dee2cd86a12fb6f842138c7
|
version: 21304a94172ae3a09dee2cd86a12fb6f842138c7
|
||||||
- name: github.com/minio/minio-go
|
- name: github.com/minio/minio-go
|
||||||
version: 1a09415eed6025360c2c3142f92d3bcf339f873d
|
version: 4e0f567303d4cc90ceb055a451959fb9fc391fb9
|
||||||
subpackages:
|
subpackages:
|
||||||
- pkg/credentials
|
- pkg/credentials
|
||||||
- pkg/encrypt
|
- pkg/encrypt
|
||||||
@@ -128,22 +130,22 @@ imports:
|
|||||||
- name: github.com/mitchellh/mapstructure
|
- name: github.com/mitchellh/mapstructure
|
||||||
version: d0303fe809921458f417bcf828397a65db30a7e4
|
version: d0303fe809921458f417bcf828397a65db30a7e4
|
||||||
- name: github.com/mssola/user_agent
|
- name: github.com/mssola/user_agent
|
||||||
version: 85b2f5798558a46fc23443c596e781712f4b7792
|
version: a2f39d5a9b15ecc1fa1005b6aae73cd83da240ef
|
||||||
- name: github.com/nicksnyder/go-i18n
|
- name: github.com/nicksnyder/go-i18n
|
||||||
version: 3e70a1a463008cea6726380c908b1a6a8bdf7b24
|
version: ca33e78c8a430e2df435b02f63a3944fa8e9ea11
|
||||||
subpackages:
|
subpackages:
|
||||||
- i18n
|
- i18n
|
||||||
- i18n/bundle
|
- i18n/bundle
|
||||||
- i18n/language
|
- i18n/language
|
||||||
- i18n/translation
|
- i18n/translation
|
||||||
- name: github.com/NYTimes/gziphandler
|
- name: github.com/NYTimes/gziphandler
|
||||||
version: 967539e5e271a2bc9b3dcb1285078a1b1df105ae
|
version: 97ae7fbaf81620fe97840685304a78a306a39c64
|
||||||
- name: github.com/pborman/uuid
|
- name: github.com/pborman/uuid
|
||||||
version: e790cca94e6cc75c7064b1332e63811d4aae1a53
|
version: e790cca94e6cc75c7064b1332e63811d4aae1a53
|
||||||
- name: github.com/pelletier/go-toml
|
- name: github.com/pelletier/go-toml
|
||||||
version: 4692b8f9babfc93db58cc592ba2689d8736781de
|
version: 16398bac157da96aa88f98a2df640c7f32af1da2
|
||||||
- name: github.com/pkg/errors
|
- name: github.com/pkg/errors
|
||||||
version: c605e284fe17294bda444b34710735b29d1a9d90
|
version: 2b3a18b5f0fb6b4f9190549597d3f962c02bc5eb
|
||||||
- name: github.com/pmezard/go-difflib
|
- name: github.com/pmezard/go-difflib
|
||||||
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
||||||
subpackages:
|
subpackages:
|
||||||
@@ -157,7 +159,7 @@ imports:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- go
|
- go
|
||||||
- name: github.com/prometheus/common
|
- name: github.com/prometheus/common
|
||||||
version: 61f87aac8082fa8c3c5655c7608d7478d46ac2ad
|
version: 2f17f4a9d485bf34b4bfaccc273805040e4f86c8
|
||||||
subpackages:
|
subpackages:
|
||||||
- expfmt
|
- expfmt
|
||||||
- name: github.com/prometheus/procfs
|
- name: github.com/prometheus/procfs
|
||||||
@@ -176,15 +178,15 @@ imports:
|
|||||||
- name: github.com/segmentio/backo-go
|
- name: github.com/segmentio/backo-go
|
||||||
version: 204274ad699c0983a70203a566887f17a717fef4
|
version: 204274ad699c0983a70203a566887f17a717fef4
|
||||||
- name: github.com/spf13/afero
|
- name: github.com/spf13/afero
|
||||||
version: 9be650865eab0c12963d8753212f4f9c66cdcf12
|
version: ee1bd8ee15a1306d1f9201acc41ef39cd9f99a1b
|
||||||
subpackages:
|
subpackages:
|
||||||
- mem
|
- mem
|
||||||
- name: github.com/spf13/cast
|
- name: github.com/spf13/cast
|
||||||
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
|
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
|
||||||
- name: github.com/spf13/cobra
|
- name: github.com/spf13/cobra
|
||||||
version: cb731b898346822cc0c225c28550a8a29d93c732
|
version: b78744579491c1ceeaaa3b40205e56b0591b93a3
|
||||||
- name: github.com/spf13/jwalterweatherman
|
- name: github.com/spf13/jwalterweatherman
|
||||||
version: 0efa5202c04663c757d84f90f5219c1250baf94f
|
version: 12bd96e66386c1960ab0f74ced1362f66f552f7b
|
||||||
- name: github.com/spf13/pflag
|
- name: github.com/spf13/pflag
|
||||||
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
|
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
|
||||||
- name: github.com/spf13/viper
|
- name: github.com/spf13/viper
|
||||||
@@ -197,22 +199,23 @@ imports:
|
|||||||
- assert
|
- assert
|
||||||
- mock
|
- mock
|
||||||
- require
|
- require
|
||||||
|
- suite
|
||||||
- name: github.com/tylerb/graceful
|
- name: github.com/tylerb/graceful
|
||||||
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
|
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
|
||||||
- name: github.com/xenolf/lego
|
- name: github.com/xenolf/lego
|
||||||
version: 92ed20909982bc411971291622e8d379e1627a0b
|
version: 5a2fd5039fbba3c06b640be91a2c436bc23f74e8
|
||||||
subpackages:
|
subpackages:
|
||||||
- acme
|
- acme
|
||||||
- name: github.com/xtgo/uuid
|
- name: github.com/xtgo/uuid
|
||||||
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
|
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
|
||||||
- name: golang.org/x/crypto
|
- name: golang.org/x/crypto
|
||||||
version: b176d7def5d71bdd214203491f89843ed217f420
|
version: 76eec36fa14229c4b25bb894c2d0e591527af429
|
||||||
subpackages:
|
subpackages:
|
||||||
- bcrypt
|
- bcrypt
|
||||||
- blowfish
|
- blowfish
|
||||||
- ocsp
|
- ocsp
|
||||||
- name: golang.org/x/image
|
- name: golang.org/x/image
|
||||||
version: 426cfd8eeb6e08ab1932954e09e3c2cb2bc6e36d
|
version: 334384d9e19178a0488c9360d94d183c1ef0f711
|
||||||
subpackages:
|
subpackages:
|
||||||
- bmp
|
- bmp
|
||||||
- font
|
- font
|
||||||
@@ -220,23 +223,23 @@ imports:
|
|||||||
- tiff
|
- tiff
|
||||||
- tiff/lzw
|
- tiff/lzw
|
||||||
- name: golang.org/x/net
|
- name: golang.org/x/net
|
||||||
version: 1c05540f6879653db88113bc4a2b70aec4bd491f
|
version: 0a9397675ba34b2845f758fe3cd68828369c6517
|
||||||
subpackages:
|
subpackages:
|
||||||
- context
|
- context
|
||||||
- html
|
- html
|
||||||
- html/atom
|
- html/atom
|
||||||
- publicsuffix
|
- publicsuffix
|
||||||
- name: golang.org/x/sys
|
- name: golang.org/x/sys
|
||||||
version: 9f7170bcd8e9f4d3691c06401119c46a769a1e03
|
version: 314a259e304ff91bd6985da2a7149bbf91237993
|
||||||
subpackages:
|
subpackages:
|
||||||
- unix
|
- unix
|
||||||
- name: golang.org/x/text
|
- name: golang.org/x/text
|
||||||
version: e56139fd9c5bc7244c76116c68e500765bb6db6b
|
version: 1cbadb444a806fd9430d14ad08967ed91da4fa0a
|
||||||
subpackages:
|
subpackages:
|
||||||
- transform
|
- transform
|
||||||
- unicode/norm
|
- unicode/norm
|
||||||
- name: golang.org/x/time
|
- name: golang.org/x/time
|
||||||
version: 8be79e1e0910c292df4e79c241bb7e8f7e725959
|
version: 6dc17368e09b0e8634d71cac8168d853e869a0c7
|
||||||
subpackages:
|
subpackages:
|
||||||
- rate
|
- rate
|
||||||
- name: gopkg.in/alexcesaro/quotedprintable.v3
|
- name: gopkg.in/alexcesaro/quotedprintable.v3
|
||||||
@@ -246,7 +249,7 @@ imports:
|
|||||||
- name: gopkg.in/gomail.v2
|
- name: gopkg.in/gomail.v2
|
||||||
version: 41f3572897373c5538c50a2402db15db079fa4fd
|
version: 41f3572897373c5538c50a2402db15db079fa4fd
|
||||||
- name: gopkg.in/olivere/elastic.v5
|
- name: gopkg.in/olivere/elastic.v5
|
||||||
version: edbef41beaacc2ee95e61af8faff04e67c01e268
|
version: 2a08d39723b7f4df92b96e2dff891a60952714d6
|
||||||
subpackages:
|
subpackages:
|
||||||
- config
|
- config
|
||||||
- uritemplates
|
- uritemplates
|
||||||
|
|||||||
15
glide.yaml
15
glide.yaml
@@ -1,11 +1,11 @@
|
|||||||
package: github.com/mattermost/platform
|
package: github.com/mattermost/mattermost-server
|
||||||
import:
|
import:
|
||||||
- package: github.com/NYTimes/gziphandler
|
- package: github.com/NYTimes/gziphandler
|
||||||
- package: github.com/alecthomas/log4go
|
- package: github.com/alecthomas/log4go
|
||||||
repo: https://github.com/mattermost/log4go.git
|
repo: https://github.com/mattermost/log4go.git
|
||||||
- package: github.com/dgryski/dgoogauth
|
- package: github.com/dgryski/dgoogauth
|
||||||
- package: github.com/disintegration/imaging
|
- package: github.com/disintegration/imaging
|
||||||
version: v1.2.1
|
version: v1.2.2
|
||||||
- package: github.com/dyatlov/go-opengraph
|
- package: github.com/dyatlov/go-opengraph
|
||||||
subpackages:
|
subpackages:
|
||||||
- opengraph
|
- opengraph
|
||||||
@@ -19,7 +19,7 @@ import:
|
|||||||
- package: github.com/gorilla/handlers
|
- package: github.com/gorilla/handlers
|
||||||
version: v1.2.1
|
version: v1.2.1
|
||||||
- package: github.com/gorilla/mux
|
- package: github.com/gorilla/mux
|
||||||
version: v1.4.0
|
version: v1.5.0
|
||||||
- package: github.com/gorilla/websocket
|
- package: github.com/gorilla/websocket
|
||||||
version: v1.2.0
|
version: v1.2.0
|
||||||
- package: github.com/lib/pq
|
- package: github.com/lib/pq
|
||||||
@@ -27,11 +27,10 @@ import:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- qr
|
- qr
|
||||||
- package: github.com/minio/minio-go
|
- package: github.com/minio/minio-go
|
||||||
version: v3.0.1
|
version: v3.0.3
|
||||||
- package: github.com/mssola/user_agent
|
- package: github.com/mssola/user_agent
|
||||||
version: v0.4.1
|
|
||||||
- package: github.com/nicksnyder/go-i18n
|
- package: github.com/nicksnyder/go-i18n
|
||||||
version: v1.8.1
|
version: v1.9.0
|
||||||
subpackages:
|
subpackages:
|
||||||
- i18n
|
- i18n
|
||||||
- package: github.com/pborman/uuid
|
- package: github.com/pborman/uuid
|
||||||
@@ -82,11 +81,11 @@ import:
|
|||||||
- package: github.com/prometheus/procfs
|
- package: github.com/prometheus/procfs
|
||||||
- package: github.com/cpanato/html2text
|
- package: github.com/cpanato/html2text
|
||||||
- package: gopkg.in/olivere/elastic.v5
|
- package: gopkg.in/olivere/elastic.v5
|
||||||
version: v5.0.45
|
version: v5.0.48
|
||||||
- package: github.com/mattermost/gorp
|
- package: github.com/mattermost/gorp
|
||||||
version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a
|
version: 995ddf2264c4ad45fbaf342f7500e4787ebae84a
|
||||||
- package: github.com/go-redis/redis
|
- package: github.com/go-redis/redis
|
||||||
version: v6.5.7
|
version: v6.7.1
|
||||||
- package: github.com/stretchr/testify
|
- package: github.com/stretchr/testify
|
||||||
version: v1.1.4
|
version: v1.1.4
|
||||||
subpackages:
|
subpackages:
|
||||||
|
|||||||
201
vendor/github.com/NYTimes/gziphandler/LICENSE
сгенерированный
поставляемый
Обычный файл
201
vendor/github.com/NYTimes/gziphandler/LICENSE
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2016-2017 The New York Times Company
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
13
vendor/github.com/NYTimes/gziphandler/LICENSE.md
сгенерированный
поставляемый
13
vendor/github.com/NYTimes/gziphandler/LICENSE.md
сгенерированный
поставляемый
@@ -1,13 +0,0 @@
|
|||||||
Copyright (c) 2015 The New York Times Company
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this library except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
4
vendor/github.com/NYTimes/gziphandler/gzip.go
сгенерированный
поставляемый
4
vendor/github.com/NYTimes/gziphandler/gzip.go
сгенерированный
поставляемый
@@ -105,7 +105,7 @@ func (w *GzipResponseWriter) Write(b []byte) (int, error) {
|
|||||||
// If the global writes are bigger than the minSize and we're about to write
|
// If the global writes are bigger than the minSize and we're about to write
|
||||||
// a response containing a content type we want to handle, enable
|
// a response containing a content type we want to handle, enable
|
||||||
// compression.
|
// compression.
|
||||||
if len(w.buf) >= w.minSize && handleContentType(w.contentTypes, w) {
|
if len(w.buf) >= w.minSize && handleContentType(w.contentTypes, w) && w.Header().Get(contentEncoding) == "" {
|
||||||
err := w.startGzip()
|
err := w.startGzip()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -134,7 +134,7 @@ func (w *GzipResponseWriter) startGzip() error {
|
|||||||
// Initialize the GZIP response.
|
// Initialize the GZIP response.
|
||||||
w.init()
|
w.init()
|
||||||
|
|
||||||
// Flush the buffer into the gzip reponse.
|
// Flush the buffer into the gzip response.
|
||||||
n, err := w.gw.Write(w.buf)
|
n, err := w.gw.Write(w.buf)
|
||||||
|
|
||||||
// This should never happen (per io.Writer docs), but if the write didn't
|
// This should never happen (per io.Writer docs), but if the write didn't
|
||||||
|
|||||||
19
vendor/github.com/NYTimes/gziphandler/gzip_test.go
сгенерированный
поставляемый
19
vendor/github.com/NYTimes/gziphandler/gzip_test.go
сгенерированный
поставляемый
@@ -81,6 +81,17 @@ func TestGzipHandler(t *testing.T) {
|
|||||||
assert.Equal(t, http.DetectContentType([]byte(testBody)), res3.Header().Get("Content-Type"))
|
assert.Equal(t, http.DetectContentType([]byte(testBody)), res3.Header().Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGzipHandlerAlreadyCompressed(t *testing.T) {
|
||||||
|
handler := newTestHandler(testBody)
|
||||||
|
|
||||||
|
req, _ := http.NewRequest("GET", "/gzipped", nil)
|
||||||
|
req.Header.Set("Accept-Encoding", "gzip")
|
||||||
|
res := httptest.NewRecorder()
|
||||||
|
handler.ServeHTTP(res, req)
|
||||||
|
|
||||||
|
assert.Equal(t, testBody, res.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewGzipLevelHandler(t *testing.T) {
|
func TestNewGzipLevelHandler(t *testing.T) {
|
||||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
@@ -435,6 +446,12 @@ func runBenchmark(b *testing.B, req *http.Request, handler http.Handler) {
|
|||||||
|
|
||||||
func newTestHandler(body string) http.Handler {
|
func newTestHandler(body string) http.Handler {
|
||||||
return GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
io.WriteString(w, body)
|
switch r.URL.Path {
|
||||||
|
case "/gzipped":
|
||||||
|
w.Header().Set("Content-Encoding", "gzip")
|
||||||
|
io.WriteString(w, body)
|
||||||
|
default:
|
||||||
|
io.WriteString(w, body)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
6
vendor/github.com/armon/go-metrics/prometheus/prometheus.go
сгенерированный
поставляемый
6
vendor/github.com/armon/go-metrics/prometheus/prometheus.go
сгенерированный
поставляемый
@@ -66,7 +66,7 @@ func (p *PrometheusSink) SetGaugeWithLabels(parts []string, val float32, labels
|
|||||||
ConstLabels: prometheusLabels(labels),
|
ConstLabels: prometheusLabels(labels),
|
||||||
})
|
})
|
||||||
prometheus.MustRegister(g)
|
prometheus.MustRegister(g)
|
||||||
p.gauges[key] = g
|
p.gauges[hash] = g
|
||||||
}
|
}
|
||||||
g.Set(float64(val))
|
g.Set(float64(val))
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ func (p *PrometheusSink) AddSampleWithLabels(parts []string, val float32, labels
|
|||||||
ConstLabels: prometheusLabels(labels),
|
ConstLabels: prometheusLabels(labels),
|
||||||
})
|
})
|
||||||
prometheus.MustRegister(g)
|
prometheus.MustRegister(g)
|
||||||
p.summaries[key] = g
|
p.summaries[hash] = g
|
||||||
}
|
}
|
||||||
g.Observe(float64(val))
|
g.Observe(float64(val))
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ func (p *PrometheusSink) IncrCounterWithLabels(parts []string, val float32, labe
|
|||||||
ConstLabels: prometheusLabels(labels),
|
ConstLabels: prometheusLabels(labels),
|
||||||
})
|
})
|
||||||
prometheus.MustRegister(g)
|
prometheus.MustRegister(g)
|
||||||
p.counters[key] = g
|
p.counters[hash] = g
|
||||||
}
|
}
|
||||||
g.Add(float64(val))
|
g.Add(float64(val))
|
||||||
}
|
}
|
||||||
|
|||||||
1
vendor/github.com/cpanato/html2text/LICENSE
сгенерированный
поставляемый
1
vendor/github.com/cpanato/html2text/LICENSE
сгенерированный
поставляемый
@@ -1,6 +1,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015 Jay Taylor
|
Copyright (c) 2015 Jay Taylor
|
||||||
|
Modified work: Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
5
vendor/github.com/disintegration/imaging/.travis.yml
сгенерированный
поставляемый
5
vendor/github.com/disintegration/imaging/.travis.yml
сгенерированный
поставляемый
@@ -4,12 +4,9 @@ sudo: false
|
|||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.2
|
- 1.2
|
||||||
- 1.3
|
|
||||||
- 1.4
|
|
||||||
- 1.5
|
|
||||||
- 1.6
|
|
||||||
- 1.7
|
- 1.7
|
||||||
- 1.8
|
- 1.8
|
||||||
|
- 1.9
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- go get golang.org/x/tools/cmd/cover
|
- go get golang.org/x/tools/cmd/cover
|
||||||
|
|||||||
429
vendor/github.com/disintegration/imaging/helpers.go
сгенерированный
поставляемый
429
vendor/github.com/disintegration/imaging/helpers.go
сгенерированный
поставляемый
@@ -168,213 +168,266 @@ func New(width, height int, fillColor color.Color) *image.NRGBA {
|
|||||||
|
|
||||||
// Clone returns a copy of the given image.
|
// Clone returns a copy of the given image.
|
||||||
func Clone(img image.Image) *image.NRGBA {
|
func Clone(img image.Image) *image.NRGBA {
|
||||||
srcBounds := img.Bounds()
|
dstBounds := img.Bounds().Sub(img.Bounds().Min)
|
||||||
srcMinX := srcBounds.Min.X
|
|
||||||
srcMinY := srcBounds.Min.Y
|
|
||||||
|
|
||||||
dstBounds := srcBounds.Sub(srcBounds.Min)
|
|
||||||
dstW := dstBounds.Dx()
|
|
||||||
dstH := dstBounds.Dy()
|
|
||||||
dst := image.NewNRGBA(dstBounds)
|
dst := image.NewNRGBA(dstBounds)
|
||||||
|
|
||||||
switch src := img.(type) {
|
switch src := img.(type) {
|
||||||
|
|
||||||
case *image.NRGBA:
|
case *image.NRGBA:
|
||||||
rowSize := srcBounds.Dx() * 4
|
copyNRGBA(dst, src)
|
||||||
parallel(dstH, func(partStart, partEnd int) {
|
|
||||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
|
||||||
di := dst.PixOffset(0, dstY)
|
|
||||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
|
||||||
copy(dst.Pix[di:di+rowSize], src.Pix[si:si+rowSize])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
case *image.NRGBA64:
|
case *image.NRGBA64:
|
||||||
parallel(dstH, func(partStart, partEnd int) {
|
copyNRGBA64(dst, src)
|
||||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
|
||||||
di := dst.PixOffset(0, dstY)
|
|
||||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
|
||||||
for dstX := 0; dstX < dstW; dstX++ {
|
|
||||||
dst.Pix[di+0] = src.Pix[si+0]
|
|
||||||
dst.Pix[di+1] = src.Pix[si+2]
|
|
||||||
dst.Pix[di+2] = src.Pix[si+4]
|
|
||||||
dst.Pix[di+3] = src.Pix[si+6]
|
|
||||||
di += 4
|
|
||||||
si += 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
case *image.RGBA:
|
case *image.RGBA:
|
||||||
parallel(dstH, func(partStart, partEnd int) {
|
copyRGBA(dst, src)
|
||||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
|
||||||
di := dst.PixOffset(0, dstY)
|
|
||||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
|
||||||
for dstX := 0; dstX < dstW; dstX++ {
|
|
||||||
a := src.Pix[si+3]
|
|
||||||
dst.Pix[di+3] = a
|
|
||||||
|
|
||||||
switch a {
|
|
||||||
case 0:
|
|
||||||
dst.Pix[di+0] = 0
|
|
||||||
dst.Pix[di+1] = 0
|
|
||||||
dst.Pix[di+2] = 0
|
|
||||||
case 0xff:
|
|
||||||
dst.Pix[di+0] = src.Pix[si+0]
|
|
||||||
dst.Pix[di+1] = src.Pix[si+1]
|
|
||||||
dst.Pix[di+2] = src.Pix[si+2]
|
|
||||||
default:
|
|
||||||
var tmp uint16
|
|
||||||
tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
|
|
||||||
dst.Pix[di+0] = uint8(tmp)
|
|
||||||
tmp = uint16(src.Pix[si+1]) * 0xff / uint16(a)
|
|
||||||
dst.Pix[di+1] = uint8(tmp)
|
|
||||||
tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
|
|
||||||
dst.Pix[di+2] = uint8(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
di += 4
|
|
||||||
si += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
case *image.RGBA64:
|
case *image.RGBA64:
|
||||||
parallel(dstH, func(partStart, partEnd int) {
|
copyRGBA64(dst, src)
|
||||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
|
||||||
di := dst.PixOffset(0, dstY)
|
|
||||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
|
||||||
for dstX := 0; dstX < dstW; dstX++ {
|
|
||||||
a := src.Pix[si+6]
|
|
||||||
dst.Pix[di+3] = a
|
|
||||||
|
|
||||||
switch a {
|
|
||||||
case 0:
|
|
||||||
dst.Pix[di+0] = 0
|
|
||||||
dst.Pix[di+1] = 0
|
|
||||||
dst.Pix[di+2] = 0
|
|
||||||
case 0xff:
|
|
||||||
dst.Pix[di+0] = src.Pix[si+0]
|
|
||||||
dst.Pix[di+1] = src.Pix[si+2]
|
|
||||||
dst.Pix[di+2] = src.Pix[si+4]
|
|
||||||
default:
|
|
||||||
var tmp uint16
|
|
||||||
tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
|
|
||||||
dst.Pix[di+0] = uint8(tmp)
|
|
||||||
tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
|
|
||||||
dst.Pix[di+1] = uint8(tmp)
|
|
||||||
tmp = uint16(src.Pix[si+4]) * 0xff / uint16(a)
|
|
||||||
dst.Pix[di+2] = uint8(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
di += 4
|
|
||||||
si += 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
case *image.Gray:
|
case *image.Gray:
|
||||||
parallel(dstH, func(partStart, partEnd int) {
|
copyGray(dst, src)
|
||||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
|
||||||
di := dst.PixOffset(0, dstY)
|
|
||||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
|
||||||
for dstX := 0; dstX < dstW; dstX++ {
|
|
||||||
c := src.Pix[si]
|
|
||||||
dst.Pix[di+0] = c
|
|
||||||
dst.Pix[di+1] = c
|
|
||||||
dst.Pix[di+2] = c
|
|
||||||
dst.Pix[di+3] = 0xff
|
|
||||||
di += 4
|
|
||||||
si += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
case *image.Gray16:
|
case *image.Gray16:
|
||||||
parallel(dstH, func(partStart, partEnd int) {
|
copyGray16(dst, src)
|
||||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
|
||||||
di := dst.PixOffset(0, dstY)
|
|
||||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
|
||||||
for dstX := 0; dstX < dstW; dstX++ {
|
|
||||||
c := src.Pix[si]
|
|
||||||
dst.Pix[di+0] = c
|
|
||||||
dst.Pix[di+1] = c
|
|
||||||
dst.Pix[di+2] = c
|
|
||||||
dst.Pix[di+3] = 0xff
|
|
||||||
di += 4
|
|
||||||
si += 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
case *image.YCbCr:
|
case *image.YCbCr:
|
||||||
parallel(dstH, func(partStart, partEnd int) {
|
copyYCbCr(dst, src)
|
||||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
|
||||||
di := dst.PixOffset(0, dstY)
|
|
||||||
for dstX := 0; dstX < dstW; dstX++ {
|
|
||||||
srcX := srcMinX + dstX
|
|
||||||
srcY := srcMinY + dstY
|
|
||||||
siy := src.YOffset(srcX, srcY)
|
|
||||||
sic := src.COffset(srcX, srcY)
|
|
||||||
r, g, b := color.YCbCrToRGB(src.Y[siy], src.Cb[sic], src.Cr[sic])
|
|
||||||
dst.Pix[di+0] = r
|
|
||||||
dst.Pix[di+1] = g
|
|
||||||
dst.Pix[di+2] = b
|
|
||||||
dst.Pix[di+3] = 0xff
|
|
||||||
di += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
case *image.Paletted:
|
case *image.Paletted:
|
||||||
plen := len(src.Palette)
|
copyPaletted(dst, src)
|
||||||
pnew := make([]color.NRGBA, plen)
|
|
||||||
for i := 0; i < plen; i++ {
|
|
||||||
pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA)
|
|
||||||
}
|
|
||||||
parallel(dstH, func(partStart, partEnd int) {
|
|
||||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
|
||||||
di := dst.PixOffset(0, dstY)
|
|
||||||
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
|
||||||
for dstX := 0; dstX < dstW; dstX++ {
|
|
||||||
c := pnew[src.Pix[si]]
|
|
||||||
dst.Pix[di+0] = c.R
|
|
||||||
dst.Pix[di+1] = c.G
|
|
||||||
dst.Pix[di+2] = c.B
|
|
||||||
dst.Pix[di+3] = c.A
|
|
||||||
di += 4
|
|
||||||
si += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
parallel(dstH, func(partStart, partEnd int) {
|
copyImage(dst, src)
|
||||||
for dstY := partStart; dstY < partEnd; dstY++ {
|
|
||||||
di := dst.PixOffset(0, dstY)
|
|
||||||
for dstX := 0; dstX < dstW; dstX++ {
|
|
||||||
c := color.NRGBAModel.Convert(img.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA)
|
|
||||||
dst.Pix[di+0] = c.R
|
|
||||||
dst.Pix[di+1] = c.G
|
|
||||||
dst.Pix[di+2] = c.B
|
|
||||||
dst.Pix[di+3] = c.A
|
|
||||||
di += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyNRGBA(dst *image.NRGBA, src *image.NRGBA) {
|
||||||
|
srcMinX := src.Rect.Min.X
|
||||||
|
srcMinY := src.Rect.Min.Y
|
||||||
|
dstW := dst.Rect.Dx()
|
||||||
|
dstH := dst.Rect.Dy()
|
||||||
|
rowSize := dstW * 4
|
||||||
|
parallel(dstH, func(partStart, partEnd int) {
|
||||||
|
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||||
|
di := dst.PixOffset(0, dstY)
|
||||||
|
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||||
|
copy(dst.Pix[di:di+rowSize], src.Pix[si:si+rowSize])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyNRGBA64(dst *image.NRGBA, src *image.NRGBA64) {
|
||||||
|
srcMinX := src.Rect.Min.X
|
||||||
|
srcMinY := src.Rect.Min.Y
|
||||||
|
dstW := dst.Rect.Dx()
|
||||||
|
dstH := dst.Rect.Dy()
|
||||||
|
parallel(dstH, func(partStart, partEnd int) {
|
||||||
|
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||||
|
di := dst.PixOffset(0, dstY)
|
||||||
|
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||||
|
for dstX := 0; dstX < dstW; dstX++ {
|
||||||
|
dst.Pix[di+0] = src.Pix[si+0]
|
||||||
|
dst.Pix[di+1] = src.Pix[si+2]
|
||||||
|
dst.Pix[di+2] = src.Pix[si+4]
|
||||||
|
dst.Pix[di+3] = src.Pix[si+6]
|
||||||
|
di += 4
|
||||||
|
si += 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyRGBA(dst *image.NRGBA, src *image.RGBA) {
|
||||||
|
srcMinX := src.Rect.Min.X
|
||||||
|
srcMinY := src.Rect.Min.Y
|
||||||
|
dstW := dst.Rect.Dx()
|
||||||
|
dstH := dst.Rect.Dy()
|
||||||
|
parallel(dstH, func(partStart, partEnd int) {
|
||||||
|
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||||
|
di := dst.PixOffset(0, dstY)
|
||||||
|
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||||
|
for dstX := 0; dstX < dstW; dstX++ {
|
||||||
|
a := src.Pix[si+3]
|
||||||
|
dst.Pix[di+3] = a
|
||||||
|
|
||||||
|
switch a {
|
||||||
|
case 0:
|
||||||
|
dst.Pix[di+0] = 0
|
||||||
|
dst.Pix[di+1] = 0
|
||||||
|
dst.Pix[di+2] = 0
|
||||||
|
case 0xff:
|
||||||
|
dst.Pix[di+0] = src.Pix[si+0]
|
||||||
|
dst.Pix[di+1] = src.Pix[si+1]
|
||||||
|
dst.Pix[di+2] = src.Pix[si+2]
|
||||||
|
default:
|
||||||
|
var tmp uint16
|
||||||
|
tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
|
||||||
|
dst.Pix[di+0] = uint8(tmp)
|
||||||
|
tmp = uint16(src.Pix[si+1]) * 0xff / uint16(a)
|
||||||
|
dst.Pix[di+1] = uint8(tmp)
|
||||||
|
tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
|
||||||
|
dst.Pix[di+2] = uint8(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
di += 4
|
||||||
|
si += 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyRGBA64(dst *image.NRGBA, src *image.RGBA64) {
|
||||||
|
srcMinX := src.Rect.Min.X
|
||||||
|
srcMinY := src.Rect.Min.Y
|
||||||
|
dstW := dst.Rect.Dx()
|
||||||
|
dstH := dst.Rect.Dy()
|
||||||
|
parallel(dstH, func(partStart, partEnd int) {
|
||||||
|
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||||
|
di := dst.PixOffset(0, dstY)
|
||||||
|
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||||
|
for dstX := 0; dstX < dstW; dstX++ {
|
||||||
|
a := src.Pix[si+6]
|
||||||
|
dst.Pix[di+3] = a
|
||||||
|
|
||||||
|
switch a {
|
||||||
|
case 0:
|
||||||
|
dst.Pix[di+0] = 0
|
||||||
|
dst.Pix[di+1] = 0
|
||||||
|
dst.Pix[di+2] = 0
|
||||||
|
case 0xff:
|
||||||
|
dst.Pix[di+0] = src.Pix[si+0]
|
||||||
|
dst.Pix[di+1] = src.Pix[si+2]
|
||||||
|
dst.Pix[di+2] = src.Pix[si+4]
|
||||||
|
default:
|
||||||
|
var tmp uint16
|
||||||
|
tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
|
||||||
|
dst.Pix[di+0] = uint8(tmp)
|
||||||
|
tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
|
||||||
|
dst.Pix[di+1] = uint8(tmp)
|
||||||
|
tmp = uint16(src.Pix[si+4]) * 0xff / uint16(a)
|
||||||
|
dst.Pix[di+2] = uint8(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
di += 4
|
||||||
|
si += 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyGray(dst *image.NRGBA, src *image.Gray) {
|
||||||
|
srcMinX := src.Rect.Min.X
|
||||||
|
srcMinY := src.Rect.Min.Y
|
||||||
|
dstW := dst.Rect.Dx()
|
||||||
|
dstH := dst.Rect.Dy()
|
||||||
|
parallel(dstH, func(partStart, partEnd int) {
|
||||||
|
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||||
|
di := dst.PixOffset(0, dstY)
|
||||||
|
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||||
|
for dstX := 0; dstX < dstW; dstX++ {
|
||||||
|
c := src.Pix[si]
|
||||||
|
dst.Pix[di+0] = c
|
||||||
|
dst.Pix[di+1] = c
|
||||||
|
dst.Pix[di+2] = c
|
||||||
|
dst.Pix[di+3] = 0xff
|
||||||
|
di += 4
|
||||||
|
si++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyGray16(dst *image.NRGBA, src *image.Gray16) {
|
||||||
|
srcMinX := src.Rect.Min.X
|
||||||
|
srcMinY := src.Rect.Min.Y
|
||||||
|
dstW := dst.Rect.Dx()
|
||||||
|
dstH := dst.Rect.Dy()
|
||||||
|
parallel(dstH, func(partStart, partEnd int) {
|
||||||
|
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||||
|
di := dst.PixOffset(0, dstY)
|
||||||
|
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||||
|
for dstX := 0; dstX < dstW; dstX++ {
|
||||||
|
c := src.Pix[si]
|
||||||
|
dst.Pix[di+0] = c
|
||||||
|
dst.Pix[di+1] = c
|
||||||
|
dst.Pix[di+2] = c
|
||||||
|
dst.Pix[di+3] = 0xff
|
||||||
|
di += 4
|
||||||
|
si += 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyYCbCr(dst *image.NRGBA, src *image.YCbCr) {
|
||||||
|
srcMinX := src.Rect.Min.X
|
||||||
|
srcMinY := src.Rect.Min.Y
|
||||||
|
dstW := dst.Rect.Dx()
|
||||||
|
dstH := dst.Rect.Dy()
|
||||||
|
parallel(dstH, func(partStart, partEnd int) {
|
||||||
|
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||||
|
di := dst.PixOffset(0, dstY)
|
||||||
|
for dstX := 0; dstX < dstW; dstX++ {
|
||||||
|
srcX := srcMinX + dstX
|
||||||
|
srcY := srcMinY + dstY
|
||||||
|
siy := src.YOffset(srcX, srcY)
|
||||||
|
sic := src.COffset(srcX, srcY)
|
||||||
|
r, g, b := color.YCbCrToRGB(src.Y[siy], src.Cb[sic], src.Cr[sic])
|
||||||
|
dst.Pix[di+0] = r
|
||||||
|
dst.Pix[di+1] = g
|
||||||
|
dst.Pix[di+2] = b
|
||||||
|
dst.Pix[di+3] = 0xff
|
||||||
|
di += 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyPaletted(dst *image.NRGBA, src *image.Paletted) {
|
||||||
|
srcMinX := src.Rect.Min.X
|
||||||
|
srcMinY := src.Rect.Min.Y
|
||||||
|
dstW := dst.Rect.Dx()
|
||||||
|
dstH := dst.Rect.Dy()
|
||||||
|
plen := len(src.Palette)
|
||||||
|
pnew := make([]color.NRGBA, plen)
|
||||||
|
for i := 0; i < plen; i++ {
|
||||||
|
pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA)
|
||||||
|
}
|
||||||
|
parallel(dstH, func(partStart, partEnd int) {
|
||||||
|
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||||
|
di := dst.PixOffset(0, dstY)
|
||||||
|
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
||||||
|
for dstX := 0; dstX < dstW; dstX++ {
|
||||||
|
c := pnew[src.Pix[si]]
|
||||||
|
dst.Pix[di+0] = c.R
|
||||||
|
dst.Pix[di+1] = c.G
|
||||||
|
dst.Pix[di+2] = c.B
|
||||||
|
dst.Pix[di+3] = c.A
|
||||||
|
di += 4
|
||||||
|
si++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyImage(dst *image.NRGBA, src image.Image) {
|
||||||
|
srcMinX := src.Bounds().Min.X
|
||||||
|
srcMinY := src.Bounds().Min.Y
|
||||||
|
dstW := dst.Bounds().Dx()
|
||||||
|
dstH := dst.Bounds().Dy()
|
||||||
|
parallel(dstH, func(partStart, partEnd int) {
|
||||||
|
for dstY := partStart; dstY < partEnd; dstY++ {
|
||||||
|
di := dst.PixOffset(0, dstY)
|
||||||
|
for dstX := 0; dstX < dstW; dstX++ {
|
||||||
|
c := color.NRGBAModel.Convert(src.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA)
|
||||||
|
dst.Pix[di+0] = c.R
|
||||||
|
dst.Pix[di+1] = c.G
|
||||||
|
dst.Pix[di+2] = c.B
|
||||||
|
dst.Pix[di+3] = c.A
|
||||||
|
di += 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// toNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).
|
// toNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).
|
||||||
func toNRGBA(img image.Image) *image.NRGBA {
|
func toNRGBA(img image.Image) *image.NRGBA {
|
||||||
srcBounds := img.Bounds()
|
if img, ok := img.(*image.NRGBA); ok && img.Bounds().Min.Eq(image.ZP) {
|
||||||
if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 {
|
return img
|
||||||
if src0, ok := img.(*image.NRGBA); ok {
|
|
||||||
return src0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Clone(img)
|
return Clone(img)
|
||||||
}
|
}
|
||||||
|
|||||||
1
vendor/github.com/go-redis/redis/.travis.yml
сгенерированный
поставляемый
1
vendor/github.com/go-redis/redis/.travis.yml
сгенерированный
поставляемый
@@ -8,6 +8,7 @@ go:
|
|||||||
- 1.4.x
|
- 1.4.x
|
||||||
- 1.7.x
|
- 1.7.x
|
||||||
- 1.8.x
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
|
|||||||
3
vendor/github.com/go-redis/redis/README.md
сгенерированный
поставляемый
3
vendor/github.com/go-redis/redis/README.md
сгенерированный
поставляемый
@@ -6,6 +6,7 @@
|
|||||||
Supports:
|
Supports:
|
||||||
|
|
||||||
- Redis 3 commands except QUIT, MONITOR, SLOWLOG and SYNC.
|
- Redis 3 commands except QUIT, MONITOR, SLOWLOG and SYNC.
|
||||||
|
- Automatic connection pooling with [circuit breaker](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern) support.
|
||||||
- [Pub/Sub](https://godoc.org/github.com/go-redis/redis#PubSub).
|
- [Pub/Sub](https://godoc.org/github.com/go-redis/redis#PubSub).
|
||||||
- [Transactions](https://godoc.org/github.com/go-redis/redis#Multi).
|
- [Transactions](https://godoc.org/github.com/go-redis/redis#Multi).
|
||||||
- [Pipeline](https://godoc.org/github.com/go-redis/redis#example-Client-Pipeline) and [TxPipeline](https://godoc.org/github.com/go-redis/redis#example-Client-TxPipeline).
|
- [Pipeline](https://godoc.org/github.com/go-redis/redis#example-Client-Pipeline) and [TxPipeline](https://godoc.org/github.com/go-redis/redis#example-Client-TxPipeline).
|
||||||
@@ -16,7 +17,7 @@ Supports:
|
|||||||
- [Ring](https://godoc.org/github.com/go-redis/redis#NewRing).
|
- [Ring](https://godoc.org/github.com/go-redis/redis#NewRing).
|
||||||
- [Instrumentation](https://godoc.org/github.com/go-redis/redis#ex-package--Instrumentation).
|
- [Instrumentation](https://godoc.org/github.com/go-redis/redis#ex-package--Instrumentation).
|
||||||
- [Cache friendly](https://github.com/go-redis/cache).
|
- [Cache friendly](https://github.com/go-redis/cache).
|
||||||
- [Rate limiting](https://github.com/go-redis/rate).
|
- [Rate limiting](https://github.com/go-redis/redis_rate).
|
||||||
- [Distributed Locks](https://github.com/bsm/redis-lock).
|
- [Distributed Locks](https://github.com/bsm/redis-lock).
|
||||||
|
|
||||||
API docs: https://godoc.org/github.com/go-redis/redis.
|
API docs: https://godoc.org/github.com/go-redis/redis.
|
||||||
|
|||||||
368
vendor/github.com/go-redis/redis/cluster.go
сгенерированный
поставляемый
368
vendor/github.com/go-redis/redis/cluster.go
сгенерированный
поставляемый
@@ -14,8 +14,8 @@ import (
|
|||||||
"github.com/go-redis/redis/internal/proto"
|
"github.com/go-redis/redis/internal/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errClusterNoNodes = internal.RedisError("redis: cluster has no nodes")
|
var errClusterNoNodes = fmt.Errorf("redis: cluster has no nodes")
|
||||||
var errNilClusterState = internal.RedisError("redis: cannot load cluster slots")
|
var errNilClusterState = fmt.Errorf("redis: cannot load cluster slots")
|
||||||
|
|
||||||
// ClusterOptions are used to configure a cluster client and should be
|
// ClusterOptions are used to configure a cluster client and should be
|
||||||
// passed to NewClusterClient.
|
// passed to NewClusterClient.
|
||||||
@@ -64,6 +64,19 @@ func (opt *ClusterOptions) init() {
|
|||||||
opt.ReadOnly = true
|
opt.ReadOnly = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch opt.ReadTimeout {
|
||||||
|
case -1:
|
||||||
|
opt.ReadTimeout = 0
|
||||||
|
case 0:
|
||||||
|
opt.ReadTimeout = 3 * time.Second
|
||||||
|
}
|
||||||
|
switch opt.WriteTimeout {
|
||||||
|
case -1:
|
||||||
|
opt.WriteTimeout = 0
|
||||||
|
case 0:
|
||||||
|
opt.WriteTimeout = opt.ReadTimeout
|
||||||
|
}
|
||||||
|
|
||||||
switch opt.MinRetryBackoff {
|
switch opt.MinRetryBackoff {
|
||||||
case -1:
|
case -1:
|
||||||
opt.MinRetryBackoff = 0
|
opt.MinRetryBackoff = 0
|
||||||
@@ -192,6 +205,21 @@ func (c *clusterNodes) Close() error {
|
|||||||
return firstErr
|
return firstErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *clusterNodes) Addrs() ([]string, error) {
|
||||||
|
c.mu.RLock()
|
||||||
|
closed := c.closed
|
||||||
|
addrs := c.addrs
|
||||||
|
c.mu.RUnlock()
|
||||||
|
|
||||||
|
if closed {
|
||||||
|
return nil, pool.ErrClosed
|
||||||
|
}
|
||||||
|
if len(addrs) == 0 {
|
||||||
|
return nil, errClusterNoNodes
|
||||||
|
}
|
||||||
|
return addrs, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *clusterNodes) NextGeneration() uint32 {
|
func (c *clusterNodes) NextGeneration() uint32 {
|
||||||
c.generation++
|
c.generation++
|
||||||
return c.generation
|
return c.generation
|
||||||
@@ -272,16 +300,9 @@ func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *clusterNodes) Random() (*clusterNode, error) {
|
func (c *clusterNodes) Random() (*clusterNode, error) {
|
||||||
c.mu.RLock()
|
addrs, err := c.Addrs()
|
||||||
closed := c.closed
|
if err != nil {
|
||||||
addrs := c.addrs
|
return nil, err
|
||||||
c.mu.RUnlock()
|
|
||||||
|
|
||||||
if closed {
|
|
||||||
return nil, pool.ErrClosed
|
|
||||||
}
|
|
||||||
if len(addrs) == 0 {
|
|
||||||
return nil, errClusterNoNodes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodeErr error
|
var nodeErr error
|
||||||
@@ -468,13 +489,23 @@ func (c *ClusterClient) Options() *ClusterOptions {
|
|||||||
return c.opt
|
return c.opt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) state() *clusterState {
|
func (c *ClusterClient) retryBackoff(attempt int) time.Duration {
|
||||||
|
return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClusterClient) state() (*clusterState, error) {
|
||||||
v := c._state.Load()
|
v := c._state.Load()
|
||||||
if v != nil {
|
if v != nil {
|
||||||
return v.(*clusterState)
|
return v.(*clusterState), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err := c.nodes.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
c.lazyReloadState()
|
c.lazyReloadState()
|
||||||
return nil
|
return nil, errNilClusterState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) cmdInfo(name string) *CommandInfo {
|
func (c *ClusterClient) cmdInfo(name string) *CommandInfo {
|
||||||
@@ -495,17 +526,22 @@ func (c *ClusterClient) cmdInfo(name string) *CommandInfo {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return c.cmdsInfo[name]
|
info := c.cmdsInfo[name]
|
||||||
|
if info == nil {
|
||||||
|
internal.Logf("info for cmd=%s not found", name)
|
||||||
|
}
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClusterClient) cmdSlot(cmd Cmder) int {
|
||||||
|
cmdInfo := c.cmdInfo(cmd.Name())
|
||||||
|
firstKey := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
|
return hashtag.Slot(firstKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) {
|
func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) {
|
||||||
if state == nil {
|
|
||||||
node, err := c.nodes.Random()
|
|
||||||
return 0, node, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdInfo := c.cmdInfo(cmd.Name())
|
cmdInfo := c.cmdInfo(cmd.Name())
|
||||||
firstKey := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
|
firstKey := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
slot := hashtag.Slot(firstKey)
|
slot := hashtag.Slot(firstKey)
|
||||||
|
|
||||||
if cmdInfo != nil && cmdInfo.ReadOnly && c.opt.ReadOnly {
|
if cmdInfo != nil && cmdInfo.ReadOnly && c.opt.ReadOnly {
|
||||||
@@ -523,19 +559,51 @@ func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *cl
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error {
|
func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error {
|
||||||
state := c.state()
|
if len(keys) == 0 {
|
||||||
|
return fmt.Errorf("redis: keys don't hash to the same slot")
|
||||||
var node *clusterNode
|
|
||||||
var err error
|
|
||||||
if state != nil && len(keys) > 0 {
|
|
||||||
node, err = state.slotMasterNode(hashtag.Slot(keys[0]))
|
|
||||||
} else {
|
|
||||||
node, err = c.nodes.Random()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state, err := c.state()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return node.Client.Watch(fn, keys...)
|
|
||||||
|
slot := hashtag.Slot(keys[0])
|
||||||
|
for _, key := range keys[1:] {
|
||||||
|
if hashtag.Slot(key) != slot {
|
||||||
|
return fmt.Errorf("redis: Watch requires all keys to be in the same slot")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node, err := state.slotMasterNode(slot)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ {
|
||||||
|
if attempt > 0 {
|
||||||
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = node.Client.Watch(fn, keys...)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
moved, ask, addr := internal.IsMovedError(err)
|
||||||
|
if moved || ask {
|
||||||
|
c.lazyReloadState()
|
||||||
|
node, err = c.nodes.GetOrCreate(addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the cluster client, releasing any open resources.
|
// Close closes the cluster client, releasing any open resources.
|
||||||
@@ -547,7 +615,13 @@ func (c *ClusterClient) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) Process(cmd Cmder) error {
|
func (c *ClusterClient) Process(cmd Cmder) error {
|
||||||
slot, node, err := c.cmdSlotAndNode(c.state(), cmd)
|
state, err := c.state()
|
||||||
|
if err != nil {
|
||||||
|
cmd.setErr(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, node, err := c.cmdSlotAndNode(state, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.setErr(err)
|
cmd.setErr(err)
|
||||||
return err
|
return err
|
||||||
@@ -556,7 +630,7 @@ func (c *ClusterClient) Process(cmd Cmder) error {
|
|||||||
var ask bool
|
var ask bool
|
||||||
for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ {
|
for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ {
|
||||||
if attempt > 0 {
|
if attempt > 0 {
|
||||||
time.Sleep(node.Client.retryBackoff(attempt))
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
}
|
}
|
||||||
|
|
||||||
if ask {
|
if ask {
|
||||||
@@ -572,7 +646,7 @@ func (c *ClusterClient) Process(cmd Cmder) error {
|
|||||||
|
|
||||||
// If there is no error - we are done.
|
// If there is no error - we are done.
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// If slave is loading - read from master.
|
// If slave is loading - read from master.
|
||||||
@@ -582,12 +656,11 @@ func (c *ClusterClient) Process(cmd Cmder) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// On network errors try random node.
|
if internal.IsRetryableError(err, true) {
|
||||||
if internal.IsRetryableError(err) || internal.IsClusterDownError(err) {
|
var nodeErr error
|
||||||
node, err = c.nodes.Random()
|
node, nodeErr = c.nodes.Random()
|
||||||
if err != nil {
|
if nodeErr != nil {
|
||||||
cmd.setErr(err)
|
break
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -596,20 +669,13 @@ func (c *ClusterClient) Process(cmd Cmder) error {
|
|||||||
var addr string
|
var addr string
|
||||||
moved, ask, addr = internal.IsMovedError(err)
|
moved, ask, addr = internal.IsMovedError(err)
|
||||||
if moved || ask {
|
if moved || ask {
|
||||||
state := c.state()
|
c.lazyReloadState()
|
||||||
if state != nil && slot >= 0 {
|
|
||||||
master, _ := state.slotMasterNode(slot)
|
|
||||||
if moved && (master == nil || master.Client.getAddr() != addr) {
|
|
||||||
c.lazyReloadState()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node, err = c.nodes.GetOrCreate(addr)
|
var nodeErr error
|
||||||
if err != nil {
|
node, nodeErr = c.nodes.GetOrCreate(addr)
|
||||||
cmd.setErr(err)
|
if nodeErr != nil {
|
||||||
return err
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,9 +688,9 @@ func (c *ClusterClient) Process(cmd Cmder) error {
|
|||||||
// ForEachMaster concurrently calls the fn on each master node in the cluster.
|
// ForEachMaster concurrently calls the fn on each master node in the cluster.
|
||||||
// It returns the first error if any.
|
// It returns the first error if any.
|
||||||
func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
|
func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
|
||||||
state := c.state()
|
state, err := c.state()
|
||||||
if state == nil {
|
if err != nil {
|
||||||
return errNilClusterState
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
@@ -655,9 +721,9 @@ func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
|
|||||||
// ForEachSlave concurrently calls the fn on each slave node in the cluster.
|
// ForEachSlave concurrently calls the fn on each slave node in the cluster.
|
||||||
// It returns the first error if any.
|
// It returns the first error if any.
|
||||||
func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error {
|
func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error {
|
||||||
state := c.state()
|
state, err := c.state()
|
||||||
if state == nil {
|
if err != nil {
|
||||||
return errNilClusterState
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
@@ -688,9 +754,9 @@ func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error {
|
|||||||
// ForEachNode concurrently calls the fn on each known node in the cluster.
|
// ForEachNode concurrently calls the fn on each known node in the cluster.
|
||||||
// It returns the first error if any.
|
// It returns the first error if any.
|
||||||
func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error {
|
func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error {
|
||||||
state := c.state()
|
state, err := c.state()
|
||||||
if state == nil {
|
if err != nil {
|
||||||
return errNilClusterState
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
@@ -728,27 +794,31 @@ func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error {
|
|||||||
func (c *ClusterClient) PoolStats() *PoolStats {
|
func (c *ClusterClient) PoolStats() *PoolStats {
|
||||||
var acc PoolStats
|
var acc PoolStats
|
||||||
|
|
||||||
state := c.state()
|
state, _ := c.state()
|
||||||
if state == nil {
|
if state == nil {
|
||||||
return &acc
|
return &acc
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, node := range state.masters {
|
for _, node := range state.masters {
|
||||||
s := node.Client.connPool.Stats()
|
s := node.Client.connPool.Stats()
|
||||||
acc.Requests += s.Requests
|
|
||||||
acc.Hits += s.Hits
|
acc.Hits += s.Hits
|
||||||
|
acc.Misses += s.Misses
|
||||||
acc.Timeouts += s.Timeouts
|
acc.Timeouts += s.Timeouts
|
||||||
|
|
||||||
acc.TotalConns += s.TotalConns
|
acc.TotalConns += s.TotalConns
|
||||||
acc.FreeConns += s.FreeConns
|
acc.FreeConns += s.FreeConns
|
||||||
|
acc.StaleConns += s.StaleConns
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, node := range state.slaves {
|
for _, node := range state.slaves {
|
||||||
s := node.Client.connPool.Stats()
|
s := node.Client.connPool.Stats()
|
||||||
acc.Requests += s.Requests
|
|
||||||
acc.Hits += s.Hits
|
acc.Hits += s.Hits
|
||||||
|
acc.Misses += s.Misses
|
||||||
acc.Timeouts += s.Timeouts
|
acc.Timeouts += s.Timeouts
|
||||||
|
|
||||||
acc.TotalConns += s.TotalConns
|
acc.TotalConns += s.TotalConns
|
||||||
acc.FreeConns += s.FreeConns
|
acc.FreeConns += s.FreeConns
|
||||||
|
acc.StaleConns += s.StaleConns
|
||||||
}
|
}
|
||||||
|
|
||||||
return &acc
|
return &acc
|
||||||
@@ -762,10 +832,8 @@ func (c *ClusterClient) lazyReloadState() {
|
|||||||
go func() {
|
go func() {
|
||||||
defer atomic.StoreUint32(&c.reloading, 0)
|
defer atomic.StoreUint32(&c.reloading, 0)
|
||||||
|
|
||||||
var state *clusterState
|
|
||||||
for {
|
for {
|
||||||
var err error
|
state, err := c.reloadState()
|
||||||
state, err = c.reloadState()
|
|
||||||
if err == pool.ErrClosed {
|
if err == pool.ErrClosed {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -776,11 +844,10 @@ func (c *ClusterClient) lazyReloadState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c._state.Store(state)
|
c._state.Store(state)
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
c.nodes.GC(state.generation)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
|
||||||
c.nodes.GC(state.generation)
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -810,21 +877,12 @@ func (c *ClusterClient) reaper(idleCheckFrequency time.Duration) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
var n int
|
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
nn, err := node.Client.connPool.(*pool.ConnPool).ReapStaleConns()
|
_, err := node.Client.connPool.(*pool.ConnPool).ReapStaleConns()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
internal.Logf("ReapStaleConns failed: %s", err)
|
internal.Logf("ReapStaleConns failed: %s", err)
|
||||||
} else {
|
|
||||||
n += nn
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s := c.PoolStats()
|
|
||||||
internal.Logf(
|
|
||||||
"reaper: removed %d stale conns (TotalConns=%d FreeConns=%d Requests=%d Hits=%d Timeouts=%d)",
|
|
||||||
n, s.TotalConns, s.FreeConns, s.Requests, s.Hits, s.Timeouts,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,16 +895,21 @@ func (c *ClusterClient) Pipeline() Pipeliner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
func (c *ClusterClient) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
return c.Pipeline().pipelined(fn)
|
return c.Pipeline().Pipelined(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) pipelineExec(cmds []Cmder) error {
|
func (c *ClusterClient) pipelineExec(cmds []Cmder) error {
|
||||||
cmdsMap, err := c.mapCmdsByNode(cmds)
|
cmdsMap, err := c.mapCmdsByNode(cmds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
setCmdsErr(cmds, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i <= c.opt.MaxRedirects; i++ {
|
for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ {
|
||||||
|
if attempt > 0 {
|
||||||
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
|
}
|
||||||
|
|
||||||
failedCmds := make(map[*clusterNode][]Cmder)
|
failedCmds := make(map[*clusterNode][]Cmder)
|
||||||
|
|
||||||
for node, cmds := range cmdsMap {
|
for node, cmds := range cmdsMap {
|
||||||
@@ -856,8 +919,12 @@ func (c *ClusterClient) pipelineExec(cmds []Cmder) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.pipelineProcessCmds(cn, cmds, failedCmds)
|
err = c.pipelineProcessCmds(node, cn, cmds, failedCmds)
|
||||||
node.Client.releaseConn(cn, err)
|
if err == nil || internal.IsRedisError(err) {
|
||||||
|
_ = node.Client.connPool.Put(cn)
|
||||||
|
} else {
|
||||||
|
_ = node.Client.connPool.Remove(cn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(failedCmds) == 0 {
|
if len(failedCmds) == 0 {
|
||||||
@@ -866,21 +933,20 @@ func (c *ClusterClient) pipelineExec(cmds []Cmder) error {
|
|||||||
cmdsMap = failedCmds
|
cmdsMap = failedCmds
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstErr error
|
return firstCmdsErr(cmds)
|
||||||
for _, cmd := range cmds {
|
|
||||||
if err := cmd.Err(); err != nil {
|
|
||||||
firstErr = err
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return firstErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) mapCmdsByNode(cmds []Cmder) (map[*clusterNode][]Cmder, error) {
|
func (c *ClusterClient) mapCmdsByNode(cmds []Cmder) (map[*clusterNode][]Cmder, error) {
|
||||||
state := c.state()
|
state, err := c.state()
|
||||||
|
if err != nil {
|
||||||
|
setCmdsErr(cmds, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
cmdsMap := make(map[*clusterNode][]Cmder)
|
cmdsMap := make(map[*clusterNode][]Cmder)
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
_, node, err := c.cmdSlotAndNode(state, cmd)
|
slot := c.cmdSlot(cmd)
|
||||||
|
node, err := state.slotMasterNode(slot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -890,11 +956,12 @@ func (c *ClusterClient) mapCmdsByNode(cmds []Cmder) (map[*clusterNode][]Cmder, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) pipelineProcessCmds(
|
func (c *ClusterClient) pipelineProcessCmds(
|
||||||
cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
node *clusterNode, cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
||||||
) error {
|
) error {
|
||||||
cn.SetWriteTimeout(c.opt.WriteTimeout)
|
cn.SetWriteTimeout(c.opt.WriteTimeout)
|
||||||
if err := writeCmd(cn, cmds...); err != nil {
|
if err := writeCmd(cn, cmds...); err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
|
failedCmds[node] = cmds
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -907,46 +974,53 @@ func (c *ClusterClient) pipelineProcessCmds(
|
|||||||
func (c *ClusterClient) pipelineReadCmds(
|
func (c *ClusterClient) pipelineReadCmds(
|
||||||
cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
||||||
) error {
|
) error {
|
||||||
var firstErr error
|
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
err := cmd.readReply(cn)
|
err := cmd.readReply(cn)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if firstErr == nil {
|
if c.checkMovedErr(cmd, err, failedCmds) {
|
||||||
firstErr = err
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.checkMovedErr(cmd, failedCmds)
|
if internal.IsRedisError(err) {
|
||||||
if err != nil && firstErr == nil {
|
continue
|
||||||
firstErr = err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return firstErr
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) checkMovedErr(cmd Cmder, failedCmds map[*clusterNode][]Cmder) error {
|
func (c *ClusterClient) checkMovedErr(
|
||||||
moved, ask, addr := internal.IsMovedError(cmd.Err())
|
cmd Cmder, err error, failedCmds map[*clusterNode][]Cmder,
|
||||||
|
) bool {
|
||||||
|
moved, ask, addr := internal.IsMovedError(err)
|
||||||
|
|
||||||
if moved {
|
if moved {
|
||||||
c.lazyReloadState()
|
c.lazyReloadState()
|
||||||
|
|
||||||
node, err := c.nodes.GetOrCreate(addr)
|
node, err := c.nodes.GetOrCreate(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
failedCmds[node] = append(failedCmds[node], cmd)
|
failedCmds[node] = append(failedCmds[node], cmd)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ask {
|
if ask {
|
||||||
node, err := c.nodes.GetOrCreate(addr)
|
node, err := c.nodes.GetOrCreate(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
failedCmds[node] = append(failedCmds[node], NewCmd("ASKING"), cmd)
|
failedCmds[node] = append(failedCmds[node], NewCmd("ASKING"), cmd)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxPipeline acts like Pipeline, but wraps queued commands with MULTI/EXEC.
|
// TxPipeline acts like Pipeline, but wraps queued commands with MULTI/EXEC.
|
||||||
@@ -959,29 +1033,29 @@ func (c *ClusterClient) TxPipeline() Pipeliner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
func (c *ClusterClient) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
return c.TxPipeline().pipelined(fn)
|
return c.TxPipeline().Pipelined(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) txPipelineExec(cmds []Cmder) error {
|
func (c *ClusterClient) txPipelineExec(cmds []Cmder) error {
|
||||||
cmdsMap, err := c.mapCmdsBySlot(cmds)
|
state, err := c.state()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
state := c.state()
|
cmdsMap := c.mapCmdsBySlot(cmds)
|
||||||
if state == nil {
|
|
||||||
return errNilClusterState
|
|
||||||
}
|
|
||||||
|
|
||||||
for slot, cmds := range cmdsMap {
|
for slot, cmds := range cmdsMap {
|
||||||
node, err := state.slotMasterNode(slot)
|
node, err := state.slotMasterNode(slot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdsMap := map[*clusterNode][]Cmder{node: cmds}
|
cmdsMap := map[*clusterNode][]Cmder{node: cmds}
|
||||||
for i := 0; i <= c.opt.MaxRedirects; i++ {
|
|
||||||
|
for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ {
|
||||||
|
if attempt > 0 {
|
||||||
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
|
}
|
||||||
|
|
||||||
failedCmds := make(map[*clusterNode][]Cmder)
|
failedCmds := make(map[*clusterNode][]Cmder)
|
||||||
|
|
||||||
for node, cmds := range cmdsMap {
|
for node, cmds := range cmdsMap {
|
||||||
@@ -992,7 +1066,11 @@ func (c *ClusterClient) txPipelineExec(cmds []Cmder) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = c.txPipelineProcessCmds(node, cn, cmds, failedCmds)
|
err = c.txPipelineProcessCmds(node, cn, cmds, failedCmds)
|
||||||
node.Client.releaseConn(cn, err)
|
if err == nil || internal.IsRedisError(err) {
|
||||||
|
_ = node.Client.connPool.Put(cn)
|
||||||
|
} else {
|
||||||
|
_ = node.Client.connPool.Remove(cn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(failedCmds) == 0 {
|
if len(failedCmds) == 0 {
|
||||||
@@ -1002,27 +1080,16 @@ func (c *ClusterClient) txPipelineExec(cmds []Cmder) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstErr error
|
return firstCmdsErr(cmds)
|
||||||
for _, cmd := range cmds {
|
|
||||||
if err := cmd.Err(); err != nil {
|
|
||||||
firstErr = err
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return firstErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) mapCmdsBySlot(cmds []Cmder) (map[int][]Cmder, error) {
|
func (c *ClusterClient) mapCmdsBySlot(cmds []Cmder) map[int][]Cmder {
|
||||||
state := c.state()
|
|
||||||
cmdsMap := make(map[int][]Cmder)
|
cmdsMap := make(map[int][]Cmder)
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
slot, _, err := c.cmdSlotAndNode(state, cmd)
|
slot := c.cmdSlot(cmd)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cmdsMap[slot] = append(cmdsMap[slot], cmd)
|
cmdsMap[slot] = append(cmdsMap[slot], cmd)
|
||||||
}
|
}
|
||||||
return cmdsMap, nil
|
return cmdsMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) txPipelineProcessCmds(
|
func (c *ClusterClient) txPipelineProcessCmds(
|
||||||
@@ -1039,22 +1106,20 @@ func (c *ClusterClient) txPipelineProcessCmds(
|
|||||||
cn.SetReadTimeout(c.opt.ReadTimeout)
|
cn.SetReadTimeout(c.opt.ReadTimeout)
|
||||||
|
|
||||||
if err := c.txPipelineReadQueued(cn, cmds, failedCmds); err != nil {
|
if err := c.txPipelineReadQueued(cn, cmds, failedCmds); err != nil {
|
||||||
|
setCmdsErr(cmds, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := pipelineReadCmds(cn, cmds)
|
return pipelineReadCmds(cn, cmds)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) txPipelineReadQueued(
|
func (c *ClusterClient) txPipelineReadQueued(
|
||||||
cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
||||||
) error {
|
) error {
|
||||||
var firstErr error
|
|
||||||
|
|
||||||
// Parse queued replies.
|
// Parse queued replies.
|
||||||
var statusCmd StatusCmd
|
var statusCmd StatusCmd
|
||||||
if err := statusCmd.readReply(cn); err != nil && firstErr == nil {
|
if err := statusCmd.readReply(cn); err != nil {
|
||||||
firstErr = err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
@@ -1063,15 +1128,11 @@ func (c *ClusterClient) txPipelineReadQueued(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.setErr(err)
|
if c.checkMovedErr(cmd, err, failedCmds) || internal.IsRedisError(err) {
|
||||||
if firstErr == nil {
|
continue
|
||||||
firstErr = err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.checkMovedErr(cmd, failedCmds)
|
return err
|
||||||
if err != nil && firstErr == nil {
|
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse number of replies.
|
// Parse number of replies.
|
||||||
@@ -1085,7 +1146,13 @@ func (c *ClusterClient) txPipelineReadQueued(
|
|||||||
|
|
||||||
switch line[0] {
|
switch line[0] {
|
||||||
case proto.ErrorReply:
|
case proto.ErrorReply:
|
||||||
return proto.ParseErrorReply(line)
|
err := proto.ParseErrorReply(line)
|
||||||
|
for _, cmd := range cmds {
|
||||||
|
if !c.checkMovedErr(cmd, err, failedCmds) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
case proto.ArrayReply:
|
case proto.ArrayReply:
|
||||||
// ok
|
// ok
|
||||||
default:
|
default:
|
||||||
@@ -1093,7 +1160,7 @@ func (c *ClusterClient) txPipelineReadQueued(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstErr
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) pubSub(channels []string) *PubSub {
|
func (c *ClusterClient) pubSub(channels []string) *PubSub {
|
||||||
@@ -1112,7 +1179,12 @@ func (c *ClusterClient) pubSub(channels []string) *PubSub {
|
|||||||
slot = -1
|
slot = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
masterNode, err := c.state().slotMasterNode(slot)
|
state, err := c.state()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
masterNode, err := state.slotMasterNode(slot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
22
vendor/github.com/go-redis/redis/cluster_commands.go
сгенерированный
поставляемый
Обычный файл
22
vendor/github.com/go-redis/redis/cluster_commands.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,22 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import "sync/atomic"
|
||||||
|
|
||||||
|
func (c *ClusterClient) DBSize() *IntCmd {
|
||||||
|
cmd := NewIntCmd("dbsize")
|
||||||
|
var size int64
|
||||||
|
err := c.ForEachMaster(func(master *Client) error {
|
||||||
|
n, err := master.DBSize().Result()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
atomic.AddInt64(&size, n)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
cmd.setErr(err)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
cmd.val = size
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
81
vendor/github.com/go-redis/redis/cluster_test.go
сгенерированный
поставляемый
81
vendor/github.com/go-redis/redis/cluster_test.go
сгенерированный
поставляемый
@@ -200,7 +200,7 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
|
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return client.Get("A").Val()
|
return client.Get("A").Val()
|
||||||
}).Should(Equal("VALUE"))
|
}, 30*time.Second).Should(Equal("VALUE"))
|
||||||
|
|
||||||
cnt, err := client.Del("A").Result()
|
cnt, err := client.Del("A").Result()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@@ -215,7 +215,7 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
|
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return client.Get("A").Val()
|
return client.Get("A").Val()
|
||||||
}).Should(Equal("VALUE"))
|
}, 30*time.Second).Should(Equal("VALUE"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("distributes keys", func() {
|
It("distributes keys", func() {
|
||||||
@@ -227,7 +227,7 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
for _, master := range cluster.masters() {
|
for _, master := range cluster.masters() {
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return master.Info("keyspace").Val()
|
return master.Info("keyspace").Val()
|
||||||
}, 5*time.Second).Should(Or(
|
}, 30*time.Second).Should(Or(
|
||||||
ContainSubstring("keys=31"),
|
ContainSubstring("keys=31"),
|
||||||
ContainSubstring("keys=29"),
|
ContainSubstring("keys=29"),
|
||||||
ContainSubstring("keys=40"),
|
ContainSubstring("keys=40"),
|
||||||
@@ -251,7 +251,7 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
for _, master := range cluster.masters() {
|
for _, master := range cluster.masters() {
|
||||||
Eventually(func() string {
|
Eventually(func() string {
|
||||||
return master.Info("keyspace").Val()
|
return master.Info("keyspace").Val()
|
||||||
}, 5*time.Second).Should(Or(
|
}, 30*time.Second).Should(Or(
|
||||||
ContainSubstring("keys=31"),
|
ContainSubstring("keys=31"),
|
||||||
ContainSubstring("keys=29"),
|
ContainSubstring("keys=29"),
|
||||||
ContainSubstring("keys=40"),
|
ContainSubstring("keys=40"),
|
||||||
@@ -320,10 +320,6 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(cmds).To(HaveLen(14))
|
Expect(cmds).To(HaveLen(14))
|
||||||
|
|
||||||
if opt.RouteByLatency {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
slot := hashtag.Slot(key)
|
slot := hashtag.Slot(key)
|
||||||
client.SwapSlotNodes(slot)
|
client.SwapSlotNodes(slot)
|
||||||
@@ -432,6 +428,9 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
|
_ = client.ForEachMaster(func(master *redis.Client) error {
|
||||||
|
return master.FlushDB().Err()
|
||||||
|
})
|
||||||
Expect(client.Close()).NotTo(HaveOccurred())
|
Expect(client.Close()).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -476,11 +475,9 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
})
|
})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
for _, client := range cluster.masters() {
|
size, err := client.DBSize().Result()
|
||||||
size, err := client.DBSize().Result()
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(size).To(Equal(int64(0)))
|
||||||
Expect(size).To(Equal(int64(0)))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should CLUSTER SLOTS", func() {
|
It("should CLUSTER SLOTS", func() {
|
||||||
@@ -560,6 +557,9 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
|
_ = client.ForEachMaster(func(master *redis.Client) error {
|
||||||
|
return master.FlushDB().Err()
|
||||||
|
})
|
||||||
Expect(client.Close()).NotTo(HaveOccurred())
|
Expect(client.Close()).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -575,10 +575,19 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
_ = client.ForEachMaster(func(master *redis.Client) error {
|
_ = client.ForEachMaster(func(master *redis.Client) error {
|
||||||
return master.FlushDB().Err()
|
return master.FlushDB().Err()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
_ = client.ForEachSlave(func(slave *redis.Client) error {
|
||||||
|
Eventually(func() int64 {
|
||||||
|
return client.DBSize().Val()
|
||||||
|
}, 30*time.Second).Should(Equal(int64(0)))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
client.FlushDB()
|
_ = client.ForEachMaster(func(master *redis.Client) error {
|
||||||
|
return master.FlushDB().Err()
|
||||||
|
})
|
||||||
Expect(client.Close()).NotTo(HaveOccurred())
|
Expect(client.Close()).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -597,7 +606,7 @@ var _ = Describe("ClusterClient without nodes", func() {
|
|||||||
Expect(client.Close()).NotTo(HaveOccurred())
|
Expect(client.Close()).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("returns an error", func() {
|
It("Ping returns an error", func() {
|
||||||
err := client.Ping().Err()
|
err := client.Ping().Err()
|
||||||
Expect(err).To(MatchError("redis: cluster has no nodes"))
|
Expect(err).To(MatchError("redis: cluster has no nodes"))
|
||||||
})
|
})
|
||||||
@@ -626,7 +635,7 @@ var _ = Describe("ClusterClient without valid nodes", func() {
|
|||||||
|
|
||||||
It("returns an error", func() {
|
It("returns an error", func() {
|
||||||
err := client.Ping().Err()
|
err := client.Ping().Err()
|
||||||
Expect(err).To(MatchError("ERR This instance has cluster support disabled"))
|
Expect(err).To(MatchError("redis: cannot load cluster slots"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("pipeline returns an error", func() {
|
It("pipeline returns an error", func() {
|
||||||
@@ -634,7 +643,7 @@ var _ = Describe("ClusterClient without valid nodes", func() {
|
|||||||
pipe.Ping()
|
pipe.Ping()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
Expect(err).To(MatchError("ERR This instance has cluster support disabled"))
|
Expect(err).To(MatchError("redis: cannot load cluster slots"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -664,7 +673,7 @@ var _ = Describe("ClusterClient timeout", func() {
|
|||||||
It("Tx timeouts", func() {
|
It("Tx timeouts", func() {
|
||||||
err := client.Watch(func(tx *redis.Tx) error {
|
err := client.Watch(func(tx *redis.Tx) error {
|
||||||
return tx.Ping().Err()
|
return tx.Ping().Err()
|
||||||
})
|
}, "foo")
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
Expect(err.(net.Error).Timeout()).To(BeTrue())
|
Expect(err.(net.Error).Timeout()).To(BeTrue())
|
||||||
})
|
})
|
||||||
@@ -676,42 +685,20 @@ var _ = Describe("ClusterClient timeout", func() {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
})
|
}, "foo")
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
Expect(err.(net.Error).Timeout()).To(BeTrue())
|
Expect(err.(net.Error).Timeout()).To(BeTrue())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Context("read timeout", func() {
|
const pause = time.Second
|
||||||
|
|
||||||
|
Context("read/write timeout", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
opt := redisClusterOptions()
|
opt := redisClusterOptions()
|
||||||
opt.ReadTimeout = time.Nanosecond
|
opt.ReadTimeout = 100 * time.Millisecond
|
||||||
opt.WriteTimeout = -1
|
opt.WriteTimeout = 100 * time.Millisecond
|
||||||
client = cluster.clusterClient(opt)
|
opt.MaxRedirects = 1
|
||||||
})
|
|
||||||
|
|
||||||
testTimeout()
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("write timeout", func() {
|
|
||||||
BeforeEach(func() {
|
|
||||||
opt := redisClusterOptions()
|
|
||||||
opt.ReadTimeout = time.Nanosecond
|
|
||||||
opt.WriteTimeout = -1
|
|
||||||
client = cluster.clusterClient(opt)
|
|
||||||
})
|
|
||||||
|
|
||||||
testTimeout()
|
|
||||||
})
|
|
||||||
|
|
||||||
Context("ClientPause timeout", func() {
|
|
||||||
const pause = time.Second
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
|
||||||
opt := redisClusterOptions()
|
|
||||||
opt.ReadTimeout = pause / 10
|
|
||||||
opt.WriteTimeout = pause / 10
|
|
||||||
opt.MaxRedirects = -1
|
|
||||||
client = cluster.clusterClient(opt)
|
client = cluster.clusterClient(opt)
|
||||||
|
|
||||||
err := client.ForEachNode(func(client *redis.Client) error {
|
err := client.ForEachNode(func(client *redis.Client) error {
|
||||||
|
|||||||
86
vendor/github.com/go-redis/redis/command.go
сгенерированный
поставляемый
86
vendor/github.com/go-redis/redis/command.go
сгенерированный
поставляемый
@@ -12,28 +12,10 @@ import (
|
|||||||
"github.com/go-redis/redis/internal/proto"
|
"github.com/go-redis/redis/internal/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
_ Cmder = (*Cmd)(nil)
|
|
||||||
_ Cmder = (*SliceCmd)(nil)
|
|
||||||
_ Cmder = (*StatusCmd)(nil)
|
|
||||||
_ Cmder = (*IntCmd)(nil)
|
|
||||||
_ Cmder = (*DurationCmd)(nil)
|
|
||||||
_ Cmder = (*BoolCmd)(nil)
|
|
||||||
_ Cmder = (*StringCmd)(nil)
|
|
||||||
_ Cmder = (*FloatCmd)(nil)
|
|
||||||
_ Cmder = (*StringSliceCmd)(nil)
|
|
||||||
_ Cmder = (*BoolSliceCmd)(nil)
|
|
||||||
_ Cmder = (*StringStringMapCmd)(nil)
|
|
||||||
_ Cmder = (*StringIntMapCmd)(nil)
|
|
||||||
_ Cmder = (*ZSliceCmd)(nil)
|
|
||||||
_ Cmder = (*ScanCmd)(nil)
|
|
||||||
_ Cmder = (*ClusterSlotsCmd)(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
type Cmder interface {
|
type Cmder interface {
|
||||||
args() []interface{}
|
|
||||||
arg(int) string
|
|
||||||
Name() string
|
Name() string
|
||||||
|
Args() []interface{}
|
||||||
|
stringArg(int) string
|
||||||
|
|
||||||
readReply(*pool.Conn) error
|
readReply(*pool.Conn) error
|
||||||
setErr(error)
|
setErr(error)
|
||||||
@@ -46,14 +28,25 @@ type Cmder interface {
|
|||||||
|
|
||||||
func setCmdsErr(cmds []Cmder, e error) {
|
func setCmdsErr(cmds []Cmder, e error) {
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
cmd.setErr(e)
|
if cmd.Err() == nil {
|
||||||
|
cmd.setErr(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func firstCmdsErr(cmds []Cmder) error {
|
||||||
|
for _, cmd := range cmds {
|
||||||
|
if err := cmd.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func writeCmd(cn *pool.Conn, cmds ...Cmder) error {
|
func writeCmd(cn *pool.Conn, cmds ...Cmder) error {
|
||||||
cn.Wb.Reset()
|
cn.Wb.Reset()
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
if err := cn.Wb.Append(cmd.args()); err != nil {
|
if err := cn.Wb.Append(cmd.Args()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +57,7 @@ func writeCmd(cn *pool.Conn, cmds ...Cmder) error {
|
|||||||
|
|
||||||
func cmdString(cmd Cmder, val interface{}) string {
|
func cmdString(cmd Cmder, val interface{}) string {
|
||||||
var ss []string
|
var ss []string
|
||||||
for _, arg := range cmd.args() {
|
for _, arg := range cmd.Args() {
|
||||||
ss = append(ss, fmt.Sprint(arg))
|
ss = append(ss, fmt.Sprint(arg))
|
||||||
}
|
}
|
||||||
s := strings.Join(ss, " ")
|
s := strings.Join(ss, " ")
|
||||||
@@ -86,7 +79,7 @@ func cmdString(cmd Cmder, val interface{}) string {
|
|||||||
func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
|
func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
|
||||||
switch cmd.Name() {
|
switch cmd.Name() {
|
||||||
case "eval", "evalsha":
|
case "eval", "evalsha":
|
||||||
if cmd.arg(2) != "0" {
|
if cmd.stringArg(2) != "0" {
|
||||||
return 3
|
return 3
|
||||||
} else {
|
} else {
|
||||||
return -1
|
return -1
|
||||||
@@ -95,7 +88,6 @@ func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
if info == nil {
|
if info == nil {
|
||||||
internal.Logf("info for cmd=%s not found", cmd.Name())
|
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(info.FirstKeyPos)
|
return int(info.FirstKeyPos)
|
||||||
@@ -110,15 +102,17 @@ type baseCmd struct {
|
|||||||
_readTimeout *time.Duration
|
_readTimeout *time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*Cmd)(nil)
|
||||||
|
|
||||||
func (cmd *baseCmd) Err() error {
|
func (cmd *baseCmd) Err() error {
|
||||||
return cmd.err
|
return cmd.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *baseCmd) args() []interface{} {
|
func (cmd *baseCmd) Args() []interface{} {
|
||||||
return cmd._args
|
return cmd._args
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *baseCmd) arg(pos int) string {
|
func (cmd *baseCmd) stringArg(pos int) string {
|
||||||
if pos < 0 || pos >= len(cmd._args) {
|
if pos < 0 || pos >= len(cmd._args) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -129,7 +123,7 @@ func (cmd *baseCmd) arg(pos int) string {
|
|||||||
func (cmd *baseCmd) Name() string {
|
func (cmd *baseCmd) Name() string {
|
||||||
if len(cmd._args) > 0 {
|
if len(cmd._args) > 0 {
|
||||||
// Cmd name must be lower cased.
|
// Cmd name must be lower cased.
|
||||||
s := internal.ToLower(cmd.arg(0))
|
s := internal.ToLower(cmd.stringArg(0))
|
||||||
cmd._args[0] = s
|
cmd._args[0] = s
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@@ -194,6 +188,8 @@ type SliceCmd struct {
|
|||||||
val []interface{}
|
val []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*SliceCmd)(nil)
|
||||||
|
|
||||||
func NewSliceCmd(args ...interface{}) *SliceCmd {
|
func NewSliceCmd(args ...interface{}) *SliceCmd {
|
||||||
return &SliceCmd{
|
return &SliceCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -230,6 +226,8 @@ type StatusCmd struct {
|
|||||||
val string
|
val string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*StatusCmd)(nil)
|
||||||
|
|
||||||
func NewStatusCmd(args ...interface{}) *StatusCmd {
|
func NewStatusCmd(args ...interface{}) *StatusCmd {
|
||||||
return &StatusCmd{
|
return &StatusCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -261,6 +259,8 @@ type IntCmd struct {
|
|||||||
val int64
|
val int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*IntCmd)(nil)
|
||||||
|
|
||||||
func NewIntCmd(args ...interface{}) *IntCmd {
|
func NewIntCmd(args ...interface{}) *IntCmd {
|
||||||
return &IntCmd{
|
return &IntCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -293,6 +293,8 @@ type DurationCmd struct {
|
|||||||
precision time.Duration
|
precision time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*DurationCmd)(nil)
|
||||||
|
|
||||||
func NewDurationCmd(precision time.Duration, args ...interface{}) *DurationCmd {
|
func NewDurationCmd(precision time.Duration, args ...interface{}) *DurationCmd {
|
||||||
return &DurationCmd{
|
return &DurationCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -330,6 +332,8 @@ type TimeCmd struct {
|
|||||||
val time.Time
|
val time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*TimeCmd)(nil)
|
||||||
|
|
||||||
func NewTimeCmd(args ...interface{}) *TimeCmd {
|
func NewTimeCmd(args ...interface{}) *TimeCmd {
|
||||||
return &TimeCmd{
|
return &TimeCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -366,6 +370,8 @@ type BoolCmd struct {
|
|||||||
val bool
|
val bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*BoolCmd)(nil)
|
||||||
|
|
||||||
func NewBoolCmd(args ...interface{}) *BoolCmd {
|
func NewBoolCmd(args ...interface{}) *BoolCmd {
|
||||||
return &BoolCmd{
|
return &BoolCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -421,6 +427,8 @@ type StringCmd struct {
|
|||||||
val []byte
|
val []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*StringCmd)(nil)
|
||||||
|
|
||||||
func NewStringCmd(args ...interface{}) *StringCmd {
|
func NewStringCmd(args ...interface{}) *StringCmd {
|
||||||
return &StringCmd{
|
return &StringCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -484,6 +492,8 @@ type FloatCmd struct {
|
|||||||
val float64
|
val float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*FloatCmd)(nil)
|
||||||
|
|
||||||
func NewFloatCmd(args ...interface{}) *FloatCmd {
|
func NewFloatCmd(args ...interface{}) *FloatCmd {
|
||||||
return &FloatCmd{
|
return &FloatCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -515,6 +525,8 @@ type StringSliceCmd struct {
|
|||||||
val []string
|
val []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*StringSliceCmd)(nil)
|
||||||
|
|
||||||
func NewStringSliceCmd(args ...interface{}) *StringSliceCmd {
|
func NewStringSliceCmd(args ...interface{}) *StringSliceCmd {
|
||||||
return &StringSliceCmd{
|
return &StringSliceCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -555,6 +567,8 @@ type BoolSliceCmd struct {
|
|||||||
val []bool
|
val []bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*BoolSliceCmd)(nil)
|
||||||
|
|
||||||
func NewBoolSliceCmd(args ...interface{}) *BoolSliceCmd {
|
func NewBoolSliceCmd(args ...interface{}) *BoolSliceCmd {
|
||||||
return &BoolSliceCmd{
|
return &BoolSliceCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -591,6 +605,8 @@ type StringStringMapCmd struct {
|
|||||||
val map[string]string
|
val map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*StringStringMapCmd)(nil)
|
||||||
|
|
||||||
func NewStringStringMapCmd(args ...interface{}) *StringStringMapCmd {
|
func NewStringStringMapCmd(args ...interface{}) *StringStringMapCmd {
|
||||||
return &StringStringMapCmd{
|
return &StringStringMapCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -627,6 +643,8 @@ type StringIntMapCmd struct {
|
|||||||
val map[string]int64
|
val map[string]int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*StringIntMapCmd)(nil)
|
||||||
|
|
||||||
func NewStringIntMapCmd(args ...interface{}) *StringIntMapCmd {
|
func NewStringIntMapCmd(args ...interface{}) *StringIntMapCmd {
|
||||||
return &StringIntMapCmd{
|
return &StringIntMapCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -663,6 +681,8 @@ type ZSliceCmd struct {
|
|||||||
val []Z
|
val []Z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*ZSliceCmd)(nil)
|
||||||
|
|
||||||
func NewZSliceCmd(args ...interface{}) *ZSliceCmd {
|
func NewZSliceCmd(args ...interface{}) *ZSliceCmd {
|
||||||
return &ZSliceCmd{
|
return &ZSliceCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -702,6 +722,8 @@ type ScanCmd struct {
|
|||||||
process func(cmd Cmder) error
|
process func(cmd Cmder) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*ScanCmd)(nil)
|
||||||
|
|
||||||
func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd {
|
func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd {
|
||||||
return &ScanCmd{
|
return &ScanCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -752,6 +774,8 @@ type ClusterSlotsCmd struct {
|
|||||||
val []ClusterSlot
|
val []ClusterSlot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*ClusterSlotsCmd)(nil)
|
||||||
|
|
||||||
func NewClusterSlotsCmd(args ...interface{}) *ClusterSlotsCmd {
|
func NewClusterSlotsCmd(args ...interface{}) *ClusterSlotsCmd {
|
||||||
return &ClusterSlotsCmd{
|
return &ClusterSlotsCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -811,6 +835,8 @@ type GeoLocationCmd struct {
|
|||||||
locations []GeoLocation
|
locations []GeoLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*GeoLocationCmd)(nil)
|
||||||
|
|
||||||
func NewGeoLocationCmd(q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd {
|
func NewGeoLocationCmd(q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd {
|
||||||
args = append(args, q.Radius)
|
args = append(args, q.Radius)
|
||||||
if q.Unit != "" {
|
if q.Unit != "" {
|
||||||
@@ -881,6 +907,8 @@ type GeoPosCmd struct {
|
|||||||
positions []*GeoPos
|
positions []*GeoPos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*GeoPosCmd)(nil)
|
||||||
|
|
||||||
func NewGeoPosCmd(args ...interface{}) *GeoPosCmd {
|
func NewGeoPosCmd(args ...interface{}) *GeoPosCmd {
|
||||||
return &GeoPosCmd{
|
return &GeoPosCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
@@ -927,6 +955,8 @@ type CommandsInfoCmd struct {
|
|||||||
val map[string]*CommandInfo
|
val map[string]*CommandInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Cmder = (*CommandsInfoCmd)(nil)
|
||||||
|
|
||||||
func NewCommandsInfoCmd(args ...interface{}) *CommandsInfoCmd {
|
func NewCommandsInfoCmd(args ...interface{}) *CommandsInfoCmd {
|
||||||
return &CommandsInfoCmd{
|
return &CommandsInfoCmd{
|
||||||
baseCmd: baseCmd{_args: args},
|
baseCmd: baseCmd{_args: args},
|
||||||
|
|||||||
5
vendor/github.com/go-redis/redis/commands.go
сгенерированный
поставляемый
5
vendor/github.com/go-redis/redis/commands.go
сгенерированный
поставляемый
@@ -11,7 +11,7 @@ func readTimeout(timeout time.Duration) time.Duration {
|
|||||||
if timeout == 0 {
|
if timeout == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return timeout + time.Second
|
return timeout + 10*time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
func usePrecise(dur time.Duration) bool {
|
func usePrecise(dur time.Duration) bool {
|
||||||
@@ -42,6 +42,9 @@ type Cmdable interface {
|
|||||||
Pipeline() Pipeliner
|
Pipeline() Pipeliner
|
||||||
Pipelined(fn func(Pipeliner) error) ([]Cmder, error)
|
Pipelined(fn func(Pipeliner) error) ([]Cmder, error)
|
||||||
|
|
||||||
|
TxPipelined(fn func(Pipeliner) error) ([]Cmder, error)
|
||||||
|
TxPipeline() Pipeliner
|
||||||
|
|
||||||
ClientGetName() *StringCmd
|
ClientGetName() *StringCmd
|
||||||
Echo(message interface{}) *StringCmd
|
Echo(message interface{}) *StringCmd
|
||||||
Ping() *StatusCmd
|
Ping() *StatusCmd
|
||||||
|
|||||||
55
vendor/github.com/go-redis/redis/commands_test.go
сгенерированный
поставляемый
55
vendor/github.com/go-redis/redis/commands_test.go
сгенерированный
поставляемый
@@ -27,11 +27,21 @@ var _ = Describe("Commands", func() {
|
|||||||
Describe("server", func() {
|
Describe("server", func() {
|
||||||
|
|
||||||
It("should Auth", func() {
|
It("should Auth", func() {
|
||||||
_, err := client.Pipelined(func(pipe redis.Pipeliner) error {
|
cmds, err := client.Pipelined(func(pipe redis.Pipeliner) error {
|
||||||
pipe.Auth("password")
|
pipe.Auth("password")
|
||||||
|
pipe.Auth("")
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
Expect(err).To(MatchError("ERR Client sent AUTH, but no password is set"))
|
Expect(err).To(MatchError("ERR Client sent AUTH, but no password is set"))
|
||||||
|
Expect(cmds[0].Err()).To(MatchError("ERR Client sent AUTH, but no password is set"))
|
||||||
|
Expect(cmds[1].Err()).To(MatchError("ERR Client sent AUTH, but no password is set"))
|
||||||
|
|
||||||
|
stats := client.PoolStats()
|
||||||
|
Expect(stats.Hits).To(Equal(uint32(1)))
|
||||||
|
Expect(stats.Misses).To(Equal(uint32(1)))
|
||||||
|
Expect(stats.Timeouts).To(Equal(uint32(0)))
|
||||||
|
Expect(stats.TotalConns).To(Equal(uint32(1)))
|
||||||
|
Expect(stats.FreeConns).To(Equal(uint32(1)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should Echo", func() {
|
It("should Echo", func() {
|
||||||
@@ -187,6 +197,29 @@ var _ = Describe("Commands", func() {
|
|||||||
Expect(tm).To(BeTemporally("~", time.Now(), 3*time.Second))
|
Expect(tm).To(BeTemporally("~", time.Now(), 3*time.Second))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Should Command", func() {
|
||||||
|
cmds, err := client.Command().Result()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(cmds)).To(BeNumerically("~", 180, 10))
|
||||||
|
|
||||||
|
cmd := cmds["mget"]
|
||||||
|
Expect(cmd.Name).To(Equal("mget"))
|
||||||
|
Expect(cmd.Arity).To(Equal(int8(-2)))
|
||||||
|
Expect(cmd.Flags).To(ContainElement("readonly"))
|
||||||
|
Expect(cmd.FirstKeyPos).To(Equal(int8(1)))
|
||||||
|
Expect(cmd.LastKeyPos).To(Equal(int8(-1)))
|
||||||
|
Expect(cmd.StepCount).To(Equal(int8(1)))
|
||||||
|
|
||||||
|
cmd = cmds["ping"]
|
||||||
|
Expect(cmd.Name).To(Equal("ping"))
|
||||||
|
Expect(cmd.Arity).To(Equal(int8(-1)))
|
||||||
|
Expect(cmd.Flags).To(ContainElement("stale"))
|
||||||
|
Expect(cmd.Flags).To(ContainElement("fast"))
|
||||||
|
Expect(cmd.FirstKeyPos).To(Equal(int8(0)))
|
||||||
|
Expect(cmd.LastKeyPos).To(Equal(int8(0)))
|
||||||
|
Expect(cmd.StepCount).To(Equal(int8(0)))
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("debugging", func() {
|
Describe("debugging", func() {
|
||||||
@@ -1358,8 +1391,8 @@ var _ = Describe("Commands", func() {
|
|||||||
Expect(client.Ping().Err()).NotTo(HaveOccurred())
|
Expect(client.Ping().Err()).NotTo(HaveOccurred())
|
||||||
|
|
||||||
stats := client.PoolStats()
|
stats := client.PoolStats()
|
||||||
Expect(stats.Requests).To(Equal(uint32(3)))
|
|
||||||
Expect(stats.Hits).To(Equal(uint32(1)))
|
Expect(stats.Hits).To(Equal(uint32(1)))
|
||||||
|
Expect(stats.Misses).To(Equal(uint32(2)))
|
||||||
Expect(stats.Timeouts).To(Equal(uint32(0)))
|
Expect(stats.Timeouts).To(Equal(uint32(0)))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -2887,24 +2920,6 @@ var _ = Describe("Commands", func() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Command", func() {
|
|
||||||
|
|
||||||
It("returns map of commands", func() {
|
|
||||||
cmds, err := client.Command().Result()
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
Expect(len(cmds)).To(BeNumerically("~", 180, 10))
|
|
||||||
|
|
||||||
cmd := cmds["mget"]
|
|
||||||
Expect(cmd.Name).To(Equal("mget"))
|
|
||||||
Expect(cmd.Arity).To(Equal(int8(-2)))
|
|
||||||
Expect(cmd.Flags).To(ContainElement("readonly"))
|
|
||||||
Expect(cmd.FirstKeyPos).To(Equal(int8(1)))
|
|
||||||
Expect(cmd.LastKeyPos).To(Equal(int8(-1)))
|
|
||||||
Expect(cmd.StepCount).To(Equal(int8(1)))
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
Describe("Eval", func() {
|
Describe("Eval", func() {
|
||||||
|
|
||||||
It("returns keys and values", func() {
|
It("returns keys and values", func() {
|
||||||
|
|||||||
14
vendor/github.com/go-redis/redis/export_test.go
сгенерированный
поставляемый
14
vendor/github.com/go-redis/redis/export_test.go
сгенерированный
поставляемый
@@ -20,8 +20,13 @@ func (c *PubSub) ReceiveMessageTimeout(timeout time.Duration) (*Message, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) SlotAddrs(slot int) []string {
|
func (c *ClusterClient) SlotAddrs(slot int) []string {
|
||||||
|
state, err := c.state()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
var addrs []string
|
var addrs []string
|
||||||
for _, n := range c.state().slotNodes(slot) {
|
for _, n := range state.slotNodes(slot) {
|
||||||
addrs = append(addrs, n.Client.getAddr())
|
addrs = append(addrs, n.Client.getAddr())
|
||||||
}
|
}
|
||||||
return addrs
|
return addrs
|
||||||
@@ -29,7 +34,12 @@ func (c *ClusterClient) SlotAddrs(slot int) []string {
|
|||||||
|
|
||||||
// SwapSlot swaps a slot's master/slave address for testing MOVED redirects.
|
// SwapSlot swaps a slot's master/slave address for testing MOVED redirects.
|
||||||
func (c *ClusterClient) SwapSlotNodes(slot int) {
|
func (c *ClusterClient) SwapSlotNodes(slot int) {
|
||||||
nodes := c.state().slots[slot]
|
state, err := c.state()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes := state.slots[slot]
|
||||||
if len(nodes) == 2 {
|
if len(nodes) == 2 {
|
||||||
nodes[0], nodes[1] = nodes[1], nodes[0]
|
nodes[0], nodes[1] = nodes[1], nodes[0]
|
||||||
}
|
}
|
||||||
|
|||||||
27
vendor/github.com/go-redis/redis/internal/error.go
сгенерированный
поставляемый
27
vendor/github.com/go-redis/redis/internal/error.go
сгенерированный
поставляемый
@@ -12,11 +12,24 @@ type RedisError string
|
|||||||
|
|
||||||
func (e RedisError) Error() string { return string(e) }
|
func (e RedisError) Error() string { return string(e) }
|
||||||
|
|
||||||
func IsRetryableError(err error) bool {
|
func IsRetryableError(err error, retryNetError bool) bool {
|
||||||
return IsNetworkError(err) || err.Error() == "ERR max number of clients reached"
|
if IsNetworkError(err) {
|
||||||
|
return retryNetError
|
||||||
|
}
|
||||||
|
s := err.Error()
|
||||||
|
if s == "ERR max number of clients reached" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(s, "LOADING ") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(s, "CLUSTERDOWN ") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsInternalError(err error) bool {
|
func IsRedisError(err error) bool {
|
||||||
_, ok := err.(RedisError)
|
_, ok := err.(RedisError)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
@@ -33,7 +46,7 @@ func IsBadConn(err error, allowTimeout bool) bool {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if IsInternalError(err) {
|
if IsRedisError(err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if allowTimeout {
|
if allowTimeout {
|
||||||
@@ -45,7 +58,7 @@ func IsBadConn(err error, allowTimeout bool) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func IsMovedError(err error) (moved bool, ask bool, addr string) {
|
func IsMovedError(err error) (moved bool, ask bool, addr string) {
|
||||||
if !IsInternalError(err) {
|
if !IsRedisError(err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +82,3 @@ func IsMovedError(err error) (moved bool, ask bool, addr string) {
|
|||||||
func IsLoadingError(err error) bool {
|
func IsLoadingError(err error) bool {
|
||||||
return strings.HasPrefix(err.Error(), "LOADING ")
|
return strings.HasPrefix(err.Error(), "LOADING ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsClusterDownError(err error) bool {
|
|
||||||
return strings.HasPrefix(err.Error(), "CLUSTERDOWN ")
|
|
||||||
}
|
|
||||||
|
|||||||
25
vendor/github.com/go-redis/redis/internal/pool/pool.go
сгенерированный
поставляемый
25
vendor/github.com/go-redis/redis/internal/pool/pool.go
сгенерированный
поставляемый
@@ -23,12 +23,13 @@ var timers = sync.Pool{
|
|||||||
|
|
||||||
// Stats contains pool state information and accumulated stats.
|
// Stats contains pool state information and accumulated stats.
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
Requests uint32 // number of times a connection was requested by the pool
|
|
||||||
Hits uint32 // number of times free connection was found in the pool
|
Hits uint32 // number of times free connection was found in the pool
|
||||||
|
Misses uint32 // number of times free connection was NOT found in the pool
|
||||||
Timeouts uint32 // number of times a wait timeout occurred
|
Timeouts uint32 // number of times a wait timeout occurred
|
||||||
|
|
||||||
TotalConns uint32 // the number of total connections in the pool
|
TotalConns uint32 // number of total connections in the pool
|
||||||
FreeConns uint32 // the number of free connections in the pool
|
FreeConns uint32 // number of free connections in the pool
|
||||||
|
StaleConns uint32 // number of stale connections removed from the pool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pooler interface {
|
type Pooler interface {
|
||||||
@@ -150,8 +151,6 @@ func (p *ConnPool) Get() (*Conn, bool, error) {
|
|||||||
return nil, false, ErrClosed
|
return nil, false, ErrClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic.AddUint32(&p.stats.Requests, 1)
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case p.queue <- struct{}{}:
|
case p.queue <- struct{}{}:
|
||||||
default:
|
default:
|
||||||
@@ -189,6 +188,8 @@ func (p *ConnPool) Get() (*Conn, bool, error) {
|
|||||||
return cn, false, nil
|
return cn, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic.AddUint32(&p.stats.Misses, 1)
|
||||||
|
|
||||||
newcn, err := p.NewConn()
|
newcn, err := p.NewConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
<-p.queue
|
<-p.queue
|
||||||
@@ -265,11 +266,13 @@ func (p *ConnPool) FreeLen() int {
|
|||||||
|
|
||||||
func (p *ConnPool) Stats() *Stats {
|
func (p *ConnPool) Stats() *Stats {
|
||||||
return &Stats{
|
return &Stats{
|
||||||
Requests: atomic.LoadUint32(&p.stats.Requests),
|
Hits: atomic.LoadUint32(&p.stats.Hits),
|
||||||
Hits: atomic.LoadUint32(&p.stats.Hits),
|
Misses: atomic.LoadUint32(&p.stats.Misses),
|
||||||
Timeouts: atomic.LoadUint32(&p.stats.Timeouts),
|
Timeouts: atomic.LoadUint32(&p.stats.Timeouts),
|
||||||
|
|
||||||
TotalConns: uint32(p.Len()),
|
TotalConns: uint32(p.Len()),
|
||||||
FreeConns: uint32(p.FreeLen()),
|
FreeConns: uint32(p.FreeLen()),
|
||||||
|
StaleConns: atomic.LoadUint32(&p.stats.StaleConns),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,10 +365,6 @@ func (p *ConnPool) reaper(frequency time.Duration) {
|
|||||||
internal.Logf("ReapStaleConns failed: %s", err)
|
internal.Logf("ReapStaleConns failed: %s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s := p.Stats()
|
atomic.AddUint32(&p.stats.StaleConns, uint32(n))
|
||||||
internal.Logf(
|
|
||||||
"reaper: removed %d stale conns (TotalConns=%d FreeConns=%d Requests=%d Hits=%d Timeouts=%d)",
|
|
||||||
n, s.TotalConns, s.FreeConns, s.Requests, s.Hits, s.Timeouts,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/github.com/go-redis/redis/internal/proto/reader.go
сгенерированный
поставляемый
2
vendor/github.com/go-redis/redis/internal/proto/reader.go
сгенерированный
поставляемый
@@ -63,7 +63,7 @@ func (p *Reader) ReadLine() ([]byte, error) {
|
|||||||
return nil, bufio.ErrBufferFull
|
return nil, bufio.ErrBufferFull
|
||||||
}
|
}
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
return nil, internal.RedisError("redis: reply is empty")
|
return nil, fmt.Errorf("redis: reply is empty")
|
||||||
}
|
}
|
||||||
if isNilReply(line) {
|
if isNilReply(line) {
|
||||||
return nil, internal.Nil
|
return nil, internal.Nil
|
||||||
|
|||||||
2
vendor/github.com/go-redis/redis/internal/proto/scan.go
сгенерированный
поставляемый
2
vendor/github.com/go-redis/redis/internal/proto/scan.go
сгенерированный
поставляемый
@@ -11,7 +11,7 @@ import (
|
|||||||
func Scan(b []byte, v interface{}) error {
|
func Scan(b []byte, v interface{}) error {
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
return internal.RedisError("redis: Scan(nil)")
|
return fmt.Errorf("redis: Scan(nil)")
|
||||||
case *string:
|
case *string:
|
||||||
*v = internal.BytesToString(b)
|
*v = internal.BytesToString(b)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
4
vendor/github.com/go-redis/redis/main_test.go
сгенерированный
поставляемый
4
vendor/github.com/go-redis/redis/main_test.go
сгенерированный
поставляемый
@@ -50,10 +50,6 @@ var cluster = &clusterScenario{
|
|||||||
clients: make(map[string]*redis.Client, 6),
|
clients: make(map[string]*redis.Client, 6),
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
//redis.SetLogger(log.New(os.Stderr, "redis: ", log.LstdFlags|log.Lshortfile))
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = BeforeSuite(func() {
|
var _ = BeforeSuite(func() {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|||||||
10
vendor/github.com/go-redis/redis/options.go
сгенерированный
поставляемый
10
vendor/github.com/go-redis/redis/options.go
сгенерированный
поставляемый
@@ -198,13 +198,3 @@ func newConnPool(opt *Options) *pool.ConnPool {
|
|||||||
IdleCheckFrequency: opt.IdleCheckFrequency,
|
IdleCheckFrequency: opt.IdleCheckFrequency,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// PoolStats contains pool state information and accumulated stats.
|
|
||||||
type PoolStats struct {
|
|
||||||
Requests uint32 // number of times a connection was requested by the pool
|
|
||||||
Hits uint32 // number of times free connection was found in the pool
|
|
||||||
Timeouts uint32 // number of times a wait timeout occurred
|
|
||||||
|
|
||||||
TotalConns uint32 // the number of total connections in the pool
|
|
||||||
FreeConns uint32 // the number of free connections in the pool
|
|
||||||
}
|
|
||||||
|
|||||||
10
vendor/github.com/go-redis/redis/pipeline.go
сгенерированный
поставляемый
10
vendor/github.com/go-redis/redis/pipeline.go
сгенерированный
поставляемый
@@ -13,9 +13,7 @@ type Pipeliner interface {
|
|||||||
Process(cmd Cmder) error
|
Process(cmd Cmder) error
|
||||||
Close() error
|
Close() error
|
||||||
Discard() error
|
Discard() error
|
||||||
discard() error
|
|
||||||
Exec() ([]Cmder, error)
|
Exec() ([]Cmder, error)
|
||||||
pipelined(fn func(Pipeliner) error) ([]Cmder, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Pipeliner = (*Pipeline)(nil)
|
var _ Pipeliner = (*Pipeline)(nil)
|
||||||
@@ -104,3 +102,11 @@ func (c *Pipeline) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
|||||||
func (c *Pipeline) Pipeline() Pipeliner {
|
func (c *Pipeline) Pipeline() Pipeliner {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Pipeline) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
|
return c.pipelined(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Pipeline) TxPipeline() Pipeliner {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|||||||
10
vendor/github.com/go-redis/redis/pool_test.go
сгенерированный
поставляемый
10
vendor/github.com/go-redis/redis/pool_test.go
сгенерированный
поставляемый
@@ -95,8 +95,8 @@ var _ = Describe("pool", func() {
|
|||||||
Expect(pool.FreeLen()).To(Equal(1))
|
Expect(pool.FreeLen()).To(Equal(1))
|
||||||
|
|
||||||
stats := pool.Stats()
|
stats := pool.Stats()
|
||||||
Expect(stats.Requests).To(Equal(uint32(4)))
|
|
||||||
Expect(stats.Hits).To(Equal(uint32(2)))
|
Expect(stats.Hits).To(Equal(uint32(2)))
|
||||||
|
Expect(stats.Misses).To(Equal(uint32(2)))
|
||||||
Expect(stats.Timeouts).To(Equal(uint32(0)))
|
Expect(stats.Timeouts).To(Equal(uint32(0)))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -112,30 +112,32 @@ var _ = Describe("pool", func() {
|
|||||||
Expect(pool.FreeLen()).To(Equal(1))
|
Expect(pool.FreeLen()).To(Equal(1))
|
||||||
|
|
||||||
stats := pool.Stats()
|
stats := pool.Stats()
|
||||||
Expect(stats.Requests).To(Equal(uint32(101)))
|
|
||||||
Expect(stats.Hits).To(Equal(uint32(100)))
|
Expect(stats.Hits).To(Equal(uint32(100)))
|
||||||
|
Expect(stats.Misses).To(Equal(uint32(1)))
|
||||||
Expect(stats.Timeouts).To(Equal(uint32(0)))
|
Expect(stats.Timeouts).To(Equal(uint32(0)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("removes idle connections", func() {
|
It("removes idle connections", func() {
|
||||||
stats := client.PoolStats()
|
stats := client.PoolStats()
|
||||||
Expect(stats).To(Equal(&redis.PoolStats{
|
Expect(stats).To(Equal(&redis.PoolStats{
|
||||||
Requests: 1,
|
|
||||||
Hits: 0,
|
Hits: 0,
|
||||||
|
Misses: 1,
|
||||||
Timeouts: 0,
|
Timeouts: 0,
|
||||||
TotalConns: 1,
|
TotalConns: 1,
|
||||||
FreeConns: 1,
|
FreeConns: 1,
|
||||||
|
StaleConns: 0,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
stats = client.PoolStats()
|
stats = client.PoolStats()
|
||||||
Expect(stats).To(Equal(&redis.PoolStats{
|
Expect(stats).To(Equal(&redis.PoolStats{
|
||||||
Requests: 1,
|
|
||||||
Hits: 0,
|
Hits: 0,
|
||||||
|
Misses: 1,
|
||||||
Timeouts: 0,
|
Timeouts: 0,
|
||||||
TotalConns: 0,
|
TotalConns: 0,
|
||||||
FreeConns: 0,
|
FreeConns: 0,
|
||||||
|
StaleConns: 1,
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
5
vendor/github.com/go-redis/redis/pubsub.go
сгенерированный
поставляемый
5
vendor/github.com/go-redis/redis/pubsub.go
сгенерированный
поставляемый
@@ -95,7 +95,10 @@ func (c *PubSub) releaseConn(cn *pool.Conn, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *PubSub) _releaseConn(cn *pool.Conn, err error) {
|
func (c *PubSub) _releaseConn(cn *pool.Conn, err error) {
|
||||||
if internal.IsBadConn(err, true) && c.cn == cn {
|
if c.cn != cn {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if internal.IsBadConn(err, true) {
|
||||||
_ = c.closeTheCn()
|
_ = c.closeTheCn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
vendor/github.com/go-redis/redis/pubsub_test.go
сгенерированный
поставляемый
6
vendor/github.com/go-redis/redis/pubsub_test.go
сгенерированный
поставляемый
@@ -68,7 +68,7 @@ var _ = Describe("PubSub", func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stats := client.PoolStats()
|
stats := client.PoolStats()
|
||||||
Expect(stats.Requests - stats.Hits).To(Equal(uint32(2)))
|
Expect(stats.Misses).To(Equal(uint32(2)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should pub/sub channels", func() {
|
It("should pub/sub channels", func() {
|
||||||
@@ -191,7 +191,7 @@ var _ = Describe("PubSub", func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stats := client.PoolStats()
|
stats := client.PoolStats()
|
||||||
Expect(stats.Requests - stats.Hits).To(Equal(uint32(2)))
|
Expect(stats.Misses).To(Equal(uint32(2)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should ping/pong", func() {
|
It("should ping/pong", func() {
|
||||||
@@ -290,8 +290,8 @@ var _ = Describe("PubSub", func() {
|
|||||||
Eventually(done).Should(Receive())
|
Eventually(done).Should(Receive())
|
||||||
|
|
||||||
stats := client.PoolStats()
|
stats := client.PoolStats()
|
||||||
Expect(stats.Requests).To(Equal(uint32(2)))
|
|
||||||
Expect(stats.Hits).To(Equal(uint32(1)))
|
Expect(stats.Hits).To(Equal(uint32(1)))
|
||||||
|
Expect(stats.Misses).To(Equal(uint32(1)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("returns an error when subscribe fails", func() {
|
It("returns an error when subscribe fails", func() {
|
||||||
|
|||||||
92
vendor/github.com/go-redis/redis/redis.go
сгенерированный
поставляемый
92
vendor/github.com/go-redis/redis/redis.go
сгенерированный
поставляемый
@@ -3,6 +3,7 @@ package redis
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-redis/redis/internal"
|
"github.com/go-redis/redis/internal"
|
||||||
@@ -13,6 +14,10 @@ import (
|
|||||||
// Redis nil reply, .e.g. when key does not exist.
|
// Redis nil reply, .e.g. when key does not exist.
|
||||||
const Nil = internal.Nil
|
const Nil = internal.Nil
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SetLogger(log.New(os.Stderr, "redis: ", log.LstdFlags|log.Lshortfile))
|
||||||
|
}
|
||||||
|
|
||||||
func SetLogger(logger *log.Logger) {
|
func SetLogger(logger *log.Logger) {
|
||||||
internal.Logger = logger
|
internal.Logger = logger
|
||||||
}
|
}
|
||||||
@@ -131,7 +136,7 @@ func (c *baseClient) defaultProcess(cmd Cmder) error {
|
|||||||
cn, _, err := c.getConn()
|
cn, _, err := c.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.setErr(err)
|
cmd.setErr(err)
|
||||||
if internal.IsRetryableError(err) {
|
if internal.IsRetryableError(err, true) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@@ -141,7 +146,7 @@ func (c *baseClient) defaultProcess(cmd Cmder) error {
|
|||||||
if err := writeCmd(cn, cmd); err != nil {
|
if err := writeCmd(cn, cmd); err != nil {
|
||||||
c.releaseConn(cn, err)
|
c.releaseConn(cn, err)
|
||||||
cmd.setErr(err)
|
cmd.setErr(err)
|
||||||
if internal.IsRetryableError(err) {
|
if internal.IsRetryableError(err, true) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@@ -150,7 +155,7 @@ func (c *baseClient) defaultProcess(cmd Cmder) error {
|
|||||||
cn.SetReadTimeout(c.cmdTimeout(cmd))
|
cn.SetReadTimeout(c.cmdTimeout(cmd))
|
||||||
err = cmd.readReply(cn)
|
err = cmd.readReply(cn)
|
||||||
c.releaseConn(cn, err)
|
c.releaseConn(cn, err)
|
||||||
if err != nil && internal.IsRetryableError(err) {
|
if err != nil && internal.IsRetryableError(err, cmd.readTimeout() == nil) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,8 +202,11 @@ type pipelineProcessor func(*pool.Conn, []Cmder) (bool, error)
|
|||||||
|
|
||||||
func (c *baseClient) pipelineExecer(p pipelineProcessor) pipelineExecer {
|
func (c *baseClient) pipelineExecer(p pipelineProcessor) pipelineExecer {
|
||||||
return func(cmds []Cmder) error {
|
return func(cmds []Cmder) error {
|
||||||
var firstErr error
|
for attempt := 0; attempt <= c.opt.MaxRetries; attempt++ {
|
||||||
for i := 0; i <= c.opt.MaxRetries; i++ {
|
if attempt > 0 {
|
||||||
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
|
}
|
||||||
|
|
||||||
cn, _, err := c.getConn()
|
cn, _, err := c.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
@@ -206,18 +214,18 @@ func (c *baseClient) pipelineExecer(p pipelineProcessor) pipelineExecer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canRetry, err := p(cn, cmds)
|
canRetry, err := p(cn, cmds)
|
||||||
c.releaseConn(cn, err)
|
|
||||||
if err == nil {
|
if err == nil || internal.IsRedisError(err) {
|
||||||
return nil
|
_ = c.connPool.Put(cn)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
if firstErr == nil {
|
_ = c.connPool.Remove(cn)
|
||||||
firstErr = err
|
|
||||||
}
|
if !canRetry || !internal.IsRetryableError(err, true) {
|
||||||
if !canRetry || !internal.IsRetryableError(err) {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return firstErr
|
return firstCmdsErr(cmds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,23 +238,17 @@ func (c *baseClient) pipelineProcessCmds(cn *pool.Conn, cmds []Cmder) (bool, err
|
|||||||
|
|
||||||
// Set read timeout for all commands.
|
// Set read timeout for all commands.
|
||||||
cn.SetReadTimeout(c.opt.ReadTimeout)
|
cn.SetReadTimeout(c.opt.ReadTimeout)
|
||||||
return pipelineReadCmds(cn, cmds)
|
return true, pipelineReadCmds(cn, cmds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func pipelineReadCmds(cn *pool.Conn, cmds []Cmder) (retry bool, firstErr error) {
|
func pipelineReadCmds(cn *pool.Conn, cmds []Cmder) error {
|
||||||
for i, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
err := cmd.readReply(cn)
|
err := cmd.readReply(cn)
|
||||||
if err == nil {
|
if err != nil && !internal.IsRedisError(err) {
|
||||||
continue
|
return err
|
||||||
}
|
|
||||||
if i == 0 {
|
|
||||||
retry = true
|
|
||||||
}
|
|
||||||
if firstErr == nil {
|
|
||||||
firstErr = err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseClient) txPipelineProcessCmds(cn *pool.Conn, cmds []Cmder) (bool, error) {
|
func (c *baseClient) txPipelineProcessCmds(cn *pool.Conn, cmds []Cmder) (bool, error) {
|
||||||
@@ -260,11 +262,11 @@ func (c *baseClient) txPipelineProcessCmds(cn *pool.Conn, cmds []Cmder) (bool, e
|
|||||||
cn.SetReadTimeout(c.opt.ReadTimeout)
|
cn.SetReadTimeout(c.opt.ReadTimeout)
|
||||||
|
|
||||||
if err := c.txPipelineReadQueued(cn, cmds); err != nil {
|
if err := c.txPipelineReadQueued(cn, cmds); err != nil {
|
||||||
|
setCmdsErr(cmds, err)
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := pipelineReadCmds(cn, cmds)
|
return false, pipelineReadCmds(cn, cmds)
|
||||||
return false, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func txPipelineWriteMulti(cn *pool.Conn, cmds []Cmder) error {
|
func txPipelineWriteMulti(cn *pool.Conn, cmds []Cmder) error {
|
||||||
@@ -276,21 +278,16 @@ func txPipelineWriteMulti(cn *pool.Conn, cmds []Cmder) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseClient) txPipelineReadQueued(cn *pool.Conn, cmds []Cmder) error {
|
func (c *baseClient) txPipelineReadQueued(cn *pool.Conn, cmds []Cmder) error {
|
||||||
var firstErr error
|
|
||||||
|
|
||||||
// Parse queued replies.
|
// Parse queued replies.
|
||||||
var statusCmd StatusCmd
|
var statusCmd StatusCmd
|
||||||
if err := statusCmd.readReply(cn); err != nil && firstErr == nil {
|
if err := statusCmd.readReply(cn); err != nil {
|
||||||
firstErr = err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cmd := range cmds {
|
for _ = range cmds {
|
||||||
err := statusCmd.readReply(cn)
|
err := statusCmd.readReply(cn)
|
||||||
if err != nil {
|
if err != nil && !internal.IsRedisError(err) {
|
||||||
cmd.setErr(err)
|
return err
|
||||||
if firstErr == nil {
|
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,21 +352,16 @@ func (c *Client) Options() *Options {
|
|||||||
return c.opt
|
return c.opt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PoolStats pool.Stats
|
||||||
|
|
||||||
// PoolStats returns connection pool stats.
|
// PoolStats returns connection pool stats.
|
||||||
func (c *Client) PoolStats() *PoolStats {
|
func (c *Client) PoolStats() *PoolStats {
|
||||||
s := c.connPool.Stats()
|
stats := c.connPool.Stats()
|
||||||
return &PoolStats{
|
return (*PoolStats)(stats)
|
||||||
Requests: s.Requests,
|
|
||||||
Hits: s.Hits,
|
|
||||||
Timeouts: s.Timeouts,
|
|
||||||
|
|
||||||
TotalConns: s.TotalConns,
|
|
||||||
FreeConns: s.FreeConns,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
func (c *Client) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
return c.Pipeline().pipelined(fn)
|
return c.Pipeline().Pipelined(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Pipeline() Pipeliner {
|
func (c *Client) Pipeline() Pipeliner {
|
||||||
@@ -381,7 +373,7 @@ func (c *Client) Pipeline() Pipeliner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
func (c *Client) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
return c.TxPipeline().pipelined(fn)
|
return c.TxPipeline().Pipelined(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxPipeline acts like Pipeline, but wraps queued commands with MULTI/EXEC.
|
// TxPipeline acts like Pipeline, but wraps queued commands with MULTI/EXEC.
|
||||||
@@ -433,7 +425,7 @@ type Conn struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
func (c *Conn) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
return c.Pipeline().pipelined(fn)
|
return c.Pipeline().Pipelined(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Pipeline() Pipeliner {
|
func (c *Conn) Pipeline() Pipeliner {
|
||||||
@@ -445,7 +437,7 @@ func (c *Conn) Pipeline() Pipeliner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
func (c *Conn) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
return c.TxPipeline().pipelined(fn)
|
return c.TxPipeline().Pipelined(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxPipeline acts like Pipeline, but wraps queued commands with MULTI/EXEC.
|
// TxPipeline acts like Pipeline, but wraps queued commands with MULTI/EXEC.
|
||||||
|
|||||||
121
vendor/github.com/go-redis/redis/ring.go
сгенерированный
поставляемый
121
vendor/github.com/go-redis/redis/ring.go
сгенерированный
поставляемый
@@ -34,7 +34,9 @@ type RingOptions struct {
|
|||||||
DB int
|
DB int
|
||||||
Password string
|
Password string
|
||||||
|
|
||||||
MaxRetries int
|
MaxRetries int
|
||||||
|
MinRetryBackoff time.Duration
|
||||||
|
MaxRetryBackoff time.Duration
|
||||||
|
|
||||||
DialTimeout time.Duration
|
DialTimeout time.Duration
|
||||||
ReadTimeout time.Duration
|
ReadTimeout time.Duration
|
||||||
@@ -50,6 +52,19 @@ func (opt *RingOptions) init() {
|
|||||||
if opt.HeartbeatFrequency == 0 {
|
if opt.HeartbeatFrequency == 0 {
|
||||||
opt.HeartbeatFrequency = 500 * time.Millisecond
|
opt.HeartbeatFrequency = 500 * time.Millisecond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch opt.MinRetryBackoff {
|
||||||
|
case -1:
|
||||||
|
opt.MinRetryBackoff = 0
|
||||||
|
case 0:
|
||||||
|
opt.MinRetryBackoff = 8 * time.Millisecond
|
||||||
|
}
|
||||||
|
switch opt.MaxRetryBackoff {
|
||||||
|
case -1:
|
||||||
|
opt.MaxRetryBackoff = 0
|
||||||
|
case 0:
|
||||||
|
opt.MaxRetryBackoff = 512 * time.Millisecond
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opt *RingOptions) clientOptions() *Options {
|
func (opt *RingOptions) clientOptions() *Options {
|
||||||
@@ -130,9 +145,10 @@ type Ring struct {
|
|||||||
opt *RingOptions
|
opt *RingOptions
|
||||||
nreplicas int
|
nreplicas int
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
hash *consistenthash.Map
|
hash *consistenthash.Map
|
||||||
shards map[string]*ringShard
|
shards map[string]*ringShard
|
||||||
|
shardsList []*ringShard
|
||||||
|
|
||||||
cmdsInfoOnce internal.Once
|
cmdsInfoOnce internal.Once
|
||||||
cmdsInfo map[string]*CommandInfo
|
cmdsInfo map[string]*CommandInfo
|
||||||
@@ -154,24 +170,41 @@ func NewRing(opt *RingOptions) *Ring {
|
|||||||
for name, addr := range opt.Addrs {
|
for name, addr := range opt.Addrs {
|
||||||
clopt := opt.clientOptions()
|
clopt := opt.clientOptions()
|
||||||
clopt.Addr = addr
|
clopt.Addr = addr
|
||||||
ring.addClient(name, NewClient(clopt))
|
ring.addShard(name, NewClient(clopt))
|
||||||
}
|
}
|
||||||
go ring.heartbeat()
|
go ring.heartbeat()
|
||||||
return ring
|
return ring
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Ring) addShard(name string, cl *Client) {
|
||||||
|
shard := &ringShard{Client: cl}
|
||||||
|
c.mu.Lock()
|
||||||
|
c.hash.Add(name)
|
||||||
|
c.shards[name] = shard
|
||||||
|
c.shardsList = append(c.shardsList, shard)
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// Options returns read-only Options that were used to create the client.
|
// Options returns read-only Options that were used to create the client.
|
||||||
func (c *Ring) Options() *RingOptions {
|
func (c *Ring) Options() *RingOptions {
|
||||||
return c.opt
|
return c.opt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Ring) retryBackoff(attempt int) time.Duration {
|
||||||
|
return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff)
|
||||||
|
}
|
||||||
|
|
||||||
// PoolStats returns accumulated connection pool stats.
|
// PoolStats returns accumulated connection pool stats.
|
||||||
func (c *Ring) PoolStats() *PoolStats {
|
func (c *Ring) PoolStats() *PoolStats {
|
||||||
|
c.mu.RLock()
|
||||||
|
shards := c.shardsList
|
||||||
|
c.mu.RUnlock()
|
||||||
|
|
||||||
var acc PoolStats
|
var acc PoolStats
|
||||||
for _, shard := range c.shards {
|
for _, shard := range shards {
|
||||||
s := shard.Client.connPool.Stats()
|
s := shard.Client.connPool.Stats()
|
||||||
acc.Requests += s.Requests
|
|
||||||
acc.Hits += s.Hits
|
acc.Hits += s.Hits
|
||||||
|
acc.Misses += s.Misses
|
||||||
acc.Timeouts += s.Timeouts
|
acc.Timeouts += s.Timeouts
|
||||||
acc.TotalConns += s.TotalConns
|
acc.TotalConns += s.TotalConns
|
||||||
acc.FreeConns += s.FreeConns
|
acc.FreeConns += s.FreeConns
|
||||||
@@ -210,9 +243,13 @@ func (c *Ring) PSubscribe(channels ...string) *PubSub {
|
|||||||
// ForEachShard concurrently calls the fn on each live shard in the ring.
|
// ForEachShard concurrently calls the fn on each live shard in the ring.
|
||||||
// It returns the first error if any.
|
// It returns the first error if any.
|
||||||
func (c *Ring) ForEachShard(fn func(client *Client) error) error {
|
func (c *Ring) ForEachShard(fn func(client *Client) error) error {
|
||||||
|
c.mu.RLock()
|
||||||
|
shards := c.shardsList
|
||||||
|
c.mu.RUnlock()
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
errCh := make(chan error, 1)
|
errCh := make(chan error, 1)
|
||||||
for _, shard := range c.shards {
|
for _, shard := range shards {
|
||||||
if shard.IsDown() {
|
if shard.IsDown() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -241,8 +278,12 @@ func (c *Ring) ForEachShard(fn func(client *Client) error) error {
|
|||||||
|
|
||||||
func (c *Ring) cmdInfo(name string) *CommandInfo {
|
func (c *Ring) cmdInfo(name string) *CommandInfo {
|
||||||
err := c.cmdsInfoOnce.Do(func() error {
|
err := c.cmdsInfoOnce.Do(func() error {
|
||||||
|
c.mu.RLock()
|
||||||
|
shards := c.shardsList
|
||||||
|
c.mu.RUnlock()
|
||||||
|
|
||||||
var firstErr error
|
var firstErr error
|
||||||
for _, shard := range c.shards {
|
for _, shard := range shards {
|
||||||
cmdsInfo, err := shard.Client.Command().Result()
|
cmdsInfo, err := shard.Client.Command().Result()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.cmdsInfo = cmdsInfo
|
c.cmdsInfo = cmdsInfo
|
||||||
@@ -257,14 +298,11 @@ func (c *Ring) cmdInfo(name string) *CommandInfo {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return c.cmdsInfo[name]
|
info := c.cmdsInfo[name]
|
||||||
}
|
if info == nil {
|
||||||
|
internal.Logf("info for cmd=%s not found", name)
|
||||||
func (c *Ring) addClient(name string, cl *Client) {
|
}
|
||||||
c.mu.Lock()
|
return info
|
||||||
c.hash.Add(name)
|
|
||||||
c.shards[name] = &ringShard{Client: cl}
|
|
||||||
c.mu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Ring) shardByKey(key string) (*ringShard, error) {
|
func (c *Ring) shardByKey(key string) (*ringShard, error) {
|
||||||
@@ -305,7 +343,7 @@ func (c *Ring) shardByName(name string) (*ringShard, error) {
|
|||||||
|
|
||||||
func (c *Ring) cmdShard(cmd Cmder) (*ringShard, error) {
|
func (c *Ring) cmdShard(cmd Cmder) (*ringShard, error) {
|
||||||
cmdInfo := c.cmdInfo(cmd.Name())
|
cmdInfo := c.cmdInfo(cmd.Name())
|
||||||
firstKey := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
|
firstKey := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
return c.shardByKey(firstKey)
|
return c.shardByKey(firstKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +384,10 @@ func (c *Ring) heartbeat() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, shard := range c.shards {
|
shards := c.shardsList
|
||||||
|
c.mu.RUnlock()
|
||||||
|
|
||||||
|
for _, shard := range shards {
|
||||||
err := shard.Client.Ping().Err()
|
err := shard.Client.Ping().Err()
|
||||||
if shard.Vote(err == nil || err == pool.ErrPoolTimeout) {
|
if shard.Vote(err == nil || err == pool.ErrPoolTimeout) {
|
||||||
internal.Logf("ring shard state changed: %s", shard)
|
internal.Logf("ring shard state changed: %s", shard)
|
||||||
@@ -354,8 +395,6 @@ func (c *Ring) heartbeat() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mu.RUnlock()
|
|
||||||
|
|
||||||
if rebalance {
|
if rebalance {
|
||||||
c.rebalance()
|
c.rebalance()
|
||||||
}
|
}
|
||||||
@@ -383,6 +422,7 @@ func (c *Ring) Close() error {
|
|||||||
}
|
}
|
||||||
c.hash = nil
|
c.hash = nil
|
||||||
c.shards = nil
|
c.shards = nil
|
||||||
|
c.shardsList = nil
|
||||||
|
|
||||||
return firstErr
|
return firstErr
|
||||||
}
|
}
|
||||||
@@ -396,51 +436,48 @@ func (c *Ring) Pipeline() Pipeliner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Ring) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
func (c *Ring) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
return c.Pipeline().pipelined(fn)
|
return c.Pipeline().Pipelined(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Ring) pipelineExec(cmds []Cmder) (firstErr error) {
|
func (c *Ring) pipelineExec(cmds []Cmder) error {
|
||||||
cmdsMap := make(map[string][]Cmder)
|
cmdsMap := make(map[string][]Cmder)
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
cmdInfo := c.cmdInfo(cmd.Name())
|
cmdInfo := c.cmdInfo(cmd.Name())
|
||||||
name := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
|
name := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
if name != "" {
|
if name != "" {
|
||||||
name = c.hash.Get(hashtag.Key(name))
|
name = c.hash.Get(hashtag.Key(name))
|
||||||
}
|
}
|
||||||
cmdsMap[name] = append(cmdsMap[name], cmd)
|
cmdsMap[name] = append(cmdsMap[name], cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i <= c.opt.MaxRetries; i++ {
|
for attempt := 0; attempt <= c.opt.MaxRetries; attempt++ {
|
||||||
|
if attempt > 0 {
|
||||||
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
|
}
|
||||||
|
|
||||||
var failedCmdsMap map[string][]Cmder
|
var failedCmdsMap map[string][]Cmder
|
||||||
|
|
||||||
for name, cmds := range cmdsMap {
|
for name, cmds := range cmdsMap {
|
||||||
shard, err := c.shardByName(name)
|
shard, err := c.shardByName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
if firstErr == nil {
|
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cn, _, err := shard.Client.getConn()
|
cn, _, err := shard.Client.getConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
if firstErr == nil {
|
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
canRetry, err := shard.Client.pipelineProcessCmds(cn, cmds)
|
canRetry, err := shard.Client.pipelineProcessCmds(cn, cmds)
|
||||||
shard.Client.releaseConn(cn, err)
|
if err == nil || internal.IsRedisError(err) {
|
||||||
if err == nil {
|
_ = shard.Client.connPool.Put(cn)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if firstErr == nil {
|
_ = shard.Client.connPool.Remove(cn)
|
||||||
firstErr = err
|
|
||||||
}
|
if canRetry && internal.IsRetryableError(err, true) {
|
||||||
if canRetry && internal.IsRetryableError(err) {
|
|
||||||
if failedCmdsMap == nil {
|
if failedCmdsMap == nil {
|
||||||
failedCmdsMap = make(map[string][]Cmder)
|
failedCmdsMap = make(map[string][]Cmder)
|
||||||
}
|
}
|
||||||
@@ -454,5 +491,13 @@ func (c *Ring) pipelineExec(cmds []Cmder) (firstErr error) {
|
|||||||
cmdsMap = failedCmdsMap
|
cmdsMap = failedCmdsMap
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstErr
|
return firstCmdsErr(cmds)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Ring) TxPipeline() Pipeliner {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Ring) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|||||||
6
vendor/github.com/go-redis/redis/sentinel.go
сгенерированный
поставляемый
6
vendor/github.com/go-redis/redis/sentinel.go
сгенерированный
поставляемый
@@ -301,8 +301,10 @@ func (d *sentinelFailover) listen(sentinel *sentinelClient) {
|
|||||||
|
|
||||||
msg, err := pubsub.ReceiveMessage()
|
msg, err := pubsub.ReceiveMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
internal.Logf("sentinel: ReceiveMessage failed: %s", err)
|
if err != pool.ErrClosed {
|
||||||
pubsub.Close()
|
internal.Logf("sentinel: ReceiveMessage failed: %s", err)
|
||||||
|
pubsub.Close()
|
||||||
|
}
|
||||||
d.resetSentinel()
|
d.resetSentinel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
23
vendor/github.com/go-redis/redis/tx.go
сгенерированный
поставляемый
23
vendor/github.com/go-redis/redis/tx.go
сгенерированный
поставляемый
@@ -36,11 +36,10 @@ func (c *Client) Watch(fn func(*Tx) error, keys ...string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
firstErr := fn(tx)
|
|
||||||
if err := tx.Close(); err != nil && firstErr == nil {
|
err := fn(tx)
|
||||||
firstErr = err
|
_ = tx.Close()
|
||||||
}
|
return err
|
||||||
return firstErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// close closes the transaction, releasing any open resources.
|
// close closes the transaction, releasing any open resources.
|
||||||
@@ -53,7 +52,7 @@ func (c *Tx) Close() error {
|
|||||||
// of a transaction.
|
// of a transaction.
|
||||||
func (c *Tx) Watch(keys ...string) *StatusCmd {
|
func (c *Tx) Watch(keys ...string) *StatusCmd {
|
||||||
args := make([]interface{}, 1+len(keys))
|
args := make([]interface{}, 1+len(keys))
|
||||||
args[0] = "WATCH"
|
args[0] = "watch"
|
||||||
for i, key := range keys {
|
for i, key := range keys {
|
||||||
args[1+i] = key
|
args[1+i] = key
|
||||||
}
|
}
|
||||||
@@ -65,7 +64,7 @@ func (c *Tx) Watch(keys ...string) *StatusCmd {
|
|||||||
// Unwatch flushes all the previously watched keys for a transaction.
|
// Unwatch flushes all the previously watched keys for a transaction.
|
||||||
func (c *Tx) Unwatch(keys ...string) *StatusCmd {
|
func (c *Tx) Unwatch(keys ...string) *StatusCmd {
|
||||||
args := make([]interface{}, 1+len(keys))
|
args := make([]interface{}, 1+len(keys))
|
||||||
args[0] = "UNWATCH"
|
args[0] = "unwatch"
|
||||||
for i, key := range keys {
|
for i, key := range keys {
|
||||||
args[1+i] = key
|
args[1+i] = key
|
||||||
}
|
}
|
||||||
@@ -92,5 +91,13 @@ func (c *Tx) Pipeline() Pipeliner {
|
|||||||
// TxFailedErr is returned. Otherwise Exec returns error of the first
|
// TxFailedErr is returned. Otherwise Exec returns error of the first
|
||||||
// failed command or nil.
|
// failed command or nil.
|
||||||
func (c *Tx) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
func (c *Tx) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
return c.Pipeline().pipelined(fn)
|
return c.Pipeline().Pipelined(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Tx) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) {
|
||||||
|
return c.Pipelined(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Tx) TxPipeline() Pipeliner {
|
||||||
|
return c.Pipeline()
|
||||||
}
|
}
|
||||||
|
|||||||
7
vendor/github.com/go-redis/redis/universal.go
сгенерированный
поставляемый
7
vendor/github.com/go-redis/redis/universal.go
сгенерированный
поставляемый
@@ -90,8 +90,8 @@ func (o *UniversalOptions) simple() *Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Options{
|
return &Options{
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
DB: o.DB,
|
DB: o.DB,
|
||||||
|
|
||||||
MaxRetries: o.MaxRetries,
|
MaxRetries: o.MaxRetries,
|
||||||
Password: o.Password,
|
Password: o.Password,
|
||||||
@@ -117,6 +117,9 @@ type UniversalClient interface {
|
|||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ UniversalClient = (*Client)(nil)
|
||||||
|
var _ UniversalClient = (*ClusterClient)(nil)
|
||||||
|
|
||||||
// NewUniversalClient returns a new multi client. The type of client returned depends
|
// NewUniversalClient returns a new multi client. The type of client returned depends
|
||||||
// on the following three conditions:
|
// on the following three conditions:
|
||||||
//
|
//
|
||||||
|
|||||||
1
vendor/github.com/golang/protobuf/.travis.yml
сгенерированный
поставляемый
1
vendor/github.com/golang/protobuf/.travis.yml
сгенерированный
поставляемый
@@ -4,6 +4,7 @@ go:
|
|||||||
- 1.6.x
|
- 1.6.x
|
||||||
- 1.7.x
|
- 1.7.x
|
||||||
- 1.8.x
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- go get -v -d -t github.com/golang/protobuf/...
|
- go get -v -d -t github.com/golang/protobuf/...
|
||||||
|
|||||||
1
vendor/github.com/golang/protobuf/README.md
сгенерированный
поставляемый
1
vendor/github.com/golang/protobuf/README.md
сгенерированный
поставляемый
@@ -111,6 +111,7 @@ When the .proto file specifies `syntax="proto3"`, there are some differences:
|
|||||||
Consider file test.proto, containing
|
Consider file test.proto, containing
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
|
syntax = "proto2";
|
||||||
package example;
|
package example;
|
||||||
|
|
||||||
enum FOO { X = 17; };
|
enum FOO { X = 17; };
|
||||||
|
|||||||
66
vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
сгенерированный
поставляемый
66
vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
сгенерированный
поставляемый
@@ -73,6 +73,31 @@ type Marshaler struct {
|
|||||||
|
|
||||||
// Whether to use the original (.proto) name for fields.
|
// Whether to use the original (.proto) name for fields.
|
||||||
OrigName bool
|
OrigName bool
|
||||||
|
|
||||||
|
// A custom URL resolver to use when marshaling Any messages to JSON.
|
||||||
|
// If unset, the default resolution strategy is to extract the
|
||||||
|
// fully-qualified type name from the type URL and pass that to
|
||||||
|
// proto.MessageType(string).
|
||||||
|
AnyResolver AnyResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyResolver takes a type URL, present in an Any message, and resolves it into
|
||||||
|
// an instance of the associated message.
|
||||||
|
type AnyResolver interface {
|
||||||
|
Resolve(typeUrl string) (proto.Message, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultResolveAny(typeUrl string) (proto.Message, error) {
|
||||||
|
// Only the part of typeUrl after the last slash is relevant.
|
||||||
|
mname := typeUrl
|
||||||
|
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
|
||||||
|
mname = mname[slash+1:]
|
||||||
|
}
|
||||||
|
mt := proto.MessageType(mname)
|
||||||
|
if mt == nil {
|
||||||
|
return nil, fmt.Errorf("unknown message type %q", mname)
|
||||||
|
}
|
||||||
|
return reflect.New(mt.Elem()).Interface().(proto.Message), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONPBMarshaler is implemented by protobuf messages that customize the
|
// JSONPBMarshaler is implemented by protobuf messages that customize the
|
||||||
@@ -344,16 +369,17 @@ func (m *Marshaler) marshalAny(out *errWriter, any proto.Message, indent string)
|
|||||||
turl := v.Field(0).String()
|
turl := v.Field(0).String()
|
||||||
val := v.Field(1).Bytes()
|
val := v.Field(1).Bytes()
|
||||||
|
|
||||||
// Only the part of type_url after the last slash is relevant.
|
var msg proto.Message
|
||||||
mname := turl
|
var err error
|
||||||
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
|
if m.AnyResolver != nil {
|
||||||
mname = mname[slash+1:]
|
msg, err = m.AnyResolver.Resolve(turl)
|
||||||
|
} else {
|
||||||
|
msg, err = defaultResolveAny(turl)
|
||||||
}
|
}
|
||||||
mt := proto.MessageType(mname)
|
if err != nil {
|
||||||
if mt == nil {
|
return err
|
||||||
return fmt.Errorf("unknown message type %q", mname)
|
|
||||||
}
|
}
|
||||||
msg := reflect.New(mt.Elem()).Interface().(proto.Message)
|
|
||||||
if err := proto.Unmarshal(val, msg); err != nil {
|
if err := proto.Unmarshal(val, msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -590,6 +616,12 @@ type Unmarshaler struct {
|
|||||||
// Whether to allow messages to contain unknown fields, as opposed to
|
// Whether to allow messages to contain unknown fields, as opposed to
|
||||||
// failing to unmarshal.
|
// failing to unmarshal.
|
||||||
AllowUnknownFields bool
|
AllowUnknownFields bool
|
||||||
|
|
||||||
|
// A custom URL resolver to use when unmarshaling Any messages from JSON.
|
||||||
|
// If unset, the default resolution strategy is to extract the
|
||||||
|
// fully-qualified type name from the type URL and pass that to
|
||||||
|
// proto.MessageType(string).
|
||||||
|
AnyResolver AnyResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
|
// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
|
||||||
@@ -641,7 +673,8 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
|
|||||||
if targetType.Kind() == reflect.Ptr {
|
if targetType.Kind() == reflect.Ptr {
|
||||||
// If input value is "null" and target is a pointer type, then the field should be treated as not set
|
// If input value is "null" and target is a pointer type, then the field should be treated as not set
|
||||||
// UNLESS the target is structpb.Value, in which case it should be set to structpb.NullValue.
|
// UNLESS the target is structpb.Value, in which case it should be set to structpb.NullValue.
|
||||||
if string(inputValue) == "null" && targetType != reflect.TypeOf(&stpb.Value{}) {
|
_, isJSONPBUnmarshaler := target.Interface().(JSONPBUnmarshaler)
|
||||||
|
if string(inputValue) == "null" && targetType != reflect.TypeOf(&stpb.Value{}) && !isJSONPBUnmarshaler {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
target.Set(reflect.New(targetType.Elem()))
|
target.Set(reflect.New(targetType.Elem()))
|
||||||
@@ -679,16 +712,17 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
|
|||||||
}
|
}
|
||||||
target.Field(0).SetString(turl)
|
target.Field(0).SetString(turl)
|
||||||
|
|
||||||
mname := turl
|
var m proto.Message
|
||||||
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
|
var err error
|
||||||
mname = mname[slash+1:]
|
if u.AnyResolver != nil {
|
||||||
|
m, err = u.AnyResolver.Resolve(turl)
|
||||||
|
} else {
|
||||||
|
m, err = defaultResolveAny(turl)
|
||||||
}
|
}
|
||||||
mt := proto.MessageType(mname)
|
if err != nil {
|
||||||
if mt == nil {
|
return err
|
||||||
return fmt.Errorf("unknown message type %q", mname)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m := reflect.New(mt.Elem()).Interface().(proto.Message)
|
|
||||||
if _, ok := m.(wkt); ok {
|
if _, ok := m.(wkt); ok {
|
||||||
val, ok := jsonFields["value"]
|
val, ok := jsonFields["value"]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
107
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go
сгенерированный
поставляемый
107
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go
сгенерированный
поставляемый
@@ -721,6 +721,65 @@ func TestUnmarshalingBadInput(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type funcResolver func(turl string) (proto.Message, error)
|
||||||
|
|
||||||
|
func (fn funcResolver) Resolve(turl string) (proto.Message, error) {
|
||||||
|
return fn(turl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAnyWithCustomResolver(t *testing.T) {
|
||||||
|
var resolvedTypeUrls []string
|
||||||
|
resolver := funcResolver(func(turl string) (proto.Message, error) {
|
||||||
|
resolvedTypeUrls = append(resolvedTypeUrls, turl)
|
||||||
|
return new(pb.Simple), nil
|
||||||
|
})
|
||||||
|
msg := &pb.Simple{
|
||||||
|
OBytes: []byte{1, 2, 3, 4},
|
||||||
|
OBool: proto.Bool(true),
|
||||||
|
OString: proto.String("foobar"),
|
||||||
|
OInt64: proto.Int64(1020304),
|
||||||
|
}
|
||||||
|
msgBytes, err := proto.Marshal(msg)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("an unexpected error occurred when marshaling message: %v", err)
|
||||||
|
}
|
||||||
|
// make an Any with a type URL that won't resolve w/out custom resolver
|
||||||
|
any := &anypb.Any{
|
||||||
|
TypeUrl: "https://foobar.com/some.random.MessageKind",
|
||||||
|
Value: msgBytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
m := Marshaler{AnyResolver: resolver}
|
||||||
|
js, err := m.MarshalToString(any)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("an unexpected error occurred when marshaling any to JSON: %v", err)
|
||||||
|
}
|
||||||
|
if len(resolvedTypeUrls) != 1 {
|
||||||
|
t.Errorf("custom resolver was not invoked during marshaling")
|
||||||
|
} else if resolvedTypeUrls[0] != "https://foobar.com/some.random.MessageKind" {
|
||||||
|
t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[0], "https://foobar.com/some.random.MessageKind")
|
||||||
|
}
|
||||||
|
wanted := `{"@type":"https://foobar.com/some.random.MessageKind","oBool":true,"oInt64":"1020304","oString":"foobar","oBytes":"AQIDBA=="}`
|
||||||
|
if js != wanted {
|
||||||
|
t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", js, wanted)
|
||||||
|
}
|
||||||
|
|
||||||
|
u := Unmarshaler{AnyResolver: resolver}
|
||||||
|
roundTrip := &anypb.Any{}
|
||||||
|
err = u.Unmarshal(bytes.NewReader([]byte(js)), roundTrip)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("an unexpected error occurred when unmarshaling any from JSON: %v", err)
|
||||||
|
}
|
||||||
|
if len(resolvedTypeUrls) != 2 {
|
||||||
|
t.Errorf("custom resolver was not invoked during marshaling")
|
||||||
|
} else if resolvedTypeUrls[1] != "https://foobar.com/some.random.MessageKind" {
|
||||||
|
t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[1], "https://foobar.com/some.random.MessageKind")
|
||||||
|
}
|
||||||
|
if !proto.Equal(any, roundTrip) {
|
||||||
|
t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", roundTrip, any)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnmarshalJSONPBUnmarshaler(t *testing.T) {
|
func TestUnmarshalJSONPBUnmarshaler(t *testing.T) {
|
||||||
rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }`
|
rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }`
|
||||||
var msg dynamicMessage
|
var msg dynamicMessage
|
||||||
@@ -732,6 +791,19 @@ func TestUnmarshalJSONPBUnmarshaler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalNullWithJSONPBUnmarshaler(t *testing.T) {
|
||||||
|
rawJson := `{"stringField":null}`
|
||||||
|
var ptrFieldMsg ptrFieldMessage
|
||||||
|
if err := Unmarshal(strings.NewReader(rawJson), &ptrFieldMsg); err != nil {
|
||||||
|
t.Errorf("unmarshal error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := ptrFieldMessage{StringField: &stringField{IsSet: true, StringValue: "null"}}
|
||||||
|
if !proto.Equal(&ptrFieldMsg, &want) {
|
||||||
|
t.Errorf("unmarshal result StringField: got %v, want %v", ptrFieldMsg, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnmarshalAnyJSONPBUnmarshaler(t *testing.T) {
|
func TestUnmarshalAnyJSONPBUnmarshaler(t *testing.T) {
|
||||||
rawJson := `{ "@type": "blah.com/` + dynamicMessageName + `", "foo": "bar", "baz": [0, 1, 2, 3] }`
|
rawJson := `{ "@type": "blah.com/` + dynamicMessageName + `", "foo": "bar", "baz": [0, 1, 2, 3] }`
|
||||||
var got anypb.Any
|
var got anypb.Any
|
||||||
@@ -762,6 +834,41 @@ func init() {
|
|||||||
proto.RegisterType((*dynamicMessage)(nil), dynamicMessageName)
|
proto.RegisterType((*dynamicMessage)(nil), dynamicMessageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ptrFieldMessage struct {
|
||||||
|
StringField *stringField `protobuf:"bytes,1,opt,name=stringField"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ptrFieldMessage) Reset() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ptrFieldMessage) String() string {
|
||||||
|
return m.StringField.StringValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ptrFieldMessage) ProtoMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
|
type stringField struct {
|
||||||
|
IsSet bool `protobuf:"varint,1,opt,name=isSet"`
|
||||||
|
StringValue string `protobuf:"bytes,2,opt,name=stringValue"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringField) Reset() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringField) String() string {
|
||||||
|
return s.StringValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringField) ProtoMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringField) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
|
||||||
|
s.IsSet = true
|
||||||
|
s.StringValue = string(js)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// dynamicMessage implements protobuf.Message but is not a normal generated message type.
|
// dynamicMessage implements protobuf.Message but is not a normal generated message type.
|
||||||
// It provides implementations of JSONPBMarshaler and JSONPBUnmarshaler for JSON support.
|
// It provides implementations of JSONPBMarshaler and JSONPBUnmarshaler for JSON support.
|
||||||
type dynamicMessage struct {
|
type dynamicMessage struct {
|
||||||
|
|||||||
425
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go
сгенерированный
поставляемый
425
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go
сгенерированный
поставляемый
@@ -11,6 +11,7 @@ It has these top-level messages:
|
|||||||
FileDescriptorSet
|
FileDescriptorSet
|
||||||
FileDescriptorProto
|
FileDescriptorProto
|
||||||
DescriptorProto
|
DescriptorProto
|
||||||
|
ExtensionRangeOptions
|
||||||
FieldDescriptorProto
|
FieldDescriptorProto
|
||||||
OneofDescriptorProto
|
OneofDescriptorProto
|
||||||
EnumDescriptorProto
|
EnumDescriptorProto
|
||||||
@@ -137,7 +138,7 @@ func (x *FieldDescriptorProto_Type) UnmarshalJSON(data []byte) error {
|
|||||||
*x = FieldDescriptorProto_Type(value)
|
*x = FieldDescriptorProto_Type(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} }
|
func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} }
|
||||||
|
|
||||||
type FieldDescriptorProto_Label int32
|
type FieldDescriptorProto_Label int32
|
||||||
|
|
||||||
@@ -176,7 +177,7 @@ func (x *FieldDescriptorProto_Label) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) {
|
func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) {
|
||||||
return fileDescriptor0, []int{3, 1}
|
return fileDescriptor0, []int{4, 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generated classes can be optimized for speed or code size.
|
// Generated classes can be optimized for speed or code size.
|
||||||
@@ -216,7 +217,7 @@ func (x *FileOptions_OptimizeMode) UnmarshalJSON(data []byte) error {
|
|||||||
*x = FileOptions_OptimizeMode(value)
|
*x = FileOptions_OptimizeMode(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{9, 0} }
|
func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{10, 0} }
|
||||||
|
|
||||||
type FieldOptions_CType int32
|
type FieldOptions_CType int32
|
||||||
|
|
||||||
@@ -254,7 +255,7 @@ func (x *FieldOptions_CType) UnmarshalJSON(data []byte) error {
|
|||||||
*x = FieldOptions_CType(value)
|
*x = FieldOptions_CType(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{11, 0} }
|
func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 0} }
|
||||||
|
|
||||||
type FieldOptions_JSType int32
|
type FieldOptions_JSType int32
|
||||||
|
|
||||||
@@ -294,7 +295,7 @@ func (x *FieldOptions_JSType) UnmarshalJSON(data []byte) error {
|
|||||||
*x = FieldOptions_JSType(value)
|
*x = FieldOptions_JSType(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{11, 1} }
|
func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 1} }
|
||||||
|
|
||||||
// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
|
// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
|
||||||
// or neither? HTTP based RPC implementation may choose GET verb for safe
|
// or neither? HTTP based RPC implementation may choose GET verb for safe
|
||||||
@@ -335,7 +336,7 @@ func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) {
|
func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) {
|
||||||
return fileDescriptor0, []int{16, 0}
|
return fileDescriptor0, []int{17, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The protocol compiler can output a FileDescriptorSet containing the .proto
|
// The protocol compiler can output a FileDescriptorSet containing the .proto
|
||||||
@@ -567,9 +568,10 @@ func (m *DescriptorProto) GetReservedName() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DescriptorProto_ExtensionRange struct {
|
type DescriptorProto_ExtensionRange struct {
|
||||||
Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
|
Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
|
||||||
End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
|
End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *DescriptorProto_ExtensionRange) Reset() { *m = DescriptorProto_ExtensionRange{} }
|
func (m *DescriptorProto_ExtensionRange) Reset() { *m = DescriptorProto_ExtensionRange{} }
|
||||||
@@ -593,6 +595,13 @@ func (m *DescriptorProto_ExtensionRange) GetEnd() int32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *DescriptorProto_ExtensionRange) GetOptions() *ExtensionRangeOptions {
|
||||||
|
if m != nil {
|
||||||
|
return m.Options
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Range of reserved tag numbers. Reserved tag numbers may not be used by
|
// Range of reserved tag numbers. Reserved tag numbers may not be used by
|
||||||
// fields or extension ranges in the same message. Reserved ranges may
|
// fields or extension ranges in the same message. Reserved ranges may
|
||||||
// not overlap.
|
// not overlap.
|
||||||
@@ -623,6 +632,33 @@ func (m *DescriptorProto_ReservedRange) GetEnd() int32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExtensionRangeOptions struct {
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
|
||||||
|
proto.XXX_InternalExtensions `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ExtensionRangeOptions) Reset() { *m = ExtensionRangeOptions{} }
|
||||||
|
func (m *ExtensionRangeOptions) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*ExtensionRangeOptions) ProtoMessage() {}
|
||||||
|
func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||||
|
|
||||||
|
var extRange_ExtensionRangeOptions = []proto.ExtensionRange{
|
||||||
|
{1000, 536870911},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ExtensionRangeOptions) ExtensionRangeArray() []proto.ExtensionRange {
|
||||||
|
return extRange_ExtensionRangeOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption {
|
||||||
|
if m != nil {
|
||||||
|
return m.UninterpretedOption
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Describes a field within a message.
|
// Describes a field within a message.
|
||||||
type FieldDescriptorProto struct {
|
type FieldDescriptorProto struct {
|
||||||
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||||
@@ -661,7 +697,7 @@ type FieldDescriptorProto struct {
|
|||||||
func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} }
|
func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} }
|
||||||
func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*FieldDescriptorProto) ProtoMessage() {}
|
func (*FieldDescriptorProto) ProtoMessage() {}
|
||||||
func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||||
|
|
||||||
func (m *FieldDescriptorProto) GetName() string {
|
func (m *FieldDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
@@ -743,7 +779,7 @@ type OneofDescriptorProto struct {
|
|||||||
func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} }
|
func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} }
|
||||||
func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*OneofDescriptorProto) ProtoMessage() {}
|
func (*OneofDescriptorProto) ProtoMessage() {}
|
||||||
func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||||
|
|
||||||
func (m *OneofDescriptorProto) GetName() string {
|
func (m *OneofDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
@@ -770,7 +806,7 @@ type EnumDescriptorProto struct {
|
|||||||
func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} }
|
func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} }
|
||||||
func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*EnumDescriptorProto) ProtoMessage() {}
|
func (*EnumDescriptorProto) ProtoMessage() {}
|
||||||
func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
|
||||||
|
|
||||||
func (m *EnumDescriptorProto) GetName() string {
|
func (m *EnumDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
@@ -804,7 +840,7 @@ type EnumValueDescriptorProto struct {
|
|||||||
func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} }
|
func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} }
|
||||||
func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*EnumValueDescriptorProto) ProtoMessage() {}
|
func (*EnumValueDescriptorProto) ProtoMessage() {}
|
||||||
func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
|
func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
||||||
|
|
||||||
func (m *EnumValueDescriptorProto) GetName() string {
|
func (m *EnumValueDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
@@ -838,7 +874,7 @@ type ServiceDescriptorProto struct {
|
|||||||
func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} }
|
func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} }
|
||||||
func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ServiceDescriptorProto) ProtoMessage() {}
|
func (*ServiceDescriptorProto) ProtoMessage() {}
|
||||||
func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
|
||||||
|
|
||||||
func (m *ServiceDescriptorProto) GetName() string {
|
func (m *ServiceDescriptorProto) GetName() string {
|
||||||
if m != nil && m.Name != nil {
|
if m != nil && m.Name != nil {
|
||||||
@@ -879,7 +915,7 @@ type MethodDescriptorProto struct {
|
|||||||
func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} }
|
func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} }
|
||||||
func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) }
|
func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) }
|
||||||
func (*MethodDescriptorProto) ProtoMessage() {}
|
func (*MethodDescriptorProto) ProtoMessage() {}
|
||||||
func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
|
func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
|
||||||
|
|
||||||
const Default_MethodDescriptorProto_ClientStreaming bool = false
|
const Default_MethodDescriptorProto_ClientStreaming bool = false
|
||||||
const Default_MethodDescriptorProto_ServerStreaming bool = false
|
const Default_MethodDescriptorProto_ServerStreaming bool = false
|
||||||
@@ -974,7 +1010,7 @@ type FileOptions struct {
|
|||||||
CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"`
|
CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"`
|
||||||
JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"`
|
JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"`
|
||||||
PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"`
|
PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"`
|
||||||
PhpGenericServices *bool `protobuf:"varint,19,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"`
|
PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"`
|
||||||
// Is this file deprecated?
|
// Is this file deprecated?
|
||||||
// Depending on the target platform, this can emit Deprecated annotations
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
// for everything in the file, or it will be completely ignored; in the very
|
// for everything in the file, or it will be completely ignored; in the very
|
||||||
@@ -1009,7 +1045,7 @@ type FileOptions struct {
|
|||||||
func (m *FileOptions) Reset() { *m = FileOptions{} }
|
func (m *FileOptions) Reset() { *m = FileOptions{} }
|
||||||
func (m *FileOptions) String() string { return proto.CompactTextString(m) }
|
func (m *FileOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*FileOptions) ProtoMessage() {}
|
func (*FileOptions) ProtoMessage() {}
|
||||||
func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
|
func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
|
||||||
|
|
||||||
var extRange_FileOptions = []proto.ExtensionRange{
|
var extRange_FileOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
@@ -1222,7 +1258,7 @@ type MessageOptions struct {
|
|||||||
func (m *MessageOptions) Reset() { *m = MessageOptions{} }
|
func (m *MessageOptions) Reset() { *m = MessageOptions{} }
|
||||||
func (m *MessageOptions) String() string { return proto.CompactTextString(m) }
|
func (m *MessageOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*MessageOptions) ProtoMessage() {}
|
func (*MessageOptions) ProtoMessage() {}
|
||||||
func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
|
func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
|
||||||
|
|
||||||
var extRange_MessageOptions = []proto.ExtensionRange{
|
var extRange_MessageOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
@@ -1285,13 +1321,15 @@ type FieldOptions struct {
|
|||||||
Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"`
|
Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"`
|
||||||
// The jstype option determines the JavaScript type used for values of the
|
// The jstype option determines the JavaScript type used for values of the
|
||||||
// field. The option is permitted only for 64 bit integral and fixed types
|
// field. The option is permitted only for 64 bit integral and fixed types
|
||||||
// (int64, uint64, sint64, fixed64, sfixed64). By default these types are
|
// (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
|
||||||
// represented as JavaScript strings. This avoids loss of precision that can
|
// is represented as JavaScript string, which avoids loss of precision that
|
||||||
// happen when a large value is converted to a floating point JavaScript
|
// can happen when a large value is converted to a floating point JavaScript.
|
||||||
// numbers. Specifying JS_NUMBER for the jstype causes the generated
|
// Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
|
||||||
// JavaScript code to use the JavaScript "number" type instead of strings.
|
// use the JavaScript "number" type. The behavior of the default option
|
||||||
// This option is an enum to permit additional types to be added,
|
// JS_NORMAL is implementation dependent.
|
||||||
// e.g. goog.math.Integer.
|
//
|
||||||
|
// This option is an enum to permit additional types to be added, e.g.
|
||||||
|
// goog.math.Integer.
|
||||||
Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"`
|
Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"`
|
||||||
// Should this field be parsed lazily? Lazy applies only to message-type
|
// Should this field be parsed lazily? Lazy applies only to message-type
|
||||||
// fields. It means that when the outer message is initially parsed, the
|
// fields. It means that when the outer message is initially parsed, the
|
||||||
@@ -1338,7 +1376,7 @@ type FieldOptions struct {
|
|||||||
func (m *FieldOptions) Reset() { *m = FieldOptions{} }
|
func (m *FieldOptions) Reset() { *m = FieldOptions{} }
|
||||||
func (m *FieldOptions) String() string { return proto.CompactTextString(m) }
|
func (m *FieldOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*FieldOptions) ProtoMessage() {}
|
func (*FieldOptions) ProtoMessage() {}
|
||||||
func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
|
func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
|
||||||
|
|
||||||
var extRange_FieldOptions = []proto.ExtensionRange{
|
var extRange_FieldOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
@@ -1413,7 +1451,7 @@ type OneofOptions struct {
|
|||||||
func (m *OneofOptions) Reset() { *m = OneofOptions{} }
|
func (m *OneofOptions) Reset() { *m = OneofOptions{} }
|
||||||
func (m *OneofOptions) String() string { return proto.CompactTextString(m) }
|
func (m *OneofOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*OneofOptions) ProtoMessage() {}
|
func (*OneofOptions) ProtoMessage() {}
|
||||||
func (*OneofOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
|
func (*OneofOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
|
||||||
|
|
||||||
var extRange_OneofOptions = []proto.ExtensionRange{
|
var extRange_OneofOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
@@ -1448,7 +1486,7 @@ type EnumOptions struct {
|
|||||||
func (m *EnumOptions) Reset() { *m = EnumOptions{} }
|
func (m *EnumOptions) Reset() { *m = EnumOptions{} }
|
||||||
func (m *EnumOptions) String() string { return proto.CompactTextString(m) }
|
func (m *EnumOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*EnumOptions) ProtoMessage() {}
|
func (*EnumOptions) ProtoMessage() {}
|
||||||
func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
|
func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
|
||||||
|
|
||||||
var extRange_EnumOptions = []proto.ExtensionRange{
|
var extRange_EnumOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
@@ -1496,7 +1534,7 @@ type EnumValueOptions struct {
|
|||||||
func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} }
|
func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} }
|
||||||
func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) }
|
func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*EnumValueOptions) ProtoMessage() {}
|
func (*EnumValueOptions) ProtoMessage() {}
|
||||||
func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
|
func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
|
||||||
|
|
||||||
var extRange_EnumValueOptions = []proto.ExtensionRange{
|
var extRange_EnumValueOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
@@ -1537,7 +1575,7 @@ type ServiceOptions struct {
|
|||||||
func (m *ServiceOptions) Reset() { *m = ServiceOptions{} }
|
func (m *ServiceOptions) Reset() { *m = ServiceOptions{} }
|
||||||
func (m *ServiceOptions) String() string { return proto.CompactTextString(m) }
|
func (m *ServiceOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ServiceOptions) ProtoMessage() {}
|
func (*ServiceOptions) ProtoMessage() {}
|
||||||
func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
|
func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
|
||||||
|
|
||||||
var extRange_ServiceOptions = []proto.ExtensionRange{
|
var extRange_ServiceOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
@@ -1579,7 +1617,7 @@ type MethodOptions struct {
|
|||||||
func (m *MethodOptions) Reset() { *m = MethodOptions{} }
|
func (m *MethodOptions) Reset() { *m = MethodOptions{} }
|
||||||
func (m *MethodOptions) String() string { return proto.CompactTextString(m) }
|
func (m *MethodOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*MethodOptions) ProtoMessage() {}
|
func (*MethodOptions) ProtoMessage() {}
|
||||||
func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
|
func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
|
||||||
|
|
||||||
var extRange_MethodOptions = []proto.ExtensionRange{
|
var extRange_MethodOptions = []proto.ExtensionRange{
|
||||||
{1000, 536870911},
|
{1000, 536870911},
|
||||||
@@ -1635,7 +1673,7 @@ type UninterpretedOption struct {
|
|||||||
func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} }
|
func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} }
|
||||||
func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) }
|
func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) }
|
||||||
func (*UninterpretedOption) ProtoMessage() {}
|
func (*UninterpretedOption) ProtoMessage() {}
|
||||||
func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
|
func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
|
||||||
|
|
||||||
func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart {
|
func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
@@ -1701,7 +1739,7 @@ func (m *UninterpretedOption_NamePart) Reset() { *m = UninterpretedOptio
|
|||||||
func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) }
|
func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) }
|
||||||
func (*UninterpretedOption_NamePart) ProtoMessage() {}
|
func (*UninterpretedOption_NamePart) ProtoMessage() {}
|
||||||
func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) {
|
func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor0, []int{17, 0}
|
return fileDescriptor0, []int{18, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UninterpretedOption_NamePart) GetNamePart() string {
|
func (m *UninterpretedOption_NamePart) GetNamePart() string {
|
||||||
@@ -1771,7 +1809,7 @@ type SourceCodeInfo struct {
|
|||||||
func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} }
|
func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} }
|
||||||
func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) }
|
func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) }
|
||||||
func (*SourceCodeInfo) ProtoMessage() {}
|
func (*SourceCodeInfo) ProtoMessage() {}
|
||||||
func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
|
func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
|
||||||
|
|
||||||
func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location {
|
func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
@@ -1867,7 +1905,7 @@ type SourceCodeInfo_Location struct {
|
|||||||
func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} }
|
func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} }
|
||||||
func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) }
|
func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) }
|
||||||
func (*SourceCodeInfo_Location) ProtoMessage() {}
|
func (*SourceCodeInfo_Location) ProtoMessage() {}
|
||||||
func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18, 0} }
|
func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} }
|
||||||
|
|
||||||
func (m *SourceCodeInfo_Location) GetPath() []int32 {
|
func (m *SourceCodeInfo_Location) GetPath() []int32 {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
@@ -1917,7 +1955,7 @@ type GeneratedCodeInfo struct {
|
|||||||
func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} }
|
func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} }
|
||||||
func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) }
|
func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) }
|
||||||
func (*GeneratedCodeInfo) ProtoMessage() {}
|
func (*GeneratedCodeInfo) ProtoMessage() {}
|
||||||
func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
|
func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} }
|
||||||
|
|
||||||
func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation {
|
func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
@@ -1946,7 +1984,7 @@ func (m *GeneratedCodeInfo_Annotation) Reset() { *m = GeneratedCodeInfo_
|
|||||||
func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) }
|
func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) }
|
||||||
func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
|
func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
|
||||||
func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) {
|
func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor0, []int{19, 0}
|
return fileDescriptor0, []int{20, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 {
|
func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 {
|
||||||
@@ -1983,6 +2021,7 @@ func init() {
|
|||||||
proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto")
|
proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto")
|
||||||
proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange")
|
proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange")
|
||||||
proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange")
|
proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange")
|
||||||
|
proto.RegisterType((*ExtensionRangeOptions)(nil), "google.protobuf.ExtensionRangeOptions")
|
||||||
proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto")
|
proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto")
|
||||||
proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto")
|
proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto")
|
||||||
proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto")
|
proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto")
|
||||||
@@ -2014,161 +2053,163 @@ func init() {
|
|||||||
func init() { proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor0) }
|
func init() { proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor0) }
|
||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor0 = []byte{
|
||||||
// 2490 bytes of a gzipped FileDescriptorProto
|
// 2519 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x8e, 0xdb, 0xc6,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6e, 0x1b, 0xc7,
|
||||||
0x15, 0x8e, 0x7e, 0x57, 0x3a, 0xd2, 0x6a, 0x67, 0x67, 0x37, 0x36, 0xbd, 0xf9, 0xf1, 0x5a, 0xf9,
|
0x15, 0x0e, 0x7f, 0x45, 0x1e, 0x52, 0xd4, 0x68, 0xa4, 0xd8, 0x6b, 0xe5, 0xc7, 0x32, 0xf3, 0x63,
|
||||||
0xf1, 0x3a, 0x69, 0xb4, 0xc1, 0xc6, 0x76, 0x9c, 0x4d, 0xe1, 0x42, 0x2b, 0xd1, 0x1b, 0xb9, 0x5a,
|
0xd9, 0x69, 0xa8, 0x40, 0xb1, 0x1d, 0x47, 0x29, 0xd2, 0x52, 0xe4, 0x5a, 0xa1, 0x4a, 0x91, 0xec,
|
||||||
0x49, 0xa5, 0xb4, 0x8d, 0x9d, 0x1b, 0x62, 0x96, 0x1c, 0x49, 0xb4, 0x29, 0x92, 0x21, 0x29, 0xdb,
|
0x92, 0x6a, 0x7e, 0x6e, 0x16, 0xa3, 0xdd, 0x21, 0xb9, 0xf6, 0x72, 0x77, 0xb3, 0xbb, 0xb4, 0xad,
|
||||||
0x9b, 0x2b, 0x03, 0xbd, 0x2a, 0xd0, 0x07, 0x28, 0x8a, 0xa2, 0x17, 0xb9, 0x09, 0xd0, 0x07, 0x28,
|
0xa0, 0x17, 0x06, 0x7a, 0x55, 0xa0, 0x0f, 0x50, 0x14, 0x45, 0x2f, 0x72, 0x13, 0xa0, 0x0f, 0x50,
|
||||||
0xd0, 0xbb, 0x3e, 0x41, 0x81, 0xbc, 0x41, 0x51, 0x14, 0x68, 0xdf, 0xa0, 0xb7, 0xc5, 0xcc, 0x90,
|
0x20, 0x77, 0x7d, 0x82, 0x02, 0x79, 0x83, 0xa2, 0x28, 0xd0, 0x3e, 0x46, 0x31, 0x33, 0xbb, 0xcb,
|
||||||
0x14, 0xa9, 0x1f, 0x7b, 0x1b, 0xc0, 0xc9, 0x95, 0x34, 0xdf, 0xf9, 0xce, 0x99, 0x33, 0x67, 0xce,
|
0x5d, 0xfe, 0xc4, 0x6a, 0x80, 0x38, 0x57, 0xe4, 0x7c, 0xe7, 0x3b, 0x67, 0xce, 0x9c, 0x39, 0x33,
|
||||||
0xcc, 0x9c, 0x19, 0xc2, 0xee, 0xc8, 0xb6, 0x47, 0x26, 0xdd, 0x77, 0x5c, 0xdb, 0xb7, 0xcf, 0xa6,
|
0x73, 0x66, 0x16, 0x76, 0x47, 0xb6, 0x3d, 0x32, 0xe9, 0xbe, 0xe3, 0xda, 0xbe, 0x7d, 0x3e, 0x1d,
|
||||||
0xc3, 0x7d, 0x9d, 0x7a, 0x9a, 0x6b, 0x38, 0xbe, 0xed, 0xd6, 0x38, 0x86, 0x37, 0x04, 0xa3, 0x16,
|
0xee, 0xeb, 0xd4, 0xd3, 0x5c, 0xc3, 0xf1, 0x6d, 0xb7, 0xc6, 0x31, 0xbc, 0x21, 0x18, 0xb5, 0x90,
|
||||||
0x32, 0xaa, 0x27, 0xb0, 0x79, 0xcf, 0x30, 0x69, 0x33, 0x22, 0xf6, 0xa9, 0x8f, 0xef, 0x40, 0x76,
|
0x51, 0x3d, 0x85, 0xcd, 0x07, 0x86, 0x49, 0x9b, 0x11, 0xb1, 0x4f, 0x7d, 0x7c, 0x1f, 0xb2, 0x43,
|
||||||
0x68, 0x98, 0x54, 0x4a, 0xed, 0x66, 0xf6, 0x4a, 0x07, 0xef, 0xd6, 0xe6, 0x94, 0x6a, 0x49, 0x8d,
|
0xc3, 0xa4, 0x52, 0x6a, 0x37, 0xb3, 0x57, 0x3a, 0x78, 0xb3, 0x36, 0xa7, 0x54, 0x4b, 0x6a, 0xf4,
|
||||||
0x1e, 0x83, 0x15, 0xae, 0x51, 0xfd, 0x57, 0x16, 0xb6, 0x96, 0x48, 0x31, 0x86, 0xac, 0x45, 0x26,
|
0x18, 0xac, 0x70, 0x8d, 0xea, 0xbf, 0xb3, 0xb0, 0xb5, 0x44, 0x8a, 0x31, 0x64, 0x2d, 0x32, 0x61,
|
||||||
0xcc, 0x62, 0x6a, 0xaf, 0xa8, 0xf0, 0xff, 0x58, 0x82, 0x35, 0x87, 0x68, 0x8f, 0xc9, 0x88, 0x4a,
|
0x16, 0x53, 0x7b, 0x45, 0x85, 0xff, 0xc7, 0x12, 0xac, 0x39, 0x44, 0x7b, 0x44, 0x46, 0x54, 0x4a,
|
||||||
0x69, 0x0e, 0x87, 0x4d, 0xfc, 0x36, 0x80, 0x4e, 0x1d, 0x6a, 0xe9, 0xd4, 0xd2, 0xce, 0xa5, 0xcc,
|
0x73, 0x38, 0x6c, 0xe2, 0xd7, 0x01, 0x74, 0xea, 0x50, 0x4b, 0xa7, 0x96, 0x76, 0x21, 0x65, 0x76,
|
||||||
0x6e, 0x66, 0xaf, 0xa8, 0xc4, 0x10, 0xfc, 0x21, 0x6c, 0x3a, 0xd3, 0x33, 0xd3, 0xd0, 0xd4, 0x18,
|
0x33, 0x7b, 0x45, 0x25, 0x86, 0xe0, 0x77, 0x60, 0xd3, 0x99, 0x9e, 0x9b, 0x86, 0xa6, 0xc6, 0x68,
|
||||||
0x0d, 0x76, 0x33, 0x7b, 0x39, 0x05, 0x09, 0x41, 0x73, 0x46, 0xbe, 0x0e, 0x1b, 0x4f, 0x29, 0x79,
|
0xb0, 0x9b, 0xd9, 0xcb, 0x29, 0x48, 0x08, 0x9a, 0x33, 0xf2, 0x4d, 0xd8, 0x78, 0x42, 0xc9, 0xa3,
|
||||||
0x1c, 0xa7, 0x96, 0x38, 0xb5, 0xc2, 0xe0, 0x18, 0xb1, 0x01, 0xe5, 0x09, 0xf5, 0x3c, 0x32, 0xa2,
|
0x38, 0xb5, 0xc4, 0xa9, 0x15, 0x06, 0xc7, 0x88, 0x0d, 0x28, 0x4f, 0xa8, 0xe7, 0x91, 0x11, 0x55,
|
||||||
0xaa, 0x7f, 0xee, 0x50, 0x29, 0xcb, 0x47, 0xbf, 0xbb, 0x30, 0xfa, 0xf9, 0x91, 0x97, 0x02, 0xad,
|
0xfd, 0x0b, 0x87, 0x4a, 0x59, 0x3e, 0xfa, 0xdd, 0x85, 0xd1, 0xcf, 0x8f, 0xbc, 0x14, 0x68, 0x0d,
|
||||||
0xc1, 0xb9, 0x43, 0x71, 0x1d, 0x8a, 0xd4, 0x9a, 0x4e, 0x84, 0x85, 0xdc, 0x8a, 0xf8, 0xc9, 0xd6,
|
0x2e, 0x1c, 0x8a, 0xeb, 0x50, 0xa4, 0xd6, 0x74, 0x22, 0x2c, 0xe4, 0x56, 0xc4, 0x4f, 0xb6, 0xa6,
|
||||||
0x74, 0x32, 0x6f, 0xa5, 0xc0, 0xd4, 0x02, 0x13, 0x6b, 0x1e, 0x75, 0x9f, 0x18, 0x1a, 0x95, 0xf2,
|
0x93, 0x79, 0x2b, 0x05, 0xa6, 0x16, 0x98, 0x58, 0xf3, 0xa8, 0xfb, 0xd8, 0xd0, 0xa8, 0x94, 0xe7,
|
||||||
0xdc, 0xc0, 0xf5, 0x05, 0x03, 0x7d, 0x21, 0x9f, 0xb7, 0x11, 0xea, 0xe1, 0x06, 0x14, 0xe9, 0x33,
|
0x06, 0x6e, 0x2e, 0x18, 0xe8, 0x0b, 0xf9, 0xbc, 0x8d, 0x50, 0x0f, 0x37, 0xa0, 0x48, 0x9f, 0xfa,
|
||||||
0x9f, 0x5a, 0x9e, 0x61, 0x5b, 0xd2, 0x1a, 0x37, 0xf2, 0xde, 0x92, 0x59, 0xa4, 0xa6, 0x3e, 0x6f,
|
0xd4, 0xf2, 0x0c, 0xdb, 0x92, 0xd6, 0xb8, 0x91, 0xb7, 0x96, 0xcc, 0x22, 0x35, 0xf5, 0x79, 0x13,
|
||||||
0x62, 0xa6, 0x87, 0x6f, 0xc3, 0x9a, 0xed, 0xf8, 0x86, 0x6d, 0x79, 0x52, 0x61, 0x37, 0xb5, 0x57,
|
0x33, 0x3d, 0x7c, 0x0f, 0xd6, 0x6c, 0xc7, 0x37, 0x6c, 0xcb, 0x93, 0x0a, 0xbb, 0xa9, 0xbd, 0xd2,
|
||||||
0x3a, 0x78, 0x73, 0x69, 0x22, 0x74, 0x05, 0x47, 0x09, 0xc9, 0xb8, 0x05, 0xc8, 0xb3, 0xa7, 0xae,
|
0xc1, 0xab, 0x4b, 0x13, 0xa1, 0x2b, 0x38, 0x4a, 0x48, 0xc6, 0x2d, 0x40, 0x9e, 0x3d, 0x75, 0x35,
|
||||||
0x46, 0x55, 0xcd, 0xd6, 0xa9, 0x6a, 0x58, 0x43, 0x5b, 0x2a, 0x72, 0x03, 0x57, 0x17, 0x07, 0xc2,
|
0xaa, 0x6a, 0xb6, 0x4e, 0x55, 0xc3, 0x1a, 0xda, 0x52, 0x91, 0x1b, 0xb8, 0xbe, 0x38, 0x10, 0x4e,
|
||||||
0x89, 0x0d, 0x5b, 0xa7, 0x2d, 0x6b, 0x68, 0x2b, 0x15, 0x2f, 0xd1, 0xc6, 0x97, 0x20, 0xef, 0x9d,
|
0x6c, 0xd8, 0x3a, 0x6d, 0x59, 0x43, 0x5b, 0xa9, 0x78, 0x89, 0x36, 0xbe, 0x02, 0x79, 0xef, 0xc2,
|
||||||
0x5b, 0x3e, 0x79, 0x26, 0x95, 0x79, 0x86, 0x04, 0xad, 0xea, 0x7f, 0x73, 0xb0, 0x71, 0x91, 0x14,
|
0xf2, 0xc9, 0x53, 0xa9, 0xcc, 0x33, 0x24, 0x68, 0x55, 0xbf, 0xcd, 0xc3, 0xc6, 0x65, 0x52, 0xec,
|
||||||
0xfb, 0x1c, 0x72, 0x43, 0x36, 0x4a, 0x29, 0xfd, 0xff, 0xc4, 0x40, 0xe8, 0x24, 0x83, 0x98, 0xff,
|
0x23, 0xc8, 0x0d, 0xd9, 0x28, 0xa5, 0xf4, 0xff, 0x13, 0x03, 0xa1, 0x93, 0x0c, 0x62, 0xfe, 0x07,
|
||||||
0x81, 0x41, 0xac, 0x43, 0xc9, 0xa2, 0x9e, 0x4f, 0x75, 0x91, 0x11, 0x99, 0x0b, 0xe6, 0x14, 0x08,
|
0x06, 0xb1, 0x0e, 0x25, 0x8b, 0x7a, 0x3e, 0xd5, 0x45, 0x46, 0x64, 0x2e, 0x99, 0x53, 0x20, 0x94,
|
||||||
0xa5, 0xc5, 0x94, 0xca, 0xfe, 0xa0, 0x94, 0x7a, 0x00, 0x1b, 0x91, 0x4b, 0xaa, 0x4b, 0xac, 0x51,
|
0x16, 0x53, 0x2a, 0xfb, 0x83, 0x52, 0xea, 0x33, 0xd8, 0x88, 0x5c, 0x52, 0x5d, 0x62, 0x8d, 0xc2,
|
||||||
0x98, 0x9b, 0xfb, 0x2f, 0xf3, 0xa4, 0x26, 0x87, 0x7a, 0x0a, 0x53, 0x53, 0x2a, 0x34, 0xd1, 0xc6,
|
0xdc, 0xdc, 0x7f, 0x9e, 0x27, 0x35, 0x39, 0xd4, 0x53, 0x98, 0x9a, 0x52, 0xa1, 0x89, 0x36, 0x6e,
|
||||||
0x4d, 0x00, 0xdb, 0xa2, 0xf6, 0x50, 0xd5, 0xa9, 0x66, 0x4a, 0x85, 0x15, 0x51, 0xea, 0x32, 0xca,
|
0x02, 0xd8, 0x16, 0xb5, 0x87, 0xaa, 0x4e, 0x35, 0x53, 0x2a, 0xac, 0x88, 0x52, 0x97, 0x51, 0x16,
|
||||||
0x42, 0x94, 0x6c, 0x81, 0x6a, 0x26, 0xfe, 0x6c, 0x96, 0x6a, 0x6b, 0x2b, 0x32, 0xe5, 0x44, 0x2c,
|
0xa2, 0x64, 0x0b, 0x54, 0x33, 0xf1, 0x87, 0xb3, 0x54, 0x5b, 0x5b, 0x91, 0x29, 0xa7, 0x62, 0x91,
|
||||||
0xb2, 0x85, 0x6c, 0x3b, 0x85, 0x8a, 0x4b, 0x59, 0xde, 0x53, 0x3d, 0x18, 0x59, 0x91, 0x3b, 0x51,
|
0x2d, 0x64, 0xdb, 0x19, 0x54, 0x5c, 0xca, 0xf2, 0x9e, 0xea, 0xc1, 0xc8, 0x8a, 0xdc, 0x89, 0xda,
|
||||||
0x7b, 0xe9, 0xc8, 0x94, 0x40, 0x4d, 0x0c, 0x6c, 0xdd, 0x8d, 0x37, 0xf1, 0x3b, 0x10, 0x01, 0x2a,
|
0x73, 0x47, 0xa6, 0x04, 0x6a, 0x62, 0x60, 0xeb, 0x6e, 0xbc, 0x89, 0xdf, 0x80, 0x08, 0x50, 0x79,
|
||||||
0x4f, 0x2b, 0xe0, 0xbb, 0x50, 0x39, 0x04, 0x3b, 0x64, 0x42, 0x77, 0xee, 0x40, 0x25, 0x19, 0x1e,
|
0x5a, 0x01, 0xdf, 0x85, 0xca, 0x21, 0xd8, 0x21, 0x13, 0xba, 0xf3, 0x15, 0x54, 0x92, 0xe1, 0xc1,
|
||||||
0xbc, 0x0d, 0x39, 0xcf, 0x27, 0xae, 0xcf, 0xb3, 0x30, 0xa7, 0x88, 0x06, 0x46, 0x90, 0xa1, 0x96,
|
0xdb, 0x90, 0xf3, 0x7c, 0xe2, 0xfa, 0x3c, 0x0b, 0x73, 0x8a, 0x68, 0x60, 0x04, 0x19, 0x6a, 0xe9,
|
||||||
0xce, 0x77, 0xb9, 0x9c, 0xc2, 0xfe, 0xee, 0x7c, 0x0a, 0xeb, 0x89, 0xee, 0x2f, 0xaa, 0x58, 0xfd,
|
0x7c, 0x97, 0xcb, 0x29, 0xec, 0x2f, 0xfe, 0xe5, 0x6c, 0xc0, 0x19, 0x3e, 0xe0, 0xb7, 0x17, 0x67,
|
||||||
0x7d, 0x1e, 0xb6, 0x97, 0xe5, 0xdc, 0xd2, 0xf4, 0xbf, 0x04, 0x79, 0x6b, 0x3a, 0x39, 0xa3, 0xae,
|
0x34, 0x61, 0x79, 0x7e, 0xdc, 0x3b, 0x1f, 0xc0, 0x7a, 0x62, 0x00, 0x97, 0xed, 0xba, 0xfa, 0x5b,
|
||||||
0x94, 0xe1, 0x16, 0x82, 0x16, 0xae, 0x43, 0xce, 0x24, 0x67, 0xd4, 0x94, 0xb2, 0xbb, 0xa9, 0xbd,
|
0x78, 0x79, 0xa9, 0x69, 0xfc, 0x19, 0x6c, 0x4f, 0x2d, 0xc3, 0xf2, 0xa9, 0xeb, 0xb8, 0x94, 0x65,
|
||||||
0xca, 0xc1, 0x87, 0x17, 0xca, 0xea, 0x5a, 0x9b, 0xa9, 0x28, 0x42, 0x13, 0xdf, 0x85, 0x6c, 0xb0,
|
0xac, 0xe8, 0x4a, 0xfa, 0xcf, 0xda, 0x8a, 0x9c, 0x3b, 0x8b, 0xb3, 0x85, 0x15, 0x65, 0x6b, 0xba,
|
||||||
0xc5, 0x31, 0x0b, 0x1f, 0x5c, 0xcc, 0x02, 0xcb, 0x45, 0x85, 0xeb, 0xe1, 0x37, 0xa0, 0xc8, 0x7e,
|
0x08, 0xde, 0x2e, 0x16, 0xfe, 0xbb, 0x86, 0x9e, 0x3d, 0x7b, 0xf6, 0x2c, 0x5d, 0xfd, 0x63, 0x1e,
|
||||||
0x45, 0x6c, 0xf3, 0xdc, 0xe7, 0x02, 0x03, 0x58, 0x5c, 0xf1, 0x0e, 0x14, 0x78, 0x9a, 0xe9, 0x34,
|
0xb6, 0x97, 0xad, 0x99, 0xa5, 0xcb, 0xf7, 0x0a, 0xe4, 0xad, 0xe9, 0xe4, 0x9c, 0xba, 0x3c, 0x48,
|
||||||
0x3c, 0x1a, 0xa2, 0x36, 0x9b, 0x18, 0x9d, 0x0e, 0xc9, 0xd4, 0xf4, 0xd5, 0x27, 0xc4, 0x9c, 0x52,
|
0x39, 0x25, 0x68, 0xe1, 0x3a, 0xe4, 0x4c, 0x72, 0x4e, 0x4d, 0x29, 0xbb, 0x9b, 0xda, 0xab, 0x1c,
|
||||||
0x9e, 0x30, 0x45, 0xa5, 0x1c, 0x80, 0xbf, 0x66, 0x18, 0xbe, 0x0a, 0x25, 0x91, 0x95, 0x86, 0xa5,
|
0xbc, 0x73, 0xa9, 0x55, 0x59, 0x6b, 0x33, 0x15, 0x45, 0x68, 0xe2, 0x8f, 0x21, 0x1b, 0x6c, 0xd1,
|
||||||
0xd3, 0x67, 0x7c, 0xf7, 0xc9, 0x29, 0x22, 0x51, 0x5b, 0x0c, 0x61, 0xdd, 0x3f, 0xf2, 0x6c, 0x2b,
|
0xcc, 0xc2, 0xed, 0xcb, 0x59, 0x60, 0x6b, 0x49, 0xe1, 0x7a, 0xf8, 0x15, 0x28, 0xb2, 0x5f, 0x91,
|
||||||
0x9c, 0x5a, 0xde, 0x05, 0x03, 0x78, 0xf7, 0x9f, 0xce, 0x6f, 0x7c, 0x6f, 0x2d, 0x1f, 0xde, 0x7c,
|
0x1b, 0x79, 0xee, 0x73, 0x81, 0x01, 0x2c, 0x2f, 0xf0, 0x0e, 0x14, 0xf8, 0x32, 0xd1, 0x69, 0x78,
|
||||||
0x2e, 0x56, 0xff, 0x92, 0x86, 0x2c, 0x5f, 0x6f, 0x1b, 0x50, 0x1a, 0x3c, 0xec, 0xc9, 0x6a, 0xb3,
|
0xb4, 0x45, 0x6d, 0x96, 0x58, 0x3a, 0x1d, 0x92, 0xa9, 0xe9, 0xab, 0x8f, 0x89, 0x39, 0xa5, 0x3c,
|
||||||
0x7b, 0x7a, 0xd4, 0x96, 0x51, 0x0a, 0x57, 0x00, 0x38, 0x70, 0xaf, 0xdd, 0xad, 0x0f, 0x50, 0x3a,
|
0xe1, 0x8b, 0x4a, 0x39, 0x00, 0x7f, 0xc3, 0x30, 0x7c, 0x1d, 0x4a, 0x62, 0x55, 0x19, 0x96, 0x4e,
|
||||||
0x6a, 0xb7, 0x3a, 0x83, 0xdb, 0x37, 0x51, 0x26, 0x52, 0x38, 0x15, 0x40, 0x36, 0x4e, 0xf8, 0xe4,
|
0x9f, 0xf2, 0xdd, 0x33, 0xa7, 0x88, 0x85, 0xd6, 0x62, 0x08, 0xeb, 0xfe, 0xa1, 0x67, 0x5b, 0x61,
|
||||||
0x00, 0xe5, 0x30, 0x82, 0xb2, 0x30, 0xd0, 0x7a, 0x20, 0x37, 0x6f, 0xdf, 0x44, 0xf9, 0x24, 0xf2,
|
0x6a, 0xf2, 0x2e, 0x18, 0xc0, 0xbb, 0xff, 0x60, 0x7e, 0xe3, 0x7e, 0x6d, 0xf9, 0xf0, 0xe6, 0x73,
|
||||||
0xc9, 0x01, 0x5a, 0xc3, 0xeb, 0x50, 0xe4, 0xc8, 0x51, 0xb7, 0xdb, 0x46, 0x85, 0xc8, 0x66, 0x7f,
|
0xaa, 0xfa, 0xb7, 0x34, 0x64, 0xf9, 0x7e, 0xb1, 0x01, 0xa5, 0xc1, 0xe7, 0x3d, 0x59, 0x6d, 0x76,
|
||||||
0xa0, 0xb4, 0x3a, 0xc7, 0xa8, 0x18, 0xd9, 0x3c, 0x56, 0xba, 0xa7, 0x3d, 0x04, 0x91, 0x85, 0x13,
|
0xcf, 0x8e, 0xda, 0x32, 0x4a, 0xe1, 0x0a, 0x00, 0x07, 0x1e, 0xb4, 0xbb, 0xf5, 0x01, 0x4a, 0x47,
|
||||||
0xb9, 0xdf, 0xaf, 0x1f, 0xcb, 0xa8, 0x14, 0x31, 0x8e, 0x1e, 0x0e, 0xe4, 0x3e, 0x2a, 0x27, 0xdc,
|
0xed, 0x56, 0x67, 0x70, 0xef, 0x0e, 0xca, 0x44, 0x0a, 0x67, 0x02, 0xc8, 0xc6, 0x09, 0xef, 0x1f,
|
||||||
0xfa, 0xe4, 0x00, 0xad, 0x47, 0x5d, 0xc8, 0x9d, 0xd3, 0x13, 0x54, 0xc1, 0x9b, 0xb0, 0x2e, 0xba,
|
0xa0, 0x1c, 0x46, 0x50, 0x16, 0x06, 0x5a, 0x9f, 0xc9, 0xcd, 0x7b, 0x77, 0x50, 0x3e, 0x89, 0xbc,
|
||||||
0x08, 0x9d, 0xd8, 0x98, 0x83, 0x6e, 0xdf, 0x44, 0x68, 0xe6, 0x88, 0xb0, 0xb2, 0x99, 0x00, 0x6e,
|
0x7f, 0x80, 0xd6, 0xf0, 0x3a, 0x14, 0x39, 0x72, 0xd4, 0xed, 0xb6, 0x51, 0x21, 0xb2, 0xd9, 0x1f,
|
||||||
0xdf, 0x44, 0xb8, 0xda, 0x80, 0x1c, 0xcf, 0x2e, 0x8c, 0xa1, 0xd2, 0xae, 0x1f, 0xc9, 0x6d, 0xb5,
|
0x28, 0xad, 0xce, 0x31, 0x2a, 0x46, 0x36, 0x8f, 0x95, 0xee, 0x59, 0x0f, 0x41, 0x64, 0xe1, 0x54,
|
||||||
0xdb, 0x1b, 0xb4, 0xba, 0x9d, 0x7a, 0x1b, 0xa5, 0x66, 0x98, 0x22, 0xff, 0xea, 0xb4, 0xa5, 0xc8,
|
0xee, 0xf7, 0xeb, 0xc7, 0x32, 0x2a, 0x45, 0x8c, 0xa3, 0xcf, 0x07, 0x72, 0x1f, 0x95, 0x13, 0x6e,
|
||||||
0x4d, 0x94, 0x8e, 0x63, 0x3d, 0xb9, 0x3e, 0x90, 0x9b, 0x28, 0x53, 0xd5, 0x60, 0x7b, 0xd9, 0x3e,
|
0xbd, 0x7f, 0x80, 0xd6, 0xa3, 0x2e, 0xe4, 0xce, 0xd9, 0x29, 0xaa, 0xe0, 0x4d, 0x58, 0x17, 0x5d,
|
||||||
0xb3, 0x74, 0x65, 0xc4, 0xa6, 0x38, 0xbd, 0x62, 0x8a, 0xb9, 0xad, 0x85, 0x29, 0xfe, 0x36, 0x05,
|
0x84, 0x4e, 0x6c, 0xcc, 0x41, 0xf7, 0xee, 0x20, 0x34, 0x73, 0x44, 0x58, 0xd9, 0x4c, 0x00, 0xf7,
|
||||||
0x5b, 0x4b, 0xf6, 0xda, 0xa5, 0x9d, 0xfc, 0x02, 0x72, 0x22, 0x45, 0xc5, 0xe9, 0x73, 0x63, 0xe9,
|
0xee, 0x20, 0x5c, 0x6d, 0x40, 0x8e, 0x67, 0x17, 0xc6, 0x50, 0x69, 0xd7, 0x8f, 0xe4, 0xb6, 0xda,
|
||||||
0xa6, 0xcd, 0x13, 0x76, 0xe1, 0x04, 0xe2, 0x7a, 0xf1, 0x13, 0x38, 0xb3, 0xe2, 0x04, 0x66, 0x26,
|
0xed, 0x0d, 0x5a, 0xdd, 0x4e, 0xbd, 0x8d, 0x52, 0x33, 0x4c, 0x91, 0x7f, 0x7d, 0xd6, 0x52, 0xe4,
|
||||||
0x16, 0x9c, 0xfc, 0x4d, 0x0a, 0xa4, 0x55, 0xb6, 0x5f, 0xb2, 0x51, 0xa4, 0x13, 0x1b, 0xc5, 0xe7,
|
0x26, 0x4a, 0xc7, 0xb1, 0x9e, 0x5c, 0x1f, 0xc8, 0x4d, 0x94, 0xa9, 0x6a, 0xb0, 0xbd, 0x6c, 0x9f,
|
||||||
0xf3, 0x0e, 0x5c, 0x5b, 0x3d, 0x86, 0x05, 0x2f, 0xbe, 0x4b, 0xc1, 0xa5, 0xe5, 0x85, 0xca, 0x52,
|
0x5c, 0xba, 0x32, 0x62, 0x53, 0x9c, 0x5e, 0x31, 0xc5, 0xdc, 0xd6, 0xc2, 0x14, 0x7f, 0x9d, 0x82,
|
||||||
0x1f, 0xee, 0x42, 0x7e, 0x42, 0xfd, 0xb1, 0x1d, 0x1e, 0xd6, 0xef, 0x2f, 0x39, 0x02, 0x98, 0x78,
|
0xad, 0x25, 0x67, 0xc5, 0xd2, 0x4e, 0x7e, 0x01, 0x39, 0x91, 0xa2, 0xe2, 0xf4, 0xbc, 0xb5, 0xf4,
|
||||||
0x3e, 0x56, 0x81, 0x56, 0xfc, 0x0c, 0xc9, 0xac, 0xaa, 0x36, 0x84, 0x37, 0x0b, 0x9e, 0xfe, 0x36,
|
0xd0, 0xe1, 0x09, 0xbb, 0x70, 0x82, 0x72, 0xbd, 0x78, 0x05, 0x91, 0x59, 0x51, 0x41, 0x30, 0x13,
|
||||||
0x0d, 0xaf, 0x2f, 0x35, 0xbe, 0xd4, 0xd1, 0xb7, 0x00, 0x0c, 0xcb, 0x99, 0xfa, 0xe2, 0x40, 0x16,
|
0x0b, 0x4e, 0xfe, 0x2e, 0x05, 0xd2, 0x2a, 0xdb, 0xcf, 0xd9, 0x28, 0xd2, 0x89, 0x8d, 0xe2, 0xa3,
|
||||||
|
0x79, 0x07, 0x6e, 0xac, 0x1e, 0xc3, 0x82, 0x17, 0xdf, 0xa4, 0xe0, 0xca, 0xf2, 0x42, 0x6b, 0xa9,
|
||||||
|
0x0f, 0x1f, 0x43, 0x7e, 0x42, 0xfd, 0xb1, 0x1d, 0x16, 0x1b, 0x6f, 0x2f, 0x39, 0xc2, 0x98, 0x78,
|
||||||
|
0x3e, 0x56, 0x81, 0x56, 0xfc, 0x0c, 0xcc, 0xac, 0xaa, 0x96, 0x84, 0x37, 0x0b, 0x9e, 0xfe, 0x3e,
|
||||||
|
0x0d, 0x2f, 0x2f, 0x35, 0xbe, 0xd4, 0xd1, 0xd7, 0x00, 0x0c, 0xcb, 0x99, 0xfa, 0xa2, 0xa0, 0x10,
|
||||||
0xfb, 0x53, 0x91, 0x23, 0x7c, 0xed, 0xb3, 0xbd, 0x67, 0xea, 0x47, 0xf2, 0x0c, 0x97, 0x83, 0x80,
|
0xfb, 0x53, 0x91, 0x23, 0x7c, 0xed, 0xb3, 0xbd, 0x67, 0xea, 0x47, 0xf2, 0x0c, 0x97, 0x83, 0x80,
|
||||||
0x38, 0xe1, 0xce, 0xcc, 0xd1, 0x2c, 0x77, 0xf4, 0xed, 0x15, 0x23, 0x5d, 0x38, 0xeb, 0x3e, 0x06,
|
0x38, 0xe1, 0xfe, 0xcc, 0xd1, 0x2c, 0x77, 0xf4, 0xf5, 0x15, 0x23, 0x5d, 0x38, 0xab, 0xdf, 0x03,
|
||||||
0xa4, 0x99, 0x06, 0xb5, 0x7c, 0xd5, 0xf3, 0x5d, 0x4a, 0x26, 0x86, 0x35, 0xe2, 0x1b, 0x70, 0xe1,
|
0xa4, 0x99, 0x06, 0xb5, 0x7c, 0xd5, 0xf3, 0x5d, 0x4a, 0x26, 0x86, 0x35, 0xe2, 0x1b, 0x70, 0xe1,
|
||||||
0x30, 0x37, 0x24, 0xa6, 0x47, 0x95, 0x0d, 0x21, 0xee, 0x87, 0x52, 0xa6, 0xc1, 0x4f, 0x19, 0x37,
|
0x30, 0x37, 0x24, 0xa6, 0x47, 0x95, 0x0d, 0x21, 0xee, 0x87, 0x52, 0xa6, 0xc1, 0xcf, 0x38, 0x37,
|
||||||
0xa6, 0x91, 0x4f, 0x68, 0x08, 0x71, 0xa4, 0x51, 0xfd, 0x6b, 0x01, 0x4a, 0xb1, 0xb2, 0x0e, 0x5f,
|
0xa6, 0x91, 0x4f, 0x68, 0x08, 0x71, 0xa4, 0x51, 0xfd, 0xb6, 0x00, 0xa5, 0x58, 0x59, 0x8a, 0x6f,
|
||||||
0x83, 0xf2, 0x23, 0xf2, 0x84, 0xa8, 0x61, 0xa9, 0x2e, 0x22, 0x51, 0x62, 0x58, 0x2f, 0x28, 0xd7,
|
0x40, 0xf9, 0x21, 0x79, 0x4c, 0xd4, 0xf0, 0xaa, 0x21, 0x22, 0x51, 0x62, 0x58, 0x2f, 0xb8, 0x6e,
|
||||||
0x3f, 0x86, 0x6d, 0x4e, 0xb1, 0xa7, 0x3e, 0x75, 0x55, 0xcd, 0x24, 0x9e, 0xc7, 0x83, 0x56, 0xe0,
|
0xbc, 0x07, 0xdb, 0x9c, 0x62, 0x4f, 0x7d, 0xea, 0xaa, 0x9a, 0x49, 0x3c, 0x8f, 0x07, 0xad, 0xc0,
|
||||||
0x54, 0xcc, 0x64, 0x5d, 0x26, 0x6a, 0x84, 0x12, 0x7c, 0x0b, 0xb6, 0xb8, 0xc6, 0x64, 0x6a, 0xfa,
|
0xa9, 0x98, 0xc9, 0xba, 0x4c, 0xd4, 0x08, 0x25, 0xf8, 0x2e, 0x6c, 0x71, 0x8d, 0xc9, 0xd4, 0xf4,
|
||||||
0x86, 0x63, 0x52, 0x95, 0x5d, 0x1e, 0x3c, 0xbe, 0x11, 0x47, 0x9e, 0x6d, 0x32, 0xc6, 0x49, 0x40,
|
0x0d, 0xc7, 0xa4, 0x2a, 0xbb, 0xfc, 0x78, 0x7c, 0x23, 0x8e, 0x3c, 0xdb, 0x64, 0x8c, 0xd3, 0x80,
|
||||||
0x60, 0x1e, 0x79, 0xb8, 0x09, 0x6f, 0x71, 0xb5, 0x11, 0xb5, 0xa8, 0x4b, 0x7c, 0xaa, 0xd2, 0xaf,
|
0xc0, 0x3c, 0xf2, 0x70, 0x13, 0x5e, 0xe3, 0x6a, 0x23, 0x6a, 0x51, 0x97, 0xf8, 0x54, 0xa5, 0x5f,
|
||||||
0xa7, 0xc4, 0xf4, 0x54, 0x62, 0xe9, 0xea, 0x98, 0x78, 0x63, 0x69, 0x9b, 0x19, 0x38, 0x4a, 0x4b,
|
0x4e, 0x89, 0xe9, 0xa9, 0xc4, 0xd2, 0xd5, 0x31, 0xf1, 0xc6, 0xd2, 0x36, 0x33, 0x70, 0x94, 0x96,
|
||||||
0x29, 0xe5, 0x0a, 0x23, 0x1e, 0x07, 0x3c, 0x99, 0xd3, 0xea, 0x96, 0xfe, 0x05, 0xf1, 0xc6, 0xf8,
|
0x52, 0xca, 0x35, 0x46, 0x3c, 0x0e, 0x78, 0x32, 0xa7, 0xd5, 0x2d, 0xfd, 0x13, 0xe2, 0x8d, 0xf1,
|
||||||
0x10, 0x2e, 0x71, 0x2b, 0x9e, 0xef, 0x1a, 0xd6, 0x48, 0xd5, 0xc6, 0x54, 0x7b, 0xac, 0x4e, 0xfd,
|
0x21, 0x5c, 0xe1, 0x56, 0x3c, 0xdf, 0x35, 0xac, 0x91, 0xaa, 0x8d, 0xa9, 0xf6, 0x48, 0x9d, 0xfa,
|
||||||
0xe1, 0x1d, 0xe9, 0x8d, 0x78, 0xff, 0xdc, 0xc3, 0x3e, 0xe7, 0x34, 0x18, 0xe5, 0xd4, 0x1f, 0xde,
|
0xc3, 0xfb, 0xd2, 0x2b, 0xf1, 0xfe, 0xb9, 0x87, 0x7d, 0xce, 0x69, 0x30, 0xca, 0x99, 0x3f, 0xbc,
|
||||||
0xc1, 0x7d, 0x28, 0xb3, 0xc9, 0x98, 0x18, 0xdf, 0x50, 0x75, 0x68, 0xbb, 0xfc, 0x64, 0xa9, 0x2c,
|
0x8f, 0xfb, 0x50, 0x66, 0x93, 0x31, 0x31, 0xbe, 0xa2, 0xea, 0xd0, 0x76, 0xf9, 0xc9, 0x52, 0x59,
|
||||||
0x59, 0xd9, 0xb1, 0x08, 0xd6, 0xba, 0x81, 0xc2, 0x89, 0xad, 0xd3, 0xc3, 0x5c, 0xbf, 0x27, 0xcb,
|
0xb2, 0xb2, 0x63, 0x11, 0xac, 0x75, 0x03, 0x85, 0x53, 0x5b, 0xa7, 0x87, 0xb9, 0x7e, 0x4f, 0x96,
|
||||||
0x4d, 0xa5, 0x14, 0x5a, 0xb9, 0x67, 0xbb, 0x2c, 0xa1, 0x46, 0x76, 0x14, 0xe0, 0x92, 0x48, 0xa8,
|
0x9b, 0x4a, 0x29, 0xb4, 0xf2, 0xc0, 0x76, 0x59, 0x42, 0x8d, 0xec, 0x28, 0xc0, 0x25, 0x91, 0x50,
|
||||||
0x91, 0x1d, 0x86, 0xf7, 0x16, 0x6c, 0x69, 0x9a, 0x18, 0xb3, 0xa1, 0xa9, 0x41, 0x89, 0xef, 0x49,
|
0x23, 0x3b, 0x0c, 0xef, 0x5d, 0xd8, 0xd2, 0x34, 0x31, 0x66, 0x43, 0x53, 0x83, 0x2b, 0x8a, 0x27,
|
||||||
0x28, 0x11, 0x2c, 0x4d, 0x3b, 0x16, 0x84, 0x20, 0xc7, 0x3d, 0xfc, 0x19, 0xbc, 0x3e, 0x0b, 0x56,
|
0xa1, 0x44, 0xb0, 0x34, 0xed, 0x58, 0x10, 0x82, 0x1c, 0xf7, 0xf0, 0x87, 0xf0, 0xf2, 0x2c, 0x58,
|
||||||
0x5c, 0x71, 0x73, 0x61, 0x94, 0xf3, 0xaa, 0xb7, 0x60, 0xcb, 0x39, 0x5f, 0x54, 0xc4, 0x89, 0x1e,
|
0x71, 0xc5, 0xcd, 0x85, 0x51, 0xce, 0xab, 0xde, 0x85, 0x2d, 0xe7, 0x62, 0x51, 0x11, 0x27, 0x7a,
|
||||||
0x9d, 0xf3, 0x79, 0xb5, 0x4f, 0x61, 0xdb, 0x19, 0x3b, 0x8b, 0x7a, 0x5b, 0x71, 0x3d, 0xec, 0x8c,
|
0x74, 0x2e, 0xe6, 0xd5, 0x3e, 0x80, 0x6d, 0x67, 0xec, 0x2c, 0xea, 0xdd, 0x8e, 0xeb, 0x61, 0x67,
|
||||||
0x9d, 0x79, 0xc5, 0xf7, 0xf8, 0x7d, 0xcf, 0xa5, 0x1a, 0xf1, 0xa9, 0x2e, 0x5d, 0x8e, 0xd3, 0x63,
|
0xec, 0xcc, 0x2b, 0xbe, 0xc5, 0xef, 0xab, 0x2e, 0xd5, 0x88, 0x4f, 0x75, 0xe9, 0x6a, 0x9c, 0x1e,
|
||||||
0x02, 0xbc, 0x0f, 0x48, 0xd3, 0x54, 0x6a, 0x91, 0x33, 0x93, 0xaa, 0xc4, 0xa5, 0x16, 0xf1, 0xa4,
|
0x13, 0xe0, 0x7d, 0x40, 0x9a, 0xa6, 0x52, 0x8b, 0x9c, 0x9b, 0x54, 0x25, 0x2e, 0xb5, 0x88, 0x27,
|
||||||
0xab, 0x71, 0x72, 0x45, 0xd3, 0x64, 0x2e, 0xad, 0x73, 0x21, 0xfe, 0x00, 0x36, 0xed, 0xb3, 0x47,
|
0x5d, 0x8f, 0x93, 0x2b, 0x9a, 0x26, 0x73, 0x69, 0x9d, 0x0b, 0xf1, 0x6d, 0xd8, 0xb4, 0xcf, 0x1f,
|
||||||
0x9a, 0x48, 0x49, 0xd5, 0x71, 0xe9, 0xd0, 0x78, 0x26, 0xbd, 0xcb, 0xe3, 0xbb, 0xc1, 0x04, 0x3c,
|
0x6a, 0x22, 0x25, 0x55, 0xc7, 0xa5, 0x43, 0xe3, 0xa9, 0xf4, 0x26, 0x8f, 0xef, 0x06, 0x13, 0xf0,
|
||||||
0x21, 0x7b, 0x1c, 0xc6, 0x37, 0x00, 0x69, 0xde, 0x98, 0xb8, 0x0e, 0xaf, 0x09, 0x3c, 0x87, 0x68,
|
0x84, 0xec, 0x71, 0x18, 0xdf, 0x02, 0xa4, 0x79, 0x63, 0xe2, 0x3a, 0xbc, 0x26, 0xf0, 0x1c, 0xa2,
|
||||||
0x54, 0x7a, 0x4f, 0x50, 0x05, 0xde, 0x09, 0x61, 0xb6, 0x24, 0xbc, 0xa7, 0xc6, 0xd0, 0x0f, 0x2d,
|
0x51, 0xe9, 0x2d, 0x41, 0x15, 0x78, 0x27, 0x84, 0xd9, 0x92, 0xf0, 0x9e, 0x18, 0x43, 0x3f, 0xb4,
|
||||||
0x5e, 0x17, 0x4b, 0x82, 0x63, 0x81, 0xb5, 0x3d, 0x40, 0x2c, 0x14, 0x89, 0x8e, 0xf7, 0x38, 0xad,
|
0x78, 0x53, 0x2c, 0x09, 0x8e, 0x05, 0xd6, 0xf6, 0x00, 0xb1, 0x50, 0x24, 0x3a, 0xde, 0xe3, 0xb4,
|
||||||
0xe2, 0x8c, 0x9d, 0x78, 0xbf, 0xef, 0xc0, 0x3a, 0x63, 0xce, 0x3a, 0xbd, 0x21, 0xea, 0x19, 0x67,
|
0x8a, 0x33, 0x76, 0xe2, 0xfd, 0xbe, 0x01, 0xeb, 0x8c, 0x39, 0xeb, 0xf4, 0x96, 0xa8, 0x67, 0x9c,
|
||||||
0x1c, 0xeb, 0xf1, 0x01, 0x6c, 0x4f, 0x2d, 0xc3, 0xf2, 0xa9, 0xeb, 0xb8, 0x94, 0x5d, 0x26, 0xc4,
|
0x71, 0xac, 0xc7, 0x1f, 0xad, 0xb4, 0xac, 0x1e, 0x42, 0x39, 0x9e, 0x9f, 0xb8, 0x08, 0x22, 0x43,
|
||||||
0x8e, 0x20, 0xfd, 0x7b, 0x6d, 0xc5, 0x75, 0xe0, 0x34, 0xce, 0x16, 0x89, 0xa8, 0x6c, 0x4d, 0x17,
|
0x51, 0x8a, 0x9d, 0xf5, 0x8d, 0x6e, 0x93, 0x9d, 0xd2, 0x5f, 0xc8, 0x28, 0xcd, 0xaa, 0x85, 0x76,
|
||||||
0xc1, 0xea, 0x21, 0x94, 0xe3, 0xf9, 0x89, 0x8b, 0x20, 0x32, 0x14, 0xa5, 0xd8, 0x59, 0xdf, 0xe8,
|
0x6b, 0x20, 0xab, 0xca, 0x59, 0x67, 0xd0, 0x3a, 0x95, 0x51, 0x26, 0x56, 0x96, 0x9e, 0x64, 0x0b,
|
||||||
0x36, 0xd9, 0x29, 0xfd, 0x95, 0x8c, 0xd2, 0xac, 0x5a, 0x68, 0xb7, 0x06, 0xb2, 0xaa, 0x9c, 0x76,
|
0x6f, 0xa3, 0x9b, 0xd5, 0xef, 0xd2, 0x50, 0x49, 0xde, 0x33, 0xf0, 0xcf, 0xe1, 0x6a, 0xf8, 0x28,
|
||||||
0x06, 0xad, 0x13, 0x19, 0x65, 0x3e, 0x28, 0x16, 0xfe, 0xb3, 0x86, 0x9e, 0x3f, 0x7f, 0xfe, 0x3c,
|
0xe0, 0x51, 0x5f, 0x7d, 0x62, 0xb8, 0x7c, 0xe1, 0x4c, 0x88, 0xa8, 0xb3, 0xa3, 0xa9, 0xdb, 0x0e,
|
||||||
0x7d, 0x3f, 0x5b, 0x78, 0x1f, 0x5d, 0xaf, 0x7e, 0x9f, 0x86, 0x4a, 0xb2, 0x4e, 0xc7, 0x3f, 0x87,
|
0x58, 0x7d, 0xea, 0x7f, 0x6a, 0xb8, 0x6c, 0x59, 0x4c, 0x88, 0x8f, 0xdb, 0x70, 0xdd, 0xb2, 0x55,
|
||||||
0xcb, 0xe1, 0xa5, 0xda, 0xa3, 0xbe, 0xfa, 0xd4, 0x70, 0xf9, 0xc2, 0x99, 0x10, 0x51, 0xe9, 0x46,
|
0xcf, 0x27, 0x96, 0x4e, 0x5c, 0x5d, 0x9d, 0x3d, 0xc7, 0xa8, 0x44, 0xd3, 0xa8, 0xe7, 0xd9, 0xe2,
|
||||||
0x53, 0xb7, 0x1d, 0xb0, 0xfa, 0xd4, 0xff, 0xd2, 0x70, 0xd9, 0xb2, 0x98, 0x10, 0x1f, 0xb7, 0xe1,
|
0xc0, 0x8a, 0xac, 0xbc, 0x6a, 0xd9, 0xfd, 0x80, 0x3c, 0xdb, 0xc9, 0xeb, 0x01, 0x75, 0x2e, 0xcd,
|
||||||
0xaa, 0x65, 0xab, 0x9e, 0x4f, 0x2c, 0x9d, 0xb8, 0xba, 0x3a, 0x7b, 0xce, 0x50, 0x89, 0xa6, 0x51,
|
0x32, 0xab, 0xd2, 0xec, 0x15, 0x28, 0x4e, 0x88, 0xa3, 0x52, 0xcb, 0x77, 0x2f, 0x78, 0x75, 0x59,
|
||||||
0xcf, 0xb3, 0xc5, 0x81, 0x15, 0x59, 0x79, 0xd3, 0xb2, 0xfb, 0x01, 0x79, 0xb6, 0x93, 0xd7, 0x03,
|
0x50, 0x0a, 0x13, 0xe2, 0xc8, 0xac, 0xfd, 0x42, 0x8a, 0xfc, 0x93, 0x6c, 0xa1, 0x80, 0x8a, 0x27,
|
||||||
0xea, 0x5c, 0x9a, 0x65, 0x56, 0xa5, 0xd9, 0x1b, 0x50, 0x9c, 0x10, 0x47, 0xa5, 0x96, 0xef, 0x9e,
|
0xd9, 0x42, 0x11, 0x41, 0xf5, 0x5f, 0x19, 0x28, 0xc7, 0xab, 0x4d, 0x56, 0xbc, 0x6b, 0xfc, 0x64,
|
||||||
0xf3, 0xea, 0xb2, 0xa0, 0x14, 0x26, 0xc4, 0x91, 0x59, 0xfb, 0xd5, 0xcd, 0x44, 0x32, 0x9a, 0x05,
|
0x49, 0xf1, 0xbd, 0xe7, 0x8d, 0xef, 0xad, 0x4d, 0x6b, 0x0d, 0x76, 0xe4, 0x1c, 0xe6, 0x45, 0x0d,
|
||||||
0x54, 0xbc, 0x9f, 0x2d, 0x14, 0x11, 0x54, 0xff, 0x99, 0x81, 0x72, 0xbc, 0xda, 0x64, 0xc5, 0xbb,
|
0xa8, 0x08, 0x4d, 0x76, 0xdc, 0xb3, 0xdd, 0x86, 0x8a, 0x7b, 0x4d, 0x41, 0x09, 0x5a, 0xf8, 0x18,
|
||||||
0xc6, 0x4f, 0x96, 0x14, 0xdf, 0x7b, 0xde, 0x79, 0x61, 0x6d, 0x5a, 0x6b, 0xb0, 0x23, 0xe7, 0x30,
|
0xf2, 0x0f, 0x3d, 0x6e, 0x3b, 0xcf, 0x6d, 0xbf, 0xf9, 0xfd, 0xb6, 0x4f, 0xfa, 0xdc, 0x78, 0xf1,
|
||||||
0x2f, 0x6a, 0x40, 0x45, 0x68, 0xb2, 0xe3, 0x9e, 0xed, 0x36, 0x54, 0xdc, 0x2c, 0x0a, 0x4a, 0xd0,
|
0xa4, 0xaf, 0x76, 0xba, 0xca, 0x69, 0xbd, 0xad, 0x04, 0xea, 0xf8, 0x1a, 0x64, 0x4d, 0xf2, 0xd5,
|
||||||
0xc2, 0xc7, 0x90, 0x7f, 0xe4, 0x71, 0xdb, 0x79, 0x6e, 0xfb, 0xdd, 0x17, 0xdb, 0xbe, 0xdf, 0xe7,
|
0x45, 0xf2, 0x70, 0xe2, 0xd0, 0x65, 0x27, 0xe1, 0x1a, 0x64, 0x9f, 0x50, 0xf2, 0x28, 0x79, 0x24,
|
||||||
0xc6, 0x8b, 0xf7, 0xfb, 0x6a, 0xa7, 0xab, 0x9c, 0xd4, 0xdb, 0x4a, 0xa0, 0x8e, 0xaf, 0x40, 0xd6,
|
0x70, 0xe8, 0x47, 0x5c, 0x0c, 0xfb, 0x90, 0xe3, 0xf1, 0xc2, 0x00, 0x41, 0xc4, 0xd0, 0x4b, 0xb8,
|
||||||
0x24, 0xdf, 0x9c, 0x27, 0x0f, 0x27, 0x0e, 0x5d, 0x74, 0x12, 0xae, 0x40, 0xf6, 0x29, 0x25, 0x8f,
|
0x00, 0xd9, 0x46, 0x57, 0x61, 0x0b, 0x02, 0x41, 0x59, 0xa0, 0x6a, 0xaf, 0x25, 0x37, 0x64, 0x94,
|
||||||
0x93, 0x47, 0x02, 0x87, 0x5e, 0xe1, 0x62, 0xd8, 0x87, 0x1c, 0x8f, 0x17, 0x06, 0x08, 0x22, 0x86,
|
0xae, 0xde, 0x85, 0xbc, 0x08, 0x02, 0x5b, 0x2c, 0x51, 0x18, 0xd0, 0x4b, 0x41, 0x33, 0xb0, 0x91,
|
||||||
0x5e, 0xc3, 0x05, 0xc8, 0x36, 0xba, 0x0a, 0x5b, 0x10, 0x08, 0xca, 0x02, 0x55, 0x7b, 0x2d, 0xb9,
|
0x0a, 0xa5, 0x67, 0xa7, 0x47, 0xb2, 0x82, 0xd2, 0xc9, 0xa9, 0xce, 0xa2, 0x5c, 0xd5, 0x83, 0x72,
|
||||||
0x21, 0xa3, 0x74, 0xf5, 0x16, 0xe4, 0x45, 0x10, 0xd8, 0x62, 0x89, 0xc2, 0x80, 0x5e, 0x0b, 0x9a,
|
0xbc, 0xdc, 0x7c, 0x31, 0x57, 0xc9, 0xbf, 0xa7, 0xa0, 0x14, 0x2b, 0x1f, 0x59, 0xe1, 0x42, 0x4c,
|
||||||
0x81, 0x8d, 0x54, 0x28, 0x3d, 0x3d, 0x39, 0x92, 0x15, 0x94, 0x4e, 0x4e, 0x75, 0x16, 0xe5, 0xaa,
|
0xd3, 0x7e, 0xa2, 0x12, 0xd3, 0x20, 0x5e, 0x90, 0x1a, 0xc0, 0xa1, 0x3a, 0x43, 0x2e, 0x3b, 0x75,
|
||||||
0x1e, 0x94, 0xe3, 0xe5, 0xe6, 0x8f, 0x92, 0x65, 0xd5, 0xbf, 0xa5, 0xa0, 0x14, 0x2b, 0x1f, 0x59,
|
0x2f, 0x68, 0x89, 0xe4, 0x50, 0xbe, 0xfa, 0x97, 0x14, 0xa0, 0xf9, 0x02, 0x74, 0xce, 0xcd, 0xd4,
|
||||||
0xe1, 0x42, 0x4c, 0xd3, 0x7e, 0xaa, 0x12, 0xd3, 0x20, 0x5e, 0x90, 0x1a, 0xc0, 0xa1, 0x3a, 0x43,
|
0x4f, 0xe9, 0x66, 0xf5, 0xcf, 0x29, 0xa8, 0x24, 0xab, 0xce, 0x39, 0xf7, 0x6e, 0xfc, 0xa4, 0xee,
|
||||||
0x2e, 0x3a, 0x75, 0x3f, 0xd2, 0x12, 0xc9, 0xa1, 0x7c, 0xf5, 0x4f, 0x29, 0x40, 0xf3, 0x05, 0xe8,
|
0xfd, 0x33, 0x0d, 0xeb, 0x89, 0x5a, 0xf3, 0xb2, 0xde, 0x7d, 0x09, 0x9b, 0x86, 0x4e, 0x27, 0x8e,
|
||||||
0x9c, 0x9b, 0xa9, 0x9f, 0xd2, 0xcd, 0xea, 0x1f, 0x53, 0x50, 0x49, 0x56, 0x9d, 0x73, 0xee, 0x5d,
|
0xed, 0x53, 0x4b, 0xbb, 0x50, 0x4d, 0xfa, 0x98, 0x9a, 0x52, 0x95, 0x6f, 0x1a, 0xfb, 0xdf, 0x5f,
|
||||||
0xfb, 0x49, 0xdd, 0xfb, 0x47, 0x1a, 0xd6, 0x13, 0xb5, 0xe6, 0x45, 0xbd, 0xfb, 0x1a, 0x36, 0x0d,
|
0xcd, 0xd6, 0x5a, 0x33, 0xbd, 0x36, 0x53, 0x3b, 0xdc, 0x6a, 0x35, 0xe5, 0xd3, 0x5e, 0x77, 0x20,
|
||||||
0x9d, 0x4e, 0x1c, 0xdb, 0xa7, 0x96, 0x76, 0xae, 0x9a, 0xf4, 0x09, 0x35, 0xa5, 0x2a, 0xdf, 0x34,
|
0x77, 0x1a, 0x9f, 0xab, 0x67, 0x9d, 0x5f, 0x75, 0xba, 0x9f, 0x76, 0x14, 0x64, 0xcc, 0xd1, 0x7e,
|
||||||
0xf6, 0x5f, 0x5c, 0xcd, 0xd6, 0x5a, 0x33, 0xbd, 0x36, 0x53, 0x3b, 0xdc, 0x6a, 0x35, 0xe5, 0x93,
|
0xc4, 0x65, 0xdf, 0x03, 0x34, 0xef, 0x14, 0xbe, 0x0a, 0xcb, 0xdc, 0x42, 0x2f, 0xe1, 0x2d, 0xd8,
|
||||||
0x5e, 0x77, 0x20, 0x77, 0x1a, 0x0f, 0xd5, 0xd3, 0xce, 0x2f, 0x3b, 0xdd, 0x2f, 0x3b, 0x0a, 0x32,
|
0xe8, 0x74, 0xd5, 0x7e, 0xab, 0x29, 0xab, 0xf2, 0x83, 0x07, 0x72, 0x63, 0xd0, 0x17, 0xd7, 0xfb,
|
||||||
0xe6, 0x68, 0xaf, 0x70, 0xd9, 0xf7, 0x00, 0xcd, 0x3b, 0x85, 0x2f, 0xc3, 0x32, 0xb7, 0xd0, 0x6b,
|
0x88, 0x3d, 0x48, 0x2c, 0xf0, 0xea, 0x9f, 0x32, 0xb0, 0xb5, 0xc4, 0x13, 0x5c, 0x0f, 0x6e, 0x16,
|
||||||
0x78, 0x0b, 0x36, 0x3a, 0x5d, 0xb5, 0xdf, 0x6a, 0xca, 0xaa, 0x7c, 0xef, 0x9e, 0xdc, 0x18, 0xf4,
|
0xe2, 0xb2, 0xf3, 0xee, 0x65, 0xbc, 0xaf, 0xb1, 0x82, 0xa0, 0x47, 0x5c, 0x3f, 0xb8, 0x88, 0xdc,
|
||||||
0xc5, 0xf5, 0x3e, 0x62, 0x0f, 0x12, 0x0b, 0xbc, 0xfa, 0x87, 0x0c, 0x6c, 0x2d, 0xf1, 0x04, 0xd7,
|
0x02, 0x16, 0x25, 0xcb, 0x37, 0x86, 0x06, 0x75, 0x83, 0xd7, 0x10, 0x71, 0xdd, 0xd8, 0x98, 0xe1,
|
||||||
0x83, 0x9b, 0x85, 0xb8, 0xec, 0x7c, 0x74, 0x11, 0xef, 0x6b, 0xac, 0x20, 0xe8, 0x11, 0xd7, 0x0f,
|
0xe2, 0x41, 0xe4, 0x67, 0x80, 0x1d, 0xdb, 0x33, 0x7c, 0xe3, 0x31, 0x55, 0x0d, 0x2b, 0x7c, 0x3a,
|
||||||
0x2e, 0x22, 0x37, 0x80, 0x45, 0xc9, 0xf2, 0x8d, 0xa1, 0x41, 0xdd, 0xe0, 0x35, 0x44, 0x5c, 0x37,
|
0x61, 0xd7, 0x8f, 0xac, 0x82, 0x42, 0x49, 0xcb, 0xf2, 0x23, 0xb6, 0x45, 0x47, 0x64, 0x8e, 0xcd,
|
||||||
0x36, 0x66, 0xb8, 0x78, 0x10, 0xf9, 0x19, 0x60, 0xc7, 0xf6, 0x0c, 0xdf, 0x78, 0x42, 0x55, 0xc3,
|
0x36, 0xf3, 0x8c, 0x82, 0x42, 0x49, 0xc4, 0xbe, 0x01, 0x65, 0xdd, 0x9e, 0xb2, 0x9a, 0x4c, 0xf0,
|
||||||
0x0a, 0x9f, 0x4e, 0xd8, 0xf5, 0x23, 0xab, 0xa0, 0x50, 0xd2, 0xb2, 0xfc, 0x88, 0x6d, 0xd1, 0x11,
|
0xd8, 0xd9, 0x91, 0x52, 0x4a, 0x02, 0x8b, 0x28, 0x41, 0xb5, 0x3d, 0x7b, 0xb3, 0x29, 0x2b, 0x25,
|
||||||
0x99, 0x63, 0xb3, 0xcd, 0x3c, 0xa3, 0xa0, 0x50, 0x12, 0xb1, 0xaf, 0x41, 0x59, 0xb7, 0xa7, 0xac,
|
0x81, 0x09, 0xca, 0x4d, 0xd8, 0x20, 0xa3, 0x91, 0xcb, 0x8c, 0x87, 0x86, 0xc4, 0xfd, 0xa1, 0x12,
|
||||||
0x26, 0x13, 0x3c, 0x76, 0x76, 0xa4, 0x94, 0x92, 0xc0, 0x22, 0x4a, 0x50, 0x6d, 0xcf, 0xde, 0x6c,
|
0xc1, 0x9c, 0xb8, 0x73, 0x02, 0x85, 0x30, 0x0e, 0xec, 0xa8, 0x66, 0x91, 0x50, 0x1d, 0xf1, 0x6e,
|
||||||
0xca, 0x4a, 0x49, 0x60, 0x82, 0x72, 0x1d, 0x36, 0xc8, 0x68, 0xe4, 0x32, 0xe3, 0xa1, 0x21, 0x71,
|
0x97, 0xde, 0x2b, 0x2a, 0x05, 0x2b, 0x14, 0xde, 0x80, 0xb2, 0xe1, 0xa9, 0xb3, 0x27, 0xe8, 0xf4,
|
||||||
0x7f, 0xa8, 0x44, 0x30, 0x27, 0xee, 0xdc, 0x87, 0x42, 0x18, 0x07, 0x76, 0x54, 0xb3, 0x48, 0xa8,
|
0x6e, 0x7a, 0xaf, 0xa0, 0x94, 0x0c, 0x2f, 0x7a, 0xbe, 0xab, 0x7e, 0x93, 0x86, 0x4a, 0xf2, 0x09,
|
||||||
0x8e, 0x78, 0x39, 0x4b, 0xef, 0x15, 0x95, 0x82, 0x15, 0x0a, 0xaf, 0x41, 0xd9, 0xf0, 0xd4, 0xd9,
|
0x1d, 0x37, 0xa1, 0x60, 0xda, 0x1a, 0xe1, 0xa9, 0x25, 0xbe, 0xdf, 0xec, 0x3d, 0xe7, 0xd5, 0xbd,
|
||||||
0x13, 0x6e, 0x7a, 0x37, 0xbd, 0x57, 0x50, 0x4a, 0x86, 0x17, 0xbd, 0xd9, 0x55, 0xbf, 0x4b, 0x43,
|
0xd6, 0x0e, 0xf8, 0x4a, 0xa4, 0xb9, 0xf3, 0x8f, 0x14, 0x14, 0x42, 0x18, 0x5f, 0x81, 0xac, 0x43,
|
||||||
0x25, 0xf9, 0x04, 0x8d, 0x9b, 0x50, 0x30, 0x6d, 0x8d, 0xf0, 0xd4, 0x12, 0xdf, 0x3f, 0xf6, 0x5e,
|
0xfc, 0x31, 0x37, 0x97, 0x3b, 0x4a, 0xa3, 0x94, 0xc2, 0xdb, 0x0c, 0xf7, 0x1c, 0x62, 0xf1, 0x14,
|
||||||
0xf2, 0x6a, 0x5d, 0x6b, 0x07, 0x7c, 0x25, 0xd2, 0xdc, 0xf9, 0x7b, 0x0a, 0x0a, 0x21, 0x8c, 0x2f,
|
0x08, 0x70, 0xd6, 0x66, 0xf3, 0x6a, 0x52, 0xa2, 0xf3, 0xcb, 0x89, 0x3d, 0x99, 0x50, 0xcb, 0xf7,
|
||||||
0x41, 0xd6, 0x21, 0xfe, 0x98, 0x9b, 0xcb, 0x1d, 0xa5, 0x51, 0x4a, 0xe1, 0x6d, 0x86, 0x7b, 0x0e,
|
0xc2, 0x79, 0x0d, 0xf0, 0x46, 0x00, 0xe3, 0x77, 0x60, 0xd3, 0x77, 0x89, 0x61, 0x26, 0xb8, 0x59,
|
||||||
0xb1, 0x78, 0x0a, 0x04, 0x38, 0x6b, 0xb3, 0x79, 0x35, 0x29, 0xd1, 0xf9, 0xe5, 0xc4, 0x9e, 0x4c,
|
0xce, 0x45, 0xa1, 0x20, 0x22, 0x1f, 0xc2, 0xb5, 0xd0, 0xae, 0x4e, 0x7d, 0xa2, 0x8d, 0xa9, 0x3e,
|
||||||
0xa8, 0xe5, 0x7b, 0xe1, 0xbc, 0x06, 0x78, 0x23, 0x80, 0xf1, 0x87, 0xb0, 0xe9, 0xbb, 0xc4, 0x30,
|
0x53, 0xca, 0xf3, 0xf7, 0xd9, 0xab, 0x01, 0xa1, 0x19, 0xc8, 0x43, 0xdd, 0xea, 0x77, 0x29, 0xd8,
|
||||||
0x13, 0xdc, 0x2c, 0xe7, 0xa2, 0x50, 0x10, 0x91, 0x0f, 0xe1, 0x4a, 0x68, 0x57, 0xa7, 0x3e, 0xd1,
|
0x0c, 0xaf, 0x53, 0x7a, 0x14, 0xac, 0x53, 0x00, 0x62, 0x59, 0xb6, 0x1f, 0x0f, 0xd7, 0x62, 0x2a,
|
||||||
0xc6, 0x54, 0x9f, 0x29, 0xe5, 0xf9, 0xfb, 0xe6, 0xe5, 0x80, 0xd0, 0x0c, 0xe4, 0xa1, 0x6e, 0xf5,
|
0x2f, 0xe8, 0xd5, 0xea, 0x91, 0x92, 0x12, 0x33, 0xb0, 0x33, 0x01, 0x98, 0x49, 0x56, 0x86, 0xed,
|
||||||
0xfb, 0x14, 0x6c, 0x86, 0xd7, 0x29, 0x3d, 0x0a, 0xd6, 0x09, 0x00, 0xb1, 0x2c, 0xdb, 0x8f, 0x87,
|
0x3a, 0x94, 0x82, 0xef, 0x23, 0xfc, 0x23, 0x9b, 0xb8, 0x80, 0x83, 0x80, 0xd8, 0xbd, 0x0b, 0x6f,
|
||||||
0x6b, 0x31, 0x95, 0x17, 0xf4, 0x6a, 0xf5, 0x48, 0x49, 0x89, 0x19, 0xd8, 0x99, 0x00, 0xcc, 0x24,
|
0x43, 0xee, 0x9c, 0x8e, 0x0c, 0x2b, 0x78, 0xf5, 0x14, 0x8d, 0xf0, 0x25, 0x37, 0x1b, 0xbd, 0xe4,
|
||||||
0x2b, 0xc3, 0x76, 0x15, 0x4a, 0xc1, 0xf7, 0x05, 0xfe, 0x91, 0x4a, 0x5c, 0xc0, 0x41, 0x40, 0xec,
|
0x1e, 0xfd, 0x21, 0x05, 0x5b, 0x9a, 0x3d, 0x99, 0xf7, 0xf7, 0x08, 0xcd, 0xbd, 0x02, 0x78, 0x9f,
|
||||||
0xde, 0x85, 0xb7, 0x21, 0x77, 0x46, 0x47, 0x86, 0x15, 0xbc, 0x7a, 0x8a, 0x46, 0xf8, 0x96, 0x9a,
|
0xa4, 0xbe, 0xf8, 0x78, 0x64, 0xf8, 0xe3, 0xe9, 0x79, 0x4d, 0xb3, 0x27, 0xfb, 0x23, 0xdb, 0x24,
|
||||||
0x8d, 0xde, 0x52, 0x8f, 0x7e, 0x97, 0x82, 0x2d, 0xcd, 0x9e, 0xcc, 0xfb, 0x7b, 0x84, 0xe6, 0x5e,
|
0xd6, 0x68, 0xf6, 0x95, 0x90, 0xff, 0xd1, 0xde, 0x1d, 0x51, 0xeb, 0xdd, 0x91, 0x1d, 0xfb, 0x66,
|
||||||
0x01, 0xbc, 0x2f, 0x52, 0x5f, 0xdd, 0x1d, 0x19, 0xfe, 0x78, 0x7a, 0x56, 0xd3, 0xec, 0xc9, 0xfe,
|
0xf8, 0xd1, 0xec, 0xef, 0xd7, 0xe9, 0xcc, 0x71, 0xef, 0xe8, 0xaf, 0xe9, 0x9d, 0x63, 0xd1, 0x57,
|
||||||
0xc8, 0x36, 0x89, 0x35, 0x9a, 0x7d, 0x65, 0xe3, 0x7f, 0xb4, 0x8f, 0x46, 0xd4, 0xfa, 0x68, 0x64,
|
0x2f, 0x8c, 0x8d, 0x42, 0x87, 0x26, 0xd5, 0xd8, 0x78, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x0c,
|
||||||
0xc7, 0xbe, 0xb9, 0x7d, 0x3e, 0xfb, 0xfb, 0x6d, 0x3a, 0x73, 0xdc, 0x3b, 0xfa, 0x73, 0x7a, 0xe7,
|
0xab, 0xb6, 0x37, 0x7e, 0x1c, 0x00, 0x00,
|
||||||
0x58, 0xf4, 0xd5, 0x0b, 0x63, 0xa3, 0xd0, 0xa1, 0x49, 0x35, 0x36, 0xde, 0xff, 0x05, 0x00, 0x00,
|
|
||||||
0xff, 0xff, 0xa2, 0xc3, 0x4e, 0x18, 0xbe, 0x1b, 0x00, 0x00,
|
|
||||||
}
|
}
|
||||||
|
|||||||
28
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto
сгенерированный
поставляемый
28
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto
сгенерированный
поставляемый
@@ -101,6 +101,8 @@ message DescriptorProto {
|
|||||||
message ExtensionRange {
|
message ExtensionRange {
|
||||||
optional int32 start = 1;
|
optional int32 start = 1;
|
||||||
optional int32 end = 2;
|
optional int32 end = 2;
|
||||||
|
|
||||||
|
optional ExtensionRangeOptions options = 3;
|
||||||
}
|
}
|
||||||
repeated ExtensionRange extension_range = 5;
|
repeated ExtensionRange extension_range = 5;
|
||||||
|
|
||||||
@@ -121,6 +123,14 @@ message DescriptorProto {
|
|||||||
repeated string reserved_name = 10;
|
repeated string reserved_name = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ExtensionRangeOptions {
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
// Describes a field within a message.
|
// Describes a field within a message.
|
||||||
message FieldDescriptorProto {
|
message FieldDescriptorProto {
|
||||||
enum Type {
|
enum Type {
|
||||||
@@ -351,7 +361,7 @@ message FileOptions {
|
|||||||
optional bool cc_generic_services = 16 [default=false];
|
optional bool cc_generic_services = 16 [default=false];
|
||||||
optional bool java_generic_services = 17 [default=false];
|
optional bool java_generic_services = 17 [default=false];
|
||||||
optional bool py_generic_services = 18 [default=false];
|
optional bool py_generic_services = 18 [default=false];
|
||||||
optional bool php_generic_services = 19 [default=false];
|
optional bool php_generic_services = 42 [default=false];
|
||||||
|
|
||||||
// Is this file deprecated?
|
// Is this file deprecated?
|
||||||
// Depending on the target platform, this can emit Deprecated annotations
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
@@ -483,13 +493,15 @@ message FieldOptions {
|
|||||||
|
|
||||||
// The jstype option determines the JavaScript type used for values of the
|
// The jstype option determines the JavaScript type used for values of the
|
||||||
// field. The option is permitted only for 64 bit integral and fixed types
|
// field. The option is permitted only for 64 bit integral and fixed types
|
||||||
// (int64, uint64, sint64, fixed64, sfixed64). By default these types are
|
// (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
|
||||||
// represented as JavaScript strings. This avoids loss of precision that can
|
// is represented as JavaScript string, which avoids loss of precision that
|
||||||
// happen when a large value is converted to a floating point JavaScript
|
// can happen when a large value is converted to a floating point JavaScript.
|
||||||
// numbers. Specifying JS_NUMBER for the jstype causes the generated
|
// Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
|
||||||
// JavaScript code to use the JavaScript "number" type instead of strings.
|
// use the JavaScript "number" type. The behavior of the default option
|
||||||
// This option is an enum to permit additional types to be added,
|
// JS_NORMAL is implementation dependent.
|
||||||
// e.g. goog.math.Integer.
|
//
|
||||||
|
// This option is an enum to permit additional types to be added, e.g.
|
||||||
|
// goog.math.Integer.
|
||||||
optional JSType jstype = 6 [default = JS_NORMAL];
|
optional JSType jstype = 6 [default = JS_NORMAL];
|
||||||
enum JSType {
|
enum JSType {
|
||||||
// Use the default type.
|
// Use the default type.
|
||||||
|
|||||||
63
vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go
сгенерированный
поставляемый
63
vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go
сгенерированный
поставляемый
@@ -1984,7 +1984,7 @@ func (g *Generator) generateMessage(message *Descriptor) {
|
|||||||
case typename == "string":
|
case typename == "string":
|
||||||
def = strconv.Quote(def)
|
def = strconv.Quote(def)
|
||||||
case typename == "[]byte":
|
case typename == "[]byte":
|
||||||
def = "[]byte(" + strconv.Quote(def) + ")"
|
def = "[]byte(" + strconv.Quote(unescape(def)) + ")"
|
||||||
kind = "var "
|
kind = "var "
|
||||||
case def == "inf", def == "-inf", def == "nan":
|
case def == "inf", def == "-inf", def == "nan":
|
||||||
// These names are known to, and defined by, the protocol language.
|
// These names are known to, and defined by, the protocol language.
|
||||||
@@ -2508,6 +2508,67 @@ func (g *Generator) generateMessage(message *Descriptor) {
|
|||||||
g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], ccTypeName, fullName)
|
g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], ccTypeName, fullName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var escapeChars = [256]byte{
|
||||||
|
'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v', '\\': '\\', '"': '"', '\'': '\'', '?': '?',
|
||||||
|
}
|
||||||
|
|
||||||
|
// unescape reverses the "C" escaping that protoc does for default values of bytes fields.
|
||||||
|
// It is best effort in that it effectively ignores malformed input. Seemingly invalid escape
|
||||||
|
// sequences are conveyed, unmodified, into the decoded result.
|
||||||
|
func unescape(s string) string {
|
||||||
|
// NB: Sadly, we can't use strconv.Unquote because protoc will escape both
|
||||||
|
// single and double quotes, but strconv.Unquote only allows one or the
|
||||||
|
// other (based on actual surrounding quotes of its input argument).
|
||||||
|
|
||||||
|
var out []byte
|
||||||
|
for len(s) > 0 {
|
||||||
|
// regular character, or too short to be valid escape
|
||||||
|
if s[0] != '\\' || len(s) < 2 {
|
||||||
|
out = append(out, s[0])
|
||||||
|
s = s[1:]
|
||||||
|
} else if c := escapeChars[s[1]]; c != 0 {
|
||||||
|
// escape sequence
|
||||||
|
out = append(out, c)
|
||||||
|
s = s[2:]
|
||||||
|
} else if s[1] == 'x' || s[1] == 'X' {
|
||||||
|
// hex escape, e.g. "\x80
|
||||||
|
if len(s) < 4 {
|
||||||
|
// too short to be valid
|
||||||
|
out = append(out, s[:2]...)
|
||||||
|
s = s[2:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v, err := strconv.ParseUint(s[2:4], 16, 8)
|
||||||
|
if err != nil {
|
||||||
|
out = append(out, s[:4]...)
|
||||||
|
} else {
|
||||||
|
out = append(out, byte(v))
|
||||||
|
}
|
||||||
|
s = s[4:]
|
||||||
|
} else if '0' <= s[1] && s[1] <= '7' {
|
||||||
|
// octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164"
|
||||||
|
// so consume up to 2 more bytes or up to end-of-string
|
||||||
|
n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567"))
|
||||||
|
if n > 3 {
|
||||||
|
n = 3
|
||||||
|
}
|
||||||
|
v, err := strconv.ParseUint(s[1:1+n], 8, 8)
|
||||||
|
if err != nil {
|
||||||
|
out = append(out, s[:1+n]...)
|
||||||
|
} else {
|
||||||
|
out = append(out, byte(v))
|
||||||
|
}
|
||||||
|
s = s[1+n:]
|
||||||
|
} else {
|
||||||
|
// bad escape, just propagate the slash as-is
|
||||||
|
out = append(out, s[0])
|
||||||
|
s = s[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(out)
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
|
func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
|
||||||
ccTypeName := ext.DescName()
|
ccTypeName := ext.DescName()
|
||||||
|
|
||||||
|
|||||||
29
vendor/github.com/golang/protobuf/protoc-gen-go/generator/name_test.go
сгенерированный
поставляемый
29
vendor/github.com/golang/protobuf/protoc-gen-go/generator/name_test.go
сгенерированный
поставляемый
@@ -83,3 +83,32 @@ func TestGoPackageOption(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnescape(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
in string
|
||||||
|
out string
|
||||||
|
}{
|
||||||
|
// successful cases, including all kinds of escapes
|
||||||
|
{"", ""},
|
||||||
|
{"foo bar baz frob nitz", "foo bar baz frob nitz"},
|
||||||
|
{`\000\001\002\003\004\005\006\007`, string([]byte{0, 1, 2, 3, 4, 5, 6, 7})},
|
||||||
|
{`\a\b\f\n\r\t\v\\\?\'\"`, string([]byte{'\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '?', '\'', '"'})},
|
||||||
|
{`\x10\x20\x30\x40\x50\x60\x70\x80`, string([]byte{16, 32, 48, 64, 80, 96, 112, 128})},
|
||||||
|
// variable length octal escapes
|
||||||
|
{`\0\018\222\377\3\04\005\6\07`, string([]byte{0, 1, '8', 0222, 255, 3, 4, 5, 6, 7})},
|
||||||
|
// malformed escape sequences left as is
|
||||||
|
{"foo \\g bar", "foo \\g bar"},
|
||||||
|
{"foo \\xg0 bar", "foo \\xg0 bar"},
|
||||||
|
{"\\", "\\"},
|
||||||
|
{"\\x", "\\x"},
|
||||||
|
{"\\xf", "\\xf"},
|
||||||
|
{"\\777", "\\777"}, // overflows byte
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
s := unescape(tc.in)
|
||||||
|
if s != tc.out {
|
||||||
|
t.Errorf("doUnescape(%q) = %q; should have been %q", tc.in, s, tc.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
1
vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.proto
сгенерированный
поставляемый
1
vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.proto
сгенерированный
поставляемый
@@ -91,6 +91,7 @@ message CodeGeneratorRequest {
|
|||||||
|
|
||||||
// The version number of protocol compiler.
|
// The version number of protocol compiler.
|
||||||
optional Version compiler_version = 3;
|
optional Version compiler_version = 3;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The plugin writes an encoded CodeGeneratorResponse to stdout.
|
// The plugin writes an encoded CodeGeneratorResponse to stdout.
|
||||||
|
|||||||
10
vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
сгенерированный
поставляемый
10
vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
сгенерированный
поставляемый
@@ -62,6 +62,16 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
|||||||
// any.Unpack(foo)
|
// any.Unpack(foo)
|
||||||
// ...
|
// ...
|
||||||
//
|
//
|
||||||
|
// Example 4: Pack and unpack a message in Go
|
||||||
|
//
|
||||||
|
// foo := &pb.Foo{...}
|
||||||
|
// any, err := ptypes.MarshalAny(foo)
|
||||||
|
// ...
|
||||||
|
// foo := &pb.Foo{}
|
||||||
|
// if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
//
|
||||||
// The pack methods provided by protobuf library will by default use
|
// The pack methods provided by protobuf library will by default use
|
||||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||||
// methods only use the fully qualified type name after the last '/'
|
// methods only use the fully qualified type name after the last '/'
|
||||||
|
|||||||
10
vendor/github.com/golang/protobuf/ptypes/any/any.proto
сгенерированный
поставляемый
10
vendor/github.com/golang/protobuf/ptypes/any/any.proto
сгенерированный
поставляемый
@@ -74,6 +74,16 @@ option objc_class_prefix = "GPB";
|
|||||||
// any.Unpack(foo)
|
// any.Unpack(foo)
|
||||||
// ...
|
// ...
|
||||||
//
|
//
|
||||||
|
// Example 4: Pack and unpack a message in Go
|
||||||
|
//
|
||||||
|
// foo := &pb.Foo{...}
|
||||||
|
// any, err := ptypes.MarshalAny(foo)
|
||||||
|
// ...
|
||||||
|
// foo := &pb.Foo{}
|
||||||
|
// if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
//
|
||||||
// The pack methods provided by protobuf library will by default use
|
// The pack methods provided by protobuf library will by default use
|
||||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||||
// methods only use the fully qualified type name after the last '/'
|
// methods only use the fully qualified type name after the last '/'
|
||||||
|
|||||||
50
vendor/github.com/gorilla/mux/README.md
сгенерированный
поставляемый
50
vendor/github.com/gorilla/mux/README.md
сгенерированный
поставляемый
@@ -15,7 +15,7 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv
|
|||||||
|
|
||||||
* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`.
|
* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`.
|
||||||
* Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers.
|
* Requests can be matched based on URL host, path, path prefix, schemes, header and query values, HTTP methods or using custom matchers.
|
||||||
* URL hosts and paths can have variables with an optional regular expression.
|
* URL hosts, paths and query values can have variables with an optional regular expression.
|
||||||
* Registered URLs can be built, or "reversed", which helps maintaining references to resources.
|
* Registered URLs can be built, or "reversed", which helps maintaining references to resources.
|
||||||
* Routes can be used as subrouters: nested routes are only tested if the parent route matches. This is useful to define groups of routes that share common conditions like a host, a path prefix or other repeated attributes. As a bonus, this optimizes request matching.
|
* Routes can be used as subrouters: nested routes are only tested if the parent route matches. This is useful to define groups of routes that share common conditions like a host, a path prefix or other repeated attributes. As a bonus, this optimizes request matching.
|
||||||
|
|
||||||
@@ -24,9 +24,9 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv
|
|||||||
* [Install](#install)
|
* [Install](#install)
|
||||||
* [Examples](#examples)
|
* [Examples](#examples)
|
||||||
* [Matching Routes](#matching-routes)
|
* [Matching Routes](#matching-routes)
|
||||||
* [Listing Routes](#listing-routes)
|
|
||||||
* [Static Files](#static-files)
|
* [Static Files](#static-files)
|
||||||
* [Registered URLs](#registered-urls)
|
* [Registered URLs](#registered-urls)
|
||||||
|
* [Walking Routes](#walking-routes)
|
||||||
* [Full Example](#full-example)
|
* [Full Example](#full-example)
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -168,7 +168,6 @@ s.HandleFunc("/{key}/", ProductHandler)
|
|||||||
// "/products/{key}/details"
|
// "/products/{key}/details"
|
||||||
s.HandleFunc("/{key}/details", ProductDetailsHandler)
|
s.HandleFunc("/{key}/details", ProductDetailsHandler)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Listing Routes
|
### Listing Routes
|
||||||
|
|
||||||
Routes on a mux can be listed using the Router.Walk method—useful for generating documentation:
|
Routes on a mux can be listed using the Router.Walk method—useful for generating documentation:
|
||||||
@@ -191,9 +190,9 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
func main() {
|
func main() {
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.HandleFunc("/", handler)
|
r.HandleFunc("/", handler)
|
||||||
r.Methods("POST").HandleFunc("/products", handler)
|
r.HandleFunc("/products", handler).Methods("POST")
|
||||||
r.Methods("GET").HandleFunc("/articles", handler)
|
r.HandleFunc("/articles", handler).Methods("GET")
|
||||||
r.Methods("GET", "PUT").HandleFunc("/articles/{id}", handler)
|
r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
|
||||||
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
||||||
t, err := route.GetPathTemplate()
|
t, err := route.GetPathTemplate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -269,19 +268,21 @@ url, err := r.Get("article").URL("category", "technology", "id", "42")
|
|||||||
"/articles/technology/42"
|
"/articles/technology/42"
|
||||||
```
|
```
|
||||||
|
|
||||||
This also works for host variables:
|
This also works for host and query value variables:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.Host("{subdomain}.domain.com").
|
r.Host("{subdomain}.domain.com").
|
||||||
Path("/articles/{category}/{id:[0-9]+}").
|
Path("/articles/{category}/{id:[0-9]+}").
|
||||||
|
Queries("filter", "{filter}").
|
||||||
HandlerFunc(ArticleHandler).
|
HandlerFunc(ArticleHandler).
|
||||||
Name("article")
|
Name("article")
|
||||||
|
|
||||||
// url.String() will be "http://news.domain.com/articles/technology/42"
|
// url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla"
|
||||||
url, err := r.Get("article").URL("subdomain", "news",
|
url, err := r.Get("article").URL("subdomain", "news",
|
||||||
"category", "technology",
|
"category", "technology",
|
||||||
"id", "42")
|
"id", "42",
|
||||||
|
"filter", "gorilla")
|
||||||
```
|
```
|
||||||
|
|
||||||
All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a generated URL will always match a registered route -- the only exception is for explicitly defined "build-only" routes which never match.
|
All variables defined in the route are required, and their values must conform to the corresponding patterns. These requirements guarantee that a generated URL will always match a registered route -- the only exception is for explicitly defined "build-only" routes which never match.
|
||||||
@@ -319,6 +320,37 @@ url, err := r.Get("article").URL("subdomain", "news",
|
|||||||
"id", "42")
|
"id", "42")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Walking Routes
|
||||||
|
|
||||||
|
The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example,
|
||||||
|
the following prints all of the registered routes:
|
||||||
|
|
||||||
|
```go
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/", handler)
|
||||||
|
r.HandleFunc("/products", handler).Methods("POST")
|
||||||
|
r.HandleFunc("/articles", handler).Methods("GET")
|
||||||
|
r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
|
||||||
|
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
||||||
|
t, err := route.GetPathTemplate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// p will contain a regular expression that is compatible with regular expressions in Perl, Python, and other languages.
|
||||||
|
// For example, the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'.
|
||||||
|
p, err := route.GetPathRegexp()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m, err := route.GetMethods()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(strings.Join(m, ","), t, p)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
## Full Example
|
## Full Example
|
||||||
|
|
||||||
Here's a complete, runnable example of a small `mux` based server:
|
Here's a complete, runnable example of a small `mux` based server:
|
||||||
|
|||||||
12
vendor/github.com/gorilla/mux/doc.go
сгенерированный
поставляемый
12
vendor/github.com/gorilla/mux/doc.go
сгенерированный
поставляемый
@@ -12,8 +12,8 @@ or other conditions. The main features are:
|
|||||||
|
|
||||||
* Requests can be matched based on URL host, path, path prefix, schemes,
|
* Requests can be matched based on URL host, path, path prefix, schemes,
|
||||||
header and query values, HTTP methods or using custom matchers.
|
header and query values, HTTP methods or using custom matchers.
|
||||||
* URL hosts and paths can have variables with an optional regular
|
* URL hosts, paths and query values can have variables with an optional
|
||||||
expression.
|
regular expression.
|
||||||
* Registered URLs can be built, or "reversed", which helps maintaining
|
* Registered URLs can be built, or "reversed", which helps maintaining
|
||||||
references to resources.
|
references to resources.
|
||||||
* Routes can be used as subrouters: nested routes are only tested if the
|
* Routes can be used as subrouters: nested routes are only tested if the
|
||||||
@@ -188,18 +188,20 @@ key/value pairs for the route variables. For the previous route, we would do:
|
|||||||
|
|
||||||
"/articles/technology/42"
|
"/articles/technology/42"
|
||||||
|
|
||||||
This also works for host variables:
|
This also works for host and query value variables:
|
||||||
|
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.Host("{subdomain}.domain.com").
|
r.Host("{subdomain}.domain.com").
|
||||||
Path("/articles/{category}/{id:[0-9]+}").
|
Path("/articles/{category}/{id:[0-9]+}").
|
||||||
|
Queries("filter", "{filter}").
|
||||||
HandlerFunc(ArticleHandler).
|
HandlerFunc(ArticleHandler).
|
||||||
Name("article")
|
Name("article")
|
||||||
|
|
||||||
// url.String() will be "http://news.domain.com/articles/technology/42"
|
// url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla"
|
||||||
url, err := r.Get("article").URL("subdomain", "news",
|
url, err := r.Get("article").URL("subdomain", "news",
|
||||||
"category", "technology",
|
"category", "technology",
|
||||||
"id", "42")
|
"id", "42",
|
||||||
|
"filter", "gorilla")
|
||||||
|
|
||||||
All variables defined in the route are required, and their values must
|
All variables defined in the route are required, and their values must
|
||||||
conform to the corresponding patterns. These requirements guarantee that a
|
conform to the corresponding patterns. These requirements guarantee that a
|
||||||
|
|||||||
48
vendor/github.com/gorilla/mux/mux.go
сгенерированный
поставляемый
48
vendor/github.com/gorilla/mux/mux.go
сгенерированный
поставляемый
@@ -13,6 +13,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrMethodMismatch = errors.New("method is not allowed")
|
||||||
|
)
|
||||||
|
|
||||||
// NewRouter returns a new router instance.
|
// NewRouter returns a new router instance.
|
||||||
func NewRouter() *Router {
|
func NewRouter() *Router {
|
||||||
return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
|
return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
|
||||||
@@ -39,6 +43,10 @@ func NewRouter() *Router {
|
|||||||
type Router struct {
|
type Router struct {
|
||||||
// Configurable Handler to be used when no route matches.
|
// Configurable Handler to be used when no route matches.
|
||||||
NotFoundHandler http.Handler
|
NotFoundHandler http.Handler
|
||||||
|
|
||||||
|
// Configurable Handler to be used when the request method does not match the route.
|
||||||
|
MethodNotAllowedHandler http.Handler
|
||||||
|
|
||||||
// Parent route, if this is a subrouter.
|
// Parent route, if this is a subrouter.
|
||||||
parent parentRoute
|
parent parentRoute
|
||||||
// Routes to be matched, in order.
|
// Routes to be matched, in order.
|
||||||
@@ -65,6 +73,11 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if match.MatchErr == ErrMethodMismatch && r.MethodNotAllowedHandler != nil {
|
||||||
|
match.Handler = r.MethodNotAllowedHandler
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Closest match for a router (includes sub-routers)
|
// Closest match for a router (includes sub-routers)
|
||||||
if r.NotFoundHandler != nil {
|
if r.NotFoundHandler != nil {
|
||||||
match.Handler = r.NotFoundHandler
|
match.Handler = r.NotFoundHandler
|
||||||
@@ -105,9 +118,15 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
req = setVars(req, match.Vars)
|
req = setVars(req, match.Vars)
|
||||||
req = setCurrentRoute(req, match.Route)
|
req = setCurrentRoute(req, match.Route)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if handler == nil && match.MatchErr == ErrMethodMismatch {
|
||||||
|
handler = methodNotAllowedHandler()
|
||||||
|
}
|
||||||
|
|
||||||
if handler == nil {
|
if handler == nil {
|
||||||
handler = http.NotFoundHandler()
|
handler = http.NotFoundHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !r.KeepContext {
|
if !r.KeepContext {
|
||||||
defer contextClear(req)
|
defer contextClear(req)
|
||||||
}
|
}
|
||||||
@@ -176,6 +195,13 @@ func (r *Router) UseEncodedPath() *Router {
|
|||||||
// parentRoute
|
// parentRoute
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func (r *Router) getBuildScheme() string {
|
||||||
|
if r.parent != nil {
|
||||||
|
return r.parent.getBuildScheme()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// getNamedRoutes returns the map where named routes are registered.
|
// getNamedRoutes returns the map where named routes are registered.
|
||||||
func (r *Router) getNamedRoutes() map[string]*Route {
|
func (r *Router) getNamedRoutes() map[string]*Route {
|
||||||
if r.namedRoutes == nil {
|
if r.namedRoutes == nil {
|
||||||
@@ -299,10 +325,6 @@ type WalkFunc func(route *Route, router *Router, ancestors []*Route) error
|
|||||||
|
|
||||||
func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {
|
func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {
|
||||||
for _, t := range r.routes {
|
for _, t := range r.routes {
|
||||||
if t.regexp == nil || t.regexp.path == nil || t.regexp.path.template == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err := walkFn(t, r, ancestors)
|
err := walkFn(t, r, ancestors)
|
||||||
if err == SkipRouter {
|
if err == SkipRouter {
|
||||||
continue
|
continue
|
||||||
@@ -312,10 +334,12 @@ func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {
|
|||||||
}
|
}
|
||||||
for _, sr := range t.matchers {
|
for _, sr := range t.matchers {
|
||||||
if h, ok := sr.(*Router); ok {
|
if h, ok := sr.(*Router); ok {
|
||||||
|
ancestors = append(ancestors, t)
|
||||||
err := h.walk(walkFn, ancestors)
|
err := h.walk(walkFn, ancestors)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
ancestors = ancestors[:len(ancestors)-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if h, ok := t.handler.(*Router); ok {
|
if h, ok := t.handler.(*Router); ok {
|
||||||
@@ -339,6 +363,11 @@ type RouteMatch struct {
|
|||||||
Route *Route
|
Route *Route
|
||||||
Handler http.Handler
|
Handler http.Handler
|
||||||
Vars map[string]string
|
Vars map[string]string
|
||||||
|
|
||||||
|
// MatchErr is set to appropriate matching error
|
||||||
|
// It is set to ErrMethodMismatch if there is a mismatch in
|
||||||
|
// the request method and route method
|
||||||
|
MatchErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
type contextKey int
|
type contextKey int
|
||||||
@@ -458,7 +487,7 @@ func mapFromPairsToString(pairs ...string) (map[string]string, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// mapFromPairsToRegex converts variadic string paramers to a
|
// mapFromPairsToRegex converts variadic string parameters to a
|
||||||
// string to regex map.
|
// string to regex map.
|
||||||
func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) {
|
func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) {
|
||||||
length, err := checkPairs(pairs...)
|
length, err := checkPairs(pairs...)
|
||||||
@@ -540,3 +569,12 @@ func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]s
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// methodNotAllowed replies to the request with an HTTP status code 405.
|
||||||
|
func methodNotAllowed(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// methodNotAllowedHandler returns a simple request handler
|
||||||
|
// that replies to each request with a status code 405.
|
||||||
|
func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) }
|
||||||
|
|||||||
145
vendor/github.com/gorilla/mux/mux_test.go
сгенерированный
поставляемый
145
vendor/github.com/gorilla/mux/mux_test.go
сгенерированный
поставляемый
@@ -11,6 +11,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -35,6 +36,7 @@ type routeTest struct {
|
|||||||
scheme string // the expected scheme of the built URL
|
scheme string // the expected scheme of the built URL
|
||||||
host string // the expected host of the built URL
|
host string // the expected host of the built URL
|
||||||
path string // the expected path of the built URL
|
path string // the expected path of the built URL
|
||||||
|
query string // the expected query string of the built URL
|
||||||
pathTemplate string // the expected path template of the route
|
pathTemplate string // the expected path template of the route
|
||||||
hostTemplate string // the expected host template of the route
|
hostTemplate string // the expected host template of the route
|
||||||
methods []string // the expected route methods
|
methods []string // the expected route methods
|
||||||
@@ -743,6 +745,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=bar&baz=ding",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -752,6 +755,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=bar&baz=ding",
|
||||||
pathTemplate: `/api`,
|
pathTemplate: `/api`,
|
||||||
hostTemplate: `www.example.com`,
|
hostTemplate: `www.example.com`,
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
@@ -763,6 +767,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=bar&baz=ding",
|
||||||
pathTemplate: `/api`,
|
pathTemplate: `/api`,
|
||||||
hostTemplate: `www.example.com`,
|
hostTemplate: `www.example.com`,
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
@@ -783,6 +788,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v1": "bar"},
|
vars: map[string]string{"v1": "bar"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=bar",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -792,6 +798,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v1": "bar", "v2": "ding"},
|
vars: map[string]string{"v1": "bar", "v2": "ding"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=bar&baz=ding",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -801,6 +808,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v1": "10"},
|
vars: map[string]string{"v1": "10"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=10",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -819,6 +827,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v1": "1"},
|
vars: map[string]string{"v1": "1"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=1",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -828,6 +837,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v1": "1"},
|
vars: map[string]string{"v1": "1"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=1",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -846,6 +856,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v1": "1a"},
|
vars: map[string]string{"v1": "1a"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=1a",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -864,6 +875,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v-1": "bar"},
|
vars: map[string]string{"v-1": "bar"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=bar",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -873,6 +885,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v-1": "bar", "v-2": "ding"},
|
vars: map[string]string{"v-1": "bar", "v-2": "ding"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=bar&baz=ding",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -882,6 +895,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v-1": "10"},
|
vars: map[string]string{"v-1": "10"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=10",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -891,6 +905,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"v-1": "1a"},
|
vars: map[string]string{"v-1": "1a"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=1a",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -900,6 +915,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -918,6 +934,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -945,6 +962,7 @@ func TestQueries(t *testing.T) {
|
|||||||
vars: map[string]string{"foo": ""},
|
vars: map[string]string{"foo": ""},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
|
query: "foo=",
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -956,6 +974,16 @@ func TestQueries(t *testing.T) {
|
|||||||
path: "",
|
path: "",
|
||||||
shouldMatch: false,
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Queries route with pattern, match, escaped value",
|
||||||
|
route: new(Route).Queries("foo", "{v1}"),
|
||||||
|
request: newRequest("GET", "http://localhost?foo=%25bar%26%20%2F%3D%3F"),
|
||||||
|
vars: map[string]string{"v1": "%bar& /=?"},
|
||||||
|
host: "",
|
||||||
|
path: "",
|
||||||
|
query: "foo=%25bar%26+%2F%3D%3F",
|
||||||
|
shouldMatch: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
@@ -1187,6 +1215,28 @@ func TestSubRouter(t *testing.T) {
|
|||||||
pathTemplate: `/{category}`,
|
pathTemplate: `/{category}`,
|
||||||
shouldMatch: true,
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Build with scheme on parent router",
|
||||||
|
route: new(Route).Schemes("ftp").Host("google.com").Subrouter().Path("/"),
|
||||||
|
request: newRequest("GET", "ftp://google.com/"),
|
||||||
|
scheme: "ftp",
|
||||||
|
host: "google.com",
|
||||||
|
path: "/",
|
||||||
|
pathTemplate: `/`,
|
||||||
|
hostTemplate: `google.com`,
|
||||||
|
shouldMatch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Prefer scheme on child route when building URLs",
|
||||||
|
route: new(Route).Schemes("https", "ftp").Host("google.com").Subrouter().Schemes("ftp").Path("/"),
|
||||||
|
request: newRequest("GET", "ftp://google.com/"),
|
||||||
|
scheme: "ftp",
|
||||||
|
host: "google.com",
|
||||||
|
path: "/",
|
||||||
|
pathTemplate: `/`,
|
||||||
|
hostTemplate: `google.com`,
|
||||||
|
shouldMatch: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
@@ -1382,11 +1432,55 @@ func TestWalkNested(t *testing.T) {
|
|||||||
l2 := l1.PathPrefix("/l").Subrouter()
|
l2 := l1.PathPrefix("/l").Subrouter()
|
||||||
l2.Path("/a")
|
l2.Path("/a")
|
||||||
|
|
||||||
paths := []string{"/g", "/g/o", "/g/o/r", "/g/o/r/i", "/g/o/r/i/l", "/g/o/r/i/l/l", "/g/o/r/i/l/l/a"}
|
testCases := []struct {
|
||||||
|
path string
|
||||||
|
ancestors []*Route
|
||||||
|
}{
|
||||||
|
{"/g", []*Route{}},
|
||||||
|
{"/g/o", []*Route{g.parent.(*Route)}},
|
||||||
|
{"/g/o/r", []*Route{g.parent.(*Route), o.parent.(*Route)}},
|
||||||
|
{"/g/o/r/i", []*Route{g.parent.(*Route), o.parent.(*Route), r.parent.(*Route)}},
|
||||||
|
{"/g/o/r/i/l", []*Route{g.parent.(*Route), o.parent.(*Route), r.parent.(*Route), i.parent.(*Route)}},
|
||||||
|
{"/g/o/r/i/l/l", []*Route{g.parent.(*Route), o.parent.(*Route), r.parent.(*Route), i.parent.(*Route), l1.parent.(*Route)}},
|
||||||
|
{"/g/o/r/i/l/l/a", []*Route{g.parent.(*Route), o.parent.(*Route), r.parent.(*Route), i.parent.(*Route), l1.parent.(*Route), l2.parent.(*Route)}},
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := 0
|
||||||
|
err := router.Walk(func(route *Route, router *Router, ancestors []*Route) error {
|
||||||
|
path := testCases[idx].path
|
||||||
|
tpl := route.regexp.path.template
|
||||||
|
if tpl != path {
|
||||||
|
t.Errorf(`Expected %s got %s`, path, tpl)
|
||||||
|
}
|
||||||
|
currWantAncestors := testCases[idx].ancestors
|
||||||
|
if !reflect.DeepEqual(currWantAncestors, ancestors) {
|
||||||
|
t.Errorf(`Expected %+v got %+v`, currWantAncestors, ancestors)
|
||||||
|
}
|
||||||
|
idx++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if idx != len(testCases) {
|
||||||
|
t.Errorf("Expected %d routes, found %d", len(testCases), idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWalkSubrouters(t *testing.T) {
|
||||||
|
router := NewRouter()
|
||||||
|
|
||||||
|
g := router.Path("/g").Subrouter()
|
||||||
|
o := g.PathPrefix("/o").Subrouter()
|
||||||
|
o.Methods("GET")
|
||||||
|
o.Methods("PUT")
|
||||||
|
|
||||||
|
// all 4 routes should be matched, but final 2 routes do not have path templates
|
||||||
|
paths := []string{"/g", "/g/o", "", ""}
|
||||||
idx := 0
|
idx := 0
|
||||||
err := router.Walk(func(route *Route, router *Router, ancestors []*Route) error {
|
err := router.Walk(func(route *Route, router *Router, ancestors []*Route) error {
|
||||||
path := paths[idx]
|
path := paths[idx]
|
||||||
tpl := route.regexp.path.template
|
tpl, _ := route.GetPathTemplate()
|
||||||
if tpl != path {
|
if tpl != path {
|
||||||
t.Errorf(`Expected %s got %s`, path, tpl)
|
t.Errorf(`Expected %s got %s`, path, tpl)
|
||||||
}
|
}
|
||||||
@@ -1492,6 +1586,7 @@ func testRoute(t *testing.T, test routeTest) {
|
|||||||
route := test.route
|
route := test.route
|
||||||
vars := test.vars
|
vars := test.vars
|
||||||
shouldMatch := test.shouldMatch
|
shouldMatch := test.shouldMatch
|
||||||
|
query := test.query
|
||||||
shouldRedirect := test.shouldRedirect
|
shouldRedirect := test.shouldRedirect
|
||||||
uri := url.URL{
|
uri := url.URL{
|
||||||
Scheme: test.scheme,
|
Scheme: test.scheme,
|
||||||
@@ -1561,6 +1656,13 @@ func testRoute(t *testing.T, test routeTest) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if query != "" {
|
||||||
|
u, _ := route.URL(mapToPairs(match.Vars)...)
|
||||||
|
if query != u.RawQuery {
|
||||||
|
t.Errorf("(%v) URL query not equal: expected %v, got %v", test.title, query, u.RawQuery)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
if shouldRedirect && match.Handler == nil {
|
if shouldRedirect && match.Handler == nil {
|
||||||
t.Errorf("(%v) Did not redirect", test.title)
|
t.Errorf("(%v) Did not redirect", test.title)
|
||||||
return
|
return
|
||||||
@@ -1769,3 +1871,42 @@ func newRequest(method, url string) *http.Request {
|
|||||||
}
|
}
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNoMatchMethodErrorHandler(t *testing.T) {
|
||||||
|
func1 := func(w http.ResponseWriter, r *http.Request) {}
|
||||||
|
|
||||||
|
r := NewRouter()
|
||||||
|
r.HandleFunc("/", func1).Methods("GET", "POST")
|
||||||
|
|
||||||
|
req, _ := http.NewRequest("PUT", "http://localhost/", nil)
|
||||||
|
match := new(RouteMatch)
|
||||||
|
matched := r.Match(req, match)
|
||||||
|
|
||||||
|
if matched {
|
||||||
|
t.Error("Should not have matched route for methods")
|
||||||
|
}
|
||||||
|
|
||||||
|
if match.MatchErr != ErrMethodMismatch {
|
||||||
|
t.Error("Should get ErrMethodMismatch error")
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := NewRecorder()
|
||||||
|
r.ServeHTTP(resp, req)
|
||||||
|
if resp.Code != 405 {
|
||||||
|
t.Errorf("Expecting code %v", 405)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add matching route
|
||||||
|
r.HandleFunc("/", func1).Methods("PUT")
|
||||||
|
|
||||||
|
match = new(RouteMatch)
|
||||||
|
matched = r.Match(req, match)
|
||||||
|
|
||||||
|
if !matched {
|
||||||
|
t.Error("Should have matched route for methods")
|
||||||
|
}
|
||||||
|
|
||||||
|
if match.MatchErr != nil {
|
||||||
|
t.Error("Should not have any matching error. Found:", match.MatchErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
8
vendor/github.com/gorilla/mux/old_test.go
сгенерированный
поставляемый
8
vendor/github.com/gorilla/mux/old_test.go
сгенерированный
поставляемый
@@ -121,12 +121,7 @@ func TestRouteMatchers(t *testing.T) {
|
|||||||
var routeMatch RouteMatch
|
var routeMatch RouteMatch
|
||||||
matched := router.Match(request, &routeMatch)
|
matched := router.Match(request, &routeMatch)
|
||||||
if matched != shouldMatch {
|
if matched != shouldMatch {
|
||||||
// Need better messages. :)
|
t.Errorf("Expected: %v\nGot: %v\nRequest: %v %v", shouldMatch, matched, request.Method, url)
|
||||||
if matched {
|
|
||||||
t.Errorf("Should match.")
|
|
||||||
} else {
|
|
||||||
t.Errorf("Should not match.")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if matched {
|
if matched {
|
||||||
@@ -188,7 +183,6 @@ func TestRouteMatchers(t *testing.T) {
|
|||||||
match(true)
|
match(true)
|
||||||
|
|
||||||
// 2nd route --------------------------------------------------------------
|
// 2nd route --------------------------------------------------------------
|
||||||
|
|
||||||
// Everything match.
|
// Everything match.
|
||||||
reset2()
|
reset2()
|
||||||
match(true)
|
match(true)
|
||||||
|
|||||||
5
vendor/github.com/gorilla/mux/regexp.go
сгенерированный
поставляемый
5
vendor/github.com/gorilla/mux/regexp.go
сгенерированный
поставляемый
@@ -35,7 +35,7 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash,
|
|||||||
// Now let's parse it.
|
// Now let's parse it.
|
||||||
defaultPattern := "[^/]+"
|
defaultPattern := "[^/]+"
|
||||||
if matchQuery {
|
if matchQuery {
|
||||||
defaultPattern = "[^?&]*"
|
defaultPattern = ".*"
|
||||||
} else if matchHost {
|
} else if matchHost {
|
||||||
defaultPattern = "[^.]+"
|
defaultPattern = "[^.]+"
|
||||||
matchPrefix = false
|
matchPrefix = false
|
||||||
@@ -178,6 +178,9 @@ func (r *routeRegexp) url(values map[string]string) (string, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("mux: missing route variable %q", v)
|
return "", fmt.Errorf("mux: missing route variable %q", v)
|
||||||
}
|
}
|
||||||
|
if r.matchQuery {
|
||||||
|
value = url.QueryEscape(value)
|
||||||
|
}
|
||||||
urlValues[k] = value
|
urlValues[k] = value
|
||||||
}
|
}
|
||||||
rv := fmt.Sprintf(r.reverse, urlValues...)
|
rv := fmt.Sprintf(r.reverse, urlValues...)
|
||||||
|
|||||||
50
vendor/github.com/gorilla/mux/route.go
сгенерированный
поставляемый
50
vendor/github.com/gorilla/mux/route.go
сгенерированный
поставляемый
@@ -52,12 +52,27 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
|
|||||||
if r.buildOnly || r.err != nil {
|
if r.buildOnly || r.err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var matchErr error
|
||||||
|
|
||||||
// Match everything.
|
// Match everything.
|
||||||
for _, m := range r.matchers {
|
for _, m := range r.matchers {
|
||||||
if matched := m.Match(req, match); !matched {
|
if matched := m.Match(req, match); !matched {
|
||||||
|
if _, ok := m.(methodMatcher); ok {
|
||||||
|
matchErr = ErrMethodMismatch
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
matchErr = nil
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if matchErr != nil {
|
||||||
|
match.MatchErr = matchErr
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
match.MatchErr = nil
|
||||||
// Yay, we have a match. Let's collect some info about it.
|
// Yay, we have a match. Let's collect some info about it.
|
||||||
if match.Route == nil {
|
if match.Route == nil {
|
||||||
match.Route = r
|
match.Route = r
|
||||||
@@ -68,6 +83,7 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
|
|||||||
if match.Vars == nil {
|
if match.Vars == nil {
|
||||||
match.Vars = make(map[string]string)
|
match.Vars = make(map[string]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set variables.
|
// Set variables.
|
||||||
if r.regexp != nil {
|
if r.regexp != nil {
|
||||||
r.regexp.setMatch(req, match, r)
|
r.regexp.setMatch(req, match, r)
|
||||||
@@ -482,13 +498,14 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var scheme, host, path string
|
var scheme, host, path string
|
||||||
|
queries := make([]string, 0, len(r.regexp.queries))
|
||||||
if r.regexp.host != nil {
|
if r.regexp.host != nil {
|
||||||
if host, err = r.regexp.host.url(values); err != nil {
|
if host, err = r.regexp.host.url(values); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
scheme = "http"
|
scheme = "http"
|
||||||
if r.buildScheme != "" {
|
if s := r.getBuildScheme(); s != "" {
|
||||||
scheme = r.buildScheme
|
scheme = s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if r.regexp.path != nil {
|
if r.regexp.path != nil {
|
||||||
@@ -496,10 +513,18 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, q := range r.regexp.queries {
|
||||||
|
var query string
|
||||||
|
if query, err = q.url(values); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
queries = append(queries, query)
|
||||||
|
}
|
||||||
return &url.URL{
|
return &url.URL{
|
||||||
Scheme: scheme,
|
Scheme: scheme,
|
||||||
Host: host,
|
Host: host,
|
||||||
Path: path,
|
Path: path,
|
||||||
|
RawQuery: strings.Join(queries, "&"),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,8 +550,8 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) {
|
|||||||
Scheme: "http",
|
Scheme: "http",
|
||||||
Host: host,
|
Host: host,
|
||||||
}
|
}
|
||||||
if r.buildScheme != "" {
|
if s := r.getBuildScheme(); s != "" {
|
||||||
u.Scheme = r.buildScheme
|
u.Scheme = s
|
||||||
}
|
}
|
||||||
return u, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
@@ -640,11 +665,22 @@ func (r *Route) buildVars(m map[string]string) map[string]string {
|
|||||||
|
|
||||||
// parentRoute allows routes to know about parent host and path definitions.
|
// parentRoute allows routes to know about parent host and path definitions.
|
||||||
type parentRoute interface {
|
type parentRoute interface {
|
||||||
|
getBuildScheme() string
|
||||||
getNamedRoutes() map[string]*Route
|
getNamedRoutes() map[string]*Route
|
||||||
getRegexpGroup() *routeRegexpGroup
|
getRegexpGroup() *routeRegexpGroup
|
||||||
buildVars(map[string]string) map[string]string
|
buildVars(map[string]string) map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Route) getBuildScheme() string {
|
||||||
|
if r.buildScheme != "" {
|
||||||
|
return r.buildScheme
|
||||||
|
}
|
||||||
|
if r.parent != nil {
|
||||||
|
return r.parent.getBuildScheme()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// getNamedRoutes returns the map where named routes are registered.
|
// getNamedRoutes returns the map where named routes are registered.
|
||||||
func (r *Route) getNamedRoutes() map[string]*Route {
|
func (r *Route) getNamedRoutes() map[string]*Route {
|
||||||
if r.parent == nil {
|
if r.parent == nil {
|
||||||
|
|||||||
2
vendor/github.com/hashicorp/hcl/decoder.go
сгенерированный
поставляемый
2
vendor/github.com/hashicorp/hcl/decoder.go
сгенерированный
поставляемый
@@ -137,7 +137,7 @@ func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) e
|
|||||||
func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error {
|
func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error {
|
||||||
switch n := node.(type) {
|
switch n := node.(type) {
|
||||||
case *ast.LiteralType:
|
case *ast.LiteralType:
|
||||||
if n.Token.Type == token.FLOAT {
|
if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER {
|
||||||
v, err := strconv.ParseFloat(n.Token.Text, 64)
|
v, err := strconv.ParseFloat(n.Token.Text, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
9
vendor/github.com/hashicorp/hcl/decoder_test.go
сгенерированный
поставляемый
9
vendor/github.com/hashicorp/hcl/decoder_test.go
сгенерированный
поставляемый
@@ -73,6 +73,7 @@ func TestDecode_interface(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"a": 1.02,
|
"a": 1.02,
|
||||||
|
"b": 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -811,6 +812,7 @@ func TestDecode_intString(t *testing.T) {
|
|||||||
func TestDecode_float32(t *testing.T) {
|
func TestDecode_float32(t *testing.T) {
|
||||||
var value struct {
|
var value struct {
|
||||||
A float32 `hcl:"a"`
|
A float32 `hcl:"a"`
|
||||||
|
B float32 `hcl:"b"`
|
||||||
}
|
}
|
||||||
|
|
||||||
err := Decode(&value, testReadFile(t, "float.hcl"))
|
err := Decode(&value, testReadFile(t, "float.hcl"))
|
||||||
@@ -821,11 +823,15 @@ func TestDecode_float32(t *testing.T) {
|
|||||||
if got, want := value.A, float32(1.02); got != want {
|
if got, want := value.A, float32(1.02); got != want {
|
||||||
t.Fatalf("wrong result %#v; want %#v", got, want)
|
t.Fatalf("wrong result %#v; want %#v", got, want)
|
||||||
}
|
}
|
||||||
|
if got, want := value.B, float32(2); got != want {
|
||||||
|
t.Fatalf("wrong result %#v; want %#v", got, want)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDecode_float64(t *testing.T) {
|
func TestDecode_float64(t *testing.T) {
|
||||||
var value struct {
|
var value struct {
|
||||||
A float64 `hcl:"a"`
|
A float64 `hcl:"a"`
|
||||||
|
B float64 `hcl:"b"`
|
||||||
}
|
}
|
||||||
|
|
||||||
err := Decode(&value, testReadFile(t, "float.hcl"))
|
err := Decode(&value, testReadFile(t, "float.hcl"))
|
||||||
@@ -836,6 +842,9 @@ func TestDecode_float64(t *testing.T) {
|
|||||||
if got, want := value.A, float64(1.02); got != want {
|
if got, want := value.A, float64(1.02); got != want {
|
||||||
t.Fatalf("wrong result %#v; want %#v", got, want)
|
t.Fatalf("wrong result %#v; want %#v", got, want)
|
||||||
}
|
}
|
||||||
|
if got, want := value.B, float64(2); got != want {
|
||||||
|
t.Fatalf("wrong result %#v; want %#v", got, want)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDecode_intStringAliased(t *testing.T) {
|
func TestDecode_intStringAliased(t *testing.T) {
|
||||||
|
|||||||
14
vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
сгенерированный
поставляемый
14
vendor/github.com/hashicorp/hcl/hcl/parser/parser.go
сгенерированный
поставляемый
@@ -197,9 +197,12 @@ func (p *Parser) objectItem() (*ast.ObjectItem, error) {
|
|||||||
keyStr = append(keyStr, k.Token.Text)
|
keyStr = append(keyStr, k.Token.Text)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf(
|
return nil, &PosError{
|
||||||
"key '%s' expected start of object ('{') or assignment ('=')",
|
Pos: p.tok.Pos,
|
||||||
strings.Join(keyStr, " "))
|
Err: fmt.Errorf(
|
||||||
|
"key '%s' expected start of object ('{') or assignment ('=')",
|
||||||
|
strings.Join(keyStr, " ")),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// do a look-ahead for line comment
|
// do a look-ahead for line comment
|
||||||
@@ -319,7 +322,10 @@ func (p *Parser) objectType() (*ast.ObjectType, error) {
|
|||||||
|
|
||||||
// No error, scan and expect the ending to be a brace
|
// No error, scan and expect the ending to be a brace
|
||||||
if tok := p.scan(); tok.Type != token.RBRACE {
|
if tok := p.scan(); tok.Type != token.RBRACE {
|
||||||
return nil, fmt.Errorf("object expected closing RBRACE got: %s", tok.Type)
|
return nil, &PosError{
|
||||||
|
Pos: tok.Pos,
|
||||||
|
Err: fmt.Errorf("object expected closing RBRACE got: %s", tok.Type),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
o.List = l
|
o.List = l
|
||||||
|
|||||||
1
vendor/github.com/hashicorp/hcl/test-fixtures/float.hcl
сгенерированный
поставляемый
1
vendor/github.com/hashicorp/hcl/test-fixtures/float.hcl
сгенерированный
поставляемый
@@ -1 +1,2 @@
|
|||||||
a = 1.02
|
a = 1.02
|
||||||
|
b = 2
|
||||||
|
|||||||
3
vendor/github.com/hashicorp/hcl/test-fixtures/float.json
сгенерированный
поставляемый
3
vendor/github.com/hashicorp/hcl/test-fixtures/float.json
сгенерированный
поставляемый
@@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"a": 1.02
|
"a": 1.02,
|
||||||
|
"b": 2
|
||||||
}
|
}
|
||||||
|
|||||||
4
vendor/github.com/hashicorp/memberlist/memberlist.go
сгенерированный
поставляемый
4
vendor/github.com/hashicorp/memberlist/memberlist.go
сгенерированный
поставляемый
@@ -127,7 +127,7 @@ func newMemberlist(conf *Config) (*Memberlist, error) {
|
|||||||
return nt, nil
|
return nt, nil
|
||||||
}
|
}
|
||||||
if strings.Contains(err.Error(), "address already in use") {
|
if strings.Contains(err.Error(), "address already in use") {
|
||||||
logger.Printf("[DEBUG] Got bind error: %v", err)
|
logger.Printf("[DEBUG] memberlist: Got bind error: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ func newMemberlist(conf *Config) (*Memberlist, error) {
|
|||||||
port := nt.GetAutoBindPort()
|
port := nt.GetAutoBindPort()
|
||||||
conf.BindPort = port
|
conf.BindPort = port
|
||||||
conf.AdvertisePort = port
|
conf.AdvertisePort = port
|
||||||
logger.Printf("[DEBUG] Using dynamic bind port %d", port)
|
logger.Printf("[DEBUG] memberlist: Using dynamic bind port %d", port)
|
||||||
}
|
}
|
||||||
transport = nt
|
transport = nt
|
||||||
}
|
}
|
||||||
|
|||||||
1
vendor/github.com/lib/pq/.travis.yml
сгенерированный
поставляемый
1
vendor/github.com/lib/pq/.travis.yml
сгенерированный
поставляемый
@@ -5,6 +5,7 @@ go:
|
|||||||
- 1.6.x
|
- 1.6.x
|
||||||
- 1.7.x
|
- 1.7.x
|
||||||
- 1.8.x
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
- master
|
- master
|
||||||
|
|
||||||
sudo: true
|
sudo: true
|
||||||
|
|||||||
34
vendor/github.com/lib/pq/conn.go
сгенерированный
поставляемый
34
vendor/github.com/lib/pq/conn.go
сгенерированный
поставляемый
@@ -706,7 +706,7 @@ func (noRows) RowsAffected() (int64, error) {
|
|||||||
|
|
||||||
// Decides which column formats to use for a prepared statement. The input is
|
// Decides which column formats to use for a prepared statement. The input is
|
||||||
// an array of type oids, one element per result column.
|
// an array of type oids, one element per result column.
|
||||||
func decideColumnFormats(colTyps []oid.Oid, forceText bool) (colFmts []format, colFmtData []byte) {
|
func decideColumnFormats(colTyps []fieldDesc, forceText bool) (colFmts []format, colFmtData []byte) {
|
||||||
if len(colTyps) == 0 {
|
if len(colTyps) == 0 {
|
||||||
return nil, colFmtDataAllText
|
return nil, colFmtDataAllText
|
||||||
}
|
}
|
||||||
@@ -718,8 +718,8 @@ func decideColumnFormats(colTyps []oid.Oid, forceText bool) (colFmts []format, c
|
|||||||
|
|
||||||
allBinary := true
|
allBinary := true
|
||||||
allText := true
|
allText := true
|
||||||
for i, o := range colTyps {
|
for i, t := range colTyps {
|
||||||
switch o {
|
switch t.OID {
|
||||||
// This is the list of types to use binary mode for when receiving them
|
// This is the list of types to use binary mode for when receiving them
|
||||||
// through a prepared statement. If a type appears in this list, it
|
// through a prepared statement. If a type appears in this list, it
|
||||||
// must also be implemented in binaryDecode in encode.go.
|
// must also be implemented in binaryDecode in encode.go.
|
||||||
@@ -1155,7 +1155,7 @@ type stmt struct {
|
|||||||
colNames []string
|
colNames []string
|
||||||
colFmts []format
|
colFmts []format
|
||||||
colFmtData []byte
|
colFmtData []byte
|
||||||
colTyps []oid.Oid
|
colTyps []fieldDesc
|
||||||
paramTyps []oid.Oid
|
paramTyps []oid.Oid
|
||||||
closed bool
|
closed bool
|
||||||
}
|
}
|
||||||
@@ -1318,7 +1318,7 @@ type rows struct {
|
|||||||
cn *conn
|
cn *conn
|
||||||
finish func()
|
finish func()
|
||||||
colNames []string
|
colNames []string
|
||||||
colTyps []oid.Oid
|
colTyps []fieldDesc
|
||||||
colFmts []format
|
colFmts []format
|
||||||
done bool
|
done bool
|
||||||
rb readBuf
|
rb readBuf
|
||||||
@@ -1406,7 +1406,7 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
|
|||||||
dest[i] = nil
|
dest[i] = nil
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dest[i] = decode(&conn.parameterStatus, rs.rb.next(l), rs.colTyps[i], rs.colFmts[i])
|
dest[i] = decode(&conn.parameterStatus, rs.rb.next(l), rs.colTyps[i].OID, rs.colFmts[i])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case 'T':
|
case 'T':
|
||||||
@@ -1573,7 +1573,7 @@ func (cn *conn) readParseResponse() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames []string, colTyps []oid.Oid) {
|
func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames []string, colTyps []fieldDesc) {
|
||||||
for {
|
for {
|
||||||
t, r := cn.recv1()
|
t, r := cn.recv1()
|
||||||
switch t {
|
switch t {
|
||||||
@@ -1599,7 +1599,7 @@ func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cn *conn) readPortalDescribeResponse() (colNames []string, colFmts []format, colTyps []oid.Oid) {
|
func (cn *conn) readPortalDescribeResponse() (colNames []string, colFmts []format, colTyps []fieldDesc) {
|
||||||
t, r := cn.recv1()
|
t, r := cn.recv1()
|
||||||
switch t {
|
switch t {
|
||||||
case 'T':
|
case 'T':
|
||||||
@@ -1695,31 +1695,33 @@ func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []oid.Oid) {
|
func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []fieldDesc) {
|
||||||
n := r.int16()
|
n := r.int16()
|
||||||
colNames = make([]string, n)
|
colNames = make([]string, n)
|
||||||
colTyps = make([]oid.Oid, n)
|
colTyps = make([]fieldDesc, n)
|
||||||
for i := range colNames {
|
for i := range colNames {
|
||||||
colNames[i] = r.string()
|
colNames[i] = r.string()
|
||||||
r.next(6)
|
r.next(6)
|
||||||
colTyps[i] = r.oid()
|
colTyps[i].OID = r.oid()
|
||||||
r.next(6)
|
colTyps[i].Len = r.int16()
|
||||||
|
colTyps[i].Mod = r.int32()
|
||||||
// format code not known when describing a statement; always 0
|
// format code not known when describing a statement; always 0
|
||||||
r.next(2)
|
r.next(2)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, colTyps []oid.Oid) {
|
func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, colTyps []fieldDesc) {
|
||||||
n := r.int16()
|
n := r.int16()
|
||||||
colNames = make([]string, n)
|
colNames = make([]string, n)
|
||||||
colFmts = make([]format, n)
|
colFmts = make([]format, n)
|
||||||
colTyps = make([]oid.Oid, n)
|
colTyps = make([]fieldDesc, n)
|
||||||
for i := range colNames {
|
for i := range colNames {
|
||||||
colNames[i] = r.string()
|
colNames[i] = r.string()
|
||||||
r.next(6)
|
r.next(6)
|
||||||
colTyps[i] = r.oid()
|
colTyps[i].OID = r.oid()
|
||||||
r.next(6)
|
colTyps[i].Len = r.int16()
|
||||||
|
colTyps[i].Mod = r.int32()
|
||||||
colFmts[i] = format(r.int16())
|
colFmts[i] = format(r.int16())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
12
vendor/github.com/lib/pq/encode.go
сгенерированный
поставляемый
12
vendor/github.com/lib/pq/encode.go
сгенерированный
поставляемый
@@ -367,8 +367,15 @@ func ParseTimestamp(currentLocation *time.Location, str string) (time.Time, erro
|
|||||||
timeSep := daySep + 3
|
timeSep := daySep + 3
|
||||||
day := p.mustAtoi(str, daySep+1, timeSep)
|
day := p.mustAtoi(str, daySep+1, timeSep)
|
||||||
|
|
||||||
|
minLen := monSep + len("01-01") + 1
|
||||||
|
|
||||||
|
isBC := strings.HasSuffix(str, " BC")
|
||||||
|
if isBC {
|
||||||
|
minLen += 3
|
||||||
|
}
|
||||||
|
|
||||||
var hour, minute, second int
|
var hour, minute, second int
|
||||||
if len(str) > monSep+len("01-01")+1 {
|
if len(str) > minLen {
|
||||||
p.expect(str, ' ', timeSep)
|
p.expect(str, ' ', timeSep)
|
||||||
minSep := timeSep + 3
|
minSep := timeSep + 3
|
||||||
p.expect(str, ':', minSep)
|
p.expect(str, ':', minSep)
|
||||||
@@ -424,7 +431,8 @@ func ParseTimestamp(currentLocation *time.Location, str string) (time.Time, erro
|
|||||||
tzOff = tzSign * ((tzHours * 60 * 60) + (tzMin * 60) + tzSec)
|
tzOff = tzSign * ((tzHours * 60 * 60) + (tzMin * 60) + tzSec)
|
||||||
}
|
}
|
||||||
var isoYear int
|
var isoYear int
|
||||||
if remainderIdx+3 <= len(str) && str[remainderIdx:remainderIdx+3] == " BC" {
|
|
||||||
|
if isBC {
|
||||||
isoYear = 1 - year
|
isoYear = 1 - year
|
||||||
remainderIdx += 3
|
remainderIdx += 3
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
9
vendor/github.com/lib/pq/encode_test.go
сгенерированный
поставляемый
9
vendor/github.com/lib/pq/encode_test.go
сгенерированный
поставляемый
@@ -37,6 +37,8 @@ var timeTests = []struct {
|
|||||||
}{
|
}{
|
||||||
{"22001-02-03", time.Date(22001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
|
{"22001-02-03", time.Date(22001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
|
||||||
{"2001-02-03", time.Date(2001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
|
{"2001-02-03", time.Date(2001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
|
||||||
|
{"0001-12-31 BC", time.Date(0, time.December, 31, 0, 0, 0, 0, time.FixedZone("", 0))},
|
||||||
|
{"2001-02-03 BC", time.Date(-2000, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
|
||||||
{"2001-02-03 04:05:06", time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))},
|
{"2001-02-03 04:05:06", time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))},
|
||||||
{"2001-02-03 04:05:06.000001", time.Date(2001, time.February, 3, 4, 5, 6, 1000, time.FixedZone("", 0))},
|
{"2001-02-03 04:05:06.000001", time.Date(2001, time.February, 3, 4, 5, 6, 1000, time.FixedZone("", 0))},
|
||||||
{"2001-02-03 04:05:06.00001", time.Date(2001, time.February, 3, 4, 5, 6, 10000, time.FixedZone("", 0))},
|
{"2001-02-03 04:05:06.00001", time.Date(2001, time.February, 3, 4, 5, 6, 10000, time.FixedZone("", 0))},
|
||||||
@@ -86,15 +88,22 @@ func TestParseTs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var timeErrorTests = []string{
|
var timeErrorTests = []string{
|
||||||
|
"BC",
|
||||||
|
" BC",
|
||||||
"2001",
|
"2001",
|
||||||
"2001-2-03",
|
"2001-2-03",
|
||||||
"2001-02-3",
|
"2001-02-3",
|
||||||
"2001-02-03 ",
|
"2001-02-03 ",
|
||||||
|
"2001-02-03 B",
|
||||||
"2001-02-03 04",
|
"2001-02-03 04",
|
||||||
"2001-02-03 04:",
|
"2001-02-03 04:",
|
||||||
"2001-02-03 04:05",
|
"2001-02-03 04:05",
|
||||||
|
"2001-02-03 04:05 B",
|
||||||
|
"2001-02-03 04:05 BC",
|
||||||
"2001-02-03 04:05:",
|
"2001-02-03 04:05:",
|
||||||
"2001-02-03 04:05:6",
|
"2001-02-03 04:05:6",
|
||||||
|
"2001-02-03 04:05:06 B",
|
||||||
|
"2001-02-03 04:05:06BC",
|
||||||
"2001-02-03 04:05:06.123 B",
|
"2001-02-03 04:05:06.123 B",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
59
vendor/github.com/lib/pq/oid/gen.go
сгенерированный
поставляемый
59
vendor/github.com/lib/pq/oid/gen.go
сгенерированный
поставляемый
@@ -10,10 +10,22 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OID represent a postgres Object Identifier Type.
|
||||||
|
type OID struct {
|
||||||
|
ID int
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns an upper case version of the oid type.
|
||||||
|
func (o OID) Name() string {
|
||||||
|
return strings.ToUpper(o.Type)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
datname := os.Getenv("PGDATABASE")
|
datname := os.Getenv("PGDATABASE")
|
||||||
sslmode := os.Getenv("PGSSLMODE")
|
sslmode := os.Getenv("PGSSLMODE")
|
||||||
@@ -30,6 +42,25 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
rows, err := db.Query(`
|
||||||
|
SELECT typname, oid
|
||||||
|
FROM pg_type WHERE oid < 10000
|
||||||
|
ORDER BY oid;
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
oids := make([]*OID, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
var oid OID
|
||||||
|
if err = rows.Scan(&oid.Type, &oid.ID); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
oids = append(oids, &oid)
|
||||||
|
}
|
||||||
|
if err = rows.Err(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
cmd := exec.Command("gofmt")
|
cmd := exec.Command("gofmt")
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
w, err := cmd.StdinPipe()
|
w, err := cmd.StdinPipe()
|
||||||
@@ -45,30 +76,18 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, "// generated by 'go run gen.go'; do not edit")
|
fmt.Fprintln(w, "// Code generated by gen.go. DO NOT EDIT.")
|
||||||
fmt.Fprintln(w, "\npackage oid")
|
fmt.Fprintln(w, "\npackage oid")
|
||||||
fmt.Fprintln(w, "const (")
|
fmt.Fprintln(w, "const (")
|
||||||
rows, err := db.Query(`
|
for _, oid := range oids {
|
||||||
SELECT typname, oid
|
fmt.Fprintf(w, "T_%s Oid = %d\n", oid.Type, oid.ID)
|
||||||
FROM pg_type WHERE oid < 10000
|
|
||||||
ORDER BY oid;
|
|
||||||
`)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
var name string
|
|
||||||
var oid int
|
|
||||||
for rows.Next() {
|
|
||||||
err = rows.Scan(&name, &oid)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "T_%s Oid = %d\n", name, oid)
|
|
||||||
}
|
|
||||||
if err = rows.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, ")")
|
fmt.Fprintln(w, ")")
|
||||||
|
fmt.Fprintln(w, "var TypeName = map[Oid]string{")
|
||||||
|
for _, oid := range oids {
|
||||||
|
fmt.Fprintf(w, "T_%s: \"%s\",\n", oid.Type, oid.Name())
|
||||||
|
}
|
||||||
|
fmt.Fprintln(w, "}")
|
||||||
w.Close()
|
w.Close()
|
||||||
cmd.Wait()
|
cmd.Wait()
|
||||||
}
|
}
|
||||||
|
|||||||
172
vendor/github.com/lib/pq/oid/types.go
сгенерированный
поставляемый
172
vendor/github.com/lib/pq/oid/types.go
сгенерированный
поставляемый
@@ -1,4 +1,4 @@
|
|||||||
// generated by 'go run gen.go'; do not edit
|
// Code generated by gen.go. DO NOT EDIT.
|
||||||
|
|
||||||
package oid
|
package oid
|
||||||
|
|
||||||
@@ -171,3 +171,173 @@ const (
|
|||||||
T_regrole Oid = 4096
|
T_regrole Oid = 4096
|
||||||
T__regrole Oid = 4097
|
T__regrole Oid = 4097
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var TypeName = map[Oid]string{
|
||||||
|
T_bool: "BOOL",
|
||||||
|
T_bytea: "BYTEA",
|
||||||
|
T_char: "CHAR",
|
||||||
|
T_name: "NAME",
|
||||||
|
T_int8: "INT8",
|
||||||
|
T_int2: "INT2",
|
||||||
|
T_int2vector: "INT2VECTOR",
|
||||||
|
T_int4: "INT4",
|
||||||
|
T_regproc: "REGPROC",
|
||||||
|
T_text: "TEXT",
|
||||||
|
T_oid: "OID",
|
||||||
|
T_tid: "TID",
|
||||||
|
T_xid: "XID",
|
||||||
|
T_cid: "CID",
|
||||||
|
T_oidvector: "OIDVECTOR",
|
||||||
|
T_pg_ddl_command: "PG_DDL_COMMAND",
|
||||||
|
T_pg_type: "PG_TYPE",
|
||||||
|
T_pg_attribute: "PG_ATTRIBUTE",
|
||||||
|
T_pg_proc: "PG_PROC",
|
||||||
|
T_pg_class: "PG_CLASS",
|
||||||
|
T_json: "JSON",
|
||||||
|
T_xml: "XML",
|
||||||
|
T__xml: "_XML",
|
||||||
|
T_pg_node_tree: "PG_NODE_TREE",
|
||||||
|
T__json: "_JSON",
|
||||||
|
T_smgr: "SMGR",
|
||||||
|
T_index_am_handler: "INDEX_AM_HANDLER",
|
||||||
|
T_point: "POINT",
|
||||||
|
T_lseg: "LSEG",
|
||||||
|
T_path: "PATH",
|
||||||
|
T_box: "BOX",
|
||||||
|
T_polygon: "POLYGON",
|
||||||
|
T_line: "LINE",
|
||||||
|
T__line: "_LINE",
|
||||||
|
T_cidr: "CIDR",
|
||||||
|
T__cidr: "_CIDR",
|
||||||
|
T_float4: "FLOAT4",
|
||||||
|
T_float8: "FLOAT8",
|
||||||
|
T_abstime: "ABSTIME",
|
||||||
|
T_reltime: "RELTIME",
|
||||||
|
T_tinterval: "TINTERVAL",
|
||||||
|
T_unknown: "UNKNOWN",
|
||||||
|
T_circle: "CIRCLE",
|
||||||
|
T__circle: "_CIRCLE",
|
||||||
|
T_money: "MONEY",
|
||||||
|
T__money: "_MONEY",
|
||||||
|
T_macaddr: "MACADDR",
|
||||||
|
T_inet: "INET",
|
||||||
|
T__bool: "_BOOL",
|
||||||
|
T__bytea: "_BYTEA",
|
||||||
|
T__char: "_CHAR",
|
||||||
|
T__name: "_NAME",
|
||||||
|
T__int2: "_INT2",
|
||||||
|
T__int2vector: "_INT2VECTOR",
|
||||||
|
T__int4: "_INT4",
|
||||||
|
T__regproc: "_REGPROC",
|
||||||
|
T__text: "_TEXT",
|
||||||
|
T__tid: "_TID",
|
||||||
|
T__xid: "_XID",
|
||||||
|
T__cid: "_CID",
|
||||||
|
T__oidvector: "_OIDVECTOR",
|
||||||
|
T__bpchar: "_BPCHAR",
|
||||||
|
T__varchar: "_VARCHAR",
|
||||||
|
T__int8: "_INT8",
|
||||||
|
T__point: "_POINT",
|
||||||
|
T__lseg: "_LSEG",
|
||||||
|
T__path: "_PATH",
|
||||||
|
T__box: "_BOX",
|
||||||
|
T__float4: "_FLOAT4",
|
||||||
|
T__float8: "_FLOAT8",
|
||||||
|
T__abstime: "_ABSTIME",
|
||||||
|
T__reltime: "_RELTIME",
|
||||||
|
T__tinterval: "_TINTERVAL",
|
||||||
|
T__polygon: "_POLYGON",
|
||||||
|
T__oid: "_OID",
|
||||||
|
T_aclitem: "ACLITEM",
|
||||||
|
T__aclitem: "_ACLITEM",
|
||||||
|
T__macaddr: "_MACADDR",
|
||||||
|
T__inet: "_INET",
|
||||||
|
T_bpchar: "BPCHAR",
|
||||||
|
T_varchar: "VARCHAR",
|
||||||
|
T_date: "DATE",
|
||||||
|
T_time: "TIME",
|
||||||
|
T_timestamp: "TIMESTAMP",
|
||||||
|
T__timestamp: "_TIMESTAMP",
|
||||||
|
T__date: "_DATE",
|
||||||
|
T__time: "_TIME",
|
||||||
|
T_timestamptz: "TIMESTAMPTZ",
|
||||||
|
T__timestamptz: "_TIMESTAMPTZ",
|
||||||
|
T_interval: "INTERVAL",
|
||||||
|
T__interval: "_INTERVAL",
|
||||||
|
T__numeric: "_NUMERIC",
|
||||||
|
T_pg_database: "PG_DATABASE",
|
||||||
|
T__cstring: "_CSTRING",
|
||||||
|
T_timetz: "TIMETZ",
|
||||||
|
T__timetz: "_TIMETZ",
|
||||||
|
T_bit: "BIT",
|
||||||
|
T__bit: "_BIT",
|
||||||
|
T_varbit: "VARBIT",
|
||||||
|
T__varbit: "_VARBIT",
|
||||||
|
T_numeric: "NUMERIC",
|
||||||
|
T_refcursor: "REFCURSOR",
|
||||||
|
T__refcursor: "_REFCURSOR",
|
||||||
|
T_regprocedure: "REGPROCEDURE",
|
||||||
|
T_regoper: "REGOPER",
|
||||||
|
T_regoperator: "REGOPERATOR",
|
||||||
|
T_regclass: "REGCLASS",
|
||||||
|
T_regtype: "REGTYPE",
|
||||||
|
T__regprocedure: "_REGPROCEDURE",
|
||||||
|
T__regoper: "_REGOPER",
|
||||||
|
T__regoperator: "_REGOPERATOR",
|
||||||
|
T__regclass: "_REGCLASS",
|
||||||
|
T__regtype: "_REGTYPE",
|
||||||
|
T_record: "RECORD",
|
||||||
|
T_cstring: "CSTRING",
|
||||||
|
T_any: "ANY",
|
||||||
|
T_anyarray: "ANYARRAY",
|
||||||
|
T_void: "VOID",
|
||||||
|
T_trigger: "TRIGGER",
|
||||||
|
T_language_handler: "LANGUAGE_HANDLER",
|
||||||
|
T_internal: "INTERNAL",
|
||||||
|
T_opaque: "OPAQUE",
|
||||||
|
T_anyelement: "ANYELEMENT",
|
||||||
|
T__record: "_RECORD",
|
||||||
|
T_anynonarray: "ANYNONARRAY",
|
||||||
|
T_pg_authid: "PG_AUTHID",
|
||||||
|
T_pg_auth_members: "PG_AUTH_MEMBERS",
|
||||||
|
T__txid_snapshot: "_TXID_SNAPSHOT",
|
||||||
|
T_uuid: "UUID",
|
||||||
|
T__uuid: "_UUID",
|
||||||
|
T_txid_snapshot: "TXID_SNAPSHOT",
|
||||||
|
T_fdw_handler: "FDW_HANDLER",
|
||||||
|
T_pg_lsn: "PG_LSN",
|
||||||
|
T__pg_lsn: "_PG_LSN",
|
||||||
|
T_tsm_handler: "TSM_HANDLER",
|
||||||
|
T_anyenum: "ANYENUM",
|
||||||
|
T_tsvector: "TSVECTOR",
|
||||||
|
T_tsquery: "TSQUERY",
|
||||||
|
T_gtsvector: "GTSVECTOR",
|
||||||
|
T__tsvector: "_TSVECTOR",
|
||||||
|
T__gtsvector: "_GTSVECTOR",
|
||||||
|
T__tsquery: "_TSQUERY",
|
||||||
|
T_regconfig: "REGCONFIG",
|
||||||
|
T__regconfig: "_REGCONFIG",
|
||||||
|
T_regdictionary: "REGDICTIONARY",
|
||||||
|
T__regdictionary: "_REGDICTIONARY",
|
||||||
|
T_jsonb: "JSONB",
|
||||||
|
T__jsonb: "_JSONB",
|
||||||
|
T_anyrange: "ANYRANGE",
|
||||||
|
T_event_trigger: "EVENT_TRIGGER",
|
||||||
|
T_int4range: "INT4RANGE",
|
||||||
|
T__int4range: "_INT4RANGE",
|
||||||
|
T_numrange: "NUMRANGE",
|
||||||
|
T__numrange: "_NUMRANGE",
|
||||||
|
T_tsrange: "TSRANGE",
|
||||||
|
T__tsrange: "_TSRANGE",
|
||||||
|
T_tstzrange: "TSTZRANGE",
|
||||||
|
T__tstzrange: "_TSTZRANGE",
|
||||||
|
T_daterange: "DATERANGE",
|
||||||
|
T__daterange: "_DATERANGE",
|
||||||
|
T_int8range: "INT8RANGE",
|
||||||
|
T__int8range: "_INT8RANGE",
|
||||||
|
T_pg_shseclabel: "PG_SHSECLABEL",
|
||||||
|
T_regnamespace: "REGNAMESPACE",
|
||||||
|
T__regnamespace: "_REGNAMESPACE",
|
||||||
|
T_regrole: "REGROLE",
|
||||||
|
T__regrole: "_REGROLE",
|
||||||
|
}
|
||||||
|
|||||||
93
vendor/github.com/lib/pq/rows.go
сгенерированный
поставляемый
Обычный файл
93
vendor/github.com/lib/pq/rows.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,93 @@
|
|||||||
|
package pq
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/lib/pq/oid"
|
||||||
|
)
|
||||||
|
|
||||||
|
const headerSize = 4
|
||||||
|
|
||||||
|
type fieldDesc struct {
|
||||||
|
// The object ID of the data type.
|
||||||
|
OID oid.Oid
|
||||||
|
// The data type size (see pg_type.typlen).
|
||||||
|
// Note that negative values denote variable-width types.
|
||||||
|
Len int
|
||||||
|
// The type modifier (see pg_attribute.atttypmod).
|
||||||
|
// The meaning of the modifier is type-specific.
|
||||||
|
Mod int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fd fieldDesc) Type() reflect.Type {
|
||||||
|
switch fd.OID {
|
||||||
|
case oid.T_int8:
|
||||||
|
return reflect.TypeOf(int64(0))
|
||||||
|
case oid.T_int4:
|
||||||
|
return reflect.TypeOf(int32(0))
|
||||||
|
case oid.T_int2:
|
||||||
|
return reflect.TypeOf(int16(0))
|
||||||
|
case oid.T_varchar, oid.T_text:
|
||||||
|
return reflect.TypeOf("")
|
||||||
|
case oid.T_bool:
|
||||||
|
return reflect.TypeOf(false)
|
||||||
|
case oid.T_date, oid.T_time, oid.T_timetz, oid.T_timestamp, oid.T_timestamptz:
|
||||||
|
return reflect.TypeOf(time.Time{})
|
||||||
|
case oid.T_bytea:
|
||||||
|
return reflect.TypeOf([]byte(nil))
|
||||||
|
default:
|
||||||
|
return reflect.TypeOf(new(interface{})).Elem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fd fieldDesc) Name() string {
|
||||||
|
return oid.TypeName[fd.OID]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fd fieldDesc) Length() (length int64, ok bool) {
|
||||||
|
switch fd.OID {
|
||||||
|
case oid.T_text, oid.T_bytea:
|
||||||
|
return math.MaxInt64, true
|
||||||
|
case oid.T_varchar, oid.T_bpchar:
|
||||||
|
return int64(fd.Mod - headerSize), true
|
||||||
|
default:
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fd fieldDesc) PrecisionScale() (precision, scale int64, ok bool) {
|
||||||
|
switch fd.OID {
|
||||||
|
case oid.T_numeric, oid.T__numeric:
|
||||||
|
mod := fd.Mod - headerSize
|
||||||
|
precision = int64((mod >> 16) & 0xffff)
|
||||||
|
scale = int64(mod & 0xffff)
|
||||||
|
return precision, scale, true
|
||||||
|
default:
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColumnTypeScanType returns the value type that can be used to scan types into.
|
||||||
|
func (rs *rows) ColumnTypeScanType(index int) reflect.Type {
|
||||||
|
return rs.colTyps[index].Type()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColumnTypeDatabaseTypeName return the database system type name.
|
||||||
|
func (rs *rows) ColumnTypeDatabaseTypeName(index int) string {
|
||||||
|
return rs.colTyps[index].Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColumnTypeLength returns the length of the column type if the column is a
|
||||||
|
// variable length type. If the column is not a variable length type ok
|
||||||
|
// should return false.
|
||||||
|
func (rs *rows) ColumnTypeLength(index int) (length int64, ok bool) {
|
||||||
|
return rs.colTyps[index].Length()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColumnTypePrecisionScale should return the precision and scale for decimal
|
||||||
|
// types. If not applicable, ok should be false.
|
||||||
|
func (rs *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
|
||||||
|
return rs.colTyps[index].PrecisionScale()
|
||||||
|
}
|
||||||
220
vendor/github.com/lib/pq/rows_test.go
сгенерированный
поставляемый
Обычный файл
220
vendor/github.com/lib/pq/rows_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,220 @@
|
|||||||
|
// +build go1.8
|
||||||
|
|
||||||
|
package pq
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/lib/pq/oid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDataTypeName(t *testing.T) {
|
||||||
|
tts := []struct {
|
||||||
|
typ oid.Oid
|
||||||
|
name string
|
||||||
|
}{
|
||||||
|
{oid.T_int8, "INT8"},
|
||||||
|
{oid.T_int4, "INT4"},
|
||||||
|
{oid.T_int2, "INT2"},
|
||||||
|
{oid.T_varchar, "VARCHAR"},
|
||||||
|
{oid.T_text, "TEXT"},
|
||||||
|
{oid.T_bool, "BOOL"},
|
||||||
|
{oid.T_numeric, "NUMERIC"},
|
||||||
|
{oid.T_date, "DATE"},
|
||||||
|
{oid.T_time, "TIME"},
|
||||||
|
{oid.T_timetz, "TIMETZ"},
|
||||||
|
{oid.T_timestamp, "TIMESTAMP"},
|
||||||
|
{oid.T_timestamptz, "TIMESTAMPTZ"},
|
||||||
|
{oid.T_bytea, "BYTEA"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tts {
|
||||||
|
dt := fieldDesc{OID: tt.typ}
|
||||||
|
if name := dt.Name(); name != tt.name {
|
||||||
|
t.Errorf("(%d) got: %s want: %s", i, name, tt.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDataType(t *testing.T) {
|
||||||
|
tts := []struct {
|
||||||
|
typ oid.Oid
|
||||||
|
kind reflect.Kind
|
||||||
|
}{
|
||||||
|
{oid.T_int8, reflect.Int64},
|
||||||
|
{oid.T_int4, reflect.Int32},
|
||||||
|
{oid.T_int2, reflect.Int16},
|
||||||
|
{oid.T_varchar, reflect.String},
|
||||||
|
{oid.T_text, reflect.String},
|
||||||
|
{oid.T_bool, reflect.Bool},
|
||||||
|
{oid.T_date, reflect.Struct},
|
||||||
|
{oid.T_time, reflect.Struct},
|
||||||
|
{oid.T_timetz, reflect.Struct},
|
||||||
|
{oid.T_timestamp, reflect.Struct},
|
||||||
|
{oid.T_timestamptz, reflect.Struct},
|
||||||
|
{oid.T_bytea, reflect.Slice},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tts {
|
||||||
|
dt := fieldDesc{OID: tt.typ}
|
||||||
|
if kind := dt.Type().Kind(); kind != tt.kind {
|
||||||
|
t.Errorf("(%d) got: %s want: %s", i, kind, tt.kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDataTypeLength(t *testing.T) {
|
||||||
|
tts := []struct {
|
||||||
|
typ oid.Oid
|
||||||
|
len int
|
||||||
|
mod int
|
||||||
|
length int64
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{oid.T_int4, 0, -1, 0, false},
|
||||||
|
{oid.T_varchar, 65535, 9, 5, true},
|
||||||
|
{oid.T_text, 65535, -1, math.MaxInt64, true},
|
||||||
|
{oid.T_bytea, 65535, -1, math.MaxInt64, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tts {
|
||||||
|
dt := fieldDesc{OID: tt.typ, Len: tt.len, Mod: tt.mod}
|
||||||
|
if l, k := dt.Length(); k != tt.ok || l != tt.length {
|
||||||
|
t.Errorf("(%d) got: %d, %t want: %d, %t", i, l, k, tt.length, tt.ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDataTypePrecisionScale(t *testing.T) {
|
||||||
|
tts := []struct {
|
||||||
|
typ oid.Oid
|
||||||
|
mod int
|
||||||
|
precision, scale int64
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{oid.T_int4, -1, 0, 0, false},
|
||||||
|
{oid.T_numeric, 589830, 9, 2, true},
|
||||||
|
{oid.T_text, -1, 0, 0, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tts {
|
||||||
|
dt := fieldDesc{OID: tt.typ, Mod: tt.mod}
|
||||||
|
p, s, k := dt.PrecisionScale()
|
||||||
|
if k != tt.ok {
|
||||||
|
t.Errorf("(%d) got: %t want: %t", i, k, tt.ok)
|
||||||
|
}
|
||||||
|
if p != tt.precision {
|
||||||
|
t.Errorf("(%d) wrong precision got: %d want: %d", i, p, tt.precision)
|
||||||
|
}
|
||||||
|
if s != tt.scale {
|
||||||
|
t.Errorf("(%d) wrong scale got: %d want: %d", i, s, tt.scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRowsColumnTypes(t *testing.T) {
|
||||||
|
columnTypesTests := []struct {
|
||||||
|
Name string
|
||||||
|
TypeName string
|
||||||
|
Length struct {
|
||||||
|
Len int64
|
||||||
|
OK bool
|
||||||
|
}
|
||||||
|
DecimalSize struct {
|
||||||
|
Precision int64
|
||||||
|
Scale int64
|
||||||
|
OK bool
|
||||||
|
}
|
||||||
|
ScanType reflect.Type
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "a",
|
||||||
|
TypeName: "INT4",
|
||||||
|
Length: struct {
|
||||||
|
Len int64
|
||||||
|
OK bool
|
||||||
|
}{
|
||||||
|
Len: 0,
|
||||||
|
OK: false,
|
||||||
|
},
|
||||||
|
DecimalSize: struct {
|
||||||
|
Precision int64
|
||||||
|
Scale int64
|
||||||
|
OK bool
|
||||||
|
}{
|
||||||
|
Precision: 0,
|
||||||
|
Scale: 0,
|
||||||
|
OK: false,
|
||||||
|
},
|
||||||
|
ScanType: reflect.TypeOf(int32(0)),
|
||||||
|
}, {
|
||||||
|
Name: "bar",
|
||||||
|
TypeName: "TEXT",
|
||||||
|
Length: struct {
|
||||||
|
Len int64
|
||||||
|
OK bool
|
||||||
|
}{
|
||||||
|
Len: math.MaxInt64,
|
||||||
|
OK: true,
|
||||||
|
},
|
||||||
|
DecimalSize: struct {
|
||||||
|
Precision int64
|
||||||
|
Scale int64
|
||||||
|
OK bool
|
||||||
|
}{
|
||||||
|
Precision: 0,
|
||||||
|
Scale: 0,
|
||||||
|
OK: false,
|
||||||
|
},
|
||||||
|
ScanType: reflect.TypeOf(""),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
db := openTestConn(t)
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
rows, err := db.Query("SELECT 1 AS a, text 'bar' AS bar, 1.28::numeric(9, 2) AS dec")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
columns, err := rows.ColumnTypes()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(columns) != 3 {
|
||||||
|
t.Errorf("expected 3 columns found %d", len(columns))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range columnTypesTests {
|
||||||
|
c := columns[i]
|
||||||
|
if c.Name() != tt.Name {
|
||||||
|
t.Errorf("(%d) got: %s, want: %s", i, c.Name(), tt.Name)
|
||||||
|
}
|
||||||
|
if c.DatabaseTypeName() != tt.TypeName {
|
||||||
|
t.Errorf("(%d) got: %s, want: %s", i, c.DatabaseTypeName(), tt.TypeName)
|
||||||
|
}
|
||||||
|
l, ok := c.Length()
|
||||||
|
if l != tt.Length.Len {
|
||||||
|
t.Errorf("(%d) got: %d, want: %d", i, l, tt.Length.Len)
|
||||||
|
}
|
||||||
|
if ok != tt.Length.OK {
|
||||||
|
t.Errorf("(%d) got: %t, want: %t", i, ok, tt.Length.OK)
|
||||||
|
}
|
||||||
|
p, s, ok := c.DecimalSize()
|
||||||
|
if p != tt.DecimalSize.Precision {
|
||||||
|
t.Errorf("(%d) got: %d, want: %d", i, p, tt.DecimalSize.Precision)
|
||||||
|
}
|
||||||
|
if s != tt.DecimalSize.Scale {
|
||||||
|
t.Errorf("(%d) got: %d, want: %d", i, s, tt.DecimalSize.Scale)
|
||||||
|
}
|
||||||
|
if ok != tt.DecimalSize.OK {
|
||||||
|
t.Errorf("(%d) got: %t, want: %t", i, ok, tt.DecimalSize.OK)
|
||||||
|
}
|
||||||
|
if c.ScanType() != tt.ScanType {
|
||||||
|
t.Errorf("(%d) got: %v, want: %v", i, c.ScanType(), tt.ScanType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
vendor/github.com/magiconair/properties/.travis.yml
сгенерированный
поставляемый
1
vendor/github.com/magiconair/properties/.travis.yml
сгенерированный
поставляемый
@@ -5,4 +5,5 @@ go:
|
|||||||
- 1.6.x
|
- 1.6.x
|
||||||
- 1.7.x
|
- 1.7.x
|
||||||
- 1.8.x
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
- tip
|
- tip
|
||||||
|
|||||||
5
vendor/github.com/magiconair/properties/CHANGELOG.md
сгенерированный
поставляемый
5
vendor/github.com/magiconair/properties/CHANGELOG.md
сгенерированный
поставляемый
@@ -1,5 +1,10 @@
|
|||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### Unreleased
|
||||||
|
|
||||||
|
* [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled
|
||||||
|
Thanks to @mgurov for the fix.
|
||||||
|
|
||||||
### [1.7.3](https://github.com/magiconair/properties/tags/v1.7.3) - 10 Jul 2017
|
### [1.7.3](https://github.com/magiconair/properties/tags/v1.7.3) - 10 Jul 2017
|
||||||
|
|
||||||
* [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
|
* [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
|
||||||
|
|||||||
3
vendor/github.com/magiconair/properties/properties.go
сгенерированный
поставляемый
3
vendor/github.com/magiconair/properties/properties.go
сгенерированный
поставляемый
@@ -511,6 +511,9 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
|
|||||||
if p.DisableExpansion {
|
if p.DisableExpansion {
|
||||||
prev, ok = p.Get(key)
|
prev, ok = p.Get(key)
|
||||||
p.m[key] = value
|
p.m[key] = value
|
||||||
|
if !ok {
|
||||||
|
p.k = append(p.k, key)
|
||||||
|
}
|
||||||
return prev, ok, nil
|
return prev, ok, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
vendor/github.com/magiconair/properties/properties_test.go
сгенерированный
поставляемый
13
vendor/github.com/magiconair/properties/properties_test.go
сгенерированный
поставляемый
@@ -458,6 +458,19 @@ func TestDisableExpansion(t *testing.T) {
|
|||||||
assert.Equal(t, p.MustGet("keyB"), "${keyA}")
|
assert.Equal(t, p.MustGet("keyB"), "${keyA}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDisableExpansionStillUpdatesKeys(t *testing.T) {
|
||||||
|
p := NewProperties()
|
||||||
|
p.MustSet("p1", "a")
|
||||||
|
assert.Equal(t, p.Keys(), []string{"p1"})
|
||||||
|
assert.Equal(t, p.String(), "p1 = a\n")
|
||||||
|
|
||||||
|
p.DisableExpansion = true
|
||||||
|
p.MustSet("p2", "b")
|
||||||
|
|
||||||
|
assert.Equal(t, p.Keys(), []string{"p1", "p2"})
|
||||||
|
assert.Equal(t, p.String(), "p1 = a\np2 = b\n")
|
||||||
|
}
|
||||||
|
|
||||||
func TestMustGet(t *testing.T) {
|
func TestMustGet(t *testing.T) {
|
||||||
input := "key = value\nkey2 = ghi"
|
input := "key = value\nkey2 = ghi"
|
||||||
p := mustParse(t, input)
|
p := mustParse(t, input)
|
||||||
|
|||||||
1
vendor/github.com/mattermost/html2text/LICENSE
сгенерированный
поставляемый
1
vendor/github.com/mattermost/html2text/LICENSE
сгенерированный
поставляемый
@@ -1,6 +1,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015 Jay Taylor
|
Copyright (c) 2015 Jay Taylor
|
||||||
|
Modified work: Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
1
vendor/github.com/miekg/dns/CONTRIBUTORS
сгенерированный
поставляемый
1
vendor/github.com/miekg/dns/CONTRIBUTORS
сгенерированный
поставляемый
@@ -7,3 +7,4 @@ Marek Majkowski
|
|||||||
Peter van Dijk
|
Peter van Dijk
|
||||||
Omri Bahumi
|
Omri Bahumi
|
||||||
Alex Sergeyev
|
Alex Sergeyev
|
||||||
|
James Hartig
|
||||||
|
|||||||
340
vendor/github.com/miekg/dns/client.go
сгенерированный
поставляемый
340
vendor/github.com/miekg/dns/client.go
сгенерированный
поставляемый
@@ -9,6 +9,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,11 +28,15 @@ type Conn struct {
|
|||||||
|
|
||||||
// A Client defines parameters for a DNS client.
|
// A Client defines parameters for a DNS client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
|
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
|
||||||
UDPSize uint16 // minimum receive buffer for UDP messages
|
UDPSize uint16 // minimum receive buffer for UDP messages
|
||||||
TLSConfig *tls.Config // TLS connection configuration
|
TLSConfig *tls.Config // TLS connection configuration
|
||||||
Timeout time.Duration // a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout and WriteTimeout when non-zero
|
Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more
|
||||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
|
||||||
|
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
|
||||||
|
// Client.Dialer) or context.Context.Deadline (see the deprecated ExchangeContext)
|
||||||
|
Timeout time.Duration
|
||||||
|
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
|
||||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
||||||
@@ -44,140 +49,11 @@ type Client struct {
|
|||||||
// will it fall back to TCP in case of truncation.
|
// will it fall back to TCP in case of truncation.
|
||||||
// See client.Exchange for more information on setting larger buffer sizes.
|
// See client.Exchange for more information on setting larger buffer sizes.
|
||||||
func Exchange(m *Msg, a string) (r *Msg, err error) {
|
func Exchange(m *Msg, a string) (r *Msg, err error) {
|
||||||
var co *Conn
|
client := Client{Net: "udp"}
|
||||||
co, err = DialTimeout("udp", a, dnsTimeout)
|
r, _, err = client.Exchange(m, a)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer co.Close()
|
|
||||||
|
|
||||||
opt := m.IsEdns0()
|
|
||||||
// If EDNS0 is used use that for size.
|
|
||||||
if opt != nil && opt.UDPSize() >= MinMsgSize {
|
|
||||||
co.UDPSize = opt.UDPSize()
|
|
||||||
}
|
|
||||||
|
|
||||||
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
|
|
||||||
if err = co.WriteMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
co.SetReadDeadline(time.Now().Add(dnsTimeout))
|
|
||||||
r, err = co.ReadMsg()
|
|
||||||
if err == nil && r.Id != m.Id {
|
|
||||||
err = ErrId
|
|
||||||
}
|
|
||||||
return r, err
|
return r, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExchangeContext performs a synchronous UDP query, like Exchange. It
|
|
||||||
// additionally obeys deadlines from the passed Context.
|
|
||||||
func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
|
|
||||||
// Combine context deadline with built-in timeout. Context chooses whichever
|
|
||||||
// is sooner.
|
|
||||||
timeoutCtx, cancel := context.WithTimeout(ctx, dnsTimeout)
|
|
||||||
defer cancel()
|
|
||||||
deadline, _ := timeoutCtx.Deadline()
|
|
||||||
|
|
||||||
co := new(Conn)
|
|
||||||
dialer := net.Dialer{}
|
|
||||||
co.Conn, err = dialer.DialContext(timeoutCtx, "udp", a)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer co.Conn.Close()
|
|
||||||
|
|
||||||
opt := m.IsEdns0()
|
|
||||||
// If EDNS0 is used use that for size.
|
|
||||||
if opt != nil && opt.UDPSize() >= MinMsgSize {
|
|
||||||
co.UDPSize = opt.UDPSize()
|
|
||||||
}
|
|
||||||
|
|
||||||
co.SetWriteDeadline(deadline)
|
|
||||||
if err = co.WriteMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
co.SetReadDeadline(deadline)
|
|
||||||
r, err = co.ReadMsg()
|
|
||||||
if err == nil && r.Id != m.Id {
|
|
||||||
err = ErrId
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExchangeConn performs a synchronous query. It sends the message m via the connection
|
|
||||||
// c and waits for a reply. The connection c is not closed by ExchangeConn.
|
|
||||||
// This function is going away, but can easily be mimicked:
|
|
||||||
//
|
|
||||||
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
|
||||||
// co.WriteMsg(m)
|
|
||||||
// in, _ := co.ReadMsg()
|
|
||||||
// co.Close()
|
|
||||||
//
|
|
||||||
func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
|
||||||
println("dns: this function is deprecated")
|
|
||||||
co := new(Conn)
|
|
||||||
co.Conn = c
|
|
||||||
if err = co.WriteMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
r, err = co.ReadMsg()
|
|
||||||
if err == nil && r.Id != m.Id {
|
|
||||||
err = ErrId
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exchange performs a synchronous query. It sends the message m to the address
|
|
||||||
// contained in a and waits for a reply. Basic use pattern with a *dns.Client:
|
|
||||||
//
|
|
||||||
// c := new(dns.Client)
|
|
||||||
// in, rtt, err := c.Exchange(message, "127.0.0.1:53")
|
|
||||||
//
|
|
||||||
// Exchange does not retry a failed query, nor will it fall back to TCP in
|
|
||||||
// case of truncation.
|
|
||||||
// It is up to the caller to create a message that allows for larger responses to be
|
|
||||||
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
|
|
||||||
// buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
|
|
||||||
// of 512 bytes.
|
|
||||||
func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
|
||||||
return c.ExchangeContext(context.Background(), m, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExchangeContext acts like Exchange, but honors the deadline on the provided
|
|
||||||
// context, if present. If there is both a context deadline and a configured
|
|
||||||
// timeout on the client, the earliest of the two takes effect.
|
|
||||||
func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (
|
|
||||||
r *Msg,
|
|
||||||
rtt time.Duration,
|
|
||||||
err error) {
|
|
||||||
if !c.SingleInflight {
|
|
||||||
return c.exchange(ctx, m, a)
|
|
||||||
}
|
|
||||||
// This adds a bunch of garbage, TODO(miek).
|
|
||||||
t := "nop"
|
|
||||||
if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
|
|
||||||
t = t1
|
|
||||||
}
|
|
||||||
cl := "nop"
|
|
||||||
if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
|
|
||||||
cl = cl1
|
|
||||||
}
|
|
||||||
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
|
|
||||||
return c.exchange(ctx, m, a)
|
|
||||||
})
|
|
||||||
if r != nil && shared {
|
|
||||||
r = r.Copy()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return r, rtt, err
|
|
||||||
}
|
|
||||||
return r, rtt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) dialTimeout() time.Duration {
|
func (c *Client) dialTimeout() time.Duration {
|
||||||
if c.Timeout != 0 {
|
if c.Timeout != 0 {
|
||||||
return c.Timeout
|
return c.Timeout
|
||||||
@@ -202,40 +78,87 @@ func (c *Client) writeTimeout() time.Duration {
|
|||||||
return dnsTimeout
|
return dnsTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) exchange(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
func (c *Client) Dial(address string) (conn *Conn, err error) {
|
||||||
var co *Conn
|
// create a new dialer with the appropriate timeout
|
||||||
|
var d net.Dialer
|
||||||
|
if c.Dialer == nil {
|
||||||
|
d = net.Dialer{}
|
||||||
|
} else {
|
||||||
|
d = net.Dialer(*c.Dialer)
|
||||||
|
}
|
||||||
|
d.Timeout = c.getTimeoutForRequest(c.writeTimeout())
|
||||||
|
|
||||||
network := "udp"
|
network := "udp"
|
||||||
tls := false
|
useTLS := false
|
||||||
|
|
||||||
switch c.Net {
|
switch c.Net {
|
||||||
case "tcp-tls":
|
case "tcp-tls":
|
||||||
network = "tcp"
|
network = "tcp"
|
||||||
tls = true
|
useTLS = true
|
||||||
case "tcp4-tls":
|
case "tcp4-tls":
|
||||||
network = "tcp4"
|
network = "tcp4"
|
||||||
tls = true
|
useTLS = true
|
||||||
case "tcp6-tls":
|
case "tcp6-tls":
|
||||||
network = "tcp6"
|
network = "tcp6"
|
||||||
tls = true
|
useTLS = true
|
||||||
default:
|
default:
|
||||||
if c.Net != "" {
|
if c.Net != "" {
|
||||||
network = c.Net
|
network = c.Net
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var deadline time.Time
|
conn = new(Conn)
|
||||||
if c.Timeout != 0 {
|
if useTLS {
|
||||||
deadline = time.Now().Add(c.Timeout)
|
conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
|
||||||
}
|
|
||||||
|
|
||||||
dialDeadline := deadlineOrTimeoutOrCtx(ctx, deadline, c.dialTimeout())
|
|
||||||
dialTimeout := dialDeadline.Sub(time.Now())
|
|
||||||
|
|
||||||
if tls {
|
|
||||||
co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, dialTimeout)
|
|
||||||
} else {
|
} else {
|
||||||
co, err = DialTimeout(network, a, dialTimeout)
|
conn.Conn, err = d.Dial(network, address)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exchange performs a synchronous query. It sends the message m to the address
|
||||||
|
// contained in a and waits for a reply. Basic use pattern with a *dns.Client:
|
||||||
|
//
|
||||||
|
// c := new(dns.Client)
|
||||||
|
// in, rtt, err := c.Exchange(message, "127.0.0.1:53")
|
||||||
|
//
|
||||||
|
// Exchange does not retry a failed query, nor will it fall back to TCP in
|
||||||
|
// case of truncation.
|
||||||
|
// It is up to the caller to create a message that allows for larger responses to be
|
||||||
|
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
|
||||||
|
// buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
|
||||||
|
// of 512 bytes
|
||||||
|
// To specify a local address or a timeout, the caller has to set the `Client.Dialer`
|
||||||
|
// attribute appropriately
|
||||||
|
func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
|
||||||
|
if !c.SingleInflight {
|
||||||
|
return c.exchange(m, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
t := "nop"
|
||||||
|
if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
|
||||||
|
t = t1
|
||||||
|
}
|
||||||
|
cl := "nop"
|
||||||
|
if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
|
||||||
|
cl = cl1
|
||||||
|
}
|
||||||
|
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
|
||||||
|
return c.exchange(m, address)
|
||||||
|
})
|
||||||
|
if r != nil && shared {
|
||||||
|
r = r.Copy()
|
||||||
|
}
|
||||||
|
return r, rtt, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||||
|
var co *Conn
|
||||||
|
|
||||||
|
co, err = c.Dial(a)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -253,12 +176,13 @@ func (c *Client) exchange(ctx context.Context, m *Msg, a string) (r *Msg, rtt ti
|
|||||||
}
|
}
|
||||||
|
|
||||||
co.TsigSecret = c.TsigSecret
|
co.TsigSecret = c.TsigSecret
|
||||||
co.SetWriteDeadline(deadlineOrTimeoutOrCtx(ctx, deadline, c.writeTimeout()))
|
// write with the appropriate write timeout
|
||||||
|
co.SetWriteDeadline(time.Now().Add(c.getTimeoutForRequest(c.writeTimeout())))
|
||||||
if err = co.WriteMsg(m); err != nil {
|
if err = co.WriteMsg(m); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
co.SetReadDeadline(deadlineOrTimeoutOrCtx(ctx, deadline, c.readTimeout()))
|
co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout())))
|
||||||
r, err = co.ReadMsg()
|
r, err = co.ReadMsg()
|
||||||
if err == nil && r.Id != m.Id {
|
if err == nil && r.Id != m.Id {
|
||||||
err = ErrId
|
err = ErrId
|
||||||
@@ -352,7 +276,7 @@ func tcpMsgLen(t io.Reader) (int, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// As seen with my local router/switch, retursn 1 byte on the above read,
|
// As seen with my local router/switch, returns 1 byte on the above read,
|
||||||
// resulting a a ShortRead. Just write it out (instead of loop) and read the
|
// resulting a a ShortRead. Just write it out (instead of loop) and read the
|
||||||
// other byte.
|
// other byte.
|
||||||
if n == 1 {
|
if n == 1 {
|
||||||
@@ -467,6 +391,24 @@ func (co *Conn) Write(p []byte) (n int, err error) {
|
|||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the appropriate timeout for a specific request
|
||||||
|
func (c *Client) getTimeoutForRequest(timeout time.Duration) time.Duration {
|
||||||
|
var requestTimeout time.Duration
|
||||||
|
if c.Timeout != 0 {
|
||||||
|
requestTimeout = c.Timeout
|
||||||
|
} else {
|
||||||
|
requestTimeout = timeout
|
||||||
|
}
|
||||||
|
// net.Dialer.Timeout has priority if smaller than the timeouts computed so
|
||||||
|
// far
|
||||||
|
if c.Dialer != nil && c.Dialer.Timeout != 0 {
|
||||||
|
if c.Dialer.Timeout < requestTimeout {
|
||||||
|
requestTimeout = c.Dialer.Timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return requestTimeout
|
||||||
|
}
|
||||||
|
|
||||||
// Dial connects to the address on the named network.
|
// Dial connects to the address on the named network.
|
||||||
func Dial(network, address string) (conn *Conn, err error) {
|
func Dial(network, address string) (conn *Conn, err error) {
|
||||||
conn = new(Conn)
|
conn = new(Conn)
|
||||||
@@ -477,10 +419,44 @@ func Dial(network, address string) (conn *Conn, err error) {
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExchangeContext performs a synchronous UDP query, like Exchange. It
|
||||||
|
// additionally obeys deadlines from the passed Context.
|
||||||
|
func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
|
||||||
|
client := Client{Net: "udp"}
|
||||||
|
r, _, err = client.ExchangeContext(ctx, m, a)
|
||||||
|
// ignorint rtt to leave the original ExchangeContext API unchanged, but
|
||||||
|
// this function will go away
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExchangeConn performs a synchronous query. It sends the message m via the connection
|
||||||
|
// c and waits for a reply. The connection c is not closed by ExchangeConn.
|
||||||
|
// This function is going away, but can easily be mimicked:
|
||||||
|
//
|
||||||
|
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
||||||
|
// co.WriteMsg(m)
|
||||||
|
// in, _ := co.ReadMsg()
|
||||||
|
// co.Close()
|
||||||
|
//
|
||||||
|
func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
||||||
|
println("dns: ExchangeConn: this function is deprecated")
|
||||||
|
co := new(Conn)
|
||||||
|
co.Conn = c
|
||||||
|
if err = co.WriteMsg(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r, err = co.ReadMsg()
|
||||||
|
if err == nil && r.Id != m.Id {
|
||||||
|
err = ErrId
|
||||||
|
}
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
// DialTimeout acts like Dial but takes a timeout.
|
// DialTimeout acts like Dial but takes a timeout.
|
||||||
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
||||||
conn = new(Conn)
|
|
||||||
conn.Conn, err = net.DialTimeout(network, address, timeout)
|
client := Client{Net: "udp", Dialer: &net.Dialer{Timeout: timeout}}
|
||||||
|
conn, err = client.Dial(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -489,8 +465,12 @@ func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, er
|
|||||||
|
|
||||||
// DialWithTLS connects to the address on the named network with TLS.
|
// DialWithTLS connects to the address on the named network with TLS.
|
||||||
func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
|
func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
|
||||||
conn = new(Conn)
|
if !strings.HasSuffix(network, "-tls") {
|
||||||
conn.Conn, err = tls.Dial(network, address, tlsConfig)
|
network += "-tls"
|
||||||
|
}
|
||||||
|
client := Client{Net: network, TLSConfig: tlsConfig}
|
||||||
|
conn, err = client.Dial(address)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -499,33 +479,29 @@ func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, er
|
|||||||
|
|
||||||
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
|
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
|
||||||
func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
|
func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
|
||||||
var dialer net.Dialer
|
if !strings.HasSuffix(network, "-tls") {
|
||||||
dialer.Timeout = timeout
|
network += "-tls"
|
||||||
|
}
|
||||||
conn = new(Conn)
|
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
|
||||||
conn.Conn, err = tls.DialWithDialer(&dialer, network, address, tlsConfig)
|
conn, err = client.Dial(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// deadlineOrTimeout chooses between the provided deadline and timeout
|
// ExchangeContext acts like Exchange, but honors the deadline on the provided
|
||||||
// by always preferring the deadline so long as it's non-zero (regardless
|
// context, if present. If there is both a context deadline and a configured
|
||||||
// of which is bigger), and returns the equivalent deadline value.
|
// timeout on the client, the earliest of the two takes effect.
|
||||||
func deadlineOrTimeout(deadline time.Time, timeout time.Duration) time.Time {
|
func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||||
if deadline.IsZero() {
|
var timeout time.Duration
|
||||||
return time.Now().Add(timeout)
|
if deadline, ok := ctx.Deadline(); !ok {
|
||||||
|
timeout = 0
|
||||||
|
} else {
|
||||||
|
timeout = deadline.Sub(time.Now())
|
||||||
}
|
}
|
||||||
return deadline
|
// not passing the context to the underlying calls, as the API does not support
|
||||||
}
|
// context. For timeouts you should set up Client.Dialer and call Client.Exchange.
|
||||||
|
c.Dialer = &net.Dialer{Timeout: timeout}
|
||||||
// deadlineOrTimeoutOrCtx returns the earliest of: a context deadline, or the
|
return c.Exchange(m, a)
|
||||||
// output of deadlineOrtimeout.
|
|
||||||
func deadlineOrTimeoutOrCtx(ctx context.Context, deadline time.Time, timeout time.Duration) time.Time {
|
|
||||||
result := deadlineOrTimeout(deadline, timeout)
|
|
||||||
if ctxDeadline, ok := ctx.Deadline(); ok && ctxDeadline.Before(result) {
|
|
||||||
result = ctxDeadline
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|||||||
168
vendor/github.com/miekg/dns/client_test.go
сгенерированный
поставляемый
168
vendor/github.com/miekg/dns/client_test.go
сгенерированный
поставляемый
@@ -11,6 +11,29 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestDialUDP(t *testing.T) {
|
||||||
|
HandleFunc("miek.nl.", HelloServer)
|
||||||
|
defer HandleRemove("miek.nl.")
|
||||||
|
|
||||||
|
s, addrstr, err := RunLocalUDPServer("[::1]:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to run test server: %v", err)
|
||||||
|
}
|
||||||
|
defer s.Shutdown()
|
||||||
|
|
||||||
|
m := new(Msg)
|
||||||
|
m.SetQuestion("miek.nl.", TypeSOA)
|
||||||
|
|
||||||
|
c := new(Client)
|
||||||
|
conn, err := c.Dial(addrstr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to dial: %v", err)
|
||||||
|
}
|
||||||
|
if conn == nil {
|
||||||
|
t.Fatalf("conn is nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestClientSync(t *testing.T) {
|
func TestClientSync(t *testing.T) {
|
||||||
HandleFunc("miek.nl.", HelloServer)
|
HandleFunc("miek.nl.", HelloServer)
|
||||||
defer HandleRemove("miek.nl.")
|
defer HandleRemove("miek.nl.")
|
||||||
@@ -27,9 +50,12 @@ func TestClientSync(t *testing.T) {
|
|||||||
c := new(Client)
|
c := new(Client)
|
||||||
r, _, err := c.Exchange(m, addrstr)
|
r, _, err := c.Exchange(m, addrstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to exchange: %v", err)
|
t.Fatalf("failed to exchange: %v", err)
|
||||||
}
|
}
|
||||||
if r != nil && r.Rcode != RcodeSuccess {
|
if r == nil {
|
||||||
|
t.Fatal("response is nil")
|
||||||
|
}
|
||||||
|
if r.Rcode != RcodeSuccess {
|
||||||
t.Errorf("failed to get an valid answer\n%v", r)
|
t.Errorf("failed to get an valid answer\n%v", r)
|
||||||
}
|
}
|
||||||
// And now with plain Exchange().
|
// And now with plain Exchange().
|
||||||
@@ -42,7 +68,42 @@ func TestClientSync(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientTLSSync(t *testing.T) {
|
func TestClientLocalAddress(t *testing.T) {
|
||||||
|
HandleFunc("miek.nl.", HelloServerEchoAddrPort)
|
||||||
|
defer HandleRemove("miek.nl.")
|
||||||
|
|
||||||
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to run test server: %v", err)
|
||||||
|
}
|
||||||
|
defer s.Shutdown()
|
||||||
|
|
||||||
|
m := new(Msg)
|
||||||
|
m.SetQuestion("miek.nl.", TypeSOA)
|
||||||
|
|
||||||
|
c := new(Client)
|
||||||
|
laddr := net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12345, Zone: ""}
|
||||||
|
c.Dialer = &net.Dialer{LocalAddr: &laddr}
|
||||||
|
r, _, err := c.Exchange(m, addrstr)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to exchange: %v", err)
|
||||||
|
}
|
||||||
|
if r != nil && r.Rcode != RcodeSuccess {
|
||||||
|
t.Errorf("failed to get an valid answer\n%v", r)
|
||||||
|
}
|
||||||
|
if len(r.Extra) != 1 {
|
||||||
|
t.Errorf("failed to get additional answers\n%v", r)
|
||||||
|
}
|
||||||
|
txt := r.Extra[0].(*TXT)
|
||||||
|
if txt == nil {
|
||||||
|
t.Errorf("invalid TXT response\n%v", txt)
|
||||||
|
}
|
||||||
|
if len(txt.Txt) != 1 || txt.Txt[0] != "127.0.0.1:12345" {
|
||||||
|
t.Errorf("invalid TXT response\n%v", txt.Txt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientTLSSyncV4(t *testing.T) {
|
||||||
HandleFunc("miek.nl.", HelloServer)
|
HandleFunc("miek.nl.", HelloServer)
|
||||||
defer HandleRemove("miek.nl.")
|
defer HandleRemove("miek.nl.")
|
||||||
|
|
||||||
@@ -65,6 +126,8 @@ func TestClientTLSSync(t *testing.T) {
|
|||||||
m.SetQuestion("miek.nl.", TypeSOA)
|
m.SetQuestion("miek.nl.", TypeSOA)
|
||||||
|
|
||||||
c := new(Client)
|
c := new(Client)
|
||||||
|
|
||||||
|
// test tcp-tls
|
||||||
c.Net = "tcp-tls"
|
c.Net = "tcp-tls"
|
||||||
c.TLSConfig = &tls.Config{
|
c.TLSConfig = &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
@@ -72,9 +135,88 @@ func TestClientTLSSync(t *testing.T) {
|
|||||||
|
|
||||||
r, _, err := c.Exchange(m, addrstr)
|
r, _, err := c.Exchange(m, addrstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to exchange: %v", err)
|
t.Fatalf("failed to exchange: %v", err)
|
||||||
}
|
}
|
||||||
if r != nil && r.Rcode != RcodeSuccess {
|
if r == nil {
|
||||||
|
t.Fatal("response is nil")
|
||||||
|
}
|
||||||
|
if r.Rcode != RcodeSuccess {
|
||||||
|
t.Errorf("failed to get an valid answer\n%v", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test tcp4-tls
|
||||||
|
c.Net = "tcp4-tls"
|
||||||
|
c.TLSConfig = &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
r, _, err = c.Exchange(m, addrstr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to exchange: %v", err)
|
||||||
|
}
|
||||||
|
if r == nil {
|
||||||
|
t.Fatal("response is nil")
|
||||||
|
}
|
||||||
|
if r.Rcode != RcodeSuccess {
|
||||||
|
t.Errorf("failed to get an valid answer\n%v", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientTLSSyncV6(t *testing.T) {
|
||||||
|
HandleFunc("miek.nl.", HelloServer)
|
||||||
|
defer HandleRemove("miek.nl.")
|
||||||
|
|
||||||
|
cert, err := tls.X509KeyPair(CertPEMBlock, KeyPEMBlock)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to build certificate: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
config := tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
s, addrstr, err := RunLocalTLSServer("[::1]:0", &config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to run test server: %v", err)
|
||||||
|
}
|
||||||
|
defer s.Shutdown()
|
||||||
|
|
||||||
|
m := new(Msg)
|
||||||
|
m.SetQuestion("miek.nl.", TypeSOA)
|
||||||
|
|
||||||
|
c := new(Client)
|
||||||
|
|
||||||
|
// test tcp-tls
|
||||||
|
c.Net = "tcp-tls"
|
||||||
|
c.TLSConfig = &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
r, _, err := c.Exchange(m, addrstr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to exchange: %v", err)
|
||||||
|
}
|
||||||
|
if r == nil {
|
||||||
|
t.Fatal("response is nil")
|
||||||
|
}
|
||||||
|
if r.Rcode != RcodeSuccess {
|
||||||
|
t.Errorf("failed to get an valid answer\n%v", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test tcp6-tls
|
||||||
|
c.Net = "tcp6-tls"
|
||||||
|
c.TLSConfig = &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
r, _, err = c.Exchange(m, addrstr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to exchange: %v", err)
|
||||||
|
}
|
||||||
|
if r == nil {
|
||||||
|
t.Fatal("response is nil")
|
||||||
|
}
|
||||||
|
if r.Rcode != RcodeSuccess {
|
||||||
t.Errorf("failed to get an valid answer\n%v", r)
|
t.Errorf("failed to get an valid answer\n%v", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,11 +262,11 @@ func TestClientEDNS0(t *testing.T) {
|
|||||||
c := new(Client)
|
c := new(Client)
|
||||||
r, _, err := c.Exchange(m, addrstr)
|
r, _, err := c.Exchange(m, addrstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to exchange: %v", err)
|
t.Fatalf("failed to exchange: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r != nil && r.Rcode != RcodeSuccess {
|
if r != nil && r.Rcode != RcodeSuccess {
|
||||||
t.Errorf("failed to get an valid answer\n%v", r)
|
t.Errorf("failed to get a valid answer\n%v", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,11 +313,14 @@ func TestClientEDNS0Local(t *testing.T) {
|
|||||||
c := new(Client)
|
c := new(Client)
|
||||||
r, _, err := c.Exchange(m, addrstr)
|
r, _, err := c.Exchange(m, addrstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to exchange: %s", err)
|
t.Fatalf("failed to exchange: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r != nil && r.Rcode != RcodeSuccess {
|
if r == nil {
|
||||||
t.Error("failed to get a valid answer")
|
t.Fatal("response is nil")
|
||||||
|
}
|
||||||
|
if r.Rcode != RcodeSuccess {
|
||||||
|
t.Fatal("failed to get a valid answer")
|
||||||
t.Logf("%v\n", r)
|
t.Logf("%v\n", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,6 +658,9 @@ func TestConcurrentExchanges(t *testing.T) {
|
|||||||
for i := 0; i < len(r); i++ {
|
for i := 0; i < len(r); i++ {
|
||||||
go func(i int) {
|
go func(i int) {
|
||||||
r[i], _, _ = c.Exchange(m.Copy(), addrstr)
|
r[i], _, _ = c.Exchange(m.Copy(), addrstr)
|
||||||
|
if r[i] == nil {
|
||||||
|
t.Fatalf("response %d is nil", i)
|
||||||
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(i)
|
}(i)
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/github.com/miekg/dns/dnsutil/util.go
сгенерированный
поставляемый
2
vendor/github.com/miekg/dns/dnsutil/util.go
сгенерированный
поставляемый
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddDomain adds origin to s if s is not already a FQDN.
|
// AddOrigin adds origin to s if s is not already a FQDN.
|
||||||
// Note that the result may not be a FQDN. If origin does not end
|
// Note that the result may not be a FQDN. If origin does not end
|
||||||
// with a ".", the result won't either.
|
// with a ".", the result won't either.
|
||||||
// This implements the zonefile convention (specified in RFC 1035,
|
// This implements the zonefile convention (specified in RFC 1035,
|
||||||
|
|||||||
30
vendor/github.com/miekg/dns/doc.go
сгенерированный
поставляемый
30
vendor/github.com/miekg/dns/doc.go
сгенерированный
поставляемый
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Package dns implements a full featured interface to the Domain Name System.
|
Package dns implements a full featured interface to the Domain Name System.
|
||||||
Server- and client-side programming is supported.
|
Server- and client-side programming is supported.
|
||||||
The package allows complete control over what is send out to the DNS. The package
|
The package allows complete control over what is sent out to the DNS. The package
|
||||||
API follows the less-is-more principle, by presenting a small, clean interface.
|
API follows the less-is-more principle, by presenting a small, clean interface.
|
||||||
|
|
||||||
The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
|
The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
|
||||||
@@ -14,7 +14,7 @@ Basic usage pattern for creating a new resource record:
|
|||||||
|
|
||||||
r := new(dns.MX)
|
r := new(dns.MX)
|
||||||
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
|
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
|
||||||
Class: dns.ClassINET, Ttl: 3600}
|
Class: dns.ClassINET, Ttl: 3600}
|
||||||
r.Preference = 10
|
r.Preference = 10
|
||||||
r.Mx = "mx.miek.nl."
|
r.Mx = "mx.miek.nl."
|
||||||
|
|
||||||
@@ -22,16 +22,16 @@ Or directly from a string:
|
|||||||
|
|
||||||
mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
|
mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
|
||||||
|
|
||||||
Or when the default TTL (3600) and class (IN) suit you:
|
Or when the default origin (.) and TTL (3600) and class (IN) suit you:
|
||||||
|
|
||||||
mx, err := dns.NewRR("miek.nl. MX 10 mx.miek.nl.")
|
mx, err := dns.NewRR("miek.nl MX 10 mx.miek.nl")
|
||||||
|
|
||||||
Or even:
|
Or even:
|
||||||
|
|
||||||
mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
|
mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
|
||||||
|
|
||||||
In the DNS messages are exchanged, these messages contain resource
|
In the DNS messages are exchanged, these messages contain resource
|
||||||
records (sets). Use pattern for creating a message:
|
records (sets). Use pattern for creating a message:
|
||||||
|
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetQuestion("miek.nl.", dns.TypeMX)
|
m.SetQuestion("miek.nl.", dns.TypeMX)
|
||||||
@@ -51,7 +51,7 @@ The following is slightly more verbose, but more flexible:
|
|||||||
m1.Question = make([]dns.Question, 1)
|
m1.Question = make([]dns.Question, 1)
|
||||||
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
|
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
|
||||||
|
|
||||||
After creating a message it can be send.
|
After creating a message it can be sent.
|
||||||
Basic use pattern for synchronous querying the DNS at a
|
Basic use pattern for synchronous querying the DNS at a
|
||||||
server configured on 127.0.0.1 and port 53:
|
server configured on 127.0.0.1 and port 53:
|
||||||
|
|
||||||
@@ -63,7 +63,23 @@ class) is as easy as setting:
|
|||||||
|
|
||||||
c.SingleInflight = true
|
c.SingleInflight = true
|
||||||
|
|
||||||
If these "advanced" features are not needed, a simple UDP query can be send,
|
More advanced options are availabe using a net.Dialer and the corresponding API.
|
||||||
|
For example it is possible to set a timeout, or to specify a source IP address
|
||||||
|
and port to use for the connection:
|
||||||
|
|
||||||
|
c := new(dns.Client)
|
||||||
|
laddr := net.UDPAddr{
|
||||||
|
IP: net.ParseIP("[::1]"),
|
||||||
|
Port: 12345,
|
||||||
|
Zone: "",
|
||||||
|
}
|
||||||
|
d := net.Dialer{
|
||||||
|
Timeout: 200 * time.Millisecond,
|
||||||
|
LocalAddr: &laddr,
|
||||||
|
}
|
||||||
|
in, rtt, err := c.ExchangeWithDialer(&d, m1, "8.8.8.8:53")
|
||||||
|
|
||||||
|
If these "advanced" features are not needed, a simple UDP query can be sent,
|
||||||
with:
|
with:
|
||||||
|
|
||||||
in, err := dns.Exchange(m1, "127.0.0.1:53")
|
in, err := dns.Exchange(m1, "127.0.0.1:53")
|
||||||
|
|||||||
15
vendor/github.com/miekg/dns/edns.go
сгенерированный
поставляемый
15
vendor/github.com/miekg/dns/edns.go
сгенерированный
поставляемый
@@ -21,6 +21,7 @@ const (
|
|||||||
EDNS0EXPIRE = 0x9 // EDNS0 expire
|
EDNS0EXPIRE = 0x9 // EDNS0 expire
|
||||||
EDNS0COOKIE = 0xa // EDNS0 Cookie
|
EDNS0COOKIE = 0xa // EDNS0 Cookie
|
||||||
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (RFC7828)
|
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (RFC7828)
|
||||||
|
EDNS0PADDING = 0xc // EDNS0 padding (RFC7830)
|
||||||
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
|
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
|
||||||
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
|
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
|
||||||
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
|
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
|
||||||
@@ -74,6 +75,8 @@ func (rr *OPT) String() string {
|
|||||||
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
|
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
|
||||||
case *EDNS0_LOCAL:
|
case *EDNS0_LOCAL:
|
||||||
s += "\n; LOCAL OPT: " + o.String()
|
s += "\n; LOCAL OPT: " + o.String()
|
||||||
|
case *EDNS0_PADDING:
|
||||||
|
s += "\n; PADDING: " + o.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
@@ -595,3 +598,15 @@ func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EDNS0_PADDING option is used to add padding to a request/response. The default
|
||||||
|
// value of padding SHOULD be 0x0 but other values MAY be used, for instance if
|
||||||
|
// compression is applied before encryption which may break signatures.
|
||||||
|
type EDNS0_PADDING struct {
|
||||||
|
Padding []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
|
||||||
|
func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
|
||||||
|
func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
|
||||||
|
func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) }
|
||||||
|
|||||||
7
vendor/github.com/miekg/dns/internal/socket/cmsghdr.go
сгенерированный
поставляемый
Обычный файл
7
vendor/github.com/miekg/dns/internal/socket/cmsghdr.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,7 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
func (h *cmsghdr) len() int { return int(h.Len) }
|
||||||
|
func (h *cmsghdr) lvl() int { return int(h.Level) }
|
||||||
|
func (h *cmsghdr) typ() int { return int(h.Type) }
|
||||||
20
vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go
сгенерированный
поставляемый
Обычный файл
20
vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_32bit.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,20 @@
|
|||||||
|
// +build arm mips mipsle 386
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type cmsghdr struct {
|
||||||
|
Len uint32
|
||||||
|
Level int32
|
||||||
|
Type int32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofCmsghdr = 0xc
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint32(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
||||||
20
vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go
сгенерированный
поставляемый
Обычный файл
20
vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,20 @@
|
|||||||
|
// +build arm64 amd64 ppc64 ppc64le mips64 mips64le s390x
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type cmsghdr struct {
|
||||||
|
Len uint64
|
||||||
|
Level int32
|
||||||
|
Type int32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofCmsghdr = 0x10
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {
|
||||||
|
h.Len = uint64(l)
|
||||||
|
h.Level = int32(lvl)
|
||||||
|
h.Type = int32(typ)
|
||||||
|
}
|
||||||
13
vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go
сгенерированный
поставляемый
Обычный файл
13
vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,13 @@
|
|||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
type cmsghdr struct{}
|
||||||
|
|
||||||
|
const sizeofCmsghdr = 0
|
||||||
|
|
||||||
|
func (h *cmsghdr) len() int { return 0 }
|
||||||
|
func (h *cmsghdr) lvl() int { return 0 }
|
||||||
|
func (h *cmsghdr) typ() int { return 0 }
|
||||||
|
|
||||||
|
func (h *cmsghdr) set(l, lvl, typ int) {}
|
||||||
118
vendor/github.com/miekg/dns/internal/socket/controlmessage.go
сгенерированный
поставляемый
Обычный файл
118
vendor/github.com/miekg/dns/internal/socket/controlmessage.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,118 @@
|
|||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func controlHeaderLen() int {
|
||||||
|
return roundup(sizeofCmsghdr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func controlMessageLen(dataLen int) int {
|
||||||
|
return roundup(sizeofCmsghdr) + dataLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the whole length of control message.
|
||||||
|
func ControlMessageSpace(dataLen int) int {
|
||||||
|
return roundup(sizeofCmsghdr) + roundup(dataLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ControlMessage represents the head message in a stream of control
|
||||||
|
// messages.
|
||||||
|
//
|
||||||
|
// A control message comprises of a header, data and a few padding
|
||||||
|
// fields to conform to the interface to the kernel.
|
||||||
|
//
|
||||||
|
// See RFC 3542 for further information.
|
||||||
|
type ControlMessage []byte
|
||||||
|
|
||||||
|
// Data returns the data field of the control message at the head.
|
||||||
|
func (m ControlMessage) Data(dataLen int) []byte {
|
||||||
|
l := controlHeaderLen()
|
||||||
|
if len(m) < l || len(m) < l+dataLen {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return m[l : l+dataLen]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseHeader parses and returns the header fields of the control
|
||||||
|
// message at the head.
|
||||||
|
func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
|
||||||
|
l := controlHeaderLen()
|
||||||
|
if len(m) < l {
|
||||||
|
return 0, 0, 0, errors.New("short message")
|
||||||
|
}
|
||||||
|
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
|
||||||
|
return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the control message at the next.
|
||||||
|
func (m ControlMessage) Next(dataLen int) ControlMessage {
|
||||||
|
l := ControlMessageSpace(dataLen)
|
||||||
|
if len(m) < l {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return m[l:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalHeader marshals the header fields of the control message at
|
||||||
|
// the head.
|
||||||
|
func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
|
||||||
|
if len(m) < controlHeaderLen() {
|
||||||
|
return errors.New("short message")
|
||||||
|
}
|
||||||
|
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
|
||||||
|
h.set(controlMessageLen(dataLen), lvl, typ)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal marshals the control message at the head, and returns the next
|
||||||
|
// control message.
|
||||||
|
func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
|
||||||
|
l := len(data)
|
||||||
|
if len(m) < ControlMessageSpace(l) {
|
||||||
|
return nil, errors.New("short message")
|
||||||
|
}
|
||||||
|
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
|
||||||
|
h.set(controlMessageLen(l), lvl, typ)
|
||||||
|
if l > 0 {
|
||||||
|
copy(m.Data(l), data)
|
||||||
|
}
|
||||||
|
return m.Next(l), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses as a single or multiple control messages.
|
||||||
|
func (m ControlMessage) Parse() ([]ControlMessage, error) {
|
||||||
|
var ms []ControlMessage
|
||||||
|
for len(m) >= controlHeaderLen() {
|
||||||
|
h := (*cmsghdr)(unsafe.Pointer(&m[0]))
|
||||||
|
l := h.len()
|
||||||
|
if l <= 0 {
|
||||||
|
return nil, errors.New("invalid header length")
|
||||||
|
}
|
||||||
|
if uint64(l) < uint64(controlHeaderLen()) {
|
||||||
|
return nil, errors.New("invalid message length")
|
||||||
|
}
|
||||||
|
if uint64(l) > uint64(len(m)) {
|
||||||
|
return nil, errors.New("short buffer")
|
||||||
|
}
|
||||||
|
ms = append(ms, ControlMessage(m[:l]))
|
||||||
|
ll := l - controlHeaderLen()
|
||||||
|
if len(m) >= ControlMessageSpace(ll) {
|
||||||
|
m = m[ControlMessageSpace(ll):]
|
||||||
|
} else {
|
||||||
|
m = m[controlMessageLen(ll):]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ms, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewControlMessage returns a new stream of control messages.
|
||||||
|
func NewControlMessage(dataLen []int) ControlMessage {
|
||||||
|
var l int
|
||||||
|
for i := range dataLen {
|
||||||
|
l += ControlMessageSpace(dataLen[i])
|
||||||
|
}
|
||||||
|
return make([]byte, l)
|
||||||
|
}
|
||||||
103
vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go
сгенерированный
поставляемый
Обычный файл
103
vendor/github.com/miekg/dns/internal/socket/controlmessage_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,103 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockControl struct {
|
||||||
|
Level int
|
||||||
|
Type int
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestControlMessage(t *testing.T) {
|
||||||
|
for _, tt := range []struct {
|
||||||
|
cs []mockControl
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 1, Type: 1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 2, Type: 2, Data: []byte{0xfe}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]mockControl{
|
||||||
|
{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
|
||||||
|
{Level: 2, Type: 2, Data: []byte{0xfe}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
var w []byte
|
||||||
|
var tailPadLen int
|
||||||
|
mm := NewControlMessage([]int{0})
|
||||||
|
for i, c := range tt.cs {
|
||||||
|
m := NewControlMessage([]int{len(c.Data)})
|
||||||
|
l := len(m) - len(mm)
|
||||||
|
if i == len(tt.cs)-1 && l > len(c.Data) {
|
||||||
|
tailPadLen = l - len(c.Data)
|
||||||
|
}
|
||||||
|
w = append(w, m...)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
ww := make([]byte, len(w))
|
||||||
|
copy(ww, w)
|
||||||
|
m := ControlMessage(ww)
|
||||||
|
for _, c := range tt.cs {
|
||||||
|
if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
|
||||||
|
t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
|
||||||
|
}
|
||||||
|
copy(m.Data(len(c.Data)), c.Data)
|
||||||
|
m = m.Next(len(c.Data))
|
||||||
|
}
|
||||||
|
m = ControlMessage(w)
|
||||||
|
for _, c := range tt.cs {
|
||||||
|
m, err = m.Marshal(c.Level, c.Type, c.Data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !bytes.Equal(ww, w) {
|
||||||
|
t.Fatalf("got %#v; want %#v", ww, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
ws := [][]byte{w}
|
||||||
|
if tailPadLen > 0 {
|
||||||
|
// Test a message with no tail padding.
|
||||||
|
nopad := w[:len(w)-tailPadLen]
|
||||||
|
ws = append(ws, [][]byte{nopad}...)
|
||||||
|
}
|
||||||
|
for _, w := range ws {
|
||||||
|
ms, err := ControlMessage(w).Parse()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("(%v).Parse() = %v", tt.cs, err)
|
||||||
|
}
|
||||||
|
for i, m := range ms {
|
||||||
|
lvl, typ, dataLen, err := m.ParseHeader()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
|
||||||
|
}
|
||||||
|
if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
|
||||||
|
t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
vendor/github.com/miekg/dns/internal/socket/socket.go
сгенерированный
поставляемый
Обычный файл
4
vendor/github.com/miekg/dns/internal/socket/socket.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,4 @@
|
|||||||
|
// Package socket contains ControlMessage parsing code from
|
||||||
|
// golang.org/x/net/internal/socket. Instead of supporting all possible
|
||||||
|
// architectures, we're only supporting linux 32/64 bit.
|
||||||
|
package socket
|
||||||
14
vendor/github.com/miekg/dns/internal/socket/sys.go
сгенерированный
поставляемый
Обычный файл
14
vendor/github.com/miekg/dns/internal/socket/sys.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,14 @@
|
|||||||
|
package socket
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
var (
|
||||||
|
kernelAlign = func() int {
|
||||||
|
var p uintptr
|
||||||
|
return int(unsafe.Sizeof(p))
|
||||||
|
}()
|
||||||
|
)
|
||||||
|
|
||||||
|
func roundup(l int) int {
|
||||||
|
return (l + kernelAlign - 1) & ^(kernelAlign - 1)
|
||||||
|
}
|
||||||
7
vendor/github.com/miekg/dns/msg_helpers.go
сгенерированный
поставляемый
7
vendor/github.com/miekg/dns/msg_helpers.go
сгенерированный
поставляемый
@@ -458,6 +458,13 @@ Option:
|
|||||||
}
|
}
|
||||||
edns = append(edns, e)
|
edns = append(edns, e)
|
||||||
off += int(optlen)
|
off += int(optlen)
|
||||||
|
case EDNS0PADDING:
|
||||||
|
e := new(EDNS0_PADDING)
|
||||||
|
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||||
|
return nil, len(msg), err
|
||||||
|
}
|
||||||
|
edns = append(edns, e)
|
||||||
|
off += int(optlen)
|
||||||
default:
|
default:
|
||||||
e := new(EDNS0_LOCAL)
|
e := new(EDNS0_LOCAL)
|
||||||
e.Code = code
|
e.Code = code
|
||||||
|
|||||||
188
vendor/github.com/miekg/dns/parse_test.go
сгенерированный
поставляемый
188
vendor/github.com/miekg/dns/parse_test.go
сгенерированный
поставляемый
@@ -8,6 +8,7 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -571,81 +572,88 @@ test IN CNAME test.a.example.com.
|
|||||||
t.Logf("%d RRs parsed in %.2f s (%.2f RR/s)", i, float32(delta)/1e9, float32(i)/(float32(delta)/1e9))
|
t.Logf("%d RRs parsed in %.2f s (%.2f RR/s)", i, float32(delta)/1e9, float32(i)/(float32(delta)/1e9))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleParseZone() {
|
func TestOmittedTTL(t *testing.T) {
|
||||||
zone := `$ORIGIN .
|
zone := `
|
||||||
$TTL 3600 ; 1 hour
|
$ORIGIN example.com.
|
||||||
name IN SOA a6.nstld.com. hostmaster.nic.name. (
|
example.com. 42 IN SOA ns1.example.com. hostmaster.example.com. 1 86400 60 86400 3600 ; TTL=42 SOA
|
||||||
203362132 ; serial
|
example.com. NS 2 ; TTL=42 absolute owner name
|
||||||
300 ; refresh (5 minutes)
|
@ MD 3 ; TTL=42 current-origin owner name
|
||||||
300 ; retry (5 minutes)
|
MF 4 ; TTL=42 leading-space implied owner name
|
||||||
1209600 ; expire (2 weeks)
|
43 TYPE65280 \# 1 05 ; TTL=43 implied owner name explicit TTL
|
||||||
300 ; minimum (5 minutes)
|
MB 6 ; TTL=43 leading-tab implied owner name
|
||||||
)
|
$TTL 1337
|
||||||
$TTL 10800 ; 3 hours
|
example.com. 88 MG 7 ; TTL=88 explicit TTL
|
||||||
name. 10800 IN NS name.
|
example.com. MR 8 ; TTL=1337 after first $TTL
|
||||||
IN NS g6.nstld.com.
|
$TTL 314
|
||||||
7200 NS h6.nstld.com.
|
1 TXT 9 ; TTL=1 implied owner name explicit TTL
|
||||||
3600 IN NS j6.nstld.com.
|
example.com. DNAME 10 ; TTL=314 after second $TTL
|
||||||
IN 3600 NS k6.nstld.com.
|
|
||||||
NS l6.nstld.com.
|
|
||||||
NS a6.nstld.com.
|
|
||||||
NS c6.nstld.com.
|
|
||||||
NS d6.nstld.com.
|
|
||||||
NS f6.nstld.com.
|
|
||||||
NS m6.nstld.com.
|
|
||||||
(
|
|
||||||
NS m7.nstld.com.
|
|
||||||
)
|
|
||||||
$ORIGIN name.
|
|
||||||
0-0onlus NS ns7.ehiweb.it.
|
|
||||||
NS ns8.ehiweb.it.
|
|
||||||
0-g MX 10 mx01.nic
|
|
||||||
MX 10 mx02.nic
|
|
||||||
MX 10 mx03.nic
|
|
||||||
MX 10 mx04.nic
|
|
||||||
$ORIGIN 0-g.name
|
|
||||||
moutamassey NS ns01.yahoodomains.jp.
|
|
||||||
NS ns02.yahoodomains.jp.
|
|
||||||
`
|
`
|
||||||
to := ParseZone(strings.NewReader(zone), "", "testzone")
|
reCaseFromComment := regexp.MustCompile(`TTL=(\d+)\s+(.*)`)
|
||||||
for x := range to {
|
records := ParseZone(strings.NewReader(zone), "", "")
|
||||||
fmt.Println(x.RR)
|
var i int
|
||||||
|
for record := range records {
|
||||||
|
i++
|
||||||
|
if record.Error != nil {
|
||||||
|
t.Error(record.Error)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
expected := reCaseFromComment.FindStringSubmatch(record.Comment)
|
||||||
|
expectedTTL, _ := strconv.ParseUint(expected[1], 10, 32)
|
||||||
|
ttl := record.RR.Header().Ttl
|
||||||
|
if ttl != uint32(expectedTTL) {
|
||||||
|
t.Errorf("%s: expected TTL %d, got %d", expected[2], expectedTTL, ttl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i != 10 {
|
||||||
|
t.Errorf("expected %d records, got %d", 5, i)
|
||||||
}
|
}
|
||||||
// Output:
|
|
||||||
// name. 3600 IN SOA a6.nstld.com. hostmaster.nic.name. 203362132 300 300 1209600 300
|
|
||||||
// name. 10800 IN NS name.
|
|
||||||
// name. 10800 IN NS g6.nstld.com.
|
|
||||||
// name. 7200 IN NS h6.nstld.com.
|
|
||||||
// name. 3600 IN NS j6.nstld.com.
|
|
||||||
// name. 3600 IN NS k6.nstld.com.
|
|
||||||
// name. 10800 IN NS l6.nstld.com.
|
|
||||||
// name. 10800 IN NS a6.nstld.com.
|
|
||||||
// name. 10800 IN NS c6.nstld.com.
|
|
||||||
// name. 10800 IN NS d6.nstld.com.
|
|
||||||
// name. 10800 IN NS f6.nstld.com.
|
|
||||||
// name. 10800 IN NS m6.nstld.com.
|
|
||||||
// name. 10800 IN NS m7.nstld.com.
|
|
||||||
// 0-0onlus.name. 10800 IN NS ns7.ehiweb.it.
|
|
||||||
// 0-0onlus.name. 10800 IN NS ns8.ehiweb.it.
|
|
||||||
// 0-g.name. 10800 IN MX 10 mx01.nic.name.
|
|
||||||
// 0-g.name. 10800 IN MX 10 mx02.nic.name.
|
|
||||||
// 0-g.name. 10800 IN MX 10 mx03.nic.name.
|
|
||||||
// 0-g.name. 10800 IN MX 10 mx04.nic.name.
|
|
||||||
// moutamassey.0-g.name.name. 10800 IN NS ns01.yahoodomains.jp.
|
|
||||||
// moutamassey.0-g.name.name. 10800 IN NS ns02.yahoodomains.jp.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleHIP() {
|
func TestRelativeNameErrors(t *testing.T) {
|
||||||
h := `www.example.com IN HIP ( 2 200100107B1A74DF365639CC39F1D578
|
var badZones = []struct {
|
||||||
AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p
|
label string
|
||||||
9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQ
|
zoneContents string
|
||||||
b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
|
expectedErr string
|
||||||
rvs.example.com. )`
|
}{
|
||||||
if hip, err := NewRR(h); err == nil {
|
{
|
||||||
fmt.Println(hip.String())
|
"relative owner name without origin",
|
||||||
|
"example.com 3600 IN SOA ns.example.com. hostmaster.example.com. 1 86400 60 86400 3600",
|
||||||
|
"bad owner name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relative owner name in RDATA",
|
||||||
|
"example.com. 3600 IN SOA ns hostmaster 1 86400 60 86400 3600",
|
||||||
|
"bad SOA Ns",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"origin reference without origin",
|
||||||
|
"@ 3600 IN SOA ns.example.com. hostmaster.example.com. 1 86400 60 86400 3600",
|
||||||
|
"bad owner name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relative owner name in $INCLUDE",
|
||||||
|
"$INCLUDE file.db example.com",
|
||||||
|
"bad origin name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relative owner name in $ORIGIN",
|
||||||
|
"$ORIGIN example.com",
|
||||||
|
"bad origin name",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, errorCase := range badZones {
|
||||||
|
entries := ParseZone(strings.NewReader(errorCase.zoneContents), "", "")
|
||||||
|
for entry := range entries {
|
||||||
|
if entry.Error == nil {
|
||||||
|
t.Errorf("%s: expected error, got nil", errorCase.label)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err := entry.Error.err
|
||||||
|
if err != errorCase.expectedErr {
|
||||||
|
t.Errorf("%s: expected error `%s`, got `%s`", errorCase.label, errorCase.expectedErr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Output:
|
|
||||||
// www.example.com. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHIP(t *testing.T) {
|
func TestHIP(t *testing.T) {
|
||||||
@@ -686,24 +694,6 @@ b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleSOA() {
|
|
||||||
s := "example.com. 1000 SOA master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100"
|
|
||||||
if soa, err := NewRR(s); err == nil {
|
|
||||||
fmt.Println(soa.String())
|
|
||||||
}
|
|
||||||
// Output:
|
|
||||||
// example.com. 1000 IN SOA master.example.com. admin.example.com. 1 4294967294 4294967293 4294967295 100
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLineNumberError(t *testing.T) {
|
|
||||||
s := "example.com. 1000 SOA master.example.com. admin.example.com. monkey 4294967294 4294967293 4294967295 100"
|
|
||||||
if _, err := NewRR(s); err != nil {
|
|
||||||
if err.Error() != "dns: bad SOA zone parameter: \"monkey\" at line: 1:68" {
|
|
||||||
t.Error("not expecting this error: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with no known RR on the line
|
// Test with no known RR on the line
|
||||||
func TestLineNumberError2(t *testing.T) {
|
func TestLineNumberError2(t *testing.T) {
|
||||||
tests := map[string]string{
|
tests := map[string]string{
|
||||||
@@ -801,28 +791,6 @@ func TestLowercaseTokens(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleParseZone_generate() {
|
|
||||||
// From the manual: http://www.bind9.net/manual/bind/9.3.2/Bv9ARM.ch06.html#id2566761
|
|
||||||
zone := "$GENERATE 1-2 0 NS SERVER$.EXAMPLE.\n$GENERATE 1-8 $ CNAME $.0"
|
|
||||||
to := ParseZone(strings.NewReader(zone), "0.0.192.IN-ADDR.ARPA.", "")
|
|
||||||
for x := range to {
|
|
||||||
if x.Error == nil {
|
|
||||||
fmt.Println(x.RR.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Output:
|
|
||||||
// 0.0.0.192.IN-ADDR.ARPA. 3600 IN NS SERVER1.EXAMPLE.
|
|
||||||
// 0.0.0.192.IN-ADDR.ARPA. 3600 IN NS SERVER2.EXAMPLE.
|
|
||||||
// 1.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 1.0.0.0.192.IN-ADDR.ARPA.
|
|
||||||
// 2.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 2.0.0.0.192.IN-ADDR.ARPA.
|
|
||||||
// 3.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 3.0.0.0.192.IN-ADDR.ARPA.
|
|
||||||
// 4.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 4.0.0.0.192.IN-ADDR.ARPA.
|
|
||||||
// 5.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 5.0.0.0.192.IN-ADDR.ARPA.
|
|
||||||
// 6.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 6.0.0.0.192.IN-ADDR.ARPA.
|
|
||||||
// 7.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 7.0.0.0.192.IN-ADDR.ARPA.
|
|
||||||
// 8.0.0.192.IN-ADDR.ARPA. 3600 IN CNAME 8.0.0.0.192.IN-ADDR.ARPA.
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSRVPacking(t *testing.T) {
|
func TestSRVPacking(t *testing.T) {
|
||||||
msg := Msg{}
|
msg := Msg{}
|
||||||
|
|
||||||
|
|||||||
2
vendor/github.com/miekg/dns/privaterr_test.go
сгенерированный
поставляемый
2
vendor/github.com/miekg/dns/privaterr_test.go
сгенерированный
поставляемый
@@ -143,7 +143,7 @@ func (rd *VERSION) Len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var smallzone = `$ORIGIN example.org.
|
var smallzone = `$ORIGIN example.org.
|
||||||
@ SOA sns.dns.icann.org. noc.dns.icann.org. (
|
@ 3600 IN SOA sns.dns.icann.org. noc.dns.icann.org. (
|
||||||
2014091518 7200 3600 1209600 3600
|
2014091518 7200 3600 1209600 3600
|
||||||
)
|
)
|
||||||
A 1.2.3.4
|
A 1.2.3.4
|
||||||
|
|||||||
129
vendor/github.com/miekg/dns/scan.go
сгенерированный
поставляемый
129
vendor/github.com/miekg/dns/scan.go
сгенерированный
поставляемый
@@ -105,6 +105,12 @@ type Token struct {
|
|||||||
Comment string
|
Comment string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ttlState describes the state necessary to fill in an omitted RR TTL
|
||||||
|
type ttlState struct {
|
||||||
|
ttl uint32 // ttl is the current default TTL
|
||||||
|
isByDirective bool // isByDirective indicates whether ttl was set by a $TTL directive
|
||||||
|
}
|
||||||
|
|
||||||
// NewRR reads the RR contained in the string s. Only the first RR is
|
// NewRR reads the RR contained in the string s. Only the first RR is
|
||||||
// returned. If s contains no RR, return nil with no error. The class
|
// returned. If s contains no RR, return nil with no error. The class
|
||||||
// defaults to IN and TTL defaults to 3600. The full zone file syntax
|
// defaults to IN and TTL defaults to 3600. The full zone file syntax
|
||||||
@@ -120,7 +126,8 @@ func NewRR(s string) (RR, error) {
|
|||||||
// ReadRR reads the RR contained in q.
|
// ReadRR reads the RR contained in q.
|
||||||
// See NewRR for more documentation.
|
// See NewRR for more documentation.
|
||||||
func ReadRR(q io.Reader, filename string) (RR, error) {
|
func ReadRR(q io.Reader, filename string) (RR, error) {
|
||||||
r := <-parseZoneHelper(q, ".", filename, 1)
|
defttl := &ttlState{defaultTtl, false}
|
||||||
|
r := <-parseZoneHelper(q, ".", defttl, filename, 1)
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -132,10 +139,10 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the
|
// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the
|
||||||
// returned channel, which consist out the parsed RR, a potential comment or an error.
|
// returned channel, each consisting of either a parsed RR and optional comment
|
||||||
// If there is an error the RR is nil. The string file is only used
|
// or a nil RR and an error. The string file is only used
|
||||||
// in error reporting. The string origin is used as the initial origin, as
|
// in error reporting. The string origin is used as the initial origin, as
|
||||||
// if the file would start with: $ORIGIN origin .
|
// if the file would start with an $ORIGIN directive.
|
||||||
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
|
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
|
||||||
// The channel t is closed by ParseZone when the end of r is reached.
|
// The channel t is closed by ParseZone when the end of r is reached.
|
||||||
//
|
//
|
||||||
@@ -157,16 +164,16 @@ func ReadRR(q io.Reader, filename string) (RR, error) {
|
|||||||
// The text "; this is comment" is returned in Token.Comment. Comments inside the
|
// The text "; this is comment" is returned in Token.Comment. Comments inside the
|
||||||
// RR are discarded. Comments on a line by themselves are discarded too.
|
// RR are discarded. Comments on a line by themselves are discarded too.
|
||||||
func ParseZone(r io.Reader, origin, file string) chan *Token {
|
func ParseZone(r io.Reader, origin, file string) chan *Token {
|
||||||
return parseZoneHelper(r, origin, file, 10000)
|
return parseZoneHelper(r, origin, nil, file, 10000)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseZoneHelper(r io.Reader, origin, file string, chansize int) chan *Token {
|
func parseZoneHelper(r io.Reader, origin string, defttl *ttlState, file string, chansize int) chan *Token {
|
||||||
t := make(chan *Token, chansize)
|
t := make(chan *Token, chansize)
|
||||||
go parseZone(r, origin, file, t, 0)
|
go parseZone(r, origin, defttl, file, t, 0)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
func parseZone(r io.Reader, origin string, defttl *ttlState, f string, t chan *Token, include int) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if include == 0 {
|
if include == 0 {
|
||||||
close(t)
|
close(t)
|
||||||
@@ -186,18 +193,16 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
// After detecting these, we know the zRrtype so we can jump to functions
|
// After detecting these, we know the zRrtype so we can jump to functions
|
||||||
// handling the rdata for each of these types.
|
// handling the rdata for each of these types.
|
||||||
|
|
||||||
if origin == "" {
|
if origin != "" {
|
||||||
origin = "."
|
origin = Fqdn(origin)
|
||||||
}
|
if _, ok := IsDomainName(origin); !ok {
|
||||||
origin = Fqdn(origin)
|
t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
|
||||||
if _, ok := IsDomainName(origin); !ok {
|
return
|
||||||
t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
st := zExpectOwnerDir // initial state
|
st := zExpectOwnerDir // initial state
|
||||||
var h RR_Header
|
var h RR_Header
|
||||||
var defttl uint32 = defaultTtl
|
|
||||||
var prevName string
|
var prevName string
|
||||||
for l := range c {
|
for l := range c {
|
||||||
// Lexer spotted an error already
|
// Lexer spotted an error already
|
||||||
@@ -209,27 +214,21 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
switch st {
|
switch st {
|
||||||
case zExpectOwnerDir:
|
case zExpectOwnerDir:
|
||||||
// We can also expect a directive, like $TTL or $ORIGIN
|
// We can also expect a directive, like $TTL or $ORIGIN
|
||||||
h.Ttl = defttl
|
if defttl != nil {
|
||||||
|
h.Ttl = defttl.ttl
|
||||||
|
}
|
||||||
h.Class = ClassINET
|
h.Class = ClassINET
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case zNewline:
|
case zNewline:
|
||||||
st = zExpectOwnerDir
|
st = zExpectOwnerDir
|
||||||
case zOwner:
|
case zOwner:
|
||||||
h.Name = l.token
|
h.Name = l.token
|
||||||
if l.token[0] == '@' {
|
name, ok := toAbsoluteName(l.token, origin)
|
||||||
h.Name = origin
|
|
||||||
prevName = h.Name
|
|
||||||
st = zExpectOwnerBl
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if h.Name[l.length-1] != '.' {
|
|
||||||
h.Name = appendOrigin(h.Name, origin)
|
|
||||||
}
|
|
||||||
_, ok := IsDomainName(l.token)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "bad owner name", l}}
|
t <- &Token{Error: &ParseError{f, "bad owner name", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
h.Name = name
|
||||||
prevName = h.Name
|
prevName = h.Name
|
||||||
st = zExpectOwnerBl
|
st = zExpectOwnerBl
|
||||||
case zDirTtl:
|
case zDirTtl:
|
||||||
@@ -258,8 +257,9 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.Ttl = ttl
|
h.Ttl = ttl
|
||||||
// Don't about the defttl, we should take the $TTL value
|
if defttl == nil || !defttl.isByDirective {
|
||||||
// defttl = ttl
|
defttl = &ttlState{ttl, false}
|
||||||
|
}
|
||||||
st = zExpectAnyNoTtlBl
|
st = zExpectAnyNoTtlBl
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -282,20 +282,12 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
case zBlank:
|
case zBlank:
|
||||||
l := <-c
|
l := <-c
|
||||||
if l.value == zString {
|
if l.value == zString {
|
||||||
if _, ok := IsDomainName(l.token); !ok || l.length == 0 || l.err {
|
name, ok := toAbsoluteName(l.token, origin)
|
||||||
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// a new origin is specified.
|
neworigin = name
|
||||||
if l.token[l.length-1] != '.' {
|
|
||||||
if origin != "." { // Prevent .. endings
|
|
||||||
neworigin = l.token + "." + origin
|
|
||||||
} else {
|
|
||||||
neworigin = l.token + origin
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
neworigin = l.token
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case zNewline, zEOF:
|
case zNewline, zEOF:
|
||||||
// Ok
|
// Ok
|
||||||
@@ -313,7 +305,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
|
t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
parseZone(r1, l.token, neworigin, t, include+1)
|
parseZone(r1, neworigin, defttl, l.token, t, include+1)
|
||||||
st = zExpectOwnerDir
|
st = zExpectOwnerDir
|
||||||
case zExpectDirTtlBl:
|
case zExpectDirTtlBl:
|
||||||
if l.value != zBlank {
|
if l.value != zBlank {
|
||||||
@@ -335,7 +327,7 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defttl = ttl
|
defttl = &ttlState{ttl, true}
|
||||||
st = zExpectOwnerDir
|
st = zExpectOwnerDir
|
||||||
case zExpectDirOriginBl:
|
case zExpectDirOriginBl:
|
||||||
if l.value != zBlank {
|
if l.value != zBlank {
|
||||||
@@ -351,19 +343,12 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
if e, _ := slurpRemainder(c, f); e != nil {
|
if e, _ := slurpRemainder(c, f); e != nil {
|
||||||
t <- &Token{Error: e}
|
t <- &Token{Error: e}
|
||||||
}
|
}
|
||||||
if _, ok := IsDomainName(l.token); !ok {
|
name, ok := toAbsoluteName(l.token, origin)
|
||||||
|
if !ok {
|
||||||
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if l.token[l.length-1] != '.' {
|
origin = name
|
||||||
if origin != "." { // Prevent .. endings
|
|
||||||
origin = l.token + "." + origin
|
|
||||||
} else {
|
|
||||||
origin = l.token + origin
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
origin = l.token
|
|
||||||
}
|
|
||||||
st = zExpectOwnerDir
|
st = zExpectOwnerDir
|
||||||
case zExpectDirGenerateBl:
|
case zExpectDirGenerateBl:
|
||||||
if l.value != zBlank {
|
if l.value != zBlank {
|
||||||
@@ -390,6 +375,10 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
case zExpectAny:
|
case zExpectAny:
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case zRrtpe:
|
case zRrtpe:
|
||||||
|
if defttl == nil {
|
||||||
|
t <- &Token{Error: &ParseError{f, "missing TTL with no previous value", l}}
|
||||||
|
return
|
||||||
|
}
|
||||||
h.Rrtype = l.torc
|
h.Rrtype = l.torc
|
||||||
st = zExpectRdata
|
st = zExpectRdata
|
||||||
case zClass:
|
case zClass:
|
||||||
@@ -402,7 +391,9 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.Ttl = ttl
|
h.Ttl = ttl
|
||||||
// defttl = ttl // don't set the defttl here
|
if defttl == nil || !defttl.isByDirective {
|
||||||
|
defttl = &ttlState{ttl, false}
|
||||||
|
}
|
||||||
st = zExpectAnyNoTtlBl
|
st = zExpectAnyNoTtlBl
|
||||||
default:
|
default:
|
||||||
t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
|
t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
|
||||||
@@ -441,7 +432,9 @@ func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.Ttl = ttl
|
h.Ttl = ttl
|
||||||
// defttl = ttl // don't set the def ttl anymore
|
if defttl == nil || !defttl.isByDirective {
|
||||||
|
defttl = &ttlState{ttl, false}
|
||||||
|
}
|
||||||
st = zExpectRrtypeBl
|
st = zExpectRrtypeBl
|
||||||
case zRrtpe:
|
case zRrtpe:
|
||||||
h.Rrtype = l.torc
|
h.Rrtype = l.torc
|
||||||
@@ -918,6 +911,34 @@ func stringToCm(token string) (e, m uint8, ok bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toAbsoluteName(name, origin string) (absolute string, ok bool) {
|
||||||
|
// check for an explicit origin reference
|
||||||
|
if name == "@" {
|
||||||
|
// require a nonempty origin
|
||||||
|
if origin == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return origin, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// require a valid domain name
|
||||||
|
_, ok = IsDomainName(name)
|
||||||
|
if !ok || name == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if name is already absolute
|
||||||
|
if name[len(name)-1] == '.' {
|
||||||
|
return name, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// require a nonempty origin
|
||||||
|
if origin == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return appendOrigin(name, origin), true
|
||||||
|
}
|
||||||
|
|
||||||
func appendOrigin(name, origin string) string {
|
func appendOrigin(name, origin string) string {
|
||||||
if origin == "." {
|
if origin == "." {
|
||||||
return name + origin
|
return name + origin
|
||||||
|
|||||||
592
vendor/github.com/miekg/dns/scan_rr.go
сгенерированный
поставляемый
592
vendor/github.com/miekg/dns/scan_rr.go
сгенерированный
поставляемый
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
5
vendor/github.com/miekg/dns/scan_test.go
сгенерированный
поставляемый
5
vendor/github.com/miekg/dns/scan_test.go
сгенерированный
поставляемый
@@ -21,13 +21,16 @@ func TestParseZoneInclude(t *testing.T) {
|
|||||||
t.Fatalf("could not close tmpfile %q: %s", tmpfile.Name(), err)
|
t.Fatalf("could not close tmpfile %q: %s", tmpfile.Name(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
zone := "$INCLUDE " + tmpfile.Name()
|
zone := "$ORIGIN example.org.\n$INCLUDE " + tmpfile.Name()
|
||||||
|
|
||||||
tok := ParseZone(strings.NewReader(zone), "", "")
|
tok := ParseZone(strings.NewReader(zone), "", "")
|
||||||
for x := range tok {
|
for x := range tok {
|
||||||
if x.Error != nil {
|
if x.Error != nil {
|
||||||
t.Fatalf("expected no error, but got %s", x.Error)
|
t.Fatalf("expected no error, but got %s", x.Error)
|
||||||
}
|
}
|
||||||
|
if x.RR.Header().Name != "foo.example.org." {
|
||||||
|
t.Fatalf("expected %s, but got %s", "foo.example.org.", x.RR.Header().Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Remove(tmpfile.Name())
|
os.Remove(tmpfile.Name())
|
||||||
|
|||||||
10
vendor/github.com/miekg/dns/server_test.go
сгенерированный
поставляемый
10
vendor/github.com/miekg/dns/server_test.go
сгенерированный
поставляемый
@@ -30,6 +30,16 @@ func HelloServerBadID(w ResponseWriter, req *Msg) {
|
|||||||
w.WriteMsg(m)
|
w.WriteMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HelloServerEchoAddrPort(w ResponseWriter, req *Msg) {
|
||||||
|
m := new(Msg)
|
||||||
|
m.SetReply(req)
|
||||||
|
|
||||||
|
remoteAddr := w.RemoteAddr().String()
|
||||||
|
m.Extra = make([]RR, 1)
|
||||||
|
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{remoteAddr}}
|
||||||
|
w.WriteMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
func AnotherHelloServer(w ResponseWriter, req *Msg) {
|
func AnotherHelloServer(w ResponseWriter, req *Msg) {
|
||||||
m := new(Msg)
|
m := new(Msg)
|
||||||
m.SetReply(req)
|
m.SetReply(req)
|
||||||
|
|||||||
15
vendor/github.com/miekg/dns/udp.go
сгенерированный
поставляемый
15
vendor/github.com/miekg/dns/udp.go
сгенерированный
поставляемый
@@ -27,8 +27,19 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
|||||||
return n, &SessionUDP{raddr, oob[:oobn]}, err
|
return n, &SessionUDP{raddr, oob[:oobn]}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||||
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||||
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
oob := correctSource(session.context)
|
||||||
|
n, _, err := conn.WriteMsgUDP(b, oob, session.raddr)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// correctSource takes oob data and returns new oob data with the Src equal to the Dst
|
||||||
|
func correctSource(oob []byte) []byte {
|
||||||
|
dst, err := parseUDPSocketDst(oob)
|
||||||
|
// If the destination could not be determined, ignore.
|
||||||
|
if err != nil || dst == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return marshalUDPSocketSrc(dst)
|
||||||
|
}
|
||||||
|
|||||||
115
vendor/github.com/miekg/dns/udp_linux.go
сгенерированный
поставляемый
115
vendor/github.com/miekg/dns/udp_linux.go
сгенерированный
поставляемый
@@ -13,8 +13,34 @@ package dns
|
|||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/miekg/dns/internal/socket"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofInet6Pktinfo = 0x14
|
||||||
|
sizeofInetPktinfo = 0xc
|
||||||
|
protocolIP = 0
|
||||||
|
protocolIPv6 = 41
|
||||||
|
)
|
||||||
|
|
||||||
|
type inetPktinfo struct {
|
||||||
|
Ifindex int32
|
||||||
|
Spec_dst [4]byte /* in_addr */
|
||||||
|
Addr [4]byte /* in_addr */
|
||||||
|
}
|
||||||
|
|
||||||
|
type inet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type inetControlMessage struct {
|
||||||
|
Src net.IP // source address, specifying only
|
||||||
|
Dst net.IP // destination address, receiving only
|
||||||
|
}
|
||||||
|
|
||||||
// setUDPSocketOptions sets the UDP socket options.
|
// setUDPSocketOptions sets the UDP socket options.
|
||||||
// This function is implemented on a per platform basis. See udp_*.go for more details
|
// This function is implemented on a per platform basis. See udp_*.go for more details
|
||||||
func setUDPSocketOptions(conn *net.UDPConn) error {
|
func setUDPSocketOptions(conn *net.UDPConn) error {
|
||||||
@@ -103,3 +129,92 @@ func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
return syscall.Getsockname(int(file.Fd()))
|
return syscall.Getsockname(int(file.Fd()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// marshalInetPacketInfo marshals a ipv4 control message, returning
|
||||||
|
// the byte slice for the next marshal, if any
|
||||||
|
func marshalInetPacketInfo(b []byte, cm *inetControlMessage) []byte {
|
||||||
|
m := socket.ControlMessage(b)
|
||||||
|
m.MarshalHeader(protocolIP, syscall.IP_PKTINFO, sizeofInetPktinfo)
|
||||||
|
if cm != nil {
|
||||||
|
pi := (*inetPktinfo)(unsafe.Pointer(&m.Data(sizeofInetPktinfo)[0]))
|
||||||
|
if ip := cm.Src.To4(); ip != nil {
|
||||||
|
copy(pi.Spec_dst[:], ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m.Next(sizeofInetPktinfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// marshalInet6PacketInfo marshals a ipv6 control message, returning
|
||||||
|
// the byte slice for the next marshal, if any
|
||||||
|
func marshalInet6PacketInfo(b []byte, cm *inetControlMessage) []byte {
|
||||||
|
m := socket.ControlMessage(b)
|
||||||
|
m.MarshalHeader(protocolIPv6, syscall.IPV6_PKTINFO, sizeofInet6Pktinfo)
|
||||||
|
if cm != nil {
|
||||||
|
pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0]))
|
||||||
|
if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
|
||||||
|
copy(pi.Addr[:], ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m.Next(sizeofInet6Pktinfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInetPacketInfo(cm *inetControlMessage, b []byte) {
|
||||||
|
pi := (*inetPktinfo)(unsafe.Pointer(&b[0]))
|
||||||
|
if len(cm.Dst) < net.IPv4len {
|
||||||
|
cm.Dst = make(net.IP, net.IPv4len)
|
||||||
|
}
|
||||||
|
copy(cm.Dst, pi.Addr[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInet6PacketInfo(cm *inetControlMessage, b []byte) {
|
||||||
|
pi := (*inet6Pktinfo)(unsafe.Pointer(&b[0]))
|
||||||
|
if len(cm.Dst) < net.IPv6len {
|
||||||
|
cm.Dst = make(net.IP, net.IPv6len)
|
||||||
|
}
|
||||||
|
copy(cm.Dst, pi.Addr[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseUDPSocketDst takes out-of-band data from ReadMsgUDP and parses it for
|
||||||
|
// the Dst address
|
||||||
|
func parseUDPSocketDst(oob []byte) (net.IP, error) {
|
||||||
|
cm := new(inetControlMessage)
|
||||||
|
ms, err := socket.ControlMessage(oob).Parse()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, m := range ms {
|
||||||
|
lvl, typ, l, err := m.ParseHeader()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if lvl == protocolIPv6 { // IPv6
|
||||||
|
if typ == syscall.IPV6_PKTINFO && l >= sizeofInet6Pktinfo {
|
||||||
|
parseInet6PacketInfo(cm, m.Data(l))
|
||||||
|
}
|
||||||
|
} else if lvl == protocolIP { // IPv4
|
||||||
|
if typ == syscall.IP_PKTINFO && l >= sizeofInetPktinfo {
|
||||||
|
parseInetPacketInfo(cm, m.Data(l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cm.Dst, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// marshalUDPSocketSrc takes the given src address and returns out-of-band data
|
||||||
|
// to give to WriteMsgUDP
|
||||||
|
func marshalUDPSocketSrc(src net.IP) []byte {
|
||||||
|
var oob []byte
|
||||||
|
// If the dst is definitely an ipv6, then use ipv6 control to respond
|
||||||
|
// otherwise use ipv4 because the ipv6 marshal ignores ipv4 messages.
|
||||||
|
// See marshalInet6PacketInfo
|
||||||
|
cm := new(inetControlMessage)
|
||||||
|
cm.Src = src
|
||||||
|
if src.To4() == nil {
|
||||||
|
oob = make([]byte, socket.ControlMessageSpace(sizeofInet6Pktinfo))
|
||||||
|
marshalInet6PacketInfo(oob, cm)
|
||||||
|
} else {
|
||||||
|
oob = make([]byte, socket.ControlMessageSpace(sizeofInetPktinfo))
|
||||||
|
marshalInetPacketInfo(oob, cm)
|
||||||
|
}
|
||||||
|
return oob
|
||||||
|
}
|
||||||
|
|||||||
68
vendor/github.com/miekg/dns/udp_linux_test.go
сгенерированный
поставляемый
Обычный файл
68
vendor/github.com/miekg/dns/udp_linux_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,68 @@
|
|||||||
|
// +build linux,!appengine
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseUDPSocketDst(t *testing.T) {
|
||||||
|
// dst is :ffff:100.100.100.100
|
||||||
|
oob := []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 100, 100, 100, 100, 2, 0, 0, 0}
|
||||||
|
dst, err := parseUDPSocketDst(oob)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error parsing ipv6 oob: %v", err)
|
||||||
|
}
|
||||||
|
dst4 := dst.To4()
|
||||||
|
if dst4 == nil {
|
||||||
|
t.Errorf("failed to parse ipv4: %v", dst)
|
||||||
|
} else if dst4.String() != "100.100.100.100" {
|
||||||
|
t.Errorf("unexpected ipv4: %v", dst4)
|
||||||
|
}
|
||||||
|
|
||||||
|
// dst is 2001:db8::1
|
||||||
|
oob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
dst, err = parseUDPSocketDst(oob)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error parsing ipv6 oob: %v", err)
|
||||||
|
}
|
||||||
|
dst6 := dst.To16()
|
||||||
|
if dst6 == nil {
|
||||||
|
t.Errorf("failed to parse ipv6: %v", dst)
|
||||||
|
} else if dst6.String() != "2001:db8::1" {
|
||||||
|
t.Errorf("unexpected ipv6: %v", dst4)
|
||||||
|
}
|
||||||
|
|
||||||
|
// dst is 100.100.100.100 but was received on 10.10.10.10
|
||||||
|
oob = []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 10, 10, 10, 10, 100, 100, 100, 100, 0, 0, 0, 0}
|
||||||
|
dst, err = parseUDPSocketDst(oob)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error parsing ipv4 oob: %v", err)
|
||||||
|
}
|
||||||
|
dst4 = dst.To4()
|
||||||
|
if dst4 == nil {
|
||||||
|
t.Errorf("failed to parse ipv4: %v", dst)
|
||||||
|
} else if dst4.String() != "100.100.100.100" {
|
||||||
|
t.Errorf("unexpected ipv4: %v", dst4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalUDPSocketSrc(t *testing.T) {
|
||||||
|
// src is 100.100.100.100
|
||||||
|
exoob := []byte{28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 100, 100, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
oob := marshalUDPSocketSrc(net.ParseIP("100.100.100.100"))
|
||||||
|
if !bytes.Equal(exoob, oob) {
|
||||||
|
t.Errorf("expected ipv4 oob:\n%v", exoob)
|
||||||
|
t.Errorf("actual ipv4 oob:\n%v", oob)
|
||||||
|
}
|
||||||
|
|
||||||
|
// src is 2001:db8::1
|
||||||
|
exoob = []byte{36, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 32, 1, 13, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
oob = marshalUDPSocketSrc(net.ParseIP("2001:db8::1"))
|
||||||
|
if !bytes.Equal(exoob, oob) {
|
||||||
|
t.Errorf("expected ipv6 oob:\n%v", exoob)
|
||||||
|
t.Errorf("actual ipv6 oob:\n%v", oob)
|
||||||
|
}
|
||||||
|
}
|
||||||
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Ссылка в новой задаче
Block a user