summaryrefslogtreecommitdiffhomepage
path: root/pkg/server/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/server/util.go')
-rw-r--r--pkg/server/util.go117
1 files changed, 117 insertions, 0 deletions
diff --git a/pkg/server/util.go b/pkg/server/util.go
new file mode 100644
index 00000000..ba6fe70a
--- /dev/null
+++ b/pkg/server/util.go
@@ -0,0 +1,117 @@
+// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package server
+
+import (
+ "net"
+ "os"
+ "strings"
+ "syscall"
+
+ "github.com/eapache/channels"
+
+ "github.com/osrg/gobgp/pkg/packet/bgp"
+)
+
+func cleanInfiniteChannel(ch *channels.InfiniteChannel) {
+ ch.Close()
+ // drain all remaining items
+ for range ch.Out() {
+ }
+}
+
+// Returns the binary formatted Administrative Shutdown Communication from the
+// given string value.
+func newAdministrativeCommunication(communication string) (data []byte) {
+ if communication == "" {
+ return nil
+ }
+ com := []byte(communication)
+ if len(com) > bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX {
+ data = []byte{bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX}
+ data = append(data, com[:bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX]...)
+ } else {
+ data = []byte{byte(len(com))}
+ data = append(data, com...)
+ }
+ return data
+}
+
+// Parses the given NOTIFICATION message data as a binary value and returns
+// the Administrative Shutdown Communication in string and the rest binary.
+func decodeAdministrativeCommunication(data []byte) (string, []byte) {
+ if len(data) == 0 {
+ return "", data
+ }
+ communicationLen := int(data[0])
+ if communicationLen > bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX {
+ communicationLen = bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX
+ }
+ if communicationLen > len(data)+1 {
+ communicationLen = len(data) + 1
+ }
+ return string(data[1 : communicationLen+1]), data[communicationLen+1:]
+}
+
+func extractFileAndFamilyFromTCPListener(l *net.TCPListener) (*os.File, int, error) {
+ // Note #1: TCPListener.File() has the unexpected side-effect of putting
+ // the original socket into blocking mode. See Note #2.
+ fi, err := l.File()
+ if err != nil {
+ return nil, 0, err
+ }
+
+ // Note #2: Call net.FileListener() to put the original socket back into
+ // non-blocking mode.
+ fl, err := net.FileListener(fi)
+ if err != nil {
+ fi.Close()
+ return nil, 0, err
+ }
+ fl.Close()
+
+ family := syscall.AF_INET
+ if strings.Contains(l.Addr().String(), "[") {
+ family = syscall.AF_INET6
+ }
+
+ return fi, family, nil
+}
+
+func extractFileAndFamilyFromTCPConn(conn *net.TCPConn) (*os.File, int, error) {
+ // Note #1: TCPConn.File() has the unexpected side-effect of putting
+ // the original socket into blocking mode. See Note #2.
+ fi, err := conn.File()
+ if err != nil {
+ return nil, 0, err
+ }
+
+ // Note #2: Call net.FileConn() to put the original socket back into
+ // non-blocking mode.
+ fc, err := net.FileConn(fi)
+ if err != nil {
+ fi.Close()
+ return nil, 0, err
+ }
+ fc.Close()
+
+ family := syscall.AF_INET
+ if strings.Contains(conn.RemoteAddr().String(), "[") {
+ family = syscall.AF_INET6
+ }
+
+ return fi, family, nil
+}