Signed-off-by: Wataru Ishida <ishida.wataru@lab.ntt.co.jp>
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
| ... | ... |
@@ -19,10 +19,10 @@ produces: |
| 19 | 19 |
consumes: |
| 20 | 20 |
- "application/json" |
| 21 | 21 |
- "text/plain" |
| 22 |
-basePath: "/v1.36" |
|
| 22 |
+basePath: "/v1.37" |
|
| 23 | 23 |
info: |
| 24 | 24 |
title: "Docker Engine API" |
| 25 |
- version: "1.36" |
|
| 25 |
+ version: "1.37" |
|
| 26 | 26 |
x-logo: |
| 27 | 27 |
url: "https://docs.docker.com/images/logo-docker-main.png" |
| 28 | 28 |
description: | |
| ... | ... |
@@ -49,7 +49,7 @@ info: |
| 49 | 49 |
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message |
| 50 | 50 |
is returned. |
| 51 | 51 |
|
| 52 |
- If you omit the version-prefix, the current version of the API (v1.36) is used. |
|
| 52 |
+ If you omit the version-prefix, the current version of the API (v1.37) is used. |
|
| 53 | 53 |
For example, calling `/info` is the same as calling `/v1.36/info`. Using the |
| 54 | 54 |
API without a version-prefix is deprecated and will be removed in a future release. |
| 55 | 55 |
|
| ... | ... |
@@ -167,7 +167,7 @@ definitions: |
| 167 | 167 |
Type: |
| 168 | 168 |
type: "string" |
| 169 | 169 |
x-nullable: false |
| 170 |
- enum: ["tcp", "udp"] |
|
| 170 |
+ enum: ["tcp", "udp", "sctp"] |
|
| 171 | 171 |
example: |
| 172 | 172 |
PrivatePort: 8080 |
| 173 | 173 |
PublicPort: 80 |
| ... | ... |
@@ -801,7 +801,7 @@ definitions: |
| 801 | 801 |
description: | |
| 802 | 802 |
An object mapping ports to an empty object in the form: |
| 803 | 803 |
|
| 804 |
- `{"<port>/<tcp|udp>": {}}`
|
|
| 804 |
+ `{"<port>/<tcp|udp|sctp>": {}}`
|
|
| 805 | 805 |
type: "object" |
| 806 | 806 |
additionalProperties: |
| 807 | 807 |
type: "object" |
| ... | ... |
@@ -1066,8 +1066,8 @@ definitions: |
| 1066 | 1066 |
container's port-number and protocol as key in the format `<port>/<protocol>`, |
| 1067 | 1067 |
for example, `80/udp`. |
| 1068 | 1068 |
|
| 1069 |
- If a container's port is mapped for both `tcp` and `udp`, two separate |
|
| 1070 |
- entries are added to the mapping table. |
|
| 1069 |
+ If a container's port is mapped for multiple protocols, separate entries |
|
| 1070 |
+ are added to the mapping table. |
|
| 1071 | 1071 |
type: "object" |
| 1072 | 1072 |
additionalProperties: |
| 1073 | 1073 |
type: "array" |
| ... | ... |
@@ -3046,6 +3046,7 @@ definitions: |
| 3046 | 3046 |
enum: |
| 3047 | 3047 |
- "tcp" |
| 3048 | 3048 |
- "udp" |
| 3049 |
+ - "sctp" |
|
| 3049 | 3050 |
TargetPort: |
| 3050 | 3051 |
description: "The port inside the container." |
| 3051 | 3052 |
type: "integer" |
| ... | ... |
@@ -62,6 +62,8 @@ const ( |
| 62 | 62 |
PortConfigProtocolTCP PortConfigProtocol = "tcp" |
| 63 | 63 |
// PortConfigProtocolUDP UDP |
| 64 | 64 |
PortConfigProtocolUDP PortConfigProtocol = "udp" |
| 65 |
+ // PortConfigProtocolSCTP SCTP |
|
| 66 |
+ PortConfigProtocolSCTP PortConfigProtocol = "sctp" |
|
| 65 | 67 |
) |
| 66 | 68 |
|
| 67 | 69 |
// EndpointVirtualIP represents the virtual ip of a port. |
| ... | ... |
@@ -621,6 +621,8 @@ func parsePortMap(portMap nat.PortMap) ([]*api.PortConfig, error) {
|
| 621 | 621 |
protocol = api.ProtocolTCP |
| 622 | 622 |
case "udp": |
| 623 | 623 |
protocol = api.ProtocolUDP |
| 624 |
+ case "sctp": |
|
| 625 |
+ protocol = api.ProtocolSCTP |
|
| 624 | 626 |
default: |
| 625 | 627 |
return nil, fmt.Errorf("invalid protocol: %s", parts[1])
|
| 626 | 628 |
} |
| ... | ... |
@@ -13,6 +13,12 @@ keywords: "API, Docker, rcli, REST, documentation" |
| 13 | 13 |
will be rejected. |
| 14 | 14 |
--> |
| 15 | 15 |
|
| 16 |
+## v1.37 API changes |
|
| 17 |
+ |
|
| 18 |
+[Docker Engine API v1.37](https://docs.docker.com/engine/api/v1.36/) documentation |
|
| 19 |
+ |
|
| 20 |
+* `POST /containers/create` and `POST /services/create` now supports exposing SCTP ports. |
|
| 21 |
+ |
|
| 16 | 22 |
## v1.36 API changes |
| 17 | 23 |
|
| 18 | 24 |
[Docker Engine API v1.36](https://docs.docker.com/engine/api/v1.36/) documentation |
| ... | ... |
@@ -16,7 +16,7 @@ TINI_COMMIT=949e6facb77383876aeff8a6944dde66b3089574 |
| 16 | 16 |
# LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When |
| 17 | 17 |
# updating the binary version, consider updating github.com/docker/libnetwork |
| 18 | 18 |
# in vendor.conf accordingly |
| 19 |
-LIBNETWORK_COMMIT=20dd462e0a0e883437a274bd61df4bc4de980830 |
|
| 19 |
+LIBNETWORK_COMMIT=ed2130d117c11c542327b4d5216a5db36770bc65 |
|
| 20 | 20 |
VNDR_COMMIT=a6e196d8b4b0cbbdc29aebdb20c59ac6926bb384 |
| 21 | 21 |
|
| 22 | 22 |
# Linting |
| ... | ... |
@@ -16,7 +16,7 @@ github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 |
| 16 | 16 |
golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 |
| 17 | 17 |
golang.org/x/sys 37707fdb30a5b38865cfb95e5aab41707daec7fd |
| 18 | 18 |
github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1 |
| 19 |
-github.com/docker/go-connections 98e7d807e5d804e4e42a98d74d1dd695321224ef |
|
| 19 |
+github.com/docker/go-connections 7beb39f0b969b075d1325fecb092faf27fd357b6 |
|
| 20 | 20 |
golang.org/x/text f72d8390a633d5dfb0cc84043294db9f6c935756 |
| 21 | 21 |
github.com/stretchr/testify 4d4bfba8f1d1027c4fdbe371823030df51419987 |
| 22 | 22 |
github.com/pmezard/go-difflib v1.0.0 |
| ... | ... |
@@ -33,7 +33,7 @@ github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2 |
| 33 | 33 |
#get libnetwork packages |
| 34 | 34 |
|
| 35 | 35 |
# When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/binaries-commits accordingly |
| 36 |
-github.com/docker/libnetwork 20dd462e0a0e883437a274bd61df4bc4de980830 |
|
| 36 |
+github.com/docker/libnetwork ed2130d117c11c542327b4d5216a5db36770bc65 |
|
| 37 | 37 |
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 |
| 38 | 38 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 39 | 39 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -57,6 +57,7 @@ github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065 |
| 57 | 57 |
github.com/hashicorp/consul v0.5.2 |
| 58 | 58 |
github.com/boltdb/bolt fff57c100f4dea1905678da7e90d92429dff2904 |
| 59 | 59 |
github.com/miekg/dns 75e6e86cc601825c5dbcd4e0c209eab180997cd7 |
| 60 |
+github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb |
|
| 60 | 61 |
|
| 61 | 62 |
# get graph and distribution packages |
| 62 | 63 |
github.com/docker/distribution edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c |
| ... | ... |
@@ -113,7 +113,7 @@ func SplitProtoPort(rawPort string) (string, string) {
|
| 113 | 113 |
} |
| 114 | 114 |
|
| 115 | 115 |
func validateProto(proto string) bool {
|
| 116 |
- for _, availableProto := range []string{"tcp", "udp"} {
|
|
| 116 |
+ for _, availableProto := range []string{"tcp", "udp", "sctp"} {
|
|
| 117 | 117 |
if availableProto == proto {
|
| 118 | 118 |
return true |
| 119 | 119 |
} |
| ... | ... |
@@ -1,6 +1,5 @@ |
| 1 |
-// Code generated by protoc-gen-gogo. |
|
| 1 |
+// Code generated by protoc-gen-gogo. DO NOT EDIT. |
|
| 2 | 2 |
// source: agent.proto |
| 3 |
-// DO NOT EDIT! |
|
| 4 | 3 |
|
| 5 | 4 |
/* |
| 6 | 5 |
Package libnetwork is a generated protocol buffer package. |
| ... | ... |
@@ -20,9 +19,6 @@ import math "math" |
| 20 | 20 |
import _ "github.com/gogo/protobuf/gogoproto" |
| 21 | 21 |
|
| 22 | 22 |
import strings "strings" |
| 23 |
-import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" |
|
| 24 |
-import sort "sort" |
|
| 25 |
-import strconv "strconv" |
|
| 26 | 23 |
import reflect "reflect" |
| 27 | 24 |
|
| 28 | 25 |
import io "io" |
| ... | ... |
@@ -34,22 +30,27 @@ var _ = math.Inf |
| 34 | 34 |
|
| 35 | 35 |
// This is a compile-time assertion to ensure that this generated file |
| 36 | 36 |
// is compatible with the proto package it is being compiled against. |
| 37 |
-const _ = proto.GoGoProtoPackageIsVersion1 |
|
| 37 |
+// A compilation error at this line likely means your copy of the |
|
| 38 |
+// proto package needs to be updated. |
|
| 39 |
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package |
|
| 38 | 40 |
|
| 39 | 41 |
type PortConfig_Protocol int32 |
| 40 | 42 |
|
| 41 | 43 |
const ( |
| 42 |
- ProtocolTCP PortConfig_Protocol = 0 |
|
| 43 |
- ProtocolUDP PortConfig_Protocol = 1 |
|
| 44 |
+ ProtocolTCP PortConfig_Protocol = 0 |
|
| 45 |
+ ProtocolUDP PortConfig_Protocol = 1 |
|
| 46 |
+ ProtocolSCTP PortConfig_Protocol = 2 |
|
| 44 | 47 |
) |
| 45 | 48 |
|
| 46 | 49 |
var PortConfig_Protocol_name = map[int32]string{
|
| 47 | 50 |
0: "TCP", |
| 48 | 51 |
1: "UDP", |
| 52 |
+ 2: "SCTP", |
|
| 49 | 53 |
} |
| 50 | 54 |
var PortConfig_Protocol_value = map[string]int32{
|
| 51 |
- "TCP": 0, |
|
| 52 |
- "UDP": 1, |
|
| 55 |
+ "TCP": 0, |
|
| 56 |
+ "UDP": 1, |
|
| 57 |
+ "SCTP": 2, |
|
| 53 | 58 |
} |
| 54 | 59 |
|
| 55 | 60 |
func (x PortConfig_Protocol) String() string {
|
| ... | ... |
@@ -60,7 +61,7 @@ func (PortConfig_Protocol) EnumDescriptor() ([]byte, []int) { return fileDescrip
|
| 60 | 60 |
// EndpointRecord specifies all the endpoint specific information that |
| 61 | 61 |
// needs to gossiped to nodes participating in the network. |
| 62 | 62 |
type EndpointRecord struct {
|
| 63 |
- // Name of the endpoint |
|
| 63 |
+ // Name of the container |
|
| 64 | 64 |
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` |
| 65 | 65 |
// Service name of the service to which this endpoint belongs. |
| 66 | 66 |
ServiceName string `protobuf:"bytes,2,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"` |
| ... | ... |
@@ -82,6 +83,41 @@ func (m *EndpointRecord) Reset() { *m = EndpointRecord{} }
|
| 82 | 82 |
func (*EndpointRecord) ProtoMessage() {}
|
| 83 | 83 |
func (*EndpointRecord) Descriptor() ([]byte, []int) { return fileDescriptorAgent, []int{0} }
|
| 84 | 84 |
|
| 85 |
+func (m *EndpointRecord) GetName() string {
|
|
| 86 |
+ if m != nil {
|
|
| 87 |
+ return m.Name |
|
| 88 |
+ } |
|
| 89 |
+ return "" |
|
| 90 |
+} |
|
| 91 |
+ |
|
| 92 |
+func (m *EndpointRecord) GetServiceName() string {
|
|
| 93 |
+ if m != nil {
|
|
| 94 |
+ return m.ServiceName |
|
| 95 |
+ } |
|
| 96 |
+ return "" |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+func (m *EndpointRecord) GetServiceID() string {
|
|
| 100 |
+ if m != nil {
|
|
| 101 |
+ return m.ServiceID |
|
| 102 |
+ } |
|
| 103 |
+ return "" |
|
| 104 |
+} |
|
| 105 |
+ |
|
| 106 |
+func (m *EndpointRecord) GetVirtualIP() string {
|
|
| 107 |
+ if m != nil {
|
|
| 108 |
+ return m.VirtualIP |
|
| 109 |
+ } |
|
| 110 |
+ return "" |
|
| 111 |
+} |
|
| 112 |
+ |
|
| 113 |
+func (m *EndpointRecord) GetEndpointIP() string {
|
|
| 114 |
+ if m != nil {
|
|
| 115 |
+ return m.EndpointIP |
|
| 116 |
+ } |
|
| 117 |
+ return "" |
|
| 118 |
+} |
|
| 119 |
+ |
|
| 85 | 120 |
func (m *EndpointRecord) GetIngressPorts() []*PortConfig {
|
| 86 | 121 |
if m != nil {
|
| 87 | 122 |
return m.IngressPorts |
| ... | ... |
@@ -89,6 +125,20 @@ func (m *EndpointRecord) GetIngressPorts() []*PortConfig {
|
| 89 | 89 |
return nil |
| 90 | 90 |
} |
| 91 | 91 |
|
| 92 |
+func (m *EndpointRecord) GetAliases() []string {
|
|
| 93 |
+ if m != nil {
|
|
| 94 |
+ return m.Aliases |
|
| 95 |
+ } |
|
| 96 |
+ return nil |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+func (m *EndpointRecord) GetTaskAliases() []string {
|
|
| 100 |
+ if m != nil {
|
|
| 101 |
+ return m.TaskAliases |
|
| 102 |
+ } |
|
| 103 |
+ return nil |
|
| 104 |
+} |
|
| 105 |
+ |
|
| 92 | 106 |
// PortConfig specifies an exposed port which can be |
| 93 | 107 |
// addressed using the given name. This can be later queried |
| 94 | 108 |
// using a service discovery api or a DNS SRV query. The node |
| ... | ... |
@@ -115,6 +165,34 @@ func (m *PortConfig) Reset() { *m = PortConfig{} }
|
| 115 | 115 |
func (*PortConfig) ProtoMessage() {}
|
| 116 | 116 |
func (*PortConfig) Descriptor() ([]byte, []int) { return fileDescriptorAgent, []int{1} }
|
| 117 | 117 |
|
| 118 |
+func (m *PortConfig) GetName() string {
|
|
| 119 |
+ if m != nil {
|
|
| 120 |
+ return m.Name |
|
| 121 |
+ } |
|
| 122 |
+ return "" |
|
| 123 |
+} |
|
| 124 |
+ |
|
| 125 |
+func (m *PortConfig) GetProtocol() PortConfig_Protocol {
|
|
| 126 |
+ if m != nil {
|
|
| 127 |
+ return m.Protocol |
|
| 128 |
+ } |
|
| 129 |
+ return ProtocolTCP |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 132 |
+func (m *PortConfig) GetTargetPort() uint32 {
|
|
| 133 |
+ if m != nil {
|
|
| 134 |
+ return m.TargetPort |
|
| 135 |
+ } |
|
| 136 |
+ return 0 |
|
| 137 |
+} |
|
| 138 |
+ |
|
| 139 |
+func (m *PortConfig) GetPublishedPort() uint32 {
|
|
| 140 |
+ if m != nil {
|
|
| 141 |
+ return m.PublishedPort |
|
| 142 |
+ } |
|
| 143 |
+ return 0 |
|
| 144 |
+} |
|
| 145 |
+ |
|
| 118 | 146 |
func init() {
|
| 119 | 147 |
proto.RegisterType((*EndpointRecord)(nil), "libnetwork.EndpointRecord") |
| 120 | 148 |
proto.RegisterType((*PortConfig)(nil), "libnetwork.PortConfig") |
| ... | ... |
@@ -160,74 +238,57 @@ func valueToGoStringAgent(v interface{}, typ string) string {
|
| 160 | 160 |
pv := reflect.Indirect(rv).Interface() |
| 161 | 161 |
return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
| 162 | 162 |
} |
| 163 |
-func extensionToGoStringAgent(e map[int32]github_com_gogo_protobuf_proto.Extension) string {
|
|
| 164 |
- if e == nil {
|
|
| 165 |
- return "nil" |
|
| 166 |
- } |
|
| 167 |
- s := "map[int32]proto.Extension{"
|
|
| 168 |
- keys := make([]int, 0, len(e)) |
|
| 169 |
- for k := range e {
|
|
| 170 |
- keys = append(keys, int(k)) |
|
| 171 |
- } |
|
| 172 |
- sort.Ints(keys) |
|
| 173 |
- ss := []string{}
|
|
| 174 |
- for _, k := range keys {
|
|
| 175 |
- ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) |
|
| 176 |
- } |
|
| 177 |
- s += strings.Join(ss, ",") + "}" |
|
| 178 |
- return s |
|
| 179 |
-} |
|
| 180 |
-func (m *EndpointRecord) Marshal() (data []byte, err error) {
|
|
| 163 |
+func (m *EndpointRecord) Marshal() (dAtA []byte, err error) {
|
|
| 181 | 164 |
size := m.Size() |
| 182 |
- data = make([]byte, size) |
|
| 183 |
- n, err := m.MarshalTo(data) |
|
| 165 |
+ dAtA = make([]byte, size) |
|
| 166 |
+ n, err := m.MarshalTo(dAtA) |
|
| 184 | 167 |
if err != nil {
|
| 185 | 168 |
return nil, err |
| 186 | 169 |
} |
| 187 |
- return data[:n], nil |
|
| 170 |
+ return dAtA[:n], nil |
|
| 188 | 171 |
} |
| 189 | 172 |
|
| 190 |
-func (m *EndpointRecord) MarshalTo(data []byte) (int, error) {
|
|
| 173 |
+func (m *EndpointRecord) MarshalTo(dAtA []byte) (int, error) {
|
|
| 191 | 174 |
var i int |
| 192 | 175 |
_ = i |
| 193 | 176 |
var l int |
| 194 | 177 |
_ = l |
| 195 | 178 |
if len(m.Name) > 0 {
|
| 196 |
- data[i] = 0xa |
|
| 179 |
+ dAtA[i] = 0xa |
|
| 197 | 180 |
i++ |
| 198 |
- i = encodeVarintAgent(data, i, uint64(len(m.Name))) |
|
| 199 |
- i += copy(data[i:], m.Name) |
|
| 181 |
+ i = encodeVarintAgent(dAtA, i, uint64(len(m.Name))) |
|
| 182 |
+ i += copy(dAtA[i:], m.Name) |
|
| 200 | 183 |
} |
| 201 | 184 |
if len(m.ServiceName) > 0 {
|
| 202 |
- data[i] = 0x12 |
|
| 185 |
+ dAtA[i] = 0x12 |
|
| 203 | 186 |
i++ |
| 204 |
- i = encodeVarintAgent(data, i, uint64(len(m.ServiceName))) |
|
| 205 |
- i += copy(data[i:], m.ServiceName) |
|
| 187 |
+ i = encodeVarintAgent(dAtA, i, uint64(len(m.ServiceName))) |
|
| 188 |
+ i += copy(dAtA[i:], m.ServiceName) |
|
| 206 | 189 |
} |
| 207 | 190 |
if len(m.ServiceID) > 0 {
|
| 208 |
- data[i] = 0x1a |
|
| 191 |
+ dAtA[i] = 0x1a |
|
| 209 | 192 |
i++ |
| 210 |
- i = encodeVarintAgent(data, i, uint64(len(m.ServiceID))) |
|
| 211 |
- i += copy(data[i:], m.ServiceID) |
|
| 193 |
+ i = encodeVarintAgent(dAtA, i, uint64(len(m.ServiceID))) |
|
| 194 |
+ i += copy(dAtA[i:], m.ServiceID) |
|
| 212 | 195 |
} |
| 213 | 196 |
if len(m.VirtualIP) > 0 {
|
| 214 |
- data[i] = 0x22 |
|
| 197 |
+ dAtA[i] = 0x22 |
|
| 215 | 198 |
i++ |
| 216 |
- i = encodeVarintAgent(data, i, uint64(len(m.VirtualIP))) |
|
| 217 |
- i += copy(data[i:], m.VirtualIP) |
|
| 199 |
+ i = encodeVarintAgent(dAtA, i, uint64(len(m.VirtualIP))) |
|
| 200 |
+ i += copy(dAtA[i:], m.VirtualIP) |
|
| 218 | 201 |
} |
| 219 | 202 |
if len(m.EndpointIP) > 0 {
|
| 220 |
- data[i] = 0x2a |
|
| 203 |
+ dAtA[i] = 0x2a |
|
| 221 | 204 |
i++ |
| 222 |
- i = encodeVarintAgent(data, i, uint64(len(m.EndpointIP))) |
|
| 223 |
- i += copy(data[i:], m.EndpointIP) |
|
| 205 |
+ i = encodeVarintAgent(dAtA, i, uint64(len(m.EndpointIP))) |
|
| 206 |
+ i += copy(dAtA[i:], m.EndpointIP) |
|
| 224 | 207 |
} |
| 225 | 208 |
if len(m.IngressPorts) > 0 {
|
| 226 | 209 |
for _, msg := range m.IngressPorts {
|
| 227 |
- data[i] = 0x32 |
|
| 210 |
+ dAtA[i] = 0x32 |
|
| 228 | 211 |
i++ |
| 229 |
- i = encodeVarintAgent(data, i, uint64(msg.Size())) |
|
| 230 |
- n, err := msg.MarshalTo(data[i:]) |
|
| 212 |
+ i = encodeVarintAgent(dAtA, i, uint64(msg.Size())) |
|
| 213 |
+ n, err := msg.MarshalTo(dAtA[i:]) |
|
| 231 | 214 |
if err != nil {
|
| 232 | 215 |
return 0, err |
| 233 | 216 |
} |
| ... | ... |
@@ -236,101 +297,101 @@ func (m *EndpointRecord) MarshalTo(data []byte) (int, error) {
|
| 236 | 236 |
} |
| 237 | 237 |
if len(m.Aliases) > 0 {
|
| 238 | 238 |
for _, s := range m.Aliases {
|
| 239 |
- data[i] = 0x3a |
|
| 239 |
+ dAtA[i] = 0x3a |
|
| 240 | 240 |
i++ |
| 241 | 241 |
l = len(s) |
| 242 | 242 |
for l >= 1<<7 {
|
| 243 |
- data[i] = uint8(uint64(l)&0x7f | 0x80) |
|
| 243 |
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80) |
|
| 244 | 244 |
l >>= 7 |
| 245 | 245 |
i++ |
| 246 | 246 |
} |
| 247 |
- data[i] = uint8(l) |
|
| 247 |
+ dAtA[i] = uint8(l) |
|
| 248 | 248 |
i++ |
| 249 |
- i += copy(data[i:], s) |
|
| 249 |
+ i += copy(dAtA[i:], s) |
|
| 250 | 250 |
} |
| 251 | 251 |
} |
| 252 | 252 |
if len(m.TaskAliases) > 0 {
|
| 253 | 253 |
for _, s := range m.TaskAliases {
|
| 254 |
- data[i] = 0x42 |
|
| 254 |
+ dAtA[i] = 0x42 |
|
| 255 | 255 |
i++ |
| 256 | 256 |
l = len(s) |
| 257 | 257 |
for l >= 1<<7 {
|
| 258 |
- data[i] = uint8(uint64(l)&0x7f | 0x80) |
|
| 258 |
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80) |
|
| 259 | 259 |
l >>= 7 |
| 260 | 260 |
i++ |
| 261 | 261 |
} |
| 262 |
- data[i] = uint8(l) |
|
| 262 |
+ dAtA[i] = uint8(l) |
|
| 263 | 263 |
i++ |
| 264 |
- i += copy(data[i:], s) |
|
| 264 |
+ i += copy(dAtA[i:], s) |
|
| 265 | 265 |
} |
| 266 | 266 |
} |
| 267 | 267 |
return i, nil |
| 268 | 268 |
} |
| 269 | 269 |
|
| 270 |
-func (m *PortConfig) Marshal() (data []byte, err error) {
|
|
| 270 |
+func (m *PortConfig) Marshal() (dAtA []byte, err error) {
|
|
| 271 | 271 |
size := m.Size() |
| 272 |
- data = make([]byte, size) |
|
| 273 |
- n, err := m.MarshalTo(data) |
|
| 272 |
+ dAtA = make([]byte, size) |
|
| 273 |
+ n, err := m.MarshalTo(dAtA) |
|
| 274 | 274 |
if err != nil {
|
| 275 | 275 |
return nil, err |
| 276 | 276 |
} |
| 277 |
- return data[:n], nil |
|
| 277 |
+ return dAtA[:n], nil |
|
| 278 | 278 |
} |
| 279 | 279 |
|
| 280 |
-func (m *PortConfig) MarshalTo(data []byte) (int, error) {
|
|
| 280 |
+func (m *PortConfig) MarshalTo(dAtA []byte) (int, error) {
|
|
| 281 | 281 |
var i int |
| 282 | 282 |
_ = i |
| 283 | 283 |
var l int |
| 284 | 284 |
_ = l |
| 285 | 285 |
if len(m.Name) > 0 {
|
| 286 |
- data[i] = 0xa |
|
| 286 |
+ dAtA[i] = 0xa |
|
| 287 | 287 |
i++ |
| 288 |
- i = encodeVarintAgent(data, i, uint64(len(m.Name))) |
|
| 289 |
- i += copy(data[i:], m.Name) |
|
| 288 |
+ i = encodeVarintAgent(dAtA, i, uint64(len(m.Name))) |
|
| 289 |
+ i += copy(dAtA[i:], m.Name) |
|
| 290 | 290 |
} |
| 291 | 291 |
if m.Protocol != 0 {
|
| 292 |
- data[i] = 0x10 |
|
| 292 |
+ dAtA[i] = 0x10 |
|
| 293 | 293 |
i++ |
| 294 |
- i = encodeVarintAgent(data, i, uint64(m.Protocol)) |
|
| 294 |
+ i = encodeVarintAgent(dAtA, i, uint64(m.Protocol)) |
|
| 295 | 295 |
} |
| 296 | 296 |
if m.TargetPort != 0 {
|
| 297 |
- data[i] = 0x18 |
|
| 297 |
+ dAtA[i] = 0x18 |
|
| 298 | 298 |
i++ |
| 299 |
- i = encodeVarintAgent(data, i, uint64(m.TargetPort)) |
|
| 299 |
+ i = encodeVarintAgent(dAtA, i, uint64(m.TargetPort)) |
|
| 300 | 300 |
} |
| 301 | 301 |
if m.PublishedPort != 0 {
|
| 302 |
- data[i] = 0x20 |
|
| 302 |
+ dAtA[i] = 0x20 |
|
| 303 | 303 |
i++ |
| 304 |
- i = encodeVarintAgent(data, i, uint64(m.PublishedPort)) |
|
| 304 |
+ i = encodeVarintAgent(dAtA, i, uint64(m.PublishedPort)) |
|
| 305 | 305 |
} |
| 306 | 306 |
return i, nil |
| 307 | 307 |
} |
| 308 | 308 |
|
| 309 |
-func encodeFixed64Agent(data []byte, offset int, v uint64) int {
|
|
| 310 |
- data[offset] = uint8(v) |
|
| 311 |
- data[offset+1] = uint8(v >> 8) |
|
| 312 |
- data[offset+2] = uint8(v >> 16) |
|
| 313 |
- data[offset+3] = uint8(v >> 24) |
|
| 314 |
- data[offset+4] = uint8(v >> 32) |
|
| 315 |
- data[offset+5] = uint8(v >> 40) |
|
| 316 |
- data[offset+6] = uint8(v >> 48) |
|
| 317 |
- data[offset+7] = uint8(v >> 56) |
|
| 309 |
+func encodeFixed64Agent(dAtA []byte, offset int, v uint64) int {
|
|
| 310 |
+ dAtA[offset] = uint8(v) |
|
| 311 |
+ dAtA[offset+1] = uint8(v >> 8) |
|
| 312 |
+ dAtA[offset+2] = uint8(v >> 16) |
|
| 313 |
+ dAtA[offset+3] = uint8(v >> 24) |
|
| 314 |
+ dAtA[offset+4] = uint8(v >> 32) |
|
| 315 |
+ dAtA[offset+5] = uint8(v >> 40) |
|
| 316 |
+ dAtA[offset+6] = uint8(v >> 48) |
|
| 317 |
+ dAtA[offset+7] = uint8(v >> 56) |
|
| 318 | 318 |
return offset + 8 |
| 319 | 319 |
} |
| 320 |
-func encodeFixed32Agent(data []byte, offset int, v uint32) int {
|
|
| 321 |
- data[offset] = uint8(v) |
|
| 322 |
- data[offset+1] = uint8(v >> 8) |
|
| 323 |
- data[offset+2] = uint8(v >> 16) |
|
| 324 |
- data[offset+3] = uint8(v >> 24) |
|
| 320 |
+func encodeFixed32Agent(dAtA []byte, offset int, v uint32) int {
|
|
| 321 |
+ dAtA[offset] = uint8(v) |
|
| 322 |
+ dAtA[offset+1] = uint8(v >> 8) |
|
| 323 |
+ dAtA[offset+2] = uint8(v >> 16) |
|
| 324 |
+ dAtA[offset+3] = uint8(v >> 24) |
|
| 325 | 325 |
return offset + 4 |
| 326 | 326 |
} |
| 327 |
-func encodeVarintAgent(data []byte, offset int, v uint64) int {
|
|
| 327 |
+func encodeVarintAgent(dAtA []byte, offset int, v uint64) int {
|
|
| 328 | 328 |
for v >= 1<<7 {
|
| 329 |
- data[offset] = uint8(v&0x7f | 0x80) |
|
| 329 |
+ dAtA[offset] = uint8(v&0x7f | 0x80) |
|
| 330 | 330 |
v >>= 7 |
| 331 | 331 |
offset++ |
| 332 | 332 |
} |
| 333 |
- data[offset] = uint8(v) |
|
| 333 |
+ dAtA[offset] = uint8(v) |
|
| 334 | 334 |
return offset + 1 |
| 335 | 335 |
} |
| 336 | 336 |
func (m *EndpointRecord) Size() (n int) {
|
| ... | ... |
@@ -447,8 +508,8 @@ func valueToStringAgent(v interface{}) string {
|
| 447 | 447 |
pv := reflect.Indirect(rv).Interface() |
| 448 | 448 |
return fmt.Sprintf("*%v", pv)
|
| 449 | 449 |
} |
| 450 |
-func (m *EndpointRecord) Unmarshal(data []byte) error {
|
|
| 451 |
- l := len(data) |
|
| 450 |
+func (m *EndpointRecord) Unmarshal(dAtA []byte) error {
|
|
| 451 |
+ l := len(dAtA) |
|
| 452 | 452 |
iNdEx := 0 |
| 453 | 453 |
for iNdEx < l {
|
| 454 | 454 |
preIndex := iNdEx |
| ... | ... |
@@ -460,7 +521,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 460 | 460 |
if iNdEx >= l {
|
| 461 | 461 |
return io.ErrUnexpectedEOF |
| 462 | 462 |
} |
| 463 |
- b := data[iNdEx] |
|
| 463 |
+ b := dAtA[iNdEx] |
|
| 464 | 464 |
iNdEx++ |
| 465 | 465 |
wire |= (uint64(b) & 0x7F) << shift |
| 466 | 466 |
if b < 0x80 {
|
| ... | ... |
@@ -488,7 +549,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 488 | 488 |
if iNdEx >= l {
|
| 489 | 489 |
return io.ErrUnexpectedEOF |
| 490 | 490 |
} |
| 491 |
- b := data[iNdEx] |
|
| 491 |
+ b := dAtA[iNdEx] |
|
| 492 | 492 |
iNdEx++ |
| 493 | 493 |
stringLen |= (uint64(b) & 0x7F) << shift |
| 494 | 494 |
if b < 0x80 {
|
| ... | ... |
@@ -503,7 +564,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 503 | 503 |
if postIndex > l {
|
| 504 | 504 |
return io.ErrUnexpectedEOF |
| 505 | 505 |
} |
| 506 |
- m.Name = string(data[iNdEx:postIndex]) |
|
| 506 |
+ m.Name = string(dAtA[iNdEx:postIndex]) |
|
| 507 | 507 |
iNdEx = postIndex |
| 508 | 508 |
case 2: |
| 509 | 509 |
if wireType != 2 {
|
| ... | ... |
@@ -517,7 +578,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 517 | 517 |
if iNdEx >= l {
|
| 518 | 518 |
return io.ErrUnexpectedEOF |
| 519 | 519 |
} |
| 520 |
- b := data[iNdEx] |
|
| 520 |
+ b := dAtA[iNdEx] |
|
| 521 | 521 |
iNdEx++ |
| 522 | 522 |
stringLen |= (uint64(b) & 0x7F) << shift |
| 523 | 523 |
if b < 0x80 {
|
| ... | ... |
@@ -532,7 +593,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 532 | 532 |
if postIndex > l {
|
| 533 | 533 |
return io.ErrUnexpectedEOF |
| 534 | 534 |
} |
| 535 |
- m.ServiceName = string(data[iNdEx:postIndex]) |
|
| 535 |
+ m.ServiceName = string(dAtA[iNdEx:postIndex]) |
|
| 536 | 536 |
iNdEx = postIndex |
| 537 | 537 |
case 3: |
| 538 | 538 |
if wireType != 2 {
|
| ... | ... |
@@ -546,7 +607,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 546 | 546 |
if iNdEx >= l {
|
| 547 | 547 |
return io.ErrUnexpectedEOF |
| 548 | 548 |
} |
| 549 |
- b := data[iNdEx] |
|
| 549 |
+ b := dAtA[iNdEx] |
|
| 550 | 550 |
iNdEx++ |
| 551 | 551 |
stringLen |= (uint64(b) & 0x7F) << shift |
| 552 | 552 |
if b < 0x80 {
|
| ... | ... |
@@ -561,7 +622,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 561 | 561 |
if postIndex > l {
|
| 562 | 562 |
return io.ErrUnexpectedEOF |
| 563 | 563 |
} |
| 564 |
- m.ServiceID = string(data[iNdEx:postIndex]) |
|
| 564 |
+ m.ServiceID = string(dAtA[iNdEx:postIndex]) |
|
| 565 | 565 |
iNdEx = postIndex |
| 566 | 566 |
case 4: |
| 567 | 567 |
if wireType != 2 {
|
| ... | ... |
@@ -575,7 +636,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 575 | 575 |
if iNdEx >= l {
|
| 576 | 576 |
return io.ErrUnexpectedEOF |
| 577 | 577 |
} |
| 578 |
- b := data[iNdEx] |
|
| 578 |
+ b := dAtA[iNdEx] |
|
| 579 | 579 |
iNdEx++ |
| 580 | 580 |
stringLen |= (uint64(b) & 0x7F) << shift |
| 581 | 581 |
if b < 0x80 {
|
| ... | ... |
@@ -590,7 +651,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 590 | 590 |
if postIndex > l {
|
| 591 | 591 |
return io.ErrUnexpectedEOF |
| 592 | 592 |
} |
| 593 |
- m.VirtualIP = string(data[iNdEx:postIndex]) |
|
| 593 |
+ m.VirtualIP = string(dAtA[iNdEx:postIndex]) |
|
| 594 | 594 |
iNdEx = postIndex |
| 595 | 595 |
case 5: |
| 596 | 596 |
if wireType != 2 {
|
| ... | ... |
@@ -604,7 +665,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 604 | 604 |
if iNdEx >= l {
|
| 605 | 605 |
return io.ErrUnexpectedEOF |
| 606 | 606 |
} |
| 607 |
- b := data[iNdEx] |
|
| 607 |
+ b := dAtA[iNdEx] |
|
| 608 | 608 |
iNdEx++ |
| 609 | 609 |
stringLen |= (uint64(b) & 0x7F) << shift |
| 610 | 610 |
if b < 0x80 {
|
| ... | ... |
@@ -619,7 +680,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 619 | 619 |
if postIndex > l {
|
| 620 | 620 |
return io.ErrUnexpectedEOF |
| 621 | 621 |
} |
| 622 |
- m.EndpointIP = string(data[iNdEx:postIndex]) |
|
| 622 |
+ m.EndpointIP = string(dAtA[iNdEx:postIndex]) |
|
| 623 | 623 |
iNdEx = postIndex |
| 624 | 624 |
case 6: |
| 625 | 625 |
if wireType != 2 {
|
| ... | ... |
@@ -633,7 +694,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 633 | 633 |
if iNdEx >= l {
|
| 634 | 634 |
return io.ErrUnexpectedEOF |
| 635 | 635 |
} |
| 636 |
- b := data[iNdEx] |
|
| 636 |
+ b := dAtA[iNdEx] |
|
| 637 | 637 |
iNdEx++ |
| 638 | 638 |
msglen |= (int(b) & 0x7F) << shift |
| 639 | 639 |
if b < 0x80 {
|
| ... | ... |
@@ -648,7 +709,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 648 | 648 |
return io.ErrUnexpectedEOF |
| 649 | 649 |
} |
| 650 | 650 |
m.IngressPorts = append(m.IngressPorts, &PortConfig{})
|
| 651 |
- if err := m.IngressPorts[len(m.IngressPorts)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
|
|
| 651 |
+ if err := m.IngressPorts[len(m.IngressPorts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
|
| 652 | 652 |
return err |
| 653 | 653 |
} |
| 654 | 654 |
iNdEx = postIndex |
| ... | ... |
@@ -664,7 +725,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 664 | 664 |
if iNdEx >= l {
|
| 665 | 665 |
return io.ErrUnexpectedEOF |
| 666 | 666 |
} |
| 667 |
- b := data[iNdEx] |
|
| 667 |
+ b := dAtA[iNdEx] |
|
| 668 | 668 |
iNdEx++ |
| 669 | 669 |
stringLen |= (uint64(b) & 0x7F) << shift |
| 670 | 670 |
if b < 0x80 {
|
| ... | ... |
@@ -679,7 +740,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 679 | 679 |
if postIndex > l {
|
| 680 | 680 |
return io.ErrUnexpectedEOF |
| 681 | 681 |
} |
| 682 |
- m.Aliases = append(m.Aliases, string(data[iNdEx:postIndex])) |
|
| 682 |
+ m.Aliases = append(m.Aliases, string(dAtA[iNdEx:postIndex])) |
|
| 683 | 683 |
iNdEx = postIndex |
| 684 | 684 |
case 8: |
| 685 | 685 |
if wireType != 2 {
|
| ... | ... |
@@ -693,7 +754,7 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 693 | 693 |
if iNdEx >= l {
|
| 694 | 694 |
return io.ErrUnexpectedEOF |
| 695 | 695 |
} |
| 696 |
- b := data[iNdEx] |
|
| 696 |
+ b := dAtA[iNdEx] |
|
| 697 | 697 |
iNdEx++ |
| 698 | 698 |
stringLen |= (uint64(b) & 0x7F) << shift |
| 699 | 699 |
if b < 0x80 {
|
| ... | ... |
@@ -708,11 +769,11 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 708 | 708 |
if postIndex > l {
|
| 709 | 709 |
return io.ErrUnexpectedEOF |
| 710 | 710 |
} |
| 711 |
- m.TaskAliases = append(m.TaskAliases, string(data[iNdEx:postIndex])) |
|
| 711 |
+ m.TaskAliases = append(m.TaskAliases, string(dAtA[iNdEx:postIndex])) |
|
| 712 | 712 |
iNdEx = postIndex |
| 713 | 713 |
default: |
| 714 | 714 |
iNdEx = preIndex |
| 715 |
- skippy, err := skipAgent(data[iNdEx:]) |
|
| 715 |
+ skippy, err := skipAgent(dAtA[iNdEx:]) |
|
| 716 | 716 |
if err != nil {
|
| 717 | 717 |
return err |
| 718 | 718 |
} |
| ... | ... |
@@ -731,8 +792,8 @@ func (m *EndpointRecord) Unmarshal(data []byte) error {
|
| 731 | 731 |
} |
| 732 | 732 |
return nil |
| 733 | 733 |
} |
| 734 |
-func (m *PortConfig) Unmarshal(data []byte) error {
|
|
| 735 |
- l := len(data) |
|
| 734 |
+func (m *PortConfig) Unmarshal(dAtA []byte) error {
|
|
| 735 |
+ l := len(dAtA) |
|
| 736 | 736 |
iNdEx := 0 |
| 737 | 737 |
for iNdEx < l {
|
| 738 | 738 |
preIndex := iNdEx |
| ... | ... |
@@ -744,7 +805,7 @@ func (m *PortConfig) Unmarshal(data []byte) error {
|
| 744 | 744 |
if iNdEx >= l {
|
| 745 | 745 |
return io.ErrUnexpectedEOF |
| 746 | 746 |
} |
| 747 |
- b := data[iNdEx] |
|
| 747 |
+ b := dAtA[iNdEx] |
|
| 748 | 748 |
iNdEx++ |
| 749 | 749 |
wire |= (uint64(b) & 0x7F) << shift |
| 750 | 750 |
if b < 0x80 {
|
| ... | ... |
@@ -772,7 +833,7 @@ func (m *PortConfig) Unmarshal(data []byte) error {
|
| 772 | 772 |
if iNdEx >= l {
|
| 773 | 773 |
return io.ErrUnexpectedEOF |
| 774 | 774 |
} |
| 775 |
- b := data[iNdEx] |
|
| 775 |
+ b := dAtA[iNdEx] |
|
| 776 | 776 |
iNdEx++ |
| 777 | 777 |
stringLen |= (uint64(b) & 0x7F) << shift |
| 778 | 778 |
if b < 0x80 {
|
| ... | ... |
@@ -787,7 +848,7 @@ func (m *PortConfig) Unmarshal(data []byte) error {
|
| 787 | 787 |
if postIndex > l {
|
| 788 | 788 |
return io.ErrUnexpectedEOF |
| 789 | 789 |
} |
| 790 |
- m.Name = string(data[iNdEx:postIndex]) |
|
| 790 |
+ m.Name = string(dAtA[iNdEx:postIndex]) |
|
| 791 | 791 |
iNdEx = postIndex |
| 792 | 792 |
case 2: |
| 793 | 793 |
if wireType != 0 {
|
| ... | ... |
@@ -801,7 +862,7 @@ func (m *PortConfig) Unmarshal(data []byte) error {
|
| 801 | 801 |
if iNdEx >= l {
|
| 802 | 802 |
return io.ErrUnexpectedEOF |
| 803 | 803 |
} |
| 804 |
- b := data[iNdEx] |
|
| 804 |
+ b := dAtA[iNdEx] |
|
| 805 | 805 |
iNdEx++ |
| 806 | 806 |
m.Protocol |= (PortConfig_Protocol(b) & 0x7F) << shift |
| 807 | 807 |
if b < 0x80 {
|
| ... | ... |
@@ -820,7 +881,7 @@ func (m *PortConfig) Unmarshal(data []byte) error {
|
| 820 | 820 |
if iNdEx >= l {
|
| 821 | 821 |
return io.ErrUnexpectedEOF |
| 822 | 822 |
} |
| 823 |
- b := data[iNdEx] |
|
| 823 |
+ b := dAtA[iNdEx] |
|
| 824 | 824 |
iNdEx++ |
| 825 | 825 |
m.TargetPort |= (uint32(b) & 0x7F) << shift |
| 826 | 826 |
if b < 0x80 {
|
| ... | ... |
@@ -839,7 +900,7 @@ func (m *PortConfig) Unmarshal(data []byte) error {
|
| 839 | 839 |
if iNdEx >= l {
|
| 840 | 840 |
return io.ErrUnexpectedEOF |
| 841 | 841 |
} |
| 842 |
- b := data[iNdEx] |
|
| 842 |
+ b := dAtA[iNdEx] |
|
| 843 | 843 |
iNdEx++ |
| 844 | 844 |
m.PublishedPort |= (uint32(b) & 0x7F) << shift |
| 845 | 845 |
if b < 0x80 {
|
| ... | ... |
@@ -848,7 +909,7 @@ func (m *PortConfig) Unmarshal(data []byte) error {
|
| 848 | 848 |
} |
| 849 | 849 |
default: |
| 850 | 850 |
iNdEx = preIndex |
| 851 |
- skippy, err := skipAgent(data[iNdEx:]) |
|
| 851 |
+ skippy, err := skipAgent(dAtA[iNdEx:]) |
|
| 852 | 852 |
if err != nil {
|
| 853 | 853 |
return err |
| 854 | 854 |
} |
| ... | ... |
@@ -867,8 +928,8 @@ func (m *PortConfig) Unmarshal(data []byte) error {
|
| 867 | 867 |
} |
| 868 | 868 |
return nil |
| 869 | 869 |
} |
| 870 |
-func skipAgent(data []byte) (n int, err error) {
|
|
| 871 |
- l := len(data) |
|
| 870 |
+func skipAgent(dAtA []byte) (n int, err error) {
|
|
| 871 |
+ l := len(dAtA) |
|
| 872 | 872 |
iNdEx := 0 |
| 873 | 873 |
for iNdEx < l {
|
| 874 | 874 |
var wire uint64 |
| ... | ... |
@@ -879,7 +940,7 @@ func skipAgent(data []byte) (n int, err error) {
|
| 879 | 879 |
if iNdEx >= l {
|
| 880 | 880 |
return 0, io.ErrUnexpectedEOF |
| 881 | 881 |
} |
| 882 |
- b := data[iNdEx] |
|
| 882 |
+ b := dAtA[iNdEx] |
|
| 883 | 883 |
iNdEx++ |
| 884 | 884 |
wire |= (uint64(b) & 0x7F) << shift |
| 885 | 885 |
if b < 0x80 {
|
| ... | ... |
@@ -897,7 +958,7 @@ func skipAgent(data []byte) (n int, err error) {
|
| 897 | 897 |
return 0, io.ErrUnexpectedEOF |
| 898 | 898 |
} |
| 899 | 899 |
iNdEx++ |
| 900 |
- if data[iNdEx-1] < 0x80 {
|
|
| 900 |
+ if dAtA[iNdEx-1] < 0x80 {
|
|
| 901 | 901 |
break |
| 902 | 902 |
} |
| 903 | 903 |
} |
| ... | ... |
@@ -914,7 +975,7 @@ func skipAgent(data []byte) (n int, err error) {
|
| 914 | 914 |
if iNdEx >= l {
|
| 915 | 915 |
return 0, io.ErrUnexpectedEOF |
| 916 | 916 |
} |
| 917 |
- b := data[iNdEx] |
|
| 917 |
+ b := dAtA[iNdEx] |
|
| 918 | 918 |
iNdEx++ |
| 919 | 919 |
length |= (int(b) & 0x7F) << shift |
| 920 | 920 |
if b < 0x80 {
|
| ... | ... |
@@ -937,7 +998,7 @@ func skipAgent(data []byte) (n int, err error) {
|
| 937 | 937 |
if iNdEx >= l {
|
| 938 | 938 |
return 0, io.ErrUnexpectedEOF |
| 939 | 939 |
} |
| 940 |
- b := data[iNdEx] |
|
| 940 |
+ b := dAtA[iNdEx] |
|
| 941 | 941 |
iNdEx++ |
| 942 | 942 |
innerWire |= (uint64(b) & 0x7F) << shift |
| 943 | 943 |
if b < 0x80 {
|
| ... | ... |
@@ -948,7 +1009,7 @@ func skipAgent(data []byte) (n int, err error) {
|
| 948 | 948 |
if innerWireType == 4 {
|
| 949 | 949 |
break |
| 950 | 950 |
} |
| 951 |
- next, err := skipAgent(data[start:]) |
|
| 951 |
+ next, err := skipAgent(dAtA[start:]) |
|
| 952 | 952 |
if err != nil {
|
| 953 | 953 |
return 0, err |
| 954 | 954 |
} |
| ... | ... |
@@ -972,32 +1033,36 @@ var ( |
| 972 | 972 |
ErrIntOverflowAgent = fmt.Errorf("proto: integer overflow")
|
| 973 | 973 |
) |
| 974 | 974 |
|
| 975 |
+func init() { proto.RegisterFile("agent.proto", fileDescriptorAgent) }
|
|
| 976 |
+ |
|
| 975 | 977 |
var fileDescriptorAgent = []byte{
|
| 976 |
- // 413 bytes of a gzipped FileDescriptorProto |
|
| 977 |
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x90, 0xbf, 0xae, 0xd3, 0x30, |
|
| 978 |
- 0x14, 0x87, 0x9b, 0xdb, 0x70, 0x6f, 0x73, 0x72, 0x13, 0xae, 0x2c, 0x84, 0xa2, 0x0e, 0x69, 0xa9, |
|
| 979 |
- 0x84, 0x74, 0x07, 0x94, 0x2b, 0x95, 0xb1, 0x13, 0x6d, 0x19, 0xb2, 0xa0, 0xc8, 0xfc, 0x59, 0xa3, |
|
| 980 |
- 0xb4, 0x31, 0xc1, 0x6a, 0x88, 0x23, 0xdb, 0x2d, 0x2b, 0x23, 0xe2, 0x1d, 0x98, 0x78, 0x19, 0x26, |
|
| 981 |
- 0xc4, 0xc8, 0x84, 0x68, 0x57, 0x16, 0x1e, 0x01, 0xdb, 0x49, 0x5a, 0x21, 0x75, 0x38, 0x92, 0xf3, |
|
| 982 |
- 0xfd, 0xbe, 0xe3, 0x1c, 0x1f, 0x70, 0xb3, 0x82, 0x54, 0x32, 0xaa, 0x39, 0x93, 0x0c, 0x41, 0x49, |
|
| 983 |
- 0x57, 0x15, 0x91, 0x1f, 0x18, 0xdf, 0x0c, 0x1f, 0x14, 0xac, 0x60, 0x06, 0xdf, 0xe9, 0x53, 0x63, |
|
| 984 |
- 0x4c, 0xbe, 0x5f, 0x80, 0xff, 0xbc, 0xca, 0x6b, 0x46, 0x2b, 0x89, 0xc9, 0x9a, 0xf1, 0x1c, 0x21, |
|
| 985 |
- 0xb0, 0xab, 0xec, 0x3d, 0x09, 0xac, 0xb1, 0x75, 0xeb, 0x60, 0x73, 0x46, 0x8f, 0xe0, 0x5a, 0x10, |
|
| 986 |
- 0xbe, 0xa3, 0x6b, 0x92, 0x9a, 0xec, 0xc2, 0x64, 0x6e, 0xcb, 0x5e, 0x68, 0xe5, 0x09, 0x40, 0xa7, |
|
| 987 |
- 0xd0, 0x3c, 0xe8, 0x6b, 0x61, 0xee, 0x1d, 0x7e, 0x8d, 0x9c, 0x97, 0x0d, 0x8d, 0x97, 0xd8, 0x69, |
|
| 988 |
- 0x85, 0x38, 0xd7, 0xf6, 0x8e, 0x72, 0xb9, 0xcd, 0xca, 0x94, 0xd6, 0x81, 0x7d, 0xb2, 0xdf, 0x34, |
|
| 989 |
- 0x34, 0x4e, 0xb0, 0xd3, 0x0a, 0x71, 0x8d, 0xee, 0xc0, 0x25, 0xed, 0x90, 0x5a, 0xbf, 0x67, 0x74, |
|
| 990 |
- 0x5f, 0xe9, 0xd0, 0xcd, 0xae, 0x7c, 0xe8, 0x14, 0xd5, 0x30, 0x03, 0x8f, 0x56, 0x05, 0x27, 0x42, |
|
| 991 |
- 0xa4, 0x35, 0xe3, 0x52, 0x04, 0x97, 0xe3, 0xfe, 0xad, 0x3b, 0x7d, 0x18, 0x9d, 0x16, 0x12, 0x25, |
|
| 992 |
- 0x2a, 0x58, 0xb0, 0xea, 0x2d, 0x2d, 0xf0, 0x75, 0x2b, 0x6b, 0x24, 0x50, 0x00, 0x57, 0x59, 0x49, |
|
| 993 |
- 0x33, 0x41, 0x44, 0x70, 0xa5, 0xda, 0x1c, 0xdc, 0x7d, 0xea, 0x35, 0xc8, 0x4c, 0x6c, 0xd2, 0x2e, |
|
| 994 |
- 0x1e, 0x98, 0xd8, 0xd5, 0xec, 0x59, 0x83, 0x26, 0x7f, 0x2c, 0x80, 0xd3, 0xcd, 0x67, 0x97, 0x39, |
|
| 995 |
- 0x83, 0x81, 0x59, 0xfe, 0x9a, 0x95, 0x66, 0x91, 0xfe, 0x74, 0x74, 0x7e, 0xae, 0x28, 0x69, 0x35, |
|
| 996 |
- 0x7c, 0x6c, 0x40, 0x23, 0x50, 0xbf, 0xe3, 0x05, 0x91, 0xe6, 0x61, 0x66, 0xcf, 0x1e, 0x86, 0x06, |
|
| 997 |
- 0xe9, 0x4e, 0xf4, 0x18, 0xfc, 0x7a, 0xbb, 0x2a, 0xa9, 0x78, 0x47, 0xf2, 0xc6, 0xb1, 0x8d, 0xe3, |
|
| 998 |
- 0x1d, 0xa9, 0xd6, 0x26, 0x4b, 0x18, 0x74, 0xb7, 0xab, 0x07, 0xf7, 0x5f, 0x2d, 0x92, 0x9b, 0xde, |
|
| 999 |
- 0xf0, 0xfe, 0xe7, 0x2f, 0x63, 0xb7, 0xc3, 0x0a, 0xe9, 0xe4, 0xf5, 0x32, 0xb9, 0xb1, 0xfe, 0x4f, |
|
| 1000 |
- 0x14, 0x1a, 0xda, 0x9f, 0xbe, 0x86, 0xbd, 0x79, 0xf0, 0x73, 0x1f, 0xf6, 0xfe, 0xee, 0x43, 0xeb, |
|
| 1001 |
- 0xe3, 0x21, 0xb4, 0xbe, 0xa9, 0xfa, 0xa1, 0xea, 0xb7, 0xaa, 0xd5, 0xa5, 0x99, 0xf8, 0xe9, 0xbf, |
|
| 1002 |
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x63, 0x1a, 0x0f, 0x90, 0x02, 0x00, 0x00, |
|
| 978 |
+ // 437 bytes of a gzipped FileDescriptorProto |
|
| 979 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xc1, 0x6e, 0xd3, 0x30, |
|
| 980 |
+ 0x18, 0xc7, 0x9b, 0x36, 0x6c, 0xcd, 0x97, 0xb6, 0x54, 0x16, 0x42, 0x51, 0x0e, 0x69, 0xa8, 0x84, |
|
| 981 |
+ 0xd4, 0x03, 0xea, 0xa4, 0x71, 0xdc, 0x89, 0xb5, 0x1c, 0x72, 0x41, 0x96, 0xd7, 0x71, 0x0d, 0x69, |
|
| 982 |
+ 0x63, 0x82, 0xb5, 0x10, 0x47, 0xb6, 0x37, 0xae, 0xdc, 0x40, 0x7b, 0x87, 0x9d, 0x78, 0x19, 0x4e, |
|
| 983 |
+ 0x88, 0x23, 0xa7, 0x89, 0xe5, 0x09, 0x78, 0x04, 0x64, 0x27, 0x5e, 0x35, 0x69, 0x37, 0xfb, 0xf7, |
|
| 984 |
+ 0xff, 0xd9, 0xfa, 0xbe, 0x3f, 0xf8, 0x59, 0x41, 0x2b, 0xb5, 0xac, 0x05, 0x57, 0x1c, 0x41, 0xc9, |
|
| 985 |
+ 0xb6, 0x15, 0x55, 0x5f, 0xb8, 0xb8, 0x08, 0x9f, 0x15, 0xbc, 0xe0, 0x06, 0x1f, 0xe9, 0x53, 0x6b, |
|
| 986 |
+ 0xcc, 0x7f, 0xf5, 0x61, 0xf2, 0xb6, 0xca, 0x6b, 0xce, 0x2a, 0x45, 0xe8, 0x8e, 0x8b, 0x1c, 0x21, |
|
| 987 |
+ 0x70, 0xab, 0xec, 0x33, 0x0d, 0x9c, 0xd8, 0x59, 0x78, 0xc4, 0x9c, 0xd1, 0x0b, 0x18, 0x49, 0x2a, |
|
| 988 |
+ 0xae, 0xd8, 0x8e, 0xa6, 0x26, 0xeb, 0x9b, 0xcc, 0xef, 0xd8, 0x3b, 0xad, 0xbc, 0x02, 0xb0, 0x0a, |
|
| 989 |
+ 0xcb, 0x83, 0x81, 0x16, 0x4e, 0xc7, 0xcd, 0xed, 0xcc, 0x3b, 0x6b, 0x69, 0xb2, 0x26, 0x5e, 0x27, |
|
| 990 |
+ 0x24, 0xb9, 0xb6, 0xaf, 0x98, 0x50, 0x97, 0x59, 0x99, 0xb2, 0x3a, 0x70, 0xf7, 0xf6, 0xfb, 0x96, |
|
| 991 |
+ 0x26, 0x98, 0x78, 0x9d, 0x90, 0xd4, 0xe8, 0x08, 0x7c, 0xda, 0x0d, 0xa9, 0xf5, 0x27, 0x46, 0x9f, |
|
| 992 |
+ 0x34, 0xb7, 0x33, 0xb0, 0xb3, 0x27, 0x98, 0x80, 0x55, 0x92, 0x1a, 0x9d, 0xc0, 0x98, 0x55, 0x85, |
|
| 993 |
+ 0xa0, 0x52, 0xa6, 0x35, 0x17, 0x4a, 0x06, 0x07, 0xf1, 0x60, 0xe1, 0x1f, 0x3f, 0x5f, 0xee, 0x0b, |
|
| 994 |
+ 0x59, 0x62, 0x2e, 0xd4, 0x8a, 0x57, 0x1f, 0x59, 0x41, 0x46, 0x9d, 0xac, 0x91, 0x44, 0x01, 0x1c, |
|
| 995 |
+ 0x66, 0x25, 0xcb, 0x24, 0x95, 0xc1, 0x61, 0x3c, 0x58, 0x78, 0xc4, 0x5e, 0x75, 0x0d, 0x2a, 0x93, |
|
| 996 |
+ 0x17, 0xa9, 0x8d, 0x87, 0x26, 0xf6, 0x35, 0x7b, 0xd3, 0xa2, 0xf9, 0xb7, 0x3e, 0xc0, 0xfe, 0xe7, |
|
| 997 |
+ 0x47, 0xcb, 0x3c, 0x81, 0xa1, 0x29, 0x7f, 0xc7, 0x4b, 0x53, 0xe4, 0xe4, 0x78, 0xf6, 0xf8, 0x5c, |
|
| 998 |
+ 0x4b, 0xdc, 0x69, 0xe4, 0xfe, 0x01, 0x9a, 0x81, 0xaf, 0x32, 0x51, 0x50, 0x65, 0x16, 0x33, 0x3d, |
|
| 999 |
+ 0x8f, 0x09, 0xb4, 0x48, 0xbf, 0x44, 0x2f, 0x61, 0x52, 0x5f, 0x6e, 0x4b, 0x26, 0x3f, 0xd1, 0xbc, |
|
| 1000 |
+ 0x75, 0x5c, 0xe3, 0x8c, 0xef, 0xa9, 0xd6, 0xe6, 0x1f, 0x60, 0x68, 0x7f, 0x47, 0x01, 0x0c, 0x36, |
|
| 1001 |
+ 0x2b, 0x3c, 0xed, 0x85, 0x4f, 0xaf, 0x6f, 0x62, 0xdf, 0xe2, 0xcd, 0x0a, 0xeb, 0xe4, 0x7c, 0x8d, |
|
| 1002 |
+ 0xa7, 0xce, 0xc3, 0xe4, 0x7c, 0x8d, 0x51, 0x08, 0xee, 0xd9, 0x6a, 0x83, 0xa7, 0xfd, 0x70, 0x7a, |
|
| 1003 |
+ 0x7d, 0x13, 0x8f, 0x6c, 0xa4, 0x59, 0xe8, 0x7e, 0xff, 0x11, 0xf5, 0x4e, 0x83, 0x3f, 0x77, 0x51, |
|
| 1004 |
+ 0xef, 0xdf, 0x5d, 0xe4, 0x7c, 0x6d, 0x22, 0xe7, 0x67, 0x13, 0x39, 0xbf, 0x9b, 0xc8, 0xf9, 0xdb, |
|
| 1005 |
+ 0x44, 0xce, 0xf6, 0xc0, 0x6c, 0xf3, 0xfa, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xce, 0x12, 0x15, |
|
| 1006 |
+ 0x67, 0xac, 0x02, 0x00, 0x00, |
|
| 1003 | 1007 |
} |
| ... | ... |
@@ -51,6 +51,7 @@ message PortConfig {
|
| 51 | 51 |
|
| 52 | 52 |
TCP = 0 [(gogoproto.enumvalue_customname) = "ProtocolTCP"]; |
| 53 | 53 |
UDP = 1 [(gogoproto.enumvalue_customname) = "ProtocolUDP"]; |
| 54 |
+ SCTP = 2 [(gogoproto.enumvalue_customname) = "ProtocolSCTP"]; |
|
| 54 | 55 |
} |
| 55 | 56 |
|
| 56 | 57 |
// Name for the port. If provided the port information can |
| ... | ... |
@@ -7,6 +7,7 @@ import ( |
| 7 | 7 |
"net" |
| 8 | 8 |
|
| 9 | 9 |
"github.com/docker/libnetwork/types" |
| 10 |
+ "github.com/ishidawataru/sctp" |
|
| 10 | 11 |
"github.com/sirupsen/logrus" |
| 11 | 12 |
) |
| 12 | 13 |
|
| ... | ... |
@@ -92,6 +93,9 @@ func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHos |
| 92 | 92 |
case *net.UDPAddr: |
| 93 | 93 |
bnd.HostPort = uint16(host.(*net.UDPAddr).Port) |
| 94 | 94 |
return nil |
| 95 |
+ case *sctp.SCTPAddr: |
|
| 96 |
+ bnd.HostPort = uint16(host.(*sctp.SCTPAddr).Port) |
|
| 97 |
+ return nil |
|
| 95 | 98 |
default: |
| 96 | 99 |
// For completeness |
| 97 | 100 |
return ErrUnsupportedAddressType(fmt.Sprintf("%T", netAddr))
|
| ... | ... |
@@ -42,4 +42,10 @@ const ( |
| 42 | 42 |
|
| 43 | 43 |
// DisableGatewayDNS label |
| 44 | 44 |
DisableGatewayDNS = "com.docker.network.windowsshim.disable_gatewaydns" |
| 45 |
+ |
|
| 46 |
+ // EnableOutboundNat label |
|
| 47 |
+ EnableOutboundNat = "com.docker.network.windowsshim.enable_outboundnat" |
|
| 48 |
+ |
|
| 49 |
+ // OutboundNatExceptions label |
|
| 50 |
+ OutboundNatExceptions = "com.docker.network.windowsshim.outboundnat_exceptions" |
|
| 45 | 51 |
) |
| ... | ... |
@@ -20,6 +20,7 @@ import ( |
| 20 | 20 |
"sync" |
| 21 | 21 |
|
| 22 | 22 |
"github.com/Microsoft/hcsshim" |
| 23 |
+ "github.com/docker/docker/pkg/system" |
|
| 23 | 24 |
"github.com/docker/libnetwork/datastore" |
| 24 | 25 |
"github.com/docker/libnetwork/discoverapi" |
| 25 | 26 |
"github.com/docker/libnetwork/driverapi" |
| ... | ... |
@@ -30,21 +31,23 @@ import ( |
| 30 | 30 |
|
| 31 | 31 |
// networkConfiguration for network specific configuration |
| 32 | 32 |
type networkConfiguration struct {
|
| 33 |
- ID string |
|
| 34 |
- Type string |
|
| 35 |
- Name string |
|
| 36 |
- HnsID string |
|
| 37 |
- RDID string |
|
| 38 |
- VLAN uint |
|
| 39 |
- VSID uint |
|
| 40 |
- DNSServers string |
|
| 41 |
- MacPools []hcsshim.MacPool |
|
| 42 |
- DNSSuffix string |
|
| 43 |
- SourceMac string |
|
| 44 |
- NetworkAdapterName string |
|
| 45 |
- dbIndex uint64 |
|
| 46 |
- dbExists bool |
|
| 47 |
- DisableGatewayDNS bool |
|
| 33 |
+ ID string |
|
| 34 |
+ Type string |
|
| 35 |
+ Name string |
|
| 36 |
+ HnsID string |
|
| 37 |
+ RDID string |
|
| 38 |
+ VLAN uint |
|
| 39 |
+ VSID uint |
|
| 40 |
+ DNSServers string |
|
| 41 |
+ MacPools []hcsshim.MacPool |
|
| 42 |
+ DNSSuffix string |
|
| 43 |
+ SourceMac string |
|
| 44 |
+ NetworkAdapterName string |
|
| 45 |
+ dbIndex uint64 |
|
| 46 |
+ dbExists bool |
|
| 47 |
+ DisableGatewayDNS bool |
|
| 48 |
+ EnableOutboundNat bool |
|
| 49 |
+ OutboundNatExceptions []string |
|
| 48 | 50 |
} |
| 49 | 51 |
|
| 50 | 52 |
// endpointConfiguration represents the user specified configuration for the sandbox endpoint |
| ... | ... |
@@ -208,6 +211,18 @@ func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string |
| 208 | 208 |
return nil, err |
| 209 | 209 |
} |
| 210 | 210 |
config.VSID = uint(vsid) |
| 211 |
+ case EnableOutboundNat: |
|
| 212 |
+ if system.GetOSVersion().Build <= 16236 {
|
|
| 213 |
+ return nil, fmt.Errorf("Invalid network option. OutboundNat is not supported on this OS version")
|
|
| 214 |
+ } |
|
| 215 |
+ b, err := strconv.ParseBool(value) |
|
| 216 |
+ if err != nil {
|
|
| 217 |
+ return nil, err |
|
| 218 |
+ } |
|
| 219 |
+ config.EnableOutboundNat = b |
|
| 220 |
+ case OutboundNatExceptions: |
|
| 221 |
+ s := strings.Split(value, ",") |
|
| 222 |
+ config.OutboundNatExceptions = s |
|
| 211 | 223 |
} |
| 212 | 224 |
} |
| 213 | 225 |
|
| ... | ... |
@@ -609,6 +624,19 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 609 | 609 |
|
| 610 | 610 |
endpointStruct.DisableICC = epOption.DisableICC |
| 611 | 611 |
|
| 612 |
+ // Inherit OutboundNat policy from the network |
|
| 613 |
+ if n.config.EnableOutboundNat {
|
|
| 614 |
+ outboundNatPolicy, err := json.Marshal(hcsshim.OutboundNatPolicy{
|
|
| 615 |
+ Policy: hcsshim.Policy{Type: hcsshim.OutboundNat},
|
|
| 616 |
+ Exceptions: n.config.OutboundNatExceptions, |
|
| 617 |
+ }) |
|
| 618 |
+ |
|
| 619 |
+ if err != nil {
|
|
| 620 |
+ return err |
|
| 621 |
+ } |
|
| 622 |
+ endpointStruct.Policies = append(endpointStruct.Policies, outboundNatPolicy) |
|
| 623 |
+ } |
|
| 624 |
+ |
|
| 612 | 625 |
configurationb, err := json.Marshal(endpointStruct) |
| 613 | 626 |
if err != nil {
|
| 614 | 627 |
return err |
| ... | ... |
@@ -276,7 +276,31 @@ func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr |
| 276 | 276 |
"--dport", strconv.Itoa(destPort), |
| 277 | 277 |
"-j", "MASQUERADE", |
| 278 | 278 |
} |
| 279 |
- return ProgramRule(Nat, "POSTROUTING", action, args) |
|
| 279 |
+ |
|
| 280 |
+ if err := ProgramRule(Nat, "POSTROUTING", action, args); err != nil {
|
|
| 281 |
+ return err |
|
| 282 |
+ } |
|
| 283 |
+ |
|
| 284 |
+ if proto == "sctp" {
|
|
| 285 |
+ // Linux kernel v4.9 and below enables NETIF_F_SCTP_CRC for veth by |
|
| 286 |
+ // the following commit. |
|
| 287 |
+ // This introduces a problem when conbined with a physical NIC without |
|
| 288 |
+ // NETIF_F_SCTP_CRC. As for a workaround, here we add an iptables entry |
|
| 289 |
+ // to fill the checksum. |
|
| 290 |
+ // |
|
| 291 |
+ // https://github.com/torvalds/linux/commit/c80fafbbb59ef9924962f83aac85531039395b18 |
|
| 292 |
+ args = []string{
|
|
| 293 |
+ "-p", proto, |
|
| 294 |
+ "--sport", strconv.Itoa(destPort), |
|
| 295 |
+ "-j", "CHECKSUM", |
|
| 296 |
+ "--checksum-fill", |
|
| 297 |
+ } |
|
| 298 |
+ if err := ProgramRule(Mangle, "POSTROUTING", action, args); err != nil {
|
|
| 299 |
+ return err |
|
| 300 |
+ } |
|
| 301 |
+ } |
|
| 302 |
+ |
|
| 303 |
+ return nil |
|
| 280 | 304 |
} |
| 281 | 305 |
|
| 282 | 306 |
// Link adds reciprocal ACCEPT rule for two supplied IP addresses. |
| ... | ... |
@@ -120,7 +120,7 @@ func (p *PortAllocator) RequestPortInRange(ip net.IP, proto string, portStart, p |
| 120 | 120 |
p.mutex.Lock() |
| 121 | 121 |
defer p.mutex.Unlock() |
| 122 | 122 |
|
| 123 |
- if proto != "tcp" && proto != "udp" {
|
|
| 123 |
+ if proto != "tcp" && proto != "udp" && proto != "sctp" {
|
|
| 124 | 124 |
return 0, ErrUnknownProtocol |
| 125 | 125 |
} |
| 126 | 126 |
|
| ... | ... |
@@ -131,8 +131,9 @@ func (p *PortAllocator) RequestPortInRange(ip net.IP, proto string, portStart, p |
| 131 | 131 |
protomap, ok := p.ipMap[ipstr] |
| 132 | 132 |
if !ok {
|
| 133 | 133 |
protomap = protoMap{
|
| 134 |
- "tcp": p.newPortMap(), |
|
| 135 |
- "udp": p.newPortMap(), |
|
| 134 |
+ "tcp": p.newPortMap(), |
|
| 135 |
+ "udp": p.newPortMap(), |
|
| 136 |
+ "sctp": p.newPortMap(), |
|
| 136 | 137 |
} |
| 137 | 138 |
|
| 138 | 139 |
p.ipMap[ipstr] = protomap |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
"github.com/docker/libnetwork/iptables" |
| 10 | 10 |
"github.com/docker/libnetwork/portallocator" |
| 11 |
+ "github.com/ishidawataru/sctp" |
|
| 11 | 12 |
"github.com/sirupsen/logrus" |
| 12 | 13 |
) |
| 13 | 14 |
|
| ... | ... |
@@ -27,6 +28,8 @@ var ( |
| 27 | 27 |
ErrPortMappedForIP = errors.New("port is already mapped to ip")
|
| 28 | 28 |
// ErrPortNotMapped refers to an unmapped port |
| 29 | 29 |
ErrPortNotMapped = errors.New("port is not mapped")
|
| 30 |
+ // ErrSCTPAddrNoIP refers to a SCTP address without IP address. |
|
| 31 |
+ ErrSCTPAddrNoIP = errors.New("sctp address does not contain any IP address")
|
|
| 30 | 32 |
) |
| 31 | 33 |
|
| 32 | 34 |
// PortMapper manages the network address translation |
| ... | ... |
@@ -98,7 +101,10 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, |
| 98 | 98 |
return nil, err |
| 99 | 99 |
} |
| 100 | 100 |
} else {
|
| 101 |
- m.userlandProxy = newDummyProxy(proto, hostIP, allocatedHostPort) |
|
| 101 |
+ m.userlandProxy, err = newDummyProxy(proto, hostIP, allocatedHostPort) |
|
| 102 |
+ if err != nil {
|
|
| 103 |
+ return nil, err |
|
| 104 |
+ } |
|
| 102 | 105 |
} |
| 103 | 106 |
case *net.UDPAddr: |
| 104 | 107 |
proto = "udp" |
| ... | ... |
@@ -118,7 +124,37 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, |
| 118 | 118 |
return nil, err |
| 119 | 119 |
} |
| 120 | 120 |
} else {
|
| 121 |
- m.userlandProxy = newDummyProxy(proto, hostIP, allocatedHostPort) |
|
| 121 |
+ m.userlandProxy, err = newDummyProxy(proto, hostIP, allocatedHostPort) |
|
| 122 |
+ if err != nil {
|
|
| 123 |
+ return nil, err |
|
| 124 |
+ } |
|
| 125 |
+ } |
|
| 126 |
+ case *sctp.SCTPAddr: |
|
| 127 |
+ proto = "sctp" |
|
| 128 |
+ if allocatedHostPort, err = pm.Allocator.RequestPortInRange(hostIP, proto, hostPortStart, hostPortEnd); err != nil {
|
|
| 129 |
+ return nil, err |
|
| 130 |
+ } |
|
| 131 |
+ |
|
| 132 |
+ m = &mapping{
|
|
| 133 |
+ proto: proto, |
|
| 134 |
+ host: &sctp.SCTPAddr{IP: []net.IP{hostIP}, Port: allocatedHostPort},
|
|
| 135 |
+ container: container, |
|
| 136 |
+ } |
|
| 137 |
+ |
|
| 138 |
+ if useProxy {
|
|
| 139 |
+ sctpAddr := container.(*sctp.SCTPAddr) |
|
| 140 |
+ if len(sctpAddr.IP) == 0 {
|
|
| 141 |
+ return nil, ErrSCTPAddrNoIP |
|
| 142 |
+ } |
|
| 143 |
+ m.userlandProxy, err = newProxy(proto, hostIP, allocatedHostPort, sctpAddr.IP[0], sctpAddr.Port, pm.proxyPath) |
|
| 144 |
+ if err != nil {
|
|
| 145 |
+ return nil, err |
|
| 146 |
+ } |
|
| 147 |
+ } else {
|
|
| 148 |
+ m.userlandProxy, err = newDummyProxy(proto, hostIP, allocatedHostPort) |
|
| 149 |
+ if err != nil {
|
|
| 150 |
+ return nil, err |
|
| 151 |
+ } |
|
| 122 | 152 |
} |
| 123 | 153 |
default: |
| 124 | 154 |
return nil, ErrUnknownBackendAddressType |
| ... | ... |
@@ -195,8 +231,13 @@ func (pm *PortMapper) Unmap(host net.Addr) error {
|
| 195 | 195 |
return pm.Allocator.ReleasePort(a.IP, "tcp", a.Port) |
| 196 | 196 |
case *net.UDPAddr: |
| 197 | 197 |
return pm.Allocator.ReleasePort(a.IP, "udp", a.Port) |
| 198 |
+ case *sctp.SCTPAddr: |
|
| 199 |
+ if len(a.IP) == 0 {
|
|
| 200 |
+ return ErrSCTPAddrNoIP |
|
| 201 |
+ } |
|
| 202 |
+ return pm.Allocator.ReleasePort(a.IP[0], "sctp", a.Port) |
|
| 198 | 203 |
} |
| 199 |
- return nil |
|
| 204 |
+ return ErrUnknownBackendAddressType |
|
| 200 | 205 |
} |
| 201 | 206 |
|
| 202 | 207 |
//ReMapAll will re-apply all port mappings |
| ... | ... |
@@ -219,6 +260,12 @@ func getKey(a net.Addr) string {
|
| 219 | 219 |
return fmt.Sprintf("%s:%d/%s", t.IP.String(), t.Port, "tcp")
|
| 220 | 220 |
case *net.UDPAddr: |
| 221 | 221 |
return fmt.Sprintf("%s:%d/%s", t.IP.String(), t.Port, "udp")
|
| 222 |
+ case *sctp.SCTPAddr: |
|
| 223 |
+ if len(t.IP) == 0 {
|
|
| 224 |
+ logrus.Error(ErrSCTPAddrNoIP) |
|
| 225 |
+ return "" |
|
| 226 |
+ } |
|
| 227 |
+ return fmt.Sprintf("%s:%d/%s", t.IP[0].String(), t.Port, "sctp")
|
|
| 222 | 228 |
} |
| 223 | 229 |
return "" |
| 224 | 230 |
} |
| ... | ... |
@@ -229,6 +276,12 @@ func getIPAndPort(a net.Addr) (net.IP, int) {
|
| 229 | 229 |
return t.IP, t.Port |
| 230 | 230 |
case *net.UDPAddr: |
| 231 | 231 |
return t.IP, t.Port |
| 232 |
+ case *sctp.SCTPAddr: |
|
| 233 |
+ if len(t.IP) == 0 {
|
|
| 234 |
+ logrus.Error(ErrSCTPAddrNoIP) |
|
| 235 |
+ return nil, 0 |
|
| 236 |
+ } |
|
| 237 |
+ return t.IP[0], t.Port |
|
| 232 | 238 |
} |
| 233 | 239 |
return nil, 0 |
| 234 | 240 |
} |
| ... | ... |
@@ -8,6 +8,8 @@ import ( |
| 8 | 8 |
"os" |
| 9 | 9 |
"os/exec" |
| 10 | 10 |
"time" |
| 11 |
+ |
|
| 12 |
+ "github.com/ishidawataru/sctp" |
|
| 11 | 13 |
) |
| 12 | 14 |
|
| 13 | 15 |
var userlandProxyCommandName = "docker-proxy" |
| ... | ... |
@@ -79,16 +81,20 @@ type dummyProxy struct {
|
| 79 | 79 |
addr net.Addr |
| 80 | 80 |
} |
| 81 | 81 |
|
| 82 |
-func newDummyProxy(proto string, hostIP net.IP, hostPort int) userlandProxy {
|
|
| 82 |
+func newDummyProxy(proto string, hostIP net.IP, hostPort int) (userlandProxy, error) {
|
|
| 83 | 83 |
switch proto {
|
| 84 | 84 |
case "tcp": |
| 85 | 85 |
addr := &net.TCPAddr{IP: hostIP, Port: hostPort}
|
| 86 |
- return &dummyProxy{addr: addr}
|
|
| 86 |
+ return &dummyProxy{addr: addr}, nil
|
|
| 87 | 87 |
case "udp": |
| 88 | 88 |
addr := &net.UDPAddr{IP: hostIP, Port: hostPort}
|
| 89 |
- return &dummyProxy{addr: addr}
|
|
| 89 |
+ return &dummyProxy{addr: addr}, nil
|
|
| 90 |
+ case "sctp": |
|
| 91 |
+ addr := &sctp.SCTPAddr{IP: []net.IP{hostIP}, Port: hostPort}
|
|
| 92 |
+ return &dummyProxy{addr: addr}, nil
|
|
| 93 |
+ default: |
|
| 94 |
+ return nil, fmt.Errorf("Unknown addr type: %s", proto)
|
|
| 90 | 95 |
} |
| 91 |
- return nil |
|
| 92 | 96 |
} |
| 93 | 97 |
|
| 94 | 98 |
func (p *dummyProxy) Start() error {
|
| ... | ... |
@@ -105,6 +111,12 @@ func (p *dummyProxy) Start() error {
|
| 105 | 105 |
return err |
| 106 | 106 |
} |
| 107 | 107 |
p.listener = l |
| 108 |
+ case *sctp.SCTPAddr: |
|
| 109 |
+ l, err := sctp.ListenSCTP("sctp", addr)
|
|
| 110 |
+ if err != nil {
|
|
| 111 |
+ return err |
|
| 112 |
+ } |
|
| 113 |
+ p.listener = l |
|
| 108 | 114 |
default: |
| 109 | 115 |
return fmt.Errorf("Unknown addr type: %T", p.addr)
|
| 110 | 116 |
} |
| ... | ... |
@@ -19,6 +19,7 @@ import ( |
| 19 | 19 |
"github.com/docker/libnetwork/ipvs" |
| 20 | 20 |
"github.com/docker/libnetwork/ns" |
| 21 | 21 |
"github.com/gogo/protobuf/proto" |
| 22 |
+ "github.com/ishidawataru/sctp" |
|
| 22 | 23 |
"github.com/sirupsen/logrus" |
| 23 | 24 |
"github.com/vishvananda/netlink/nl" |
| 24 | 25 |
"github.com/vishvananda/netns" |
| ... | ... |
@@ -503,6 +504,10 @@ func plumbProxy(iPort *PortConfig, isDelete bool) error {
|
| 503 | 503 |
l, err = net.ListenTCP("tcp", &net.TCPAddr{Port: int(iPort.PublishedPort)})
|
| 504 | 504 |
case ProtocolUDP: |
| 505 | 505 |
l, err = net.ListenUDP("udp", &net.UDPAddr{Port: int(iPort.PublishedPort)})
|
| 506 |
+ case ProtocolSCTP: |
|
| 507 |
+ l, err = sctp.ListenSCTP("sctp", &sctp.SCTPAddr{Port: int(iPort.PublishedPort)})
|
|
| 508 |
+ default: |
|
| 509 |
+ err = fmt.Errorf("unknown protocol %v", iPort.Protocol)
|
|
| 506 | 510 |
} |
| 507 | 511 |
|
| 508 | 512 |
if err != nil {
|
| ... | ... |
@@ -761,6 +766,7 @@ func redirecter() {
|
| 761 | 761 |
|
| 762 | 762 |
// Ensure blocking rules for anything else in/to ingress network |
| 763 | 763 |
for _, rule := range [][]string{
|
| 764 |
+ {"-d", eIP.String(), "-p", "sctp", "-j", "DROP"},
|
|
| 764 | 765 |
{"-d", eIP.String(), "-p", "udp", "-j", "DROP"},
|
| 765 | 766 |
{"-d", eIP.String(), "-p", "tcp", "-j", "DROP"},
|
| 766 | 767 |
} {
|
| ... | ... |
@@ -7,6 +7,8 @@ import ( |
| 7 | 7 |
"net" |
| 8 | 8 |
"strconv" |
| 9 | 9 |
"strings" |
| 10 |
+ |
|
| 11 |
+ "github.com/ishidawataru/sctp" |
|
| 10 | 12 |
) |
| 11 | 13 |
|
| 12 | 14 |
// constants for the IP address type |
| ... | ... |
@@ -96,6 +98,8 @@ func (p PortBinding) HostAddr() (net.Addr, error) {
|
| 96 | 96 |
return &net.UDPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
|
| 97 | 97 |
case TCP: |
| 98 | 98 |
return &net.TCPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
|
| 99 |
+ case SCTP: |
|
| 100 |
+ return &sctp.SCTPAddr{IP: []net.IP{p.HostIP}, Port: int(p.HostPort)}, nil
|
|
| 99 | 101 |
default: |
| 100 | 102 |
return nil, ErrInvalidProtocolBinding(p.Proto.String()) |
| 101 | 103 |
} |
| ... | ... |
@@ -108,6 +112,8 @@ func (p PortBinding) ContainerAddr() (net.Addr, error) {
|
| 108 | 108 |
return &net.UDPAddr{IP: p.IP, Port: int(p.Port)}, nil
|
| 109 | 109 |
case TCP: |
| 110 | 110 |
return &net.TCPAddr{IP: p.IP, Port: int(p.Port)}, nil
|
| 111 |
+ case SCTP: |
|
| 112 |
+ return &sctp.SCTPAddr{IP: []net.IP{p.IP}, Port: int(p.Port)}, nil
|
|
| 111 | 113 |
default: |
| 112 | 114 |
return nil, ErrInvalidProtocolBinding(p.Proto.String()) |
| 113 | 115 |
} |
| ... | ... |
@@ -233,6 +239,8 @@ const ( |
| 233 | 233 |
TCP = 6 |
| 234 | 234 |
// UDP is for the UDP ip protocol |
| 235 | 235 |
UDP = 17 |
| 236 |
+ // SCTP is for the SCTP ip protocol |
|
| 237 |
+ SCTP = 132 |
|
| 236 | 238 |
) |
| 237 | 239 |
|
| 238 | 240 |
// Protocol represents an IP protocol number |
| ... | ... |
@@ -246,6 +254,8 @@ func (p Protocol) String() string {
|
| 246 | 246 |
return "tcp" |
| 247 | 247 |
case UDP: |
| 248 | 248 |
return "udp" |
| 249 |
+ case SCTP: |
|
| 250 |
+ return "sctp" |
|
| 249 | 251 |
default: |
| 250 | 252 |
return fmt.Sprintf("%d", p)
|
| 251 | 253 |
} |
| ... | ... |
@@ -260,6 +270,8 @@ func ParseProtocol(s string) Protocol {
|
| 260 | 260 |
return UDP |
| 261 | 261 |
case "tcp": |
| 262 | 262 |
return TCP |
| 263 |
+ case "sctp": |
|
| 264 |
+ return SCTP |
|
| 263 | 265 |
default: |
| 264 | 266 |
return 0 |
| 265 | 267 |
} |
| ... | ... |
@@ -51,3 +51,4 @@ golang.org/x/crypto 558b6879de74bc843225cde5686419267ff707ca |
| 51 | 51 |
golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 |
| 52 | 52 |
golang.org/x/sys 07c182904dbd53199946ba614a412c61d3c548f5 |
| 53 | 53 |
github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9 |
| 54 |
+github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb |
| 54 | 55 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,201 @@ |
| 0 |
+ Apache License |
|
| 1 |
+ Version 2.0, January 2004 |
|
| 2 |
+ http://www.apache.org/licenses/ |
|
| 3 |
+ |
|
| 4 |
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
|
| 5 |
+ |
|
| 6 |
+ 1. Definitions. |
|
| 7 |
+ |
|
| 8 |
+ "License" shall mean the terms and conditions for use, reproduction, |
|
| 9 |
+ and distribution as defined by Sections 1 through 9 of this document. |
|
| 10 |
+ |
|
| 11 |
+ "Licensor" shall mean the copyright owner or entity authorized by |
|
| 12 |
+ the copyright owner that is granting the License. |
|
| 13 |
+ |
|
| 14 |
+ "Legal Entity" shall mean the union of the acting entity and all |
|
| 15 |
+ other entities that control, are controlled by, or are under common |
|
| 16 |
+ control with that entity. For the purposes of this definition, |
|
| 17 |
+ "control" means (i) the power, direct or indirect, to cause the |
|
| 18 |
+ direction or management of such entity, whether by contract or |
|
| 19 |
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the |
|
| 20 |
+ outstanding shares, or (iii) beneficial ownership of such entity. |
|
| 21 |
+ |
|
| 22 |
+ "You" (or "Your") shall mean an individual or Legal Entity |
|
| 23 |
+ exercising permissions granted by this License. |
|
| 24 |
+ |
|
| 25 |
+ "Source" form shall mean the preferred form for making modifications, |
|
| 26 |
+ including but not limited to software source code, documentation |
|
| 27 |
+ source, and configuration files. |
|
| 28 |
+ |
|
| 29 |
+ "Object" form shall mean any form resulting from mechanical |
|
| 30 |
+ transformation or translation of a Source form, including but |
|
| 31 |
+ not limited to compiled object code, generated documentation, |
|
| 32 |
+ and conversions to other media types. |
|
| 33 |
+ |
|
| 34 |
+ "Work" shall mean the work of authorship, whether in Source or |
|
| 35 |
+ Object form, made available under the License, as indicated by a |
|
| 36 |
+ copyright notice that is included in or attached to the work |
|
| 37 |
+ (an example is provided in the Appendix below). |
|
| 38 |
+ |
|
| 39 |
+ "Derivative Works" shall mean any work, whether in Source or Object |
|
| 40 |
+ form, that is based on (or derived from) the Work and for which the |
|
| 41 |
+ editorial revisions, annotations, elaborations, or other modifications |
|
| 42 |
+ represent, as a whole, an original work of authorship. For the purposes |
|
| 43 |
+ of this License, Derivative Works shall not include works that remain |
|
| 44 |
+ separable from, or merely link (or bind by name) to the interfaces of, |
|
| 45 |
+ the Work and Derivative Works thereof. |
|
| 46 |
+ |
|
| 47 |
+ "Contribution" shall mean any work of authorship, including |
|
| 48 |
+ the original version of the Work and any modifications or additions |
|
| 49 |
+ to that Work or Derivative Works thereof, that is intentionally |
|
| 50 |
+ submitted to Licensor for inclusion in the Work by the copyright owner |
|
| 51 |
+ or by an individual or Legal Entity authorized to submit on behalf of |
|
| 52 |
+ the copyright owner. For the purposes of this definition, "submitted" |
|
| 53 |
+ means any form of electronic, verbal, or written communication sent |
|
| 54 |
+ to the Licensor or its representatives, including but not limited to |
|
| 55 |
+ communication on electronic mailing lists, source code control systems, |
|
| 56 |
+ and issue tracking systems that are managed by, or on behalf of, the |
|
| 57 |
+ Licensor for the purpose of discussing and improving the Work, but |
|
| 58 |
+ excluding communication that is conspicuously marked or otherwise |
|
| 59 |
+ designated in writing by the copyright owner as "Not a Contribution." |
|
| 60 |
+ |
|
| 61 |
+ "Contributor" shall mean Licensor and any individual or Legal Entity |
|
| 62 |
+ on behalf of whom a Contribution has been received by Licensor and |
|
| 63 |
+ subsequently incorporated within the Work. |
|
| 64 |
+ |
|
| 65 |
+ 2. Grant of Copyright License. Subject to the terms and conditions of |
|
| 66 |
+ this License, each Contributor hereby grants to You a perpetual, |
|
| 67 |
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|
| 68 |
+ copyright license to reproduce, prepare Derivative Works of, |
|
| 69 |
+ publicly display, publicly perform, sublicense, and distribute the |
|
| 70 |
+ Work and such Derivative Works in Source or Object form. |
|
| 71 |
+ |
|
| 72 |
+ 3. Grant of Patent License. Subject to the terms and conditions of |
|
| 73 |
+ this License, each Contributor hereby grants to You a perpetual, |
|
| 74 |
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
|
| 75 |
+ (except as stated in this section) patent license to make, have made, |
|
| 76 |
+ use, offer to sell, sell, import, and otherwise transfer the Work, |
|
| 77 |
+ where such license applies only to those patent claims licensable |
|
| 78 |
+ by such Contributor that are necessarily infringed by their |
|
| 79 |
+ Contribution(s) alone or by combination of their Contribution(s) |
|
| 80 |
+ with the Work to which such Contribution(s) was submitted. If You |
|
| 81 |
+ institute patent litigation against any entity (including a |
|
| 82 |
+ cross-claim or counterclaim in a lawsuit) alleging that the Work |
|
| 83 |
+ or a Contribution incorporated within the Work constitutes direct |
|
| 84 |
+ or contributory patent infringement, then any patent licenses |
|
| 85 |
+ granted to You under this License for that Work shall terminate |
|
| 86 |
+ as of the date such litigation is filed. |
|
| 87 |
+ |
|
| 88 |
+ 4. Redistribution. You may reproduce and distribute copies of the |
|
| 89 |
+ Work or Derivative Works thereof in any medium, with or without |
|
| 90 |
+ modifications, and in Source or Object form, provided that You |
|
| 91 |
+ meet the following conditions: |
|
| 92 |
+ |
|
| 93 |
+ (a) You must give any other recipients of the Work or |
|
| 94 |
+ Derivative Works a copy of this License; and |
|
| 95 |
+ |
|
| 96 |
+ (b) You must cause any modified files to carry prominent notices |
|
| 97 |
+ stating that You changed the files; and |
|
| 98 |
+ |
|
| 99 |
+ (c) You must retain, in the Source form of any Derivative Works |
|
| 100 |
+ that You distribute, all copyright, patent, trademark, and |
|
| 101 |
+ attribution notices from the Source form of the Work, |
|
| 102 |
+ excluding those notices that do not pertain to any part of |
|
| 103 |
+ the Derivative Works; and |
|
| 104 |
+ |
|
| 105 |
+ (d) If the Work includes a "NOTICE" text file as part of its |
|
| 106 |
+ distribution, then any Derivative Works that You distribute must |
|
| 107 |
+ include a readable copy of the attribution notices contained |
|
| 108 |
+ within such NOTICE file, excluding those notices that do not |
|
| 109 |
+ pertain to any part of the Derivative Works, in at least one |
|
| 110 |
+ of the following places: within a NOTICE text file distributed |
|
| 111 |
+ as part of the Derivative Works; within the Source form or |
|
| 112 |
+ documentation, if provided along with the Derivative Works; or, |
|
| 113 |
+ within a display generated by the Derivative Works, if and |
|
| 114 |
+ wherever such third-party notices normally appear. The contents |
|
| 115 |
+ of the NOTICE file are for informational purposes only and |
|
| 116 |
+ do not modify the License. You may add Your own attribution |
|
| 117 |
+ notices within Derivative Works that You distribute, alongside |
|
| 118 |
+ or as an addendum to the NOTICE text from the Work, provided |
|
| 119 |
+ that such additional attribution notices cannot be construed |
|
| 120 |
+ as modifying the License. |
|
| 121 |
+ |
|
| 122 |
+ You may add Your own copyright statement to Your modifications and |
|
| 123 |
+ may provide additional or different license terms and conditions |
|
| 124 |
+ for use, reproduction, or distribution of Your modifications, or |
|
| 125 |
+ for any such Derivative Works as a whole, provided Your use, |
|
| 126 |
+ reproduction, and distribution of the Work otherwise complies with |
|
| 127 |
+ the conditions stated in this License. |
|
| 128 |
+ |
|
| 129 |
+ 5. Submission of Contributions. Unless You explicitly state otherwise, |
|
| 130 |
+ any Contribution intentionally submitted for inclusion in the Work |
|
| 131 |
+ by You to the Licensor shall be under the terms and conditions of |
|
| 132 |
+ this License, without any additional terms or conditions. |
|
| 133 |
+ Notwithstanding the above, nothing herein shall supersede or modify |
|
| 134 |
+ the terms of any separate license agreement you may have executed |
|
| 135 |
+ with Licensor regarding such Contributions. |
|
| 136 |
+ |
|
| 137 |
+ 6. Trademarks. This License does not grant permission to use the trade |
|
| 138 |
+ names, trademarks, service marks, or product names of the Licensor, |
|
| 139 |
+ except as required for reasonable and customary use in describing the |
|
| 140 |
+ origin of the Work and reproducing the content of the NOTICE file. |
|
| 141 |
+ |
|
| 142 |
+ 7. Disclaimer of Warranty. Unless required by applicable law or |
|
| 143 |
+ agreed to in writing, Licensor provides the Work (and each |
|
| 144 |
+ Contributor provides its Contributions) on an "AS IS" BASIS, |
|
| 145 |
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
|
| 146 |
+ implied, including, without limitation, any warranties or conditions |
|
| 147 |
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
|
| 148 |
+ PARTICULAR PURPOSE. You are solely responsible for determining the |
|
| 149 |
+ appropriateness of using or redistributing the Work and assume any |
|
| 150 |
+ risks associated with Your exercise of permissions under this License. |
|
| 151 |
+ |
|
| 152 |
+ 8. Limitation of Liability. In no event and under no legal theory, |
|
| 153 |
+ whether in tort (including negligence), contract, or otherwise, |
|
| 154 |
+ unless required by applicable law (such as deliberate and grossly |
|
| 155 |
+ negligent acts) or agreed to in writing, shall any Contributor be |
|
| 156 |
+ liable to You for damages, including any direct, indirect, special, |
|
| 157 |
+ incidental, or consequential damages of any character arising as a |
|
| 158 |
+ result of this License or out of the use or inability to use the |
|
| 159 |
+ Work (including but not limited to damages for loss of goodwill, |
|
| 160 |
+ work stoppage, computer failure or malfunction, or any and all |
|
| 161 |
+ other commercial damages or losses), even if such Contributor |
|
| 162 |
+ has been advised of the possibility of such damages. |
|
| 163 |
+ |
|
| 164 |
+ 9. Accepting Warranty or Additional Liability. While redistributing |
|
| 165 |
+ the Work or Derivative Works thereof, You may choose to offer, |
|
| 166 |
+ and charge a fee for, acceptance of support, warranty, indemnity, |
|
| 167 |
+ or other liability obligations and/or rights consistent with this |
|
| 168 |
+ License. However, in accepting such obligations, You may act only |
|
| 169 |
+ on Your own behalf and on Your sole responsibility, not on behalf |
|
| 170 |
+ of any other Contributor, and only if You agree to indemnify, |
|
| 171 |
+ defend, and hold each Contributor harmless for any liability |
|
| 172 |
+ incurred by, or claims asserted against, such Contributor by reason |
|
| 173 |
+ of your accepting any such warranty or additional liability. |
|
| 174 |
+ |
|
| 175 |
+ END OF TERMS AND CONDITIONS |
|
| 176 |
+ |
|
| 177 |
+ APPENDIX: How to apply the Apache License to your work. |
|
| 178 |
+ |
|
| 179 |
+ To apply the Apache License to your work, attach the following |
|
| 180 |
+ boilerplate notice, with the fields enclosed by brackets "{}"
|
|
| 181 |
+ replaced with your own identifying information. (Don't include |
|
| 182 |
+ the brackets!) The text should be enclosed in the appropriate |
|
| 183 |
+ comment syntax for the file format. We also recommend that a |
|
| 184 |
+ file or class name and description of purpose be included on the |
|
| 185 |
+ same "printed page" as the copyright notice for easier |
|
| 186 |
+ identification within third-party archives. |
|
| 187 |
+ |
|
| 188 |
+ Copyright {yyyy} {name of copyright owner}
|
|
| 189 |
+ |
|
| 190 |
+ Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 191 |
+ you may not use this file except in compliance with the License. |
|
| 192 |
+ You may obtain a copy of the License at |
|
| 193 |
+ |
|
| 194 |
+ http://www.apache.org/licenses/LICENSE-2.0 |
|
| 195 |
+ |
|
| 196 |
+ Unless required by applicable law or agreed to in writing, software |
|
| 197 |
+ distributed under the License is distributed on an "AS IS" BASIS, |
|
| 198 |
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 199 |
+ See the License for the specific language governing permissions and |
|
| 200 |
+ limitations under the License. |
| 0 | 201 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+Stream Control Transmission Protocol (SCTP) |
|
| 1 |
+---- |
|
| 2 |
+ |
|
| 3 |
+[](https://travis-ci.org/ishidawataru/sctp/builds) |
|
| 4 |
+ |
|
| 5 |
+Examples |
|
| 6 |
+---- |
|
| 7 |
+ |
|
| 8 |
+See `example/sctp.go` |
|
| 9 |
+ |
|
| 10 |
+```go |
|
| 11 |
+$ cd example |
|
| 12 |
+$ go build |
|
| 13 |
+$ # run example SCTP server |
|
| 14 |
+$ ./example -server -port 1000 -ip 10.10.0.1,10.20.0.1 |
|
| 15 |
+$ # run example SCTP client |
|
| 16 |
+$ ./example -port 1000 -ip 10.10.0.1,10.20.0.1 |
|
| 17 |
+``` |
| 0 | 18 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,656 @@ |
| 0 |
+package sctp |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "encoding/binary" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "net" |
|
| 7 |
+ "strconv" |
|
| 8 |
+ "strings" |
|
| 9 |
+ "sync" |
|
| 10 |
+ "sync/atomic" |
|
| 11 |
+ "syscall" |
|
| 12 |
+ "time" |
|
| 13 |
+ "unsafe" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+const ( |
|
| 17 |
+ SOL_SCTP = 132 |
|
| 18 |
+ |
|
| 19 |
+ SCTP_BINDX_ADD_ADDR = 0x01 |
|
| 20 |
+ SCTP_BINDX_REM_ADDR = 0x02 |
|
| 21 |
+ |
|
| 22 |
+ MSG_NOTIFICATION = 0x8000 |
|
| 23 |
+) |
|
| 24 |
+ |
|
| 25 |
+const ( |
|
| 26 |
+ SCTP_RTOINFO = iota |
|
| 27 |
+ SCTP_ASSOCINFO |
|
| 28 |
+ SCTP_INITMSG |
|
| 29 |
+ SCTP_NODELAY |
|
| 30 |
+ SCTP_AUTOCLOSE |
|
| 31 |
+ SCTP_SET_PEER_PRIMARY_ADDR |
|
| 32 |
+ SCTP_PRIMARY_ADDR |
|
| 33 |
+ SCTP_ADAPTATION_LAYER |
|
| 34 |
+ SCTP_DISABLE_FRAGMENTS |
|
| 35 |
+ SCTP_PEER_ADDR_PARAMS |
|
| 36 |
+ SCTP_DEFAULT_SENT_PARAM |
|
| 37 |
+ SCTP_EVENTS |
|
| 38 |
+ SCTP_I_WANT_MAPPED_V4_ADDR |
|
| 39 |
+ SCTP_MAXSEG |
|
| 40 |
+ SCTP_STATUS |
|
| 41 |
+ SCTP_GET_PEER_ADDR_INFO |
|
| 42 |
+ SCTP_DELAYED_ACK_TIME |
|
| 43 |
+ SCTP_DELAYED_ACK = SCTP_DELAYED_ACK_TIME |
|
| 44 |
+ SCTP_DELAYED_SACK = SCTP_DELAYED_ACK_TIME |
|
| 45 |
+ |
|
| 46 |
+ SCTP_SOCKOPT_BINDX_ADD = 100 |
|
| 47 |
+ SCTP_SOCKOPT_BINDX_REM = 101 |
|
| 48 |
+ SCTP_SOCKOPT_PEELOFF = 102 |
|
| 49 |
+ SCTP_GET_PEER_ADDRS = 108 |
|
| 50 |
+ SCTP_GET_LOCAL_ADDRS = 109 |
|
| 51 |
+ SCTP_SOCKOPT_CONNECTX = 110 |
|
| 52 |
+ SCTP_SOCKOPT_CONNECTX3 = 111 |
|
| 53 |
+) |
|
| 54 |
+ |
|
| 55 |
+const ( |
|
| 56 |
+ SCTP_EVENT_DATA_IO = 1 << iota |
|
| 57 |
+ SCTP_EVENT_ASSOCIATION |
|
| 58 |
+ SCTP_EVENT_ADDRESS |
|
| 59 |
+ SCTP_EVENT_SEND_FAILURE |
|
| 60 |
+ SCTP_EVENT_PEER_ERROR |
|
| 61 |
+ SCTP_EVENT_SHUTDOWN |
|
| 62 |
+ SCTP_EVENT_PARTIAL_DELIVERY |
|
| 63 |
+ SCTP_EVENT_ADAPTATION_LAYER |
|
| 64 |
+ SCTP_EVENT_AUTHENTICATION |
|
| 65 |
+ SCTP_EVENT_SENDER_DRY |
|
| 66 |
+ |
|
| 67 |
+ SCTP_EVENT_ALL = SCTP_EVENT_DATA_IO | SCTP_EVENT_ASSOCIATION | SCTP_EVENT_ADDRESS | SCTP_EVENT_SEND_FAILURE | SCTP_EVENT_PEER_ERROR | SCTP_EVENT_SHUTDOWN | SCTP_EVENT_PARTIAL_DELIVERY | SCTP_EVENT_ADAPTATION_LAYER | SCTP_EVENT_AUTHENTICATION | SCTP_EVENT_SENDER_DRY |
|
| 68 |
+) |
|
| 69 |
+ |
|
| 70 |
+type SCTPNotificationType int |
|
| 71 |
+ |
|
| 72 |
+const ( |
|
| 73 |
+ SCTP_SN_TYPE_BASE = SCTPNotificationType(iota + (1 << 15)) |
|
| 74 |
+ SCTP_ASSOC_CHANGE |
|
| 75 |
+ SCTP_PEER_ADDR_CHANGE |
|
| 76 |
+ SCTP_SEND_FAILED |
|
| 77 |
+ SCTP_REMOTE_ERROR |
|
| 78 |
+ SCTP_SHUTDOWN_EVENT |
|
| 79 |
+ SCTP_PARTIAL_DELIVERY_EVENT |
|
| 80 |
+ SCTP_ADAPTATION_INDICATION |
|
| 81 |
+ SCTP_AUTHENTICATION_INDICATION |
|
| 82 |
+ SCTP_SENDER_DRY_EVENT |
|
| 83 |
+) |
|
| 84 |
+ |
|
| 85 |
+type NotificationHandler func([]byte) error |
|
| 86 |
+ |
|
| 87 |
+type EventSubscribe struct {
|
|
| 88 |
+ DataIO uint8 |
|
| 89 |
+ Association uint8 |
|
| 90 |
+ Address uint8 |
|
| 91 |
+ SendFailure uint8 |
|
| 92 |
+ PeerError uint8 |
|
| 93 |
+ Shutdown uint8 |
|
| 94 |
+ PartialDelivery uint8 |
|
| 95 |
+ AdaptationLayer uint8 |
|
| 96 |
+ Authentication uint8 |
|
| 97 |
+ SenderDry uint8 |
|
| 98 |
+} |
|
| 99 |
+ |
|
| 100 |
+const ( |
|
| 101 |
+ SCTP_CMSG_INIT = iota |
|
| 102 |
+ SCTP_CMSG_SNDRCV |
|
| 103 |
+ SCTP_CMSG_SNDINFO |
|
| 104 |
+ SCTP_CMSG_RCVINFO |
|
| 105 |
+ SCTP_CMSG_NXTINFO |
|
| 106 |
+) |
|
| 107 |
+ |
|
| 108 |
+const ( |
|
| 109 |
+ SCTP_UNORDERED = 1 << iota |
|
| 110 |
+ SCTP_ADDR_OVER |
|
| 111 |
+ SCTP_ABORT |
|
| 112 |
+ SCTP_SACK_IMMEDIATELY |
|
| 113 |
+ SCTP_EOF |
|
| 114 |
+) |
|
| 115 |
+ |
|
| 116 |
+const ( |
|
| 117 |
+ SCTP_MAX_STREAM = 0xffff |
|
| 118 |
+) |
|
| 119 |
+ |
|
| 120 |
+type InitMsg struct {
|
|
| 121 |
+ NumOstreams uint16 |
|
| 122 |
+ MaxInstreams uint16 |
|
| 123 |
+ MaxAttempts uint16 |
|
| 124 |
+ MaxInitTimeout uint16 |
|
| 125 |
+} |
|
| 126 |
+ |
|
| 127 |
+type SndRcvInfo struct {
|
|
| 128 |
+ Stream uint16 |
|
| 129 |
+ SSN uint16 |
|
| 130 |
+ Flags uint16 |
|
| 131 |
+ _ uint16 |
|
| 132 |
+ PPID uint32 |
|
| 133 |
+ Context uint32 |
|
| 134 |
+ TTL uint32 |
|
| 135 |
+ TSN uint32 |
|
| 136 |
+ CumTSN uint32 |
|
| 137 |
+ AssocID int32 |
|
| 138 |
+} |
|
| 139 |
+ |
|
| 140 |
+type SndInfo struct {
|
|
| 141 |
+ SID uint16 |
|
| 142 |
+ Flags uint16 |
|
| 143 |
+ PPID uint32 |
|
| 144 |
+ Context uint32 |
|
| 145 |
+ AssocID int32 |
|
| 146 |
+} |
|
| 147 |
+ |
|
| 148 |
+type GetAddrsOld struct {
|
|
| 149 |
+ AssocID int32 |
|
| 150 |
+ AddrNum int32 |
|
| 151 |
+ Addrs uintptr |
|
| 152 |
+} |
|
| 153 |
+ |
|
| 154 |
+type NotificationHeader struct {
|
|
| 155 |
+ Type uint16 |
|
| 156 |
+ Flags uint16 |
|
| 157 |
+ Length uint32 |
|
| 158 |
+} |
|
| 159 |
+ |
|
| 160 |
+type SCTPState uint16 |
|
| 161 |
+ |
|
| 162 |
+const ( |
|
| 163 |
+ SCTP_COMM_UP = SCTPState(iota) |
|
| 164 |
+ SCTP_COMM_LOST |
|
| 165 |
+ SCTP_RESTART |
|
| 166 |
+ SCTP_SHUTDOWN_COMP |
|
| 167 |
+ SCTP_CANT_STR_ASSOC |
|
| 168 |
+) |
|
| 169 |
+ |
|
| 170 |
+var nativeEndian binary.ByteOrder |
|
| 171 |
+var sndRcvInfoSize uintptr |
|
| 172 |
+ |
|
| 173 |
+func init() {
|
|
| 174 |
+ i := uint16(1) |
|
| 175 |
+ if *(*byte)(unsafe.Pointer(&i)) == 0 {
|
|
| 176 |
+ nativeEndian = binary.BigEndian |
|
| 177 |
+ } else {
|
|
| 178 |
+ nativeEndian = binary.LittleEndian |
|
| 179 |
+ } |
|
| 180 |
+ info := SndRcvInfo{}
|
|
| 181 |
+ sndRcvInfoSize = unsafe.Sizeof(info) |
|
| 182 |
+} |
|
| 183 |
+ |
|
| 184 |
+func toBuf(v interface{}) []byte {
|
|
| 185 |
+ var buf bytes.Buffer |
|
| 186 |
+ binary.Write(&buf, nativeEndian, v) |
|
| 187 |
+ return buf.Bytes() |
|
| 188 |
+} |
|
| 189 |
+ |
|
| 190 |
+func htons(h uint16) uint16 {
|
|
| 191 |
+ if nativeEndian == binary.LittleEndian {
|
|
| 192 |
+ return (h << 8 & 0xff00) | (h >> 8 & 0xff) |
|
| 193 |
+ } |
|
| 194 |
+ return h |
|
| 195 |
+} |
|
| 196 |
+ |
|
| 197 |
+var ntohs = htons |
|
| 198 |
+ |
|
| 199 |
+func setNumOstreams(fd, num int) error {
|
|
| 200 |
+ param := InitMsg{
|
|
| 201 |
+ NumOstreams: uint16(num), |
|
| 202 |
+ } |
|
| 203 |
+ optlen := unsafe.Sizeof(param) |
|
| 204 |
+ _, _, err := setsockopt(fd, SCTP_INITMSG, uintptr(unsafe.Pointer(¶m)), uintptr(optlen)) |
|
| 205 |
+ return err |
|
| 206 |
+} |
|
| 207 |
+ |
|
| 208 |
+type SCTPAddr struct {
|
|
| 209 |
+ IP []net.IP |
|
| 210 |
+ Port int |
|
| 211 |
+} |
|
| 212 |
+ |
|
| 213 |
+func (a *SCTPAddr) ToRawSockAddrBuf() []byte {
|
|
| 214 |
+ buf := []byte{}
|
|
| 215 |
+ p := htons(uint16(a.Port)) |
|
| 216 |
+ for _, ip := range a.IP {
|
|
| 217 |
+ if ip.To4() != nil {
|
|
| 218 |
+ s := syscall.RawSockaddrInet4{
|
|
| 219 |
+ Family: syscall.AF_INET, |
|
| 220 |
+ Port: p, |
|
| 221 |
+ } |
|
| 222 |
+ copy(s.Addr[:], ip.To4()) |
|
| 223 |
+ buf = append(buf, toBuf(s)...) |
|
| 224 |
+ } else {
|
|
| 225 |
+ s := syscall.RawSockaddrInet6{
|
|
| 226 |
+ Family: syscall.AF_INET6, |
|
| 227 |
+ Port: p, |
|
| 228 |
+ } |
|
| 229 |
+ copy(s.Addr[:], ip) |
|
| 230 |
+ buf = append(buf, toBuf(s)...) |
|
| 231 |
+ } |
|
| 232 |
+ } |
|
| 233 |
+ return buf |
|
| 234 |
+} |
|
| 235 |
+ |
|
| 236 |
+func (a *SCTPAddr) String() string {
|
|
| 237 |
+ var b bytes.Buffer |
|
| 238 |
+ |
|
| 239 |
+ for n, i := range a.IP {
|
|
| 240 |
+ if a.IP[n].To4() != nil {
|
|
| 241 |
+ b.WriteString(i.String()) |
|
| 242 |
+ } else if a.IP[n].To16() != nil {
|
|
| 243 |
+ b.WriteRune('[')
|
|
| 244 |
+ b.WriteString(i.String()) |
|
| 245 |
+ b.WriteRune(']')
|
|
| 246 |
+ } |
|
| 247 |
+ if n < len(a.IP)-1 {
|
|
| 248 |
+ b.WriteRune('/')
|
|
| 249 |
+ } |
|
| 250 |
+ } |
|
| 251 |
+ b.WriteRune(':')
|
|
| 252 |
+ b.WriteString(strconv.Itoa(a.Port)) |
|
| 253 |
+ return b.String() |
|
| 254 |
+} |
|
| 255 |
+ |
|
| 256 |
+func (a *SCTPAddr) Network() string { return "sctp" }
|
|
| 257 |
+ |
|
| 258 |
+func ResolveSCTPAddr(network, addrs string) (*SCTPAddr, error) {
|
|
| 259 |
+ tcpnet := "" |
|
| 260 |
+ switch network {
|
|
| 261 |
+ case "", "sctp": |
|
| 262 |
+ case "sctp4": |
|
| 263 |
+ tcpnet = "tcp4" |
|
| 264 |
+ case "sctp6": |
|
| 265 |
+ tcpnet = "tcp6" |
|
| 266 |
+ default: |
|
| 267 |
+ return nil, fmt.Errorf("invalid net: %s", network)
|
|
| 268 |
+ } |
|
| 269 |
+ elems := strings.Split(addrs, "/") |
|
| 270 |
+ if len(elems) == 0 {
|
|
| 271 |
+ return nil, fmt.Errorf("invalid input: %s", addrs)
|
|
| 272 |
+ } |
|
| 273 |
+ ipaddrs := make([]net.IP, 0, len(elems)) |
|
| 274 |
+ for _, e := range elems[:len(elems)-1] {
|
|
| 275 |
+ tcpa, err := net.ResolveTCPAddr(tcpnet, e+":") |
|
| 276 |
+ if err != nil {
|
|
| 277 |
+ return nil, err |
|
| 278 |
+ } |
|
| 279 |
+ ipaddrs = append(ipaddrs, tcpa.IP) |
|
| 280 |
+ } |
|
| 281 |
+ tcpa, err := net.ResolveTCPAddr(tcpnet, elems[len(elems)-1]) |
|
| 282 |
+ if err != nil {
|
|
| 283 |
+ return nil, err |
|
| 284 |
+ } |
|
| 285 |
+ if tcpa.IP != nil {
|
|
| 286 |
+ ipaddrs = append(ipaddrs, tcpa.IP) |
|
| 287 |
+ } else {
|
|
| 288 |
+ ipaddrs = nil |
|
| 289 |
+ } |
|
| 290 |
+ return &SCTPAddr{
|
|
| 291 |
+ IP: ipaddrs, |
|
| 292 |
+ Port: tcpa.Port, |
|
| 293 |
+ }, nil |
|
| 294 |
+} |
|
| 295 |
+ |
|
| 296 |
+func SCTPConnect(fd int, addr *SCTPAddr) (int, error) {
|
|
| 297 |
+ buf := addr.ToRawSockAddrBuf() |
|
| 298 |
+ param := GetAddrsOld{
|
|
| 299 |
+ AddrNum: int32(len(buf)), |
|
| 300 |
+ Addrs: uintptr(uintptr(unsafe.Pointer(&buf[0]))), |
|
| 301 |
+ } |
|
| 302 |
+ optlen := unsafe.Sizeof(param) |
|
| 303 |
+ _, _, err := getsockopt(fd, SCTP_SOCKOPT_CONNECTX3, uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen))) |
|
| 304 |
+ if err == nil {
|
|
| 305 |
+ return int(param.AssocID), nil |
|
| 306 |
+ } else if err != syscall.ENOPROTOOPT {
|
|
| 307 |
+ return 0, err |
|
| 308 |
+ } |
|
| 309 |
+ r0, _, err := setsockopt(fd, SCTP_SOCKOPT_CONNECTX, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf))) |
|
| 310 |
+ return int(r0), err |
|
| 311 |
+} |
|
| 312 |
+ |
|
| 313 |
+func SCTPBind(fd int, addr *SCTPAddr, flags int) error {
|
|
| 314 |
+ var option uintptr |
|
| 315 |
+ switch flags {
|
|
| 316 |
+ case SCTP_BINDX_ADD_ADDR: |
|
| 317 |
+ option = SCTP_SOCKOPT_BINDX_ADD |
|
| 318 |
+ case SCTP_BINDX_REM_ADDR: |
|
| 319 |
+ option = SCTP_SOCKOPT_BINDX_REM |
|
| 320 |
+ default: |
|
| 321 |
+ return syscall.EINVAL |
|
| 322 |
+ } |
|
| 323 |
+ |
|
| 324 |
+ buf := addr.ToRawSockAddrBuf() |
|
| 325 |
+ _, _, err := setsockopt(fd, option, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf))) |
|
| 326 |
+ return err |
|
| 327 |
+} |
|
| 328 |
+ |
|
| 329 |
+type SCTPConn struct {
|
|
| 330 |
+ _fd int32 |
|
| 331 |
+ notificationHandler NotificationHandler |
|
| 332 |
+} |
|
| 333 |
+ |
|
| 334 |
+func (c *SCTPConn) fd() int {
|
|
| 335 |
+ return int(atomic.LoadInt32(&c._fd)) |
|
| 336 |
+} |
|
| 337 |
+ |
|
| 338 |
+func NewSCTPConn(fd int, handler NotificationHandler) *SCTPConn {
|
|
| 339 |
+ conn := &SCTPConn{
|
|
| 340 |
+ _fd: int32(fd), |
|
| 341 |
+ notificationHandler: handler, |
|
| 342 |
+ } |
|
| 343 |
+ return conn |
|
| 344 |
+} |
|
| 345 |
+ |
|
| 346 |
+func (c *SCTPConn) Write(b []byte) (int, error) {
|
|
| 347 |
+ return c.SCTPWrite(b, nil) |
|
| 348 |
+} |
|
| 349 |
+ |
|
| 350 |
+func (c *SCTPConn) Read(b []byte) (int, error) {
|
|
| 351 |
+ n, _, err := c.SCTPRead(b) |
|
| 352 |
+ if n < 0 {
|
|
| 353 |
+ n = 0 |
|
| 354 |
+ } |
|
| 355 |
+ return n, err |
|
| 356 |
+} |
|
| 357 |
+ |
|
| 358 |
+func (c *SCTPConn) SetInitMsg(numOstreams, maxInstreams, maxAttempts, maxInitTimeout int) error {
|
|
| 359 |
+ param := InitMsg{
|
|
| 360 |
+ NumOstreams: uint16(numOstreams), |
|
| 361 |
+ MaxInstreams: uint16(maxInstreams), |
|
| 362 |
+ MaxAttempts: uint16(maxAttempts), |
|
| 363 |
+ MaxInitTimeout: uint16(maxInitTimeout), |
|
| 364 |
+ } |
|
| 365 |
+ optlen := unsafe.Sizeof(param) |
|
| 366 |
+ _, _, err := setsockopt(c.fd(), SCTP_INITMSG, uintptr(unsafe.Pointer(¶m)), uintptr(optlen)) |
|
| 367 |
+ return err |
|
| 368 |
+} |
|
| 369 |
+ |
|
| 370 |
+func (c *SCTPConn) SubscribeEvents(flags int) error {
|
|
| 371 |
+ var d, a, ad, sf, p, sh, pa, ada, au, se uint8 |
|
| 372 |
+ if flags&SCTP_EVENT_DATA_IO > 0 {
|
|
| 373 |
+ d = 1 |
|
| 374 |
+ } |
|
| 375 |
+ if flags&SCTP_EVENT_ASSOCIATION > 0 {
|
|
| 376 |
+ a = 1 |
|
| 377 |
+ } |
|
| 378 |
+ if flags&SCTP_EVENT_ADDRESS > 0 {
|
|
| 379 |
+ ad = 1 |
|
| 380 |
+ } |
|
| 381 |
+ if flags&SCTP_EVENT_SEND_FAILURE > 0 {
|
|
| 382 |
+ sf = 1 |
|
| 383 |
+ } |
|
| 384 |
+ if flags&SCTP_EVENT_PEER_ERROR > 0 {
|
|
| 385 |
+ p = 1 |
|
| 386 |
+ } |
|
| 387 |
+ if flags&SCTP_EVENT_SHUTDOWN > 0 {
|
|
| 388 |
+ sh = 1 |
|
| 389 |
+ } |
|
| 390 |
+ if flags&SCTP_EVENT_PARTIAL_DELIVERY > 0 {
|
|
| 391 |
+ pa = 1 |
|
| 392 |
+ } |
|
| 393 |
+ if flags&SCTP_EVENT_ADAPTATION_LAYER > 0 {
|
|
| 394 |
+ ada = 1 |
|
| 395 |
+ } |
|
| 396 |
+ if flags&SCTP_EVENT_AUTHENTICATION > 0 {
|
|
| 397 |
+ au = 1 |
|
| 398 |
+ } |
|
| 399 |
+ if flags&SCTP_EVENT_SENDER_DRY > 0 {
|
|
| 400 |
+ se = 1 |
|
| 401 |
+ } |
|
| 402 |
+ param := EventSubscribe{
|
|
| 403 |
+ DataIO: d, |
|
| 404 |
+ Association: a, |
|
| 405 |
+ Address: ad, |
|
| 406 |
+ SendFailure: sf, |
|
| 407 |
+ PeerError: p, |
|
| 408 |
+ Shutdown: sh, |
|
| 409 |
+ PartialDelivery: pa, |
|
| 410 |
+ AdaptationLayer: ada, |
|
| 411 |
+ Authentication: au, |
|
| 412 |
+ SenderDry: se, |
|
| 413 |
+ } |
|
| 414 |
+ optlen := unsafe.Sizeof(param) |
|
| 415 |
+ _, _, err := setsockopt(c.fd(), SCTP_EVENTS, uintptr(unsafe.Pointer(¶m)), uintptr(optlen)) |
|
| 416 |
+ return err |
|
| 417 |
+} |
|
| 418 |
+ |
|
| 419 |
+func (c *SCTPConn) SubscribedEvents() (int, error) {
|
|
| 420 |
+ param := EventSubscribe{}
|
|
| 421 |
+ optlen := unsafe.Sizeof(param) |
|
| 422 |
+ _, _, err := getsockopt(c.fd(), SCTP_EVENTS, uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen))) |
|
| 423 |
+ if err != nil {
|
|
| 424 |
+ return 0, err |
|
| 425 |
+ } |
|
| 426 |
+ var flags int |
|
| 427 |
+ if param.DataIO > 0 {
|
|
| 428 |
+ flags |= SCTP_EVENT_DATA_IO |
|
| 429 |
+ } |
|
| 430 |
+ if param.Association > 0 {
|
|
| 431 |
+ flags |= SCTP_EVENT_ASSOCIATION |
|
| 432 |
+ } |
|
| 433 |
+ if param.Address > 0 {
|
|
| 434 |
+ flags |= SCTP_EVENT_ADDRESS |
|
| 435 |
+ } |
|
| 436 |
+ if param.SendFailure > 0 {
|
|
| 437 |
+ flags |= SCTP_EVENT_SEND_FAILURE |
|
| 438 |
+ } |
|
| 439 |
+ if param.PeerError > 0 {
|
|
| 440 |
+ flags |= SCTP_EVENT_PEER_ERROR |
|
| 441 |
+ } |
|
| 442 |
+ if param.Shutdown > 0 {
|
|
| 443 |
+ flags |= SCTP_EVENT_SHUTDOWN |
|
| 444 |
+ } |
|
| 445 |
+ if param.PartialDelivery > 0 {
|
|
| 446 |
+ flags |= SCTP_EVENT_PARTIAL_DELIVERY |
|
| 447 |
+ } |
|
| 448 |
+ if param.AdaptationLayer > 0 {
|
|
| 449 |
+ flags |= SCTP_EVENT_ADAPTATION_LAYER |
|
| 450 |
+ } |
|
| 451 |
+ if param.Authentication > 0 {
|
|
| 452 |
+ flags |= SCTP_EVENT_AUTHENTICATION |
|
| 453 |
+ } |
|
| 454 |
+ if param.SenderDry > 0 {
|
|
| 455 |
+ flags |= SCTP_EVENT_SENDER_DRY |
|
| 456 |
+ } |
|
| 457 |
+ return flags, nil |
|
| 458 |
+} |
|
| 459 |
+ |
|
| 460 |
+func (c *SCTPConn) SetDefaultSentParam(info *SndRcvInfo) error {
|
|
| 461 |
+ optlen := unsafe.Sizeof(*info) |
|
| 462 |
+ _, _, err := setsockopt(c.fd(), SCTP_DEFAULT_SENT_PARAM, uintptr(unsafe.Pointer(info)), uintptr(optlen)) |
|
| 463 |
+ return err |
|
| 464 |
+} |
|
| 465 |
+ |
|
| 466 |
+func (c *SCTPConn) GetDefaultSentParam() (*SndRcvInfo, error) {
|
|
| 467 |
+ info := &SndRcvInfo{}
|
|
| 468 |
+ optlen := unsafe.Sizeof(*info) |
|
| 469 |
+ _, _, err := getsockopt(c.fd(), SCTP_DEFAULT_SENT_PARAM, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(&optlen))) |
|
| 470 |
+ return info, err |
|
| 471 |
+} |
|
| 472 |
+ |
|
| 473 |
+func resolveFromRawAddr(ptr unsafe.Pointer, n int) (*SCTPAddr, error) {
|
|
| 474 |
+ addr := &SCTPAddr{
|
|
| 475 |
+ IP: make([]net.IP, n), |
|
| 476 |
+ } |
|
| 477 |
+ |
|
| 478 |
+ switch family := (*(*syscall.RawSockaddrAny)(ptr)).Addr.Family; family {
|
|
| 479 |
+ case syscall.AF_INET: |
|
| 480 |
+ addr.Port = int(ntohs(uint16((*(*syscall.RawSockaddrInet4)(ptr)).Port))) |
|
| 481 |
+ tmp := syscall.RawSockaddrInet4{}
|
|
| 482 |
+ size := unsafe.Sizeof(tmp) |
|
| 483 |
+ for i := 0; i < n; i++ {
|
|
| 484 |
+ a := *(*syscall.RawSockaddrInet4)(unsafe.Pointer( |
|
| 485 |
+ uintptr(ptr) + size*uintptr(i))) |
|
| 486 |
+ addr.IP[i] = a.Addr[:] |
|
| 487 |
+ } |
|
| 488 |
+ case syscall.AF_INET6: |
|
| 489 |
+ addr.Port = int(ntohs(uint16((*(*syscall.RawSockaddrInet4)(ptr)).Port))) |
|
| 490 |
+ tmp := syscall.RawSockaddrInet6{}
|
|
| 491 |
+ size := unsafe.Sizeof(tmp) |
|
| 492 |
+ for i := 0; i < n; i++ {
|
|
| 493 |
+ a := *(*syscall.RawSockaddrInet6)(unsafe.Pointer( |
|
| 494 |
+ uintptr(ptr) + size*uintptr(i))) |
|
| 495 |
+ addr.IP[i] = a.Addr[:] |
|
| 496 |
+ } |
|
| 497 |
+ default: |
|
| 498 |
+ return nil, fmt.Errorf("unknown address family: %d", family)
|
|
| 499 |
+ } |
|
| 500 |
+ return addr, nil |
|
| 501 |
+} |
|
| 502 |
+ |
|
| 503 |
+func sctpGetAddrs(fd, id, optname int) (*SCTPAddr, error) {
|
|
| 504 |
+ |
|
| 505 |
+ type getaddrs struct {
|
|
| 506 |
+ assocId int32 |
|
| 507 |
+ addrNum uint32 |
|
| 508 |
+ addrs [4096]byte |
|
| 509 |
+ } |
|
| 510 |
+ param := getaddrs{
|
|
| 511 |
+ assocId: int32(id), |
|
| 512 |
+ } |
|
| 513 |
+ optlen := unsafe.Sizeof(param) |
|
| 514 |
+ _, _, err := getsockopt(fd, uintptr(optname), uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen))) |
|
| 515 |
+ if err != nil {
|
|
| 516 |
+ return nil, err |
|
| 517 |
+ } |
|
| 518 |
+ return resolveFromRawAddr(unsafe.Pointer(¶m.addrs), int(param.addrNum)) |
|
| 519 |
+} |
|
| 520 |
+ |
|
| 521 |
+func (c *SCTPConn) SCTPGetPrimaryPeerAddr() (*SCTPAddr, error) {
|
|
| 522 |
+ |
|
| 523 |
+ type sctpGetSetPrim struct {
|
|
| 524 |
+ assocId int32 |
|
| 525 |
+ addrs [128]byte |
|
| 526 |
+ } |
|
| 527 |
+ param := sctpGetSetPrim{
|
|
| 528 |
+ assocId: int32(0), |
|
| 529 |
+ } |
|
| 530 |
+ optlen := unsafe.Sizeof(param) |
|
| 531 |
+ _, _, err := getsockopt(c.fd(), SCTP_PRIMARY_ADDR, uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen))) |
|
| 532 |
+ if err != nil {
|
|
| 533 |
+ return nil, err |
|
| 534 |
+ } |
|
| 535 |
+ return resolveFromRawAddr(unsafe.Pointer(¶m.addrs), 1) |
|
| 536 |
+} |
|
| 537 |
+ |
|
| 538 |
+func (c *SCTPConn) SCTPLocalAddr(id int) (*SCTPAddr, error) {
|
|
| 539 |
+ return sctpGetAddrs(c.fd(), id, SCTP_GET_LOCAL_ADDRS) |
|
| 540 |
+} |
|
| 541 |
+ |
|
| 542 |
+func (c *SCTPConn) SCTPRemoteAddr(id int) (*SCTPAddr, error) {
|
|
| 543 |
+ return sctpGetAddrs(c.fd(), id, SCTP_GET_PEER_ADDRS) |
|
| 544 |
+} |
|
| 545 |
+ |
|
| 546 |
+func (c *SCTPConn) LocalAddr() net.Addr {
|
|
| 547 |
+ addr, err := sctpGetAddrs(c.fd(), 0, SCTP_GET_LOCAL_ADDRS) |
|
| 548 |
+ if err != nil {
|
|
| 549 |
+ return nil |
|
| 550 |
+ } |
|
| 551 |
+ return addr |
|
| 552 |
+} |
|
| 553 |
+ |
|
| 554 |
+func (c *SCTPConn) RemoteAddr() net.Addr {
|
|
| 555 |
+ addr, err := sctpGetAddrs(c.fd(), 0, SCTP_GET_PEER_ADDRS) |
|
| 556 |
+ if err != nil {
|
|
| 557 |
+ return nil |
|
| 558 |
+ } |
|
| 559 |
+ return addr |
|
| 560 |
+} |
|
| 561 |
+ |
|
| 562 |
+func (c *SCTPConn) PeelOff(id int) (*SCTPConn, error) {
|
|
| 563 |
+ type peeloffArg struct {
|
|
| 564 |
+ assocId int32 |
|
| 565 |
+ sd int |
|
| 566 |
+ } |
|
| 567 |
+ param := peeloffArg{
|
|
| 568 |
+ assocId: int32(id), |
|
| 569 |
+ } |
|
| 570 |
+ optlen := unsafe.Sizeof(param) |
|
| 571 |
+ _, _, err := getsockopt(c.fd(), SCTP_SOCKOPT_PEELOFF, uintptr(unsafe.Pointer(¶m)), uintptr(unsafe.Pointer(&optlen))) |
|
| 572 |
+ if err != nil {
|
|
| 573 |
+ return nil, err |
|
| 574 |
+ } |
|
| 575 |
+ return &SCTPConn{_fd: int32(param.sd)}, nil
|
|
| 576 |
+} |
|
| 577 |
+ |
|
| 578 |
+func (c *SCTPConn) SetDeadline(t time.Time) error {
|
|
| 579 |
+ return syscall.EOPNOTSUPP |
|
| 580 |
+} |
|
| 581 |
+ |
|
| 582 |
+func (c *SCTPConn) SetReadDeadline(t time.Time) error {
|
|
| 583 |
+ return syscall.EOPNOTSUPP |
|
| 584 |
+} |
|
| 585 |
+ |
|
| 586 |
+func (c *SCTPConn) SetWriteDeadline(t time.Time) error {
|
|
| 587 |
+ return syscall.EOPNOTSUPP |
|
| 588 |
+} |
|
| 589 |
+ |
|
| 590 |
+type SCTPListener struct {
|
|
| 591 |
+ fd int |
|
| 592 |
+ m sync.Mutex |
|
| 593 |
+} |
|
| 594 |
+ |
|
| 595 |
+func (ln *SCTPListener) Addr() net.Addr {
|
|
| 596 |
+ laddr, err := sctpGetAddrs(ln.fd, 0, SCTP_GET_LOCAL_ADDRS) |
|
| 597 |
+ if err != nil {
|
|
| 598 |
+ return nil |
|
| 599 |
+ } |
|
| 600 |
+ return laddr |
|
| 601 |
+} |
|
| 602 |
+ |
|
| 603 |
+type SCTPSndRcvInfoWrappedConn struct {
|
|
| 604 |
+ conn *SCTPConn |
|
| 605 |
+} |
|
| 606 |
+ |
|
| 607 |
+func NewSCTPSndRcvInfoWrappedConn(conn *SCTPConn) *SCTPSndRcvInfoWrappedConn {
|
|
| 608 |
+ conn.SubscribeEvents(SCTP_EVENT_DATA_IO) |
|
| 609 |
+ return &SCTPSndRcvInfoWrappedConn{conn}
|
|
| 610 |
+} |
|
| 611 |
+ |
|
| 612 |
+func (c *SCTPSndRcvInfoWrappedConn) Write(b []byte) (int, error) {
|
|
| 613 |
+ if len(b) < int(sndRcvInfoSize) {
|
|
| 614 |
+ return 0, syscall.EINVAL |
|
| 615 |
+ } |
|
| 616 |
+ info := (*SndRcvInfo)(unsafe.Pointer(&b[0])) |
|
| 617 |
+ n, err := c.conn.SCTPWrite(b[sndRcvInfoSize:], info) |
|
| 618 |
+ return n + int(sndRcvInfoSize), err |
|
| 619 |
+} |
|
| 620 |
+ |
|
| 621 |
+func (c *SCTPSndRcvInfoWrappedConn) Read(b []byte) (int, error) {
|
|
| 622 |
+ if len(b) < int(sndRcvInfoSize) {
|
|
| 623 |
+ return 0, syscall.EINVAL |
|
| 624 |
+ } |
|
| 625 |
+ n, info, err := c.conn.SCTPRead(b[sndRcvInfoSize:]) |
|
| 626 |
+ if err != nil {
|
|
| 627 |
+ return n, err |
|
| 628 |
+ } |
|
| 629 |
+ copy(b, toBuf(info)) |
|
| 630 |
+ return n + int(sndRcvInfoSize), err |
|
| 631 |
+} |
|
| 632 |
+ |
|
| 633 |
+func (c *SCTPSndRcvInfoWrappedConn) Close() error {
|
|
| 634 |
+ return c.conn.Close() |
|
| 635 |
+} |
|
| 636 |
+ |
|
| 637 |
+func (c *SCTPSndRcvInfoWrappedConn) LocalAddr() net.Addr {
|
|
| 638 |
+ return c.conn.LocalAddr() |
|
| 639 |
+} |
|
| 640 |
+ |
|
| 641 |
+func (c *SCTPSndRcvInfoWrappedConn) RemoteAddr() net.Addr {
|
|
| 642 |
+ return c.conn.RemoteAddr() |
|
| 643 |
+} |
|
| 644 |
+ |
|
| 645 |
+func (c *SCTPSndRcvInfoWrappedConn) SetDeadline(t time.Time) error {
|
|
| 646 |
+ return c.conn.SetDeadline(t) |
|
| 647 |
+} |
|
| 648 |
+ |
|
| 649 |
+func (c *SCTPSndRcvInfoWrappedConn) SetReadDeadline(t time.Time) error {
|
|
| 650 |
+ return c.conn.SetReadDeadline(t) |
|
| 651 |
+} |
|
| 652 |
+ |
|
| 653 |
+func (c *SCTPSndRcvInfoWrappedConn) SetWriteDeadline(t time.Time) error {
|
|
| 654 |
+ return c.conn.SetWriteDeadline(t) |
|
| 655 |
+} |
| 0 | 656 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,227 @@ |
| 0 |
+// +build linux,!386 |
|
| 1 |
+ |
|
| 2 |
+package sctp |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "io" |
|
| 7 |
+ "net" |
|
| 8 |
+ "sync/atomic" |
|
| 9 |
+ "syscall" |
|
| 10 |
+ "unsafe" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+func setsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, error) {
|
|
| 14 |
+ // FIXME: syscall.SYS_SETSOCKOPT is undefined on 386 |
|
| 15 |
+ r0, r1, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, |
|
| 16 |
+ uintptr(fd), |
|
| 17 |
+ SOL_SCTP, |
|
| 18 |
+ optname, |
|
| 19 |
+ optval, |
|
| 20 |
+ optlen, |
|
| 21 |
+ 0) |
|
| 22 |
+ if errno != 0 {
|
|
| 23 |
+ return r0, r1, errno |
|
| 24 |
+ } |
|
| 25 |
+ return r0, r1, nil |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+func getsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, error) {
|
|
| 29 |
+ // FIXME: syscall.SYS_GETSOCKOPT is undefined on 386 |
|
| 30 |
+ r0, r1, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, |
|
| 31 |
+ uintptr(fd), |
|
| 32 |
+ SOL_SCTP, |
|
| 33 |
+ optname, |
|
| 34 |
+ optval, |
|
| 35 |
+ optlen, |
|
| 36 |
+ 0) |
|
| 37 |
+ if errno != 0 {
|
|
| 38 |
+ return r0, r1, errno |
|
| 39 |
+ } |
|
| 40 |
+ return r0, r1, nil |
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+func (c *SCTPConn) SCTPWrite(b []byte, info *SndRcvInfo) (int, error) {
|
|
| 44 |
+ var cbuf []byte |
|
| 45 |
+ if info != nil {
|
|
| 46 |
+ cmsgBuf := toBuf(info) |
|
| 47 |
+ hdr := &syscall.Cmsghdr{
|
|
| 48 |
+ Level: syscall.IPPROTO_SCTP, |
|
| 49 |
+ Type: SCTP_CMSG_SNDRCV, |
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ // bitwidth of hdr.Len is platform-specific, |
|
| 53 |
+ // so we use hdr.SetLen() rather than directly setting hdr.Len |
|
| 54 |
+ hdr.SetLen(syscall.CmsgSpace(len(cmsgBuf))) |
|
| 55 |
+ cbuf = append(toBuf(hdr), cmsgBuf...) |
|
| 56 |
+ } |
|
| 57 |
+ return syscall.SendmsgN(c.fd(), b, cbuf, nil, 0) |
|
| 58 |
+} |
|
| 59 |
+ |
|
| 60 |
+func parseSndRcvInfo(b []byte) (*SndRcvInfo, error) {
|
|
| 61 |
+ msgs, err := syscall.ParseSocketControlMessage(b) |
|
| 62 |
+ if err != nil {
|
|
| 63 |
+ return nil, err |
|
| 64 |
+ } |
|
| 65 |
+ for _, m := range msgs {
|
|
| 66 |
+ if m.Header.Level == syscall.IPPROTO_SCTP {
|
|
| 67 |
+ switch m.Header.Type {
|
|
| 68 |
+ case SCTP_CMSG_SNDRCV: |
|
| 69 |
+ return (*SndRcvInfo)(unsafe.Pointer(&m.Data[0])), nil |
|
| 70 |
+ } |
|
| 71 |
+ } |
|
| 72 |
+ } |
|
| 73 |
+ return nil, nil |
|
| 74 |
+} |
|
| 75 |
+ |
|
| 76 |
+func (c *SCTPConn) SCTPRead(b []byte) (int, *SndRcvInfo, error) {
|
|
| 77 |
+ oob := make([]byte, 254) |
|
| 78 |
+ for {
|
|
| 79 |
+ n, oobn, recvflags, _, err := syscall.Recvmsg(c.fd(), b, oob, 0) |
|
| 80 |
+ if err != nil {
|
|
| 81 |
+ return n, nil, err |
|
| 82 |
+ } |
|
| 83 |
+ |
|
| 84 |
+ if n == 0 && oobn == 0 {
|
|
| 85 |
+ return 0, nil, io.EOF |
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ if recvflags&MSG_NOTIFICATION > 0 && c.notificationHandler != nil {
|
|
| 89 |
+ if err := c.notificationHandler(b[:n]); err != nil {
|
|
| 90 |
+ return 0, nil, err |
|
| 91 |
+ } |
|
| 92 |
+ } else {
|
|
| 93 |
+ var info *SndRcvInfo |
|
| 94 |
+ if oobn > 0 {
|
|
| 95 |
+ info, err = parseSndRcvInfo(oob[:oobn]) |
|
| 96 |
+ } |
|
| 97 |
+ return n, info, err |
|
| 98 |
+ } |
|
| 99 |
+ } |
|
| 100 |
+} |
|
| 101 |
+ |
|
| 102 |
+func (c *SCTPConn) Close() error {
|
|
| 103 |
+ if c != nil {
|
|
| 104 |
+ fd := atomic.SwapInt32(&c._fd, -1) |
|
| 105 |
+ if fd > 0 {
|
|
| 106 |
+ info := &SndRcvInfo{
|
|
| 107 |
+ Flags: SCTP_EOF, |
|
| 108 |
+ } |
|
| 109 |
+ c.SCTPWrite(nil, info) |
|
| 110 |
+ syscall.Shutdown(int(fd), syscall.SHUT_RDWR) |
|
| 111 |
+ return syscall.Close(int(fd)) |
|
| 112 |
+ } |
|
| 113 |
+ } |
|
| 114 |
+ return syscall.EBADF |
|
| 115 |
+} |
|
| 116 |
+ |
|
| 117 |
+func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
|
| 118 |
+ af := syscall.AF_INET |
|
| 119 |
+ switch net {
|
|
| 120 |
+ case "sctp": |
|
| 121 |
+ hasv6 := func(addr *SCTPAddr) bool {
|
|
| 122 |
+ if addr == nil {
|
|
| 123 |
+ return false |
|
| 124 |
+ } |
|
| 125 |
+ for _, ip := range addr.IP {
|
|
| 126 |
+ if ip.To4() == nil {
|
|
| 127 |
+ return true |
|
| 128 |
+ } |
|
| 129 |
+ } |
|
| 130 |
+ return false |
|
| 131 |
+ } |
|
| 132 |
+ if hasv6(laddr) {
|
|
| 133 |
+ af = syscall.AF_INET6 |
|
| 134 |
+ } |
|
| 135 |
+ case "sctp4": |
|
| 136 |
+ case "sctp6": |
|
| 137 |
+ af = syscall.AF_INET6 |
|
| 138 |
+ default: |
|
| 139 |
+ return nil, fmt.Errorf("invalid net: %s", net)
|
|
| 140 |
+ } |
|
| 141 |
+ |
|
| 142 |
+ sock, err := syscall.Socket( |
|
| 143 |
+ af, |
|
| 144 |
+ syscall.SOCK_STREAM, |
|
| 145 |
+ syscall.IPPROTO_SCTP, |
|
| 146 |
+ ) |
|
| 147 |
+ if err != nil {
|
|
| 148 |
+ return nil, err |
|
| 149 |
+ } |
|
| 150 |
+ err = setNumOstreams(sock, SCTP_MAX_STREAM) |
|
| 151 |
+ if err != nil {
|
|
| 152 |
+ return nil, err |
|
| 153 |
+ } |
|
| 154 |
+ if laddr != nil && len(laddr.IP) != 0 {
|
|
| 155 |
+ err := SCTPBind(sock, laddr, SCTP_BINDX_ADD_ADDR) |
|
| 156 |
+ if err != nil {
|
|
| 157 |
+ return nil, err |
|
| 158 |
+ } |
|
| 159 |
+ } |
|
| 160 |
+ err = syscall.Listen(sock, syscall.SOMAXCONN) |
|
| 161 |
+ if err != nil {
|
|
| 162 |
+ return nil, err |
|
| 163 |
+ } |
|
| 164 |
+ return &SCTPListener{
|
|
| 165 |
+ fd: sock, |
|
| 166 |
+ }, nil |
|
| 167 |
+} |
|
| 168 |
+ |
|
| 169 |
+func (ln *SCTPListener) Accept() (net.Conn, error) {
|
|
| 170 |
+ fd, _, err := syscall.Accept4(ln.fd, 0) |
|
| 171 |
+ return NewSCTPConn(fd, nil), err |
|
| 172 |
+} |
|
| 173 |
+ |
|
| 174 |
+func (ln *SCTPListener) Close() error {
|
|
| 175 |
+ syscall.Shutdown(ln.fd, syscall.SHUT_RDWR) |
|
| 176 |
+ return syscall.Close(ln.fd) |
|
| 177 |
+} |
|
| 178 |
+ |
|
| 179 |
+func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
|
|
| 180 |
+ af := syscall.AF_INET |
|
| 181 |
+ switch net {
|
|
| 182 |
+ case "sctp": |
|
| 183 |
+ hasv6 := func(addr *SCTPAddr) bool {
|
|
| 184 |
+ if addr == nil {
|
|
| 185 |
+ return false |
|
| 186 |
+ } |
|
| 187 |
+ for _, ip := range addr.IP {
|
|
| 188 |
+ if ip.To4() == nil {
|
|
| 189 |
+ return true |
|
| 190 |
+ } |
|
| 191 |
+ } |
|
| 192 |
+ return false |
|
| 193 |
+ } |
|
| 194 |
+ if hasv6(laddr) || hasv6(raddr) {
|
|
| 195 |
+ af = syscall.AF_INET6 |
|
| 196 |
+ } |
|
| 197 |
+ case "sctp4": |
|
| 198 |
+ case "sctp6": |
|
| 199 |
+ af = syscall.AF_INET6 |
|
| 200 |
+ default: |
|
| 201 |
+ return nil, fmt.Errorf("invalid net: %s", net)
|
|
| 202 |
+ } |
|
| 203 |
+ sock, err := syscall.Socket( |
|
| 204 |
+ af, |
|
| 205 |
+ syscall.SOCK_STREAM, |
|
| 206 |
+ syscall.IPPROTO_SCTP, |
|
| 207 |
+ ) |
|
| 208 |
+ if err != nil {
|
|
| 209 |
+ return nil, err |
|
| 210 |
+ } |
|
| 211 |
+ err = setNumOstreams(sock, SCTP_MAX_STREAM) |
|
| 212 |
+ if err != nil {
|
|
| 213 |
+ return nil, err |
|
| 214 |
+ } |
|
| 215 |
+ if laddr != nil {
|
|
| 216 |
+ err := SCTPBind(sock, laddr, SCTP_BINDX_ADD_ADDR) |
|
| 217 |
+ if err != nil {
|
|
| 218 |
+ return nil, err |
|
| 219 |
+ } |
|
| 220 |
+ } |
|
| 221 |
+ _, err = SCTPConnect(sock, raddr) |
|
| 222 |
+ if err != nil {
|
|
| 223 |
+ return nil, err |
|
| 224 |
+ } |
|
| 225 |
+ return NewSCTPConn(sock, nil), nil |
|
| 226 |
+} |
| 0 | 227 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,47 @@ |
| 0 |
+// +build !linux linux,386 |
|
| 1 |
+ |
|
| 2 |
+package sctp |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "errors" |
|
| 6 |
+ "net" |
|
| 7 |
+ "runtime" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+var ErrUnsupported = errors.New("SCTP is unsupported on " + runtime.GOOS + "/" + runtime.GOARCH)
|
|
| 11 |
+ |
|
| 12 |
+func setsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, error) {
|
|
| 13 |
+ return 0, 0, ErrUnsupported |
|
| 14 |
+} |
|
| 15 |
+ |
|
| 16 |
+func getsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, error) {
|
|
| 17 |
+ return 0, 0, ErrUnsupported |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+func (c *SCTPConn) SCTPWrite(b []byte, info *SndRcvInfo) (int, error) {
|
|
| 21 |
+ return 0, ErrUnsupported |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func (c *SCTPConn) SCTPRead(b []byte) (int, *SndRcvInfo, error) {
|
|
| 25 |
+ return 0, nil, ErrUnsupported |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+func (c *SCTPConn) Close() error {
|
|
| 29 |
+ return ErrUnsupported |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
|
|
| 33 |
+ return nil, ErrUnsupported |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+func (ln *SCTPListener) Accept() (net.Conn, error) {
|
|
| 37 |
+ return nil, ErrUnsupported |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+func (ln *SCTPListener) Close() error {
|
|
| 41 |
+ return ErrUnsupported |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
|
|
| 45 |
+ return nil, ErrUnsupported |
|
| 46 |
+} |