github.com/fafucoder/cilium@v1.6.11/proxylib/proxylib.go (about) 1 // Copyright 2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 /* 18 #include "proxylib/types.h" 19 */ 20 import "C" 21 22 import ( 23 "github.com/cilium/cilium/proxylib/accesslog" 24 _ "github.com/cilium/cilium/proxylib/cassandra" 25 _ "github.com/cilium/cilium/proxylib/memcached" 26 "github.com/cilium/cilium/proxylib/npds" 27 . "github.com/cilium/cilium/proxylib/proxylib" 28 _ "github.com/cilium/cilium/proxylib/r2d2" 29 _ "github.com/cilium/cilium/proxylib/testparsers" 30 31 "github.com/cilium/cilium/pkg/lock" 32 log "github.com/sirupsen/logrus" 33 ) 34 35 var ( 36 // mutex protects connections 37 mutex lock.RWMutex 38 // Key uint64 is a connection ID allocated by Envoy, practically a monotonically increasing number 39 connections map[uint64]*Connection = make(map[uint64]*Connection) 40 ) 41 42 func init() { 43 log.Debug("proxylib: Initializing library") 44 } 45 46 // Copy value string from C-memory to Go-memory. 47 // Go strings are immutable, but byte slices are not. Converting to a byte slice will thus 48 // copy the memory. 49 func strcpy(str string) string { 50 return string(([]byte(str))[0:]) 51 } 52 53 // OnNewConnection is used to register a new connection of protocol 'proto'. 54 // Note that the 'origBuf' and replyBuf' type '*[]byte' corresponds to 'InjectBuf' type, but due to 55 // cgo export restrictions we can't use the go type in the prototype. 56 //export OnNewConnection 57 func OnNewConnection(instanceId uint64, proto string, connectionId uint64, ingress bool, srcId, dstId uint32, srcAddr, dstAddr, policyName string, origBuf, replyBuf *[]byte) C.FilterResult { 58 instance := FindInstance(instanceId) 59 if instance == nil { 60 return C.FILTER_INVALID_INSTANCE 61 } 62 63 err, conn := NewConnection(instance, strcpy(proto), connectionId, ingress, srcId, dstId, strcpy(srcAddr), strcpy(dstAddr), strcpy(policyName), origBuf, replyBuf) 64 if err == nil { 65 mutex.Lock() 66 connections[connectionId] = conn 67 mutex.Unlock() 68 return C.FILTER_OK 69 } 70 if res, ok := err.(FilterResult); ok { 71 return C.FilterResult(res) 72 } 73 return C.FILTER_UNKNOWN_ERROR 74 } 75 76 // Each connection is assumed to be called from a single thread, so accessing connection metadata 77 // does not need protection. 78 // 79 // OnData gets all the unparsed data the datapath has received so far. The data is provided to the parser 80 // associated with the connection, and the parser is expected to find if the data frame contains enough data 81 // to make a PASS/DROP decision for the whole data frame. Note that the whole data frame need not be received, 82 // if the decision including the length of the data frame in bytes can be determined based on the beginning of 83 // the data frame only (e.g., headers including the length of the data frame). The parser returns a decision 84 // with the number of bytes on which the decision applies. If more data is available, then the parser will be 85 // called again with the remaining data. Parser needs to return MORE if a decision can't be made with 86 // the available data, including the minimum number of additional bytes that is needed before the parser is 87 // called again. 88 // 89 // The parser can also inject at arbitrary points in the data stream. This is indecated by an INJECT operation 90 // with the number of bytes to be injected. The actual bytes to be injected are provided via an Inject() 91 // callback prior to returning the INJECT operation. The Inject() callback operates on a limited size buffer 92 // provided by the datapath, and multiple INJECT operations may be needed to inject large amounts of data. 93 // Since we get the data on one direction at a time, any frames to be injected in the reverse direction 94 // are placed in the reverse direction buffer, from where the datapath injects the data before calling 95 // us again for the reverse direction input. 96 // 97 //export OnData 98 func OnData(connectionId uint64, reply, endStream bool, data *[][]byte, filterOps *[][2]int64) C.FilterResult { 99 // Find the connection 100 mutex.RLock() 101 connection, ok := connections[connectionId] 102 mutex.RUnlock() 103 if !ok { 104 return C.FILTER_UNKNOWN_CONNECTION 105 } 106 107 return C.FilterResult(connection.OnData(reply, endStream, data, filterOps)) 108 } 109 110 // Make this more general connection event callback 111 //export Close 112 func Close(connectionId uint64) { 113 mutex.Lock() 114 delete(connections, connectionId) 115 mutex.Unlock() 116 } 117 118 // OpenModule is called before any other APIs. 119 // Called concurrently by different filter instances. 120 // Returns a library instance ID that must be passed to all other API calls. 121 // Calls with the same parameters will return the same instance. 122 // Zero return value indicates an error. 123 //export OpenModule 124 func OpenModule(params [][2]string, debug bool) uint64 { 125 var accessLogPath, xdsPath, nodeID string 126 for i := range params { 127 key := params[i][0] 128 value := strcpy(params[i][1]) 129 130 switch key { 131 case "access-log-path": 132 accessLogPath = value 133 case "xds-path": 134 xdsPath = value 135 case "node-id": 136 nodeID = value 137 default: 138 return 0 139 } 140 } 141 142 if debug { 143 mutex.Lock() 144 log.SetLevel(log.DebugLevel) 145 mutex.Unlock() 146 } 147 // Copy strings from C-memory to Go-memory so that the string remains valid 148 // also after this function returns 149 return OpenInstance(nodeID, xdsPath, npds.NewClient, accessLogPath, accesslog.NewClient) 150 } 151 152 //export CloseModule 153 func CloseModule(id uint64) { 154 CloseInstance(id) 155 } 156 157 // Must have empty main 158 func main() {}