forked from quickfixgo/quickfix
/
message_router.go
85 lines (67 loc) · 2.51 KB
/
message_router.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package quickfix
import (
"github.com/quickfixgo/quickfix/fix"
"github.com/quickfixgo/quickfix/fix/enum"
"github.com/quickfixgo/quickfix/fix/field"
)
type routeKey struct {
BeginString string
MsgType string
}
//A MessageRoute is a function can process a fromApp/fromAdmin callback
type MessageRoute func(msg Message, sessionID SessionID) MessageRejectError
//A MessageRouter is a mutex for MessageRoutes
type MessageRouter struct {
routes map[routeKey]MessageRoute
}
//NewMessageRouter returns an initialized MessageRouter instance
func NewMessageRouter() *MessageRouter {
return &MessageRouter{routes: make(map[routeKey]MessageRoute)}
}
//AddRoute adds a route to the MessageRouter instance keyed to begin string and msgType.
func (c MessageRouter) AddRoute(beginString string, msgType string, router MessageRoute) {
c.routes[routeKey{beginString, msgType}] = router
}
//Route may be called from the fromApp/fromAdmin callbacks. Messages that cannot be routed will be rejected with UnsupportedMessageType.
func (c MessageRouter) Route(msg Message, sessionID SessionID) MessageRejectError {
beginString := &field.BeginStringField{}
err := msg.Header.Get(beginString)
if err != nil {
return err
}
msgType := &field.MsgTypeField{}
err = msg.Header.Get(msgType)
if err != nil {
return err
}
return c.tryRoute(beginString, msgType, msg, sessionID)
}
func (c MessageRouter) tryRoute(beginString *field.BeginStringField, msgType *field.MsgTypeField, msg Message, sessionID SessionID) MessageRejectError {
if beginString.Value == fix.BeginString_FIXT11 && !fix.IsAdminMessageType(msgType.Value) {
applVerID := &field.ApplVerIDField{}
if err := msg.Header.Get(applVerID); err != nil {
session, _ := LookupSession(sessionID)
applVerID.Value = session.TargetDefaultApplicationVersionID()
}
switch applVerID.Value {
case enum.ApplVerID_FIX40:
beginString.Value = fix.BeginString_FIX40
case enum.ApplVerID_FIX41:
beginString.Value = fix.BeginString_FIX41
case enum.ApplVerID_FIX42:
beginString.Value = fix.BeginString_FIX42
case enum.ApplVerID_FIX43:
beginString.Value = fix.BeginString_FIX43
case enum.ApplVerID_FIX44:
beginString.Value = fix.BeginString_FIX44
case enum.ApplVerID_FIX50, enum.ApplVerID_FIX50SP1, enum.ApplVerID_FIX50SP2:
beginString.Value = fix.BeginString_FIX50
}
return c.tryRoute(beginString, msgType, msg, sessionID)
}
route, ok := c.routes[routeKey{beginString.Value, msgType.Value}]
if !ok {
return unsupportedMessageType()
}
return route(msg, sessionID)
}