blob: dff1519a2a15829f7c024b78bf8dd0f9d89b0f70 [file] [log] [blame]
sslobodr392ebd52019-01-18 12:41:49 -05001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
sslobodr392ebd52019-01-18 12:41:49 -050016
17package afrouter
18
19import (
sslobodr392ebd52019-01-18 12:41:49 -050020 "errors"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040021 "fmt"
22 "github.com/opencord/voltha-go/common/log"
sslobodr392ebd52019-01-18 12:41:49 -050023 "google.golang.org/grpc"
24 "google.golang.org/grpc/codes"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040025 "net"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040026 "strconv"
sslobodr392ebd52019-01-18 12:41:49 -050027)
28
29var (
30 clientStreamDescForProxying = &grpc.StreamDesc{
31 ServerStreams: true,
32 ClientStreams: true,
33 }
34)
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040035
sslobodr392ebd52019-01-18 12:41:49 -050036type server struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040037 running bool
38 name string
sslobodr392ebd52019-01-18 12:41:49 -050039 proxyListener net.Listener
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040040 routers map[string]map[string]Router
41 proxyServer *grpc.Server
sslobodr392ebd52019-01-18 12:41:49 -050042}
43
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040044func newServer(config *ServerConfig) (*server, error) {
sslobodr392ebd52019-01-18 12:41:49 -050045 var err error = nil
Kent Hagerman1e9061e2019-05-21 16:01:21 -040046 var rtrn_err = false
47 var s *server
sslobodr392ebd52019-01-18 12:41:49 -050048 // Change over to the new configuration format
49 // Validate the configuration
50 // There should be a name
51 if config.Name == "" {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040052 log.Error("A server has been defined with no name")
sslobodr392ebd52019-01-18 12:41:49 -050053 rtrn_err = true
54 }
55 // Validate that there's a port specified
56 if config.Port == 0 {
57 log.Errorf("Server %s does not have a valid port assigned", config.Name)
58 rtrn_err = true
59 }
60 // Validate the ip address if one is provided
61 if ip := net.ParseIP(config.Addr); config.Addr != "" && ip == nil {
62 log.Errorf("Invalid address '%s' provided for server '%s'", config.Addr, config.Name)
63 rtrn_err = true
64 }
65 if config.Type != "grpc" && config.Type != "streaming_grpc" {
66 if config.Type == "" {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040067 log.Errorf("A server 'type' must be defined for server %s", config.Name)
sslobodr392ebd52019-01-18 12:41:49 -050068 } else {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040069 log.Errorf("The server type must be either 'grpc' or 'streaming_grpc' "+
70 "but '%s' was found for server '%s'", config.Type, config.Name)
sslobodr392ebd52019-01-18 12:41:49 -050071 }
72 rtrn_err = true
73 }
74 if len(config.Routers) == 0 {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040075 log.Errorf("At least one router must be specified for server '%s'", config.Name)
sslobodr392ebd52019-01-18 12:41:49 -050076 rtrn_err = true
77 }
78
Kent Hagerman1e9061e2019-05-21 16:01:21 -040079 if rtrn_err {
sslobodr392ebd52019-01-18 12:41:49 -050080 return nil, errors.New("Server configuration failed")
81 } else {
82 // The configuration is valid, create a server and configure it.
Kent Hagerman1e9061e2019-05-21 16:01:21 -040083 s = &server{name: config.Name, routers: make(map[string]map[string]Router)}
sslobodr392ebd52019-01-18 12:41:49 -050084 // The listener
Kent Hagerman1e9061e2019-05-21 16:01:21 -040085 if s.proxyListener, err =
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040086 net.Listen("tcp", config.Addr+":"+
87 strconv.Itoa(int(config.Port))); err != nil {
sslobodr392ebd52019-01-18 12:41:49 -050088 log.Error(err)
89 return nil, err
90 }
91 // Create the routers
Kent Hagerman1e9061e2019-05-21 16:01:21 -040092 log.Debugf("Configuring the routers for server %s", s.name)
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040093 for p, r := range config.routers {
94 log.Debugf("Processing router %s for package %s", r.Name, p)
95 if dr, err := newRouter(r); err != nil {
96 log.Error(err)
97 return nil, err
98 } else {
sslobodr392ebd52019-01-18 12:41:49 -050099 log.Debugf("Adding router %s to the server %s for package %s and service %s",
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400100 dr.Name(), s.name, p, dr.Service())
101 if _, ok := s.routers[p]; ok {
102 s.routers[p][dr.Service()] = dr
sslobodr392ebd52019-01-18 12:41:49 -0500103 } else {
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400104 s.routers[p] = make(map[string]Router)
105 s.routers[p][dr.Service()] = dr
sslobodr392ebd52019-01-18 12:41:49 -0500106 }
107 }
108 }
109 // Configure the grpc handler
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400110 s.proxyServer = grpc.NewServer(
sslobodr392ebd52019-01-18 12:41:49 -0500111 grpc.CustomCodec(Codec()),
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400112 grpc.UnknownServiceHandler(s.TransparentHandler()),
sslobodr392ebd52019-01-18 12:41:49 -0500113 )
114
115 }
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400116 return s, nil
sslobodr392ebd52019-01-18 12:41:49 -0500117}
118
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400119func (s *server) Name() string {
sslobodr392ebd52019-01-18 12:41:49 -0500120 return s.name
121}
122
123func (s *server) TransparentHandler() grpc.StreamHandler {
124 return s.handler
125}
126
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400127func (s *server) getRouter(pkg string, service string) (Router, bool) {
128 if fn, ok := s.routers[pkg][service]; ok { // Both specified
sslobodr392ebd52019-01-18 12:41:49 -0500129 return fn, ok
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400130 } else if fn, ok = s.routers["*"][service]; ok { // Package wild card
sslobodr392ebd52019-01-18 12:41:49 -0500131 return fn, ok
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400132 } else if fn, ok = s.routers[pkg]["*"]; ok { // Service wild card
sslobodr392ebd52019-01-18 12:41:49 -0500133 return fn, ok
134 } else if fn, ok = s.routers["*"]["*"]; ok { // Both Wildcarded
135 return fn, ok
136 } else {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400137 return nil, false
sslobodr392ebd52019-01-18 12:41:49 -0500138 }
139}
140
sslobodr392ebd52019-01-18 12:41:49 -0500141func (s *server) handler(srv interface{}, serverStream grpc.ServerStream) error {
142 // Determine what router is intended to handle this request
143 fullMethodName, ok := grpc.MethodFromServerStream(serverStream)
144 if !ok {
145 return grpc.Errorf(codes.Internal, "lowLevelServerStream doesn't exist in context")
146 }
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400147 log.Debugf("Processing grpc request %s on server %s", fullMethodName, s.name)
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400148 methodInfo := newMethodDetails(fullMethodName)
149 r, ok := s.getRouter(methodInfo.pkg, methodInfo.service)
150 //fn, ok := s.routers[methodInfo.pkg][methodInfo.service]
sslobodr392ebd52019-01-18 12:41:49 -0500151 if !ok {
152 // TODO: Should this be punted to a default transparent router??
153 // Probably not, if one is defined yes otherwise just crap out.
154
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400155 err := fmt.Errorf("Unable to dispatch! Service '%s' for package '%s' not found.", methodInfo.service, methodInfo.pkg)
sslobodr392ebd52019-01-18 12:41:49 -0500156 log.Error(err)
157 return err
158 }
159 log.Debugf("Selected router %s\n", r.Name())
160
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400161 mk, mv, err := r.GetMetaKeyVal(serverStream)
sslobodr392ebd52019-01-18 12:41:49 -0500162 if err != nil {
163 log.Error(err)
164 return err
165 }
166
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400167 //nbR := &nbRequest(srv:srv,serverStream:serverStream,r:r,methodInfo:methodInfo,metaKey:mk,metaVal:mv)
sslobodr392ebd52019-01-18 12:41:49 -0500168
169 // Extract the cluster from the selected router and use it to manage the transfer
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400170 if cluster, err := r.BackendCluster(methodInfo.method, mk); err != nil {
sslobodr392ebd52019-01-18 12:41:49 -0500171 return err
172 } else {
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400173 //return beCluster.handler(nbR)
174 return cluster.handler(srv, serverStream, r, methodInfo, mk, mv)
sslobodr392ebd52019-01-18 12:41:49 -0500175 }
sslobodr392ebd52019-01-18 12:41:49 -0500176}