blob: 675320a5e12f096e856b61ed11573fafe7506974 [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 (
20 "fmt"
sslobodr392ebd52019-01-18 12:41:49 -050021 "github.com/golang/protobuf/proto"
22 "github.com/opencord/voltha-go/common/log"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040023 "google.golang.org/grpc"
24 "sync"
sslobodr392ebd52019-01-18 12:41:49 -050025)
26
27func Codec() grpc.Codec {
28 return CodecWithParent(&protoCodec{})
29}
30
sslobodrcd37bc52019-01-24 11:47:16 -050031func CodecWithParent(parent grpc.Codec) grpc.Codec {
32 return &transparentRoutingCodec{parent}
sslobodr392ebd52019-01-18 12:41:49 -050033}
34
sslobodrcd37bc52019-01-24 11:47:16 -050035type transparentRoutingCodec struct {
sslobodr392ebd52019-01-18 12:41:49 -050036 parentCodec grpc.Codec
37}
38
Kent Hagerman1e9061e2019-05-21 16:01:21 -040039// sbFrame is a frame being "returned" to whomever established the connection
sslobodr392ebd52019-01-18 12:41:49 -050040type sbFrame struct {
41 payload []byte
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040042 router Router
43 method string
Kent Hagerman1e9061e2019-05-21 16:01:21 -040044 backend *backend
45 mutex sync.Mutex
sslobodr392ebd52019-01-18 12:41:49 -050046 metaKey string
47 metaVal string
48}
49
Kent Hagerman1e9061e2019-05-21 16:01:21 -040050// nbFrame is a frame coming in from whomever established the connection
sslobodr392ebd52019-01-18 12:41:49 -050051type nbFrame struct {
Kent Hagerman1e9061e2019-05-21 16:01:21 -040052 payload []byte
53 router Router
54 backend *backend
55 err error
56 methodInfo methodDetails
57 serialNo uint64
58 metaKey string
59 metaVal string
sslobodr392ebd52019-01-18 12:41:49 -050060}
61
sslobodrcd37bc52019-01-24 11:47:16 -050062func (cdc *transparentRoutingCodec) Marshal(v interface{}) ([]byte, error) {
sslobodr392ebd52019-01-18 12:41:49 -050063 switch t := v.(type) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040064 case *sbFrame:
65 return t.payload, nil
66 case *nbFrame:
67 return t.payload, nil
68 default:
69 return cdc.parentCodec.Marshal(v)
sslobodr392ebd52019-01-18 12:41:49 -050070 }
sslobodr392ebd52019-01-18 12:41:49 -050071}
72
sslobodrcd37bc52019-01-24 11:47:16 -050073func (cdc *transparentRoutingCodec) Unmarshal(data []byte, v interface{}) error {
sslobodr392ebd52019-01-18 12:41:49 -050074 switch t := v.(type) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040075 case *sbFrame:
76 t.payload = data
77 // This is where the affinity is established on a northbound response
78 t.router.ReplyHandler(v)
79 return nil
80 case *nbFrame:
81 t.payload = data
82 // This is were the afinity value is pulled from the payload
83 // and the backend selected.
Kent Hagerman1e9061e2019-05-21 16:01:21 -040084 t.backend = t.router.Route(v)
85 log.Debugf("Routing returned %v for method %s", t.backend, t.methodInfo.method)
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040086 return nil
87 default:
88 return cdc.parentCodec.Unmarshal(data, v)
sslobodr392ebd52019-01-18 12:41:49 -050089 }
90}
91
sslobodrcd37bc52019-01-24 11:47:16 -050092func (cdc *transparentRoutingCodec) String() string {
93 return fmt.Sprintf("%s", cdc.parentCodec.String())
sslobodr392ebd52019-01-18 12:41:49 -050094}
95
sslobodrcd37bc52019-01-24 11:47:16 -050096// protoCodec is a Codec implementation with protobuf. It is the default Codec for gRPC.
sslobodr392ebd52019-01-18 12:41:49 -050097type protoCodec struct{}
98
99func (protoCodec) Marshal(v interface{}) ([]byte, error) {
100 return proto.Marshal(v.(proto.Message))
101}
102
103func (protoCodec) Unmarshal(data []byte, v interface{}) error {
104 return proto.Unmarshal(data, v.(proto.Message))
105}
106
107func (protoCodec) String() string {
sslobodrcd37bc52019-01-24 11:47:16 -0500108 return "protoCodec"
sslobodr392ebd52019-01-18 12:41:49 -0500109}