blob: 278fc0a51cff1574124cd81abda80d6395277f64 [file] [log] [blame]
Scott Bakere7144bc2019-10-01 14:16:47 -07001/*
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 */
16
17package afrouter
18
19import (
20 "fmt"
21 "github.com/golang/protobuf/proto"
22 "github.com/opencord/voltha-go/common/log"
23 "google.golang.org/grpc"
24)
25
26func Codec() grpc.Codec {
27 return CodecWithParent(&protoCodec{})
28}
29
30func CodecWithParent(parent grpc.Codec) grpc.Codec {
31 return &transparentRoutingCodec{parent}
32}
33
34type transparentRoutingCodec struct {
35 parentCodec grpc.Codec
36}
37
38// responseFrame is a frame being "returned" to whomever established the connection
39type responseFrame struct {
40 payload []byte
41 router Router
42 method string
43 backend *backend
44 metaKey string
45 metaVal string
46}
47
48// requestFrame is a frame coming in from whomever established the connection
49type requestFrame struct {
50 payload []byte
51 router Router
52 backend *backend
53 connection *connection // optional, if the router preferred one connection over another
54 err error
55 methodInfo methodDetails
56 serialNo string
57 metaKey string
58 metaVal string
59}
60
61func (cdc *transparentRoutingCodec) Marshal(v interface{}) ([]byte, error) {
62 switch t := v.(type) {
63 case *responseFrame:
64 return t.payload, nil
65 case *requestFrame:
66 return t.payload, nil
67 default:
68 return cdc.parentCodec.Marshal(v)
69 }
70}
71
72func (cdc *transparentRoutingCodec) Unmarshal(data []byte, v interface{}) error {
73 switch t := v.(type) {
74 case *responseFrame:
75 t.payload = data
76 // This is where the affinity is established on a northbound response
77 t.router.ReplyHandler(v)
78 return nil
79 case *requestFrame:
80 t.payload = data
81 // This is were the afinity value is pulled from the payload
82 // and the backend selected.
83 t.backend, t.connection = t.router.Route(v)
84 name := "<nil>"
85 if t.backend != nil {
86 name = t.backend.name
87 }
88 log.Debugf("Routing returned %s for method %s", name, t.methodInfo.method)
89
90 return nil
91 default:
92 return cdc.parentCodec.Unmarshal(data, v)
93 }
94}
95
96func (cdc *transparentRoutingCodec) String() string {
97 return fmt.Sprintf("%s", cdc.parentCodec.String())
98}
99
100// protoCodec is a Codec implementation with protobuf. It is the default Codec for gRPC.
101type protoCodec struct{}
102
103func (protoCodec) Marshal(v interface{}) ([]byte, error) {
104 return proto.Marshal(v.(proto.Message))
105}
106
107func (protoCodec) Unmarshal(data []byte, v interface{}) error {
108 return proto.Unmarshal(data, v.(proto.Message))
109}
110
111func (protoCodec) String() string {
112 return "protoCodec"
113}