From c46f6510799457f4fe9a213665ccfa4de56b07c6 Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Sat, 24 Sep 2022 11:26:43 +0200 Subject: [PATCH 01/47] Remove unsused Message.keepMessage Signed-off-by: Sylvain Rabot --- in_session.go | 2 -- message.go | 3 --- 2 files changed, 5 deletions(-) diff --git a/in_session.go b/in_session.go index 3ca45d7bd..15fa6bc70 100644 --- a/in_session.go +++ b/in_session.go @@ -275,8 +275,6 @@ func (state inSession) processReject(session *session, msg *Message, rej Message } nextState.messageStash[TypedError.ReceivedTarget] = msg - //do not reclaim stashed message - msg.keepMessage = true return nextState diff --git a/message.go b/message.go index d76e5ca44..256ddc814 100644 --- a/message.go +++ b/message.go @@ -89,9 +89,6 @@ type Message struct { //field bytes as they appear in the raw message fields []TagValue - - //flag is true if this message should not be returned to pool after use - keepMessage bool } //ToMessage returns the message itself From e30dcc23e4a993e9c367e2823dcbd30474cdb108 Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Mon, 26 Sep 2022 11:58:58 +0200 Subject: [PATCH 02/47] Add embed.FS for SQL files Signed-off-by: Sylvain Rabot --- _sql/embed.go | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 _sql/embed.go diff --git a/_sql/embed.go b/_sql/embed.go new file mode 100644 index 000000000..f61fe5110 --- /dev/null +++ b/_sql/embed.go @@ -0,0 +1,6 @@ +package sql + +import "embed" + +//go:embed mssql mysql oracle postgresql sqlite3 +var FS embed.FS From b038361fcdbaf905fe20415f9ea5874da987eb15 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 22 Nov 2022 22:58:18 +0300 Subject: [PATCH 03/47] add stop chan to escape writing deadlock of s.sessionEvent --- session.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/session.go b/session.go index 6ef143f2a..073651759 100644 --- a/session.go +++ b/session.go @@ -738,9 +738,22 @@ func (s *session) onAdmin(msg interface{}) { func (s *session) run() { s.Start(s) + var stopChan = make(chan struct{}) + s.stateTimer = internal.NewEventTimer(func() { + select { + //deadlock in write to chan s.sessionEvent after s.Stopped()==true and end of loop session.go:766 because no reader of chan s.sessionEvent + case s.sessionEvent <- internal.NeedHeartbeat: + case <-stopChan: + } + }) + s.peerTimer = internal.NewEventTimer(func() { + select { + //deadlock in write to chan s.sessionEvent after s.Stopped()==true and end of loop session.go:766 because no reader of chan s.sessionEvent + case s.sessionEvent <- internal.PeerTimeout: + case <-stopChan: + } - s.stateTimer = internal.NewEventTimer(func() { s.sessionEvent <- internal.NeedHeartbeat }) - s.peerTimer = internal.NewEventTimer(func() { s.sessionEvent <- internal.PeerTimeout }) + }) ticker := time.NewTicker(time.Second) defer func() { From 2941db590053550430e401e8dabb34b5778fa771 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 22 Nov 2022 23:00:10 +0300 Subject: [PATCH 04/47] add stop chan to escape writing deadlock of s.sessionEvent --- session.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/session.go b/session.go index 073651759..331af0f0f 100644 --- a/session.go +++ b/session.go @@ -11,7 +11,7 @@ import ( "github.com/quickfixgo/quickfix/internal" ) -//The Session is the primary FIX abstraction for message communication +// The Session is the primary FIX abstraction for message communication type session struct { store MessageStore @@ -50,8 +50,8 @@ func (s *session) logError(err error) { s.log.OnEvent(err.Error()) } -//TargetDefaultApplicationVersionID returns the default application version ID for messages received by this version. -//Applicable for For FIX.T.1 sessions. +// TargetDefaultApplicationVersionID returns the default application version ID for messages received by this version. +// Applicable for For FIX.T.1 sessions. func (s *session) TargetDefaultApplicationVersionID() string { return s.targetDefaultApplVerID } @@ -204,7 +204,7 @@ func (s *session) resend(msg *Message) bool { return s.application.ToApp(msg, s.sessionID) == nil } -//queueForSend will validate, persist, and queue the message for send +// queueForSend will validate, persist, and queue the message for send func (s *session) queueForSend(msg *Message) error { s.sendMutex.Lock() defer s.sendMutex.Unlock() @@ -224,7 +224,7 @@ func (s *session) queueForSend(msg *Message) error { return nil } -//send will validate, persist, queue the message. If the session is logged on, send all messages in the queue +// send will validate, persist, queue the message. If the session is logged on, send all messages in the queue func (s *session) send(msg *Message) error { return s.sendInReplyTo(msg, nil) } @@ -247,7 +247,7 @@ func (s *session) sendInReplyTo(msg *Message, inReplyTo *Message) error { return nil } -//dropAndReset will drop the send queue and reset the message store +// dropAndReset will drop the send queue and reset the message store func (s *session) dropAndReset() error { s.sendMutex.Lock() defer s.sendMutex.Unlock() @@ -256,7 +256,7 @@ func (s *session) dropAndReset() error { return s.store.Reset() } -//dropAndSend will validate and persist the message, then drops the send queue and sends the message. +// dropAndSend will validate and persist the message, then drops the send queue and sends the message. func (s *session) dropAndSend(msg *Message) error { return s.dropAndSendInReplyTo(msg, nil) } @@ -757,6 +757,7 @@ func (s *session) run() { ticker := time.NewTicker(time.Second) defer func() { + close(stopChan) s.stateTimer.Stop() s.peerTimer.Stop() ticker.Stop() From 6976a54c3528f8f5f693ddd12e9c909ad8da4f3a Mon Sep 17 00:00:00 2001 From: Sami Date: Wed, 23 Nov 2022 13:18:13 +0100 Subject: [PATCH 05/47] fix persist add store transaction --- filestore.go | 8 ++++++++ mongostore.go | 9 +++++++++ session.go | 8 +++----- sqlstore.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ store.go | 9 +++++++++ 5 files changed, 76 insertions(+), 5 deletions(-) diff --git a/filestore.go b/filestore.go index 976273754..46a83e6b4 100644 --- a/filestore.go +++ b/filestore.go @@ -301,6 +301,14 @@ func (store *fileStore) SaveMessage(seqNum int, msg []byte) error { return nil } +func (store *fileStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error { + err := store.SaveMessage(seqNum, msg) + if err != nil { + return err + } + return store.IncrNextSenderMsgSeqNum() +} + func (store *fileStore) getMessage(seqNum int) (msg []byte, found bool, err error) { msgInfo, found := store.offsets[seqNum] if !found { diff --git a/mongostore.go b/mongostore.go index 15c419347..e07cc5c7b 100644 --- a/mongostore.go +++ b/mongostore.go @@ -248,6 +248,15 @@ func (store *mongoStore) SaveMessage(seqNum int, msg []byte) (err error) { return } +func (store *mongoStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error { + // TODO add transaction + err := store.SaveMessage(seqNum, msg) + if err != nil { + return err + } + return store.IncrNextSenderMsgSeqNum() +} + func (store *mongoStore) GetMessages(beginSeqNum, endSeqNum int) (msgs [][]byte, err error) { msgFilter := generateMessageFilter(&store.sessionID) //Marshal into database form diff --git a/session.go b/session.go index 6ef143f2a..5ba2ee29d 100644 --- a/session.go +++ b/session.go @@ -321,12 +321,10 @@ func (s *session) prepMessageForSend(msg *Message, inReplyTo *Message) (msgBytes func (s *session) persist(seqNum int, msgBytes []byte) error { if !s.DisableMessagePersist { - if err := s.store.SaveMessage(seqNum, msgBytes); err != nil { - return err - } + return s.store.SaveMessageAndIncrNextSenderMsgSeqNum(seqNum, msgBytes) + } else { + return s.store.IncrNextSenderMsgSeqNum() } - - return s.store.IncrNextSenderMsgSeqNum() } func (s *session) sendQueued() { diff --git a/sqlstore.go b/sqlstore.go index a57281dd8..5aef634f3 100644 --- a/sqlstore.go +++ b/sqlstore.go @@ -274,6 +274,53 @@ func (store *sqlStore) SaveMessage(seqNum int, msg []byte) error { return err } +func (store *sqlStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error { + s := store.sessionID + + tx, err := store.db.Begin() + if err != nil { + return err + } + defer tx.Rollback() + + _, err = tx.Exec(sqlString(`INSERT INTO messages ( + msgseqnum, message, + beginstring, session_qualifier, + sendercompid, sendersubid, senderlocid, + targetcompid, targetsubid, targetlocid) + VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, store.placeholder), + seqNum, string(msg), + s.BeginString, s.Qualifier, + s.SenderCompID, s.SenderSubID, s.SenderLocationID, + s.TargetCompID, s.TargetSubID, s.TargetLocationID) + if err != nil { + return err + } + + if err := store.cache.IncrNextSenderMsgSeqNum(); err != nil { + return errors.Wrap(err, "cache incr next") + } + + next := store.cache.NextSenderMsgSeqNum() + _, err = store.db.Exec(sqlString(`UPDATE sessions SET outgoing_seqnum = ? + WHERE beginstring=? AND session_qualifier=? + AND sendercompid=? AND sendersubid=? AND senderlocid=? + AND targetcompid=? AND targetsubid=? AND targetlocid=?`, store.placeholder), + next, s.BeginString, s.Qualifier, + s.SenderCompID, s.SenderSubID, s.SenderLocationID, + s.TargetCompID, s.TargetSubID, s.TargetLocationID) + if err != nil { + return err + } + + err = store.cache.SetNextSenderMsgSeqNum(next) + if err != nil { + return err + } + + return tx.Commit() +} + func (store *sqlStore) GetMessages(beginSeqNum, endSeqNum int) ([][]byte, error) { s := store.sessionID var msgs [][]byte diff --git a/store.go b/store.go index 41b6bc0c0..b743a46cc 100644 --- a/store.go +++ b/store.go @@ -20,6 +20,7 @@ type MessageStore interface { CreationTime() time.Time SaveMessage(seqNum int, msg []byte) error + SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error GetMessages(beginSeqNum, endSeqNum int) ([][]byte, error) Refresh() error @@ -97,6 +98,14 @@ func (store *memoryStore) SaveMessage(seqNum int, msg []byte) error { return nil } +func (store *memoryStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error { + err := store.SaveMessage(seqNum, msg) + if err != nil { + return err + } + return store.IncrNextSenderMsgSeqNum() +} + func (store *memoryStore) GetMessages(beginSeqNum, endSeqNum int) ([][]byte, error) { var msgs [][]byte for seqNum := beginSeqNum; seqNum <= endSeqNum; seqNum++ { From 588c4c2b3b1eaa7e94c3612189a556254bb9491b Mon Sep 17 00:00:00 2001 From: Sami Date: Wed, 23 Nov 2022 13:26:02 +0100 Subject: [PATCH 06/47] add missing tx --- sqlstore.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlstore.go b/sqlstore.go index 5aef634f3..d34cad8b7 100644 --- a/sqlstore.go +++ b/sqlstore.go @@ -302,7 +302,7 @@ func (store *sqlStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []b } next := store.cache.NextSenderMsgSeqNum() - _, err = store.db.Exec(sqlString(`UPDATE sessions SET outgoing_seqnum = ? + _, err = tx.Exec(sqlString(`UPDATE sessions SET outgoing_seqnum = ? WHERE beginstring=? AND session_qualifier=? AND sendercompid=? AND sendersubid=? AND senderlocid=? AND targetcompid=? AND targetsubid=? AND targetlocid=?`, store.placeholder), From f5da9feaa7c1d39ce0c9f1a2a86dd697de010bb9 Mon Sep 17 00:00:00 2001 From: Sami Date: Wed, 23 Nov 2022 13:41:37 +0100 Subject: [PATCH 07/47] fix lint --- session.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/session.go b/session.go index 5ba2ee29d..73557cf45 100644 --- a/session.go +++ b/session.go @@ -322,9 +322,9 @@ func (s *session) prepMessageForSend(msg *Message, inReplyTo *Message) (msgBytes func (s *session) persist(seqNum int, msgBytes []byte) error { if !s.DisableMessagePersist { return s.store.SaveMessageAndIncrNextSenderMsgSeqNum(seqNum, msgBytes) - } else { - return s.store.IncrNextSenderMsgSeqNum() } + + return s.store.IncrNextSenderMsgSeqNum() } func (s *session) sendQueued() { From dfc17b07ff6e78ab83bceaa3e968ef4630d3fd96 Mon Sep 17 00:00:00 2001 From: Sami Date: Wed, 23 Nov 2022 17:14:24 +0100 Subject: [PATCH 08/47] move increment after tx commit --- sqlstore.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sqlstore.go b/sqlstore.go index d34cad8b7..a176b7509 100644 --- a/sqlstore.go +++ b/sqlstore.go @@ -297,11 +297,7 @@ func (store *sqlStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []b return err } - if err := store.cache.IncrNextSenderMsgSeqNum(); err != nil { - return errors.Wrap(err, "cache incr next") - } - - next := store.cache.NextSenderMsgSeqNum() + next := store.cache.NextSenderMsgSeqNum() + 1 _, err = tx.Exec(sqlString(`UPDATE sessions SET outgoing_seqnum = ? WHERE beginstring=? AND session_qualifier=? AND sendercompid=? AND sendersubid=? AND senderlocid=? @@ -313,12 +309,17 @@ func (store *sqlStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []b return err } + err = tx.Commit() + if err != nil { + return err + } + err = store.cache.SetNextSenderMsgSeqNum(next) if err != nil { return err } - return tx.Commit() + return nil } func (store *sqlStore) GetMessages(beginSeqNum, endSeqNum int) ([][]byte, error) { From afa1631e5bcf29c02035b03872edd0458771d2c1 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Tue, 6 Dec 2022 21:11:29 -0500 Subject: [PATCH 09/47] Upgrades mongo driver, resolves broken ci config, adds dynamic session fix --- .devcontainer/{Dockerfile => Dockerfile.dev} | 0 .devcontainer/devcontainer.json | 6 +- .devcontainer/docker-compose.yml | 7 +- .github/workflows/ci.yaml | 33 ++++--- Makefile | 19 +++-- README.md | 2 +- _test/{echo_server.go => test-server/main.go} | 18 ++-- acceptor.go | 2 +- cmd/generate-fix/generate-fix.go | 21 ++++- cmd/generate-fix/internal/template_helpers.go | 21 +++++ cmd/generate-fix/internal/templates.go | 3 +- config/doc.go | 2 +- go.mod | 24 ++++-- go.sum | 85 +++++++++++++------ mongostore.go | 62 ++++++++------ mongostore_test.go | 5 +- 16 files changed, 214 insertions(+), 96 deletions(-) rename .devcontainer/{Dockerfile => Dockerfile.dev} (100%) rename _test/{echo_server.go => test-server/main.go} (91%) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile.dev similarity index 100% rename from .devcontainer/Dockerfile rename to .devcontainer/Dockerfile.dev diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 8dd1b30a2..2530677e2 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,13 +1,17 @@ { - "name": "Go & Mongo DB", + "name": "Quickfix/Go Development", "dockerComposeFile": "docker-compose.yml", "service": "app", "workspaceFolder": "/workspace", + "shutdownAction": "stopCompose", "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], + "features": { + "ruby": "latest" + }, "customizations": { "vscode": { "settings": { diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index deb58bf2a..ce8de67d7 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -4,10 +4,10 @@ services: app: build: context: . - dockerfile: Dockerfile + dockerfile: Dockerfile.dev volumes: - ..:/workspace:cached - + - /var/run/docker.sock:/var/run/docker.sock # Overrides default command so things don't shut down after the process ends. command: sleep infinity @@ -25,7 +25,8 @@ services: restart: unless-stopped volumes: - mongodb-data:/data/db - + ports: + - 27017:27017 # Uncomment to change startup options # environment: # MONGO_INITDB_ROOT_USERNAME: root diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7de7c5db2..7a225fc85 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -47,15 +47,15 @@ jobs: matrix: go: [1.18] fix-version: - - FIX_TEST= - - FIX_TEST=fix40 - - FIX_TEST=fix41 - - FIX_TEST=fix42 - - FIX_TEST=fix43 - - FIX_TEST=fix44 - - FIX_TEST=fix50 - - FIX_TEST=fix50sp1 - - FIX_TEST=fix50sp2 + - + - fix40 + - fix41 + - fix42 + - fix43 + - fix44 + - fix50 + - fix50sp1 + - fix50sp2 steps: - name: Setup uses: actions/setup-go@v2 @@ -63,10 +63,15 @@ jobs: go-version: ${{ matrix.go }} - name: Check out source uses: actions/checkout@v2 - - name: Run Mongo - run: docker run -d -p 27017:27017 mongo + - name: Start MongoDB + uses: supercharge/mongodb-github-action@1.8.0 + - name: Install ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.0' - name: Test env: - GO111MODULE: "on" - MONGODB_TEST_CXN: "localhost" - run: make generate; if [ -z "$FIX_TEST" ]; then make build; make; else make build_accept; make $FIX_TEST; fi + GO111MODULE: on + MONGODB_TEST_CXN: mongodb://localhost:27017 + FIX_TEST: ${{ matrix.fix-version }} + run: if [ -z $FIX_TEST ]; then make build-src && make test-ci; else make generate-ci && make build && make $FIX_TEST; fi diff --git a/Makefile b/Makefile index ece1c82af..9dffe9d3d 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,7 @@ clean: rm -rf gen generate: clean - mkdir -p gen; cd gen; go run ../cmd/generate-fix/generate-fix.go ../spec/*.xml - go get -u all + mkdir -p gen; cd gen; go run ../cmd/generate-fix/generate-fix.go -pkg-root=github.com/quickfixgo/quickfix/gen ../spec/*.xml generate-dist: cd ..; go run quickfix/cmd/generate-fix/generate-fix.go quickfix/spec/*.xml @@ -47,15 +46,21 @@ vet: go vet `go list ./... | grep -v quickfix/gen` test: - MONGODB_TEST_CXN=localhost go test -v -cover . ./datadictionary ./internal + MONGODB_TEST_CXN=mongodb://db:27017 go test -v -cover . ./datadictionary ./internal -_build_all: +build-src: go build -v `go list ./...` -build_accept: - cd _test; go build -o echo_server +build-test-srv: + cd _test; go build -o echo_server ./test-server/ -build: _build_all build_accept +build: build-src build-test-srv + +test-ci: + go test -v -cover . ./datadictionary ./internal + +generate-ci: clean + mkdir -p gen; cd gen; go run ../cmd/generate-fix/generate-fix.go -pkg-root=github.com/quickfixgo/quickfix/gen ../spec/$(shell echo $(FIX_TEST) | tr '[:lower:]' '[:upper:]').xml; fix40: cd _test; ./runat.sh $@.cfg 5001 "definitions/server/$@/*.def" diff --git a/README.md b/README.md index fbfd16f81..6626300fa 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ To run acceptance tests, make generate # build acceptance test rig - make build_accept + make build-test-srv # run acceptance tests make accept diff --git a/_test/echo_server.go b/_test/test-server/main.go similarity index 91% rename from _test/echo_server.go rename to _test/test-server/main.go index ddd729789..b70dca258 100644 --- a/_test/echo_server.go +++ b/_test/test-server/main.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" "io/ioutil" "log" @@ -8,8 +9,8 @@ import ( "os/signal" "github.com/quickfixgo/quickfix" - "github.com/quickfixgo/quickfix/gen/field" - "github.com/quickfixgo/quickfix/gen/tag" + field "github.com/quickfixgo/quickfix/gen/field" + tag "github.com/quickfixgo/quickfix/gen/tag" ) var router *quickfix.MessageRouter = quickfix.NewMessageRouter() @@ -57,7 +58,8 @@ func (e *EchoApplication) processMsg(msg *quickfix.Message, sessionID quickfix.S } sessionOrderID := sessionID.String() + orderID.String() - if possResend.FIXBoolean { + + if bytes.Equal(possResend.Write(), []byte("Y")) { if e.OrderIds[sessionOrderID] { return nil } @@ -67,7 +69,7 @@ func (e *EchoApplication) processMsg(msg *quickfix.Message, sessionID quickfix.S } reply := copyMessage(msg) - if possResend.FIXBoolean { + if bytes.Equal(possResend.Write(), []byte("Y")) { reply.Header.Set(possResend) } @@ -109,6 +111,7 @@ func main() { router.AddRoute(quickfix.ApplVerIDFIX50SP1, "d", app.processMsg) router.AddRoute(quickfix.ApplVerIDFIX50SP2, "d", app.processMsg) + fmt.Println("starting test server") cfg, err := os.Open(os.Args[1]) if err != nil { fmt.Printf("Error opening %v, %v\n", os.Args[1], err) @@ -139,9 +142,10 @@ func main() { return } - interrupt := make(chan os.Signal) - signal.Notify(interrupt) - <-interrupt + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + <-c + fmt.Println("stopping test server") acceptor.Stop() } diff --git a/acceptor.go b/acceptor.go index 0ce8e8724..6482331d7 100644 --- a/acceptor.go +++ b/acceptor.go @@ -290,7 +290,7 @@ func (a *Acceptor) handleConnection(netConn net.Conn) { } localConnectionPort := netConn.LocalAddr().(*net.TCPAddr).Port - if expectedPort, ok := a.sessionHostPort[sessID]; !ok || expectedPort != localConnectionPort { + if expectedPort, ok := a.sessionHostPort[sessID]; ok && expectedPort != localConnectionPort { a.globalLog.OnEventf("Session %v not found for incoming message: %s", sessID, msgBytes) return } diff --git a/cmd/generate-fix/generate-fix.go b/cmd/generate-fix/generate-fix.go index 5ec5ff47a..27c5aa624 100644 --- a/cmd/generate-fix/generate-fix.go +++ b/cmd/generate-fix/generate-fix.go @@ -122,13 +122,26 @@ func main() { usage() } - specs := make([]*datadictionary.DataDictionary, flag.NArg()) - for i, dataDictPath := range flag.Args() { - var err error - specs[i], err = datadictionary.Parse(dataDictPath) + + args := flag.Args() + if len(args) == 1 { + dictpath := args[0] + if strings.Contains(dictpath, "FIX50SP1") { + args = append(args, strings.Replace(dictpath, "FIX50SP1", "FIXT11", -1)) + } else if strings.Contains(dictpath, "FIX50SP2") { + args = append(args, strings.Replace(dictpath, "FIX50SP2", "FIXT11", -1)) + } else if strings.Contains(dictpath, "FIX50") { + args = append(args, strings.Replace(dictpath, "FIX50", "FIXT11", -1)) + } + } + specs := []*datadictionary.DataDictionary{} + + for _, dataDictPath := range args { + spec, err := datadictionary.Parse(dataDictPath) if err != nil { log.Fatalf("Error Parsing %v: %v", dataDictPath, err) } + specs = append(specs, spec) } internal.BuildGlobalFieldTypes(specs) diff --git a/cmd/generate-fix/internal/template_helpers.go b/cmd/generate-fix/internal/template_helpers.go index 55de54481..31fbac55d 100644 --- a/cmd/generate-fix/internal/template_helpers.go +++ b/cmd/generate-fix/internal/template_helpers.go @@ -22,6 +22,27 @@ func checkIfDecimalImportRequiredForFields(fTypes []*datadictionary.FieldType) ( return } +func checkIfTimeImportRequiredForFields(fTypes []*datadictionary.FieldType) (ok bool, err error) { + var t string + for _, fType := range fTypes { + t, err = quickfixType(fType) + if err != nil { + return + } + + var vt string + if vt, err = quickfixValueType(t); err != nil { + return + } + + if vt == "time.Time" { + return true, nil + } + } + + return +} + func checkFieldDecimalRequired(f *datadictionary.FieldDef) (required bool, err error) { var globalType *datadictionary.FieldType if globalType, err = getGlobalFieldType(f); err != nil { diff --git a/cmd/generate-fix/internal/templates.go b/cmd/generate-fix/internal/templates.go index cae2d567d..72fb24b2c 100644 --- a/cmd/generate-fix/internal/templates.go +++ b/cmd/generate-fix/internal/templates.go @@ -26,6 +26,7 @@ func init() { "getGlobalFieldType": getGlobalFieldType, "collectExtraImports": collectExtraImports, "checkIfDecimalImportRequiredForFields": checkIfDecimalImportRequiredForFields, + "checkIfTimeImportRequiredForFields": checkIfTimeImportRequiredForFields, "checkIfEnumImportRequired": checkIfEnumImportRequired, } @@ -312,7 +313,7 @@ import( "{{ importRootPath }}/enum" "{{ importRootPath }}/tag" {{ if checkIfDecimalImportRequiredForFields . }} "github.com/shopspring/decimal" {{ end }} - "time" +{{ if checkIfTimeImportRequiredForFields . }} "time" {{ end }} ) {{ range . }} diff --git a/config/doc.go b/config/doc.go index c7223bbad..617b066ff 100644 --- a/config/doc.go +++ b/config/doc.go @@ -357,7 +357,7 @@ Directory to store sequence number and message files. Only used with FileStoreF MongoStoreConnection -The MongoDB connection URL to use (see https://godoc.org/github.com/globalsign/mgo#Dial for the URL Format). Only used with MongoStoreFactory. +The MongoDB connection URL to use (see https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo#Connect for more info). Only used with MongoStoreFactory. MongoStoreDatabase diff --git a/go.mod b/go.mod index a47647044..27e396a64 100644 --- a/go.mod +++ b/go.mod @@ -4,16 +4,30 @@ go 1.18 require ( github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a - github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 - github.com/mattn/go-sqlite3 v1.14.14 + github.com/mattn/go-sqlite3 v1.14.16 github.com/pkg/errors v0.9.1 github.com/shopspring/decimal v1.3.1 - github.com/stretchr/testify v1.8.0 - golang.org/x/net v0.0.0-20220708220712-1185a9018129 + github.com/stretchr/testify v1.8.1 + go.mongodb.org/mongo-driver v1.11.0 + golang.org/x/net v0.2.0 +) + +require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/klauspost/compress v1.15.12 // indirect + github.com/kr/pretty v0.2.1 // indirect github.com/kr/text v0.2.0 // indirect + github.com/montanaflynn/stats v0.6.6 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/objx v0.4.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.1 // indirect + github.com/xdg-go/stringprep v1.0.3 // indirect + github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect + golang.org/x/crypto v0.3.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/text v0.5.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d567c931c..dff68834f 100644 --- a/go.sum +++ b/go.sum @@ -4,49 +4,82 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= +github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v64GQ= +github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/quickfixgo/enum v0.0.0-20210629025633-9afc8539baba h1:ysNRAW5kAhJ76Wo6LMAtbuFq/64s2E5KK00cS/rR/Po= -github.com/quickfixgo/enum v0.0.0-20210629025633-9afc8539baba/go.mod h1:65gdG2/8vr6uOYcjZBObVHMuTEYc5rr/+aKVWTrFIrQ= -github.com/quickfixgo/field v0.0.0-20171007195410-74cea5ec78c7 h1:a/qsvkJNoj1vcSFTzgLqNcwTRuiM1VjchoRjDOIMNyY= -github.com/quickfixgo/field v0.0.0-20171007195410-74cea5ec78c7/go.mod h1:7kiKeQwJLOrwVXqvt2GAnk4vOH0jErrB3qO6SERmq7c= -github.com/quickfixgo/fix40 v0.0.0-20171007200002-cce875b2c2e7 h1:csHnaP2l65lrchDUvpk2LbA7BF23wsl4aqFqGVX8r10= -github.com/quickfixgo/fix40 v0.0.0-20171007200002-cce875b2c2e7/go.mod h1:RC0yl+6EULF8t40eFen3UdouFVdZu1uVwMsk7O/6i5s= -github.com/quickfixgo/fix41 v0.0.0-20171007212429-b272ca343ed2 h1:dofXBfr8IrzTXvHyu0gV9KIgzBzjVyBd5rmxERw50rE= -github.com/quickfixgo/fix41 v0.0.0-20171007212429-b272ca343ed2/go.mod h1:2CARkVxpb7YV3Ib6qRjI2UFzvlIyhP0lx/nN6GDoZ7w= -github.com/quickfixgo/fix42 v0.0.0-20171007212724-86a4567f1c77 h1:mD360ECTwAK4jbOIrqAH2MdJF3RrH5KuboFNdxSmIDM= -github.com/quickfixgo/fix42 v0.0.0-20171007212724-86a4567f1c77/go.mod h1:RyVaOPb/+NasHAt2e5UJ9PjXT+5AeqyKZfNPOB4UspE= -github.com/quickfixgo/fix43 v0.0.0-20171007213001-a7ff4f2a2470 h1:1bkIwYMs5XrjvKouIiqn2Iiw46XKcNTS1as9hCZqnMg= -github.com/quickfixgo/fix43 v0.0.0-20171007213001-a7ff4f2a2470/go.mod h1:qpAUIIjRXEQRtuMpJolR+8VkDajoU8J7Iw55Gnwm15s= -github.com/quickfixgo/fix44 v0.0.0-20171007213039-f090a1006218 h1:zrm7CRhis2ArB/xjOj0EQJOuHq5fI0JpS4AILtjwUug= -github.com/quickfixgo/fix44 v0.0.0-20171007213039-f090a1006218/go.mod h1:KFN4LkI1sidKgWnUvmpDdvsa+aNvcbExtS8iPQvA9ys= -github.com/quickfixgo/fixt11 v0.0.0-20171007213433-d9788ca97f5d h1:PlymcwOkKZXnOI3uJZu0lpnvnweTkML9YxnTuYhhzIM= -github.com/quickfixgo/fixt11 v0.0.0-20171007213433-d9788ca97f5d/go.mod h1:/oN4Arv+/8zKshQTj+ggpWfjXuVv9bMUO93zOO6R+oM= -github.com/quickfixgo/tag v0.0.0-20171007194743-cbb465760521 h1:RXfjXtjvXb4wgzBHTTFbyW5uBP04Nrlky9e9lAe8mIE= -github.com/quickfixgo/tag v0.0.0-20171007194743-cbb465760521/go.mod h1:EKAI2kkSaIuSywW0WbIgXIcuA9vS4IXfCga9U9Oax2E= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0= -golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= +github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= +go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE= +go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/mongostore.go b/mongostore.go index 15c419347..59699ecdc 100644 --- a/mongostore.go +++ b/mongostore.go @@ -1,12 +1,14 @@ package quickfix import ( + "context" "fmt" "time" - "github.com/globalsign/mgo" - "github.com/globalsign/mgo/bson" "github.com/pkg/errors" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" "github.com/quickfixgo/quickfix/config" ) @@ -22,7 +24,7 @@ type mongoStore struct { cache *memoryStore mongoURL string mongoDatabase string - db *mgo.Session + db *mongo.Client messagesCollection string sessionsCollection string } @@ -73,7 +75,10 @@ func newMongoStore(sessionID SessionID, mongoURL string, mongoDatabase string, m return } - if store.db, err = mgo.Dial(mongoURL); err != nil { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + store.db, err = mongo.Connect(ctx, options.Client().ApplyURI(mongoURL)) + if err != nil { return } err = store.populateCache() @@ -117,7 +122,7 @@ type mongoQuickFixEntryData struct { // Reset deletes the store records and sets the seqnums back to 1 func (store *mongoStore) Reset() error { msgFilter := generateMessageFilter(&store.sessionID) - _, err := store.db.DB(store.mongoDatabase).C(store.messagesCollection).RemoveAll(msgFilter) + _, err := store.db.Database(store.mongoDatabase).Collection(store.messagesCollection).DeleteMany(context.Background(), msgFilter) if err != nil { return err @@ -131,7 +136,7 @@ func (store *mongoStore) Reset() error { sessionUpdate.CreationTime = store.cache.CreationTime() sessionUpdate.IncomingSeqNum = store.cache.NextTargetMsgSeqNum() sessionUpdate.OutgoingSeqNum = store.cache.NextSenderMsgSeqNum() - err = store.db.DB(store.mongoDatabase).C(store.sessionsCollection).Update(msgFilter, sessionUpdate) + _, err = store.db.Database(store.mongoDatabase).Collection(store.sessionsCollection).UpdateOne(context.Background(), msgFilter, bson.M{"$set": sessionUpdate}) return err } @@ -146,26 +151,24 @@ func (store *mongoStore) Refresh() error { func (store *mongoStore) populateCache() error { msgFilter := generateMessageFilter(&store.sessionID) - query := store.db.DB(store.mongoDatabase).C(store.sessionsCollection).Find(msgFilter) - - cnt, err := query.Count() - if err != nil { - return errors.Wrap(err, "count") + res := store.db.Database(store.mongoDatabase).Collection(store.sessionsCollection).FindOne(context.Background(), msgFilter) + if res.Err() != nil && res.Err() != mongo.ErrNoDocuments { + return errors.Wrap(res.Err(), "query") } - if cnt > 0 { + if res.Err() != mongo.ErrNoDocuments { // session record found, load it sessionData := &mongoQuickFixEntryData{} - if err = query.One(&sessionData); err != nil { - return errors.Wrap(err, "query one") + if err := res.Decode(&sessionData); err != nil { + return errors.Wrap(err, "decode") } store.cache.creationTime = sessionData.CreationTime - if err = store.cache.SetNextTargetMsgSeqNum(sessionData.IncomingSeqNum); err != nil { + if err := store.cache.SetNextTargetMsgSeqNum(sessionData.IncomingSeqNum); err != nil { return errors.Wrap(err, "cache set next target") } - if err = store.cache.SetNextSenderMsgSeqNum(sessionData.OutgoingSeqNum); err != nil { + if err := store.cache.SetNextSenderMsgSeqNum(sessionData.OutgoingSeqNum); err != nil { return errors.Wrap(err, "cache set next sender") } @@ -177,7 +180,7 @@ func (store *mongoStore) populateCache() error { msgFilter.IncomingSeqNum = store.cache.NextTargetMsgSeqNum() msgFilter.OutgoingSeqNum = store.cache.NextSenderMsgSeqNum() - if err = store.db.DB(store.mongoDatabase).C(store.sessionsCollection).Insert(msgFilter); err != nil { + if _, err := store.db.Database(store.mongoDatabase).Collection(store.sessionsCollection).InsertOne(context.Background(), msgFilter); err != nil { return errors.Wrap(err, "insert") } return nil @@ -200,7 +203,7 @@ func (store *mongoStore) SetNextSenderMsgSeqNum(next int) error { sessionUpdate.IncomingSeqNum = store.cache.NextTargetMsgSeqNum() sessionUpdate.OutgoingSeqNum = next sessionUpdate.CreationTime = store.cache.CreationTime() - if err := store.db.DB(store.mongoDatabase).C(store.sessionsCollection).Update(msgFilter, sessionUpdate); err != nil { + if _, err := store.db.Database(store.mongoDatabase).Collection(store.sessionsCollection).UpdateOne(context.Background(), msgFilter, bson.M{"$set": sessionUpdate}); err != nil { return err } return store.cache.SetNextSenderMsgSeqNum(next) @@ -213,7 +216,7 @@ func (store *mongoStore) SetNextTargetMsgSeqNum(next int) error { sessionUpdate.IncomingSeqNum = next sessionUpdate.OutgoingSeqNum = store.cache.NextSenderMsgSeqNum() sessionUpdate.CreationTime = store.cache.CreationTime() - if err := store.db.DB(store.mongoDatabase).C(store.sessionsCollection).Update(msgFilter, sessionUpdate); err != nil { + if _, err := store.db.Database(store.mongoDatabase).Collection(store.sessionsCollection).UpdateOne(context.Background(), msgFilter, bson.M{"$set": sessionUpdate}); err != nil { return err } return store.cache.SetNextTargetMsgSeqNum(next) @@ -244,7 +247,7 @@ func (store *mongoStore) SaveMessage(seqNum int, msg []byte) (err error) { msgFilter := generateMessageFilter(&store.sessionID) msgFilter.Msgseq = seqNum msgFilter.Message = msg - err = store.db.DB(store.mongoDatabase).C(store.messagesCollection).Insert(msgFilter) + _, err = store.db.Database(store.mongoDatabase).Collection(store.messagesCollection).InsertOne(context.Background(), msgFilter) return } @@ -265,19 +268,30 @@ func (store *mongoStore) GetMessages(beginSeqNum, endSeqNum int) (msgs [][]byte, "$gte": beginSeqNum, "$lte": endSeqNum, } + sortOpt := options.Find().SetSort(bson.D{{Key: "msgseq", Value: 1}}) + cursor, err := store.db.Database(store.mongoDatabase).Collection(store.messagesCollection).Find(context.Background(), seqFilter, sortOpt) + if err != nil { + return + } - iter := store.db.DB(store.mongoDatabase).C(store.messagesCollection).Find(seqFilter).Sort("msgseq").Iter() - for iter.Next(msgFilter) { + for cursor.Next(context.Background()) { + if err = cursor.Decode(&msgFilter); err != nil { + return + } msgs = append(msgs, msgFilter.Message) } - err = iter.Close() + + err = cursor.Close(context.Background()) return } // Close closes the store's database connection func (store *mongoStore) Close() error { if store.db != nil { - store.db.Close() + err := store.db.Disconnect(context.Background()) + if err != nil { + return errors.Wrap(err, "error disconnecting from database") + } store.db = nil } return nil diff --git a/mongostore_test.go b/mongostore_test.go index 29d43d71d..1784ec3e9 100644 --- a/mongostore_test.go +++ b/mongostore_test.go @@ -45,7 +45,10 @@ TargetCompID=%s`, mongoDbCxn, mongoDatabase, sessionID.BeginString, sessionID.Se } func (suite *MongoStoreTestSuite) TearDownTest() { - suite.msgStore.Close() + if suite.msgStore != nil { + err := suite.msgStore.Close() + require.Nil(suite.T(), err) + } } func TestMongoStoreTestSuite(t *testing.T) { From 2069c953b13db3272ebd1a6cfc1b36ae7b1a57bc Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Thu, 8 Dec 2022 18:40:23 +0000 Subject: [PATCH 10/47] Adds atomicity to save and increment in mongostore --- .devcontainer/docker-compose.yml | 10 +++--- .github/workflows/ci.yaml | 2 ++ config/configuration.go | 1 + config/doc.go | 4 +++ mongostore.go | 57 ++++++++++++++++++++++++++++---- mongostore_test.go | 4 ++- sqlstore.go | 7 +--- store_test.go | 41 +++++++++++++++++++++++ 8 files changed, 107 insertions(+), 19 deletions(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index ce8de67d7..d8482fa76 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -21,17 +21,15 @@ services: # (Adding the "ports" property to this file will not forward from a Codespace.) db: - image: mongo:latest + image: bitnami/mongodb:latest restart: unless-stopped volumes: - mongodb-data:/data/db ports: - 27017:27017 - # Uncomment to change startup options - # environment: - # MONGO_INITDB_ROOT_USERNAME: root - # MONGO_INITDB_ROOT_PASSWORD: example - # MONGO_INITDB_DATABASE: your-database-here + environment: + MONGODB_REPLICA_SET_MODE: primary + ALLOW_EMPTY_PASSWORD: 'yes' # Add "forwardPorts": ["27017"] to **devcontainer.json** to forward MongoDB locally. # (Adding the "ports" property to this file will not forward from a Codespace.) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7a225fc85..947b3325e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -65,6 +65,8 @@ jobs: uses: actions/checkout@v2 - name: Start MongoDB uses: supercharge/mongodb-github-action@1.8.0 + with: + mongodb-replica-set: replicaset - name: Install ruby uses: ruby/setup-ruby@v1 with: diff --git a/config/configuration.go b/config/configuration.go index ed7f1303e..d7280e4a3 100644 --- a/config/configuration.go +++ b/config/configuration.go @@ -55,6 +55,7 @@ const ( SQLStoreConnMaxLifetime string = "SQLStoreConnMaxLifetime" MongoStoreConnection string = "MongoStoreConnection" MongoStoreDatabase string = "MongoStoreDatabase" + MongoStoreReplicaSet string = "MongoStoreReplicaSet" ValidateFieldsOutOfOrder string = "ValidateFieldsOutOfOrder" ResendRequestChunkSize string = "ResendRequestChunkSize" EnableLastMsgSeqNumProcessed string = "EnableLastMsgSeqNumProcessed" diff --git a/config/doc.go b/config/doc.go index 617b066ff..197844225 100644 --- a/config/doc.go +++ b/config/doc.go @@ -363,6 +363,10 @@ MongoStoreDatabase The MongoDB-specific name of the database to use. Only used with MongoStoreFactory. +MongoStoreReplicaSet + +The MongoDB-specific name of the replica set to use. Optional, only used with MongoStoreFactory. + SQLStoreDriver The name of the database driver to use (see https://github.com/golang/go/wiki/SQLDrivers for the list of available drivers). Only used with SqlStoreFactory. diff --git a/mongostore.go b/mongostore.go index e6685f231..a3dd8ada1 100644 --- a/mongostore.go +++ b/mongostore.go @@ -27,6 +27,7 @@ type mongoStore struct { db *mongo.Client messagesCollection string sessionsCollection string + allowTransactions bool } // NewMongoStoreFactory returns a mongo-based implementation of MessageStoreFactory @@ -57,10 +58,16 @@ func (f mongoStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, e if err != nil { return nil, err } - return newMongoStore(sessionID, mongoConnectionURL, mongoDatabase, f.messagesCollection, f.sessionsCollection) + + // Optional. + mongoReplicaSet, _ := sessionSettings.Setting(config.MongoStoreReplicaSet) + + return newMongoStore(sessionID, mongoConnectionURL, mongoDatabase, mongoReplicaSet, f.messagesCollection, f.sessionsCollection) } -func newMongoStore(sessionID SessionID, mongoURL string, mongoDatabase string, messagesCollection string, sessionsCollection string) (store *mongoStore, err error) { +func newMongoStore(sessionID SessionID, mongoURL, mongoDatabase, mongoReplicaSet, messagesCollection, sessionsCollection string) (store *mongoStore, err error) { + + allowTransactions := len(mongoReplicaSet) > 0 store = &mongoStore{ sessionID: sessionID, cache: &memoryStore{}, @@ -68,6 +75,7 @@ func newMongoStore(sessionID SessionID, mongoURL string, mongoDatabase string, m mongoDatabase: mongoDatabase, messagesCollection: messagesCollection, sessionsCollection: sessionsCollection, + allowTransactions: allowTransactions, } if err = store.cache.Reset(); err != nil { @@ -77,7 +85,7 @@ func newMongoStore(sessionID SessionID, mongoURL string, mongoDatabase string, m ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - store.db, err = mongo.Connect(ctx, options.Client().ApplyURI(mongoURL)) + store.db, err = mongo.Connect(ctx, options.Client().ApplyURI(mongoURL).SetDirect(len(mongoReplicaSet) == 0).SetReplicaSet(mongoReplicaSet)) if err != nil { return } @@ -252,12 +260,49 @@ func (store *mongoStore) SaveMessage(seqNum int, msg []byte) (err error) { } func (store *mongoStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error { - // TODO add transaction - err := store.SaveMessage(seqNum, msg) + + if !store.allowTransactions { + err := store.SaveMessage(seqNum, msg) + if err != nil { + return err + } + return store.IncrNextSenderMsgSeqNum() + } + + // If the mongodb supports replicasets, perform this operation as a transaction instead- + var next int + err := store.db.UseSession(context.Background(), func(sessionCtx mongo.SessionContext) error { + if err := sessionCtx.StartTransaction(); err != nil { + return err + } + + msgFilter := generateMessageFilter(&store.sessionID) + msgFilter.Msgseq = seqNum + msgFilter.Message = msg + _, err := store.db.Database(store.mongoDatabase).Collection(store.messagesCollection).InsertOne(sessionCtx, msgFilter) + if err != nil { + return err + } + + next = store.cache.NextSenderMsgSeqNum() + 1 + + msgFilter = generateMessageFilter(&store.sessionID) + sessionUpdate := generateMessageFilter(&store.sessionID) + sessionUpdate.IncomingSeqNum = store.cache.NextTargetMsgSeqNum() + sessionUpdate.OutgoingSeqNum = next + sessionUpdate.CreationTime = store.cache.CreationTime() + _, err = store.db.Database(store.mongoDatabase).Collection(store.sessionsCollection).UpdateOne(sessionCtx, msgFilter, bson.M{"$set": sessionUpdate}) + if err != nil { + return err + } + + return sessionCtx.CommitTransaction(context.Background()) + }) if err != nil { return err } - return store.IncrNextSenderMsgSeqNum() + + return store.cache.SetNextSenderMsgSeqNum(next) } func (store *mongoStore) GetMessages(beginSeqNum, endSeqNum int) (msgs [][]byte, err error) { diff --git a/mongostore_test.go b/mongostore_test.go index 1784ec3e9..32682b65d 100644 --- a/mongostore_test.go +++ b/mongostore_test.go @@ -23,6 +23,7 @@ func (suite *MongoStoreTestSuite) SetupTest() { suite.T().SkipNow() } mongoDatabase := "automated_testing_database" + mongoReplicaSet := "replicaset" // create settings sessionID := SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} @@ -30,11 +31,12 @@ func (suite *MongoStoreTestSuite) SetupTest() { [DEFAULT] MongoStoreConnection=%s MongoStoreDatabase=%s +MongoStoreReplicaSet=%s [SESSION] BeginString=%s SenderCompID=%s -TargetCompID=%s`, mongoDbCxn, mongoDatabase, sessionID.BeginString, sessionID.SenderCompID, sessionID.TargetCompID))) +TargetCompID=%s`, mongoDbCxn, mongoDatabase, mongoReplicaSet, sessionID.BeginString, sessionID.SenderCompID, sessionID.TargetCompID))) require.Nil(suite.T(), err) // create store diff --git a/sqlstore.go b/sqlstore.go index a176b7509..d0b1c5162 100644 --- a/sqlstore.go +++ b/sqlstore.go @@ -314,12 +314,7 @@ func (store *sqlStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []b return err } - err = store.cache.SetNextSenderMsgSeqNum(next) - if err != nil { - return err - } - - return nil + return store.cache.SetNextSenderMsgSeqNum(next) } func (store *sqlStore) GetMessages(beginSeqNum, endSeqNum int) ([][]byte, error) { diff --git a/store_test.go b/store_test.go index 7b8f6a2b8..b8e6747fb 100644 --- a/store_test.go +++ b/store_test.go @@ -113,6 +113,47 @@ func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) } + +func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_AndIncrement_GetMessage() { + s.Require().Nil(s.msgStore.SetNextSenderMsgSeqNum(420)) + + // Given the following saved messages + expectedMsgsBySeqNum := map[int]string{ + 1: "In the frozen land of Nador", + 2: "they were forced to eat Robin's minstrels", + 3: "and there was much rejoicing", + } + for seqNum, msg := range expectedMsgsBySeqNum { + s.Require().Nil(s.msgStore.SaveMessageAndIncrNextSenderMsgSeqNum(seqNum, []byte(msg))) + } + s.Equal(423, s.msgStore.NextSenderMsgSeqNum()) + + // When the messages are retrieved from the MessageStore + actualMsgs, err := s.msgStore.GetMessages(1, 3) + s.Require().Nil(err) + + // Then the messages should be + s.Require().Len(actualMsgs, 3) + s.Equal(expectedMsgsBySeqNum[1], string(actualMsgs[0])) + s.Equal(expectedMsgsBySeqNum[2], string(actualMsgs[1])) + s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) + + // When the store is refreshed from its backing store + s.Require().Nil(s.msgStore.Refresh()) + + // And the messages are retrieved from the MessageStore + actualMsgs, err = s.msgStore.GetMessages(1, 3) + s.Require().Nil(err) + + s.Equal(423, s.msgStore.NextSenderMsgSeqNum()) + + // Then the messages should still be + s.Require().Len(actualMsgs, 3) + s.Equal(expectedMsgsBySeqNum[1], string(actualMsgs[0])) + s.Equal(expectedMsgsBySeqNum[2], string(actualMsgs[1])) + s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) +} + func (s *MessageStoreTestSuite) TestMessageStore_GetMessages_EmptyStore() { // When messages are retrieved from an empty store messages, err := s.msgStore.GetMessages(1, 2) From a89c1d44ecbcfd90fefcebc4870490204e08e978 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Dec 2022 00:04:54 +0000 Subject: [PATCH 11/47] Bump go.mongodb.org/mongo-driver from 1.11.0 to 1.11.1 Bumps [go.mongodb.org/mongo-driver](https://github.com/mongodb/mongo-go-driver) from 1.11.0 to 1.11.1. - [Release notes](https://github.com/mongodb/mongo-go-driver/releases) - [Commits](https://github.com/mongodb/mongo-go-driver/compare/v1.11.0...v1.11.1) --- updated-dependencies: - dependency-name: go.mongodb.org/mongo-driver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 27e396a64..7b6f670b1 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.8.1 - go.mongodb.org/mongo-driver v1.11.0 + go.mongodb.org/mongo-driver v1.11.1 golang.org/x/net v0.2.0 ) diff --git a/go.sum b/go.sum index dff68834f..5b8965034 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= -go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= +go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8= +go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= From bc299dffd9c18449aec32da131293d222a4d458e Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 21 Dec 2022 19:26:29 +0300 Subject: [PATCH 12/47] add sync.Once to session.stop func --- session.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/session.go b/session.go index 331af0f0f..b96d54aa8 100644 --- a/session.go +++ b/session.go @@ -35,6 +35,7 @@ type session struct { stateTimer *internal.EventTimer peerTimer *internal.EventTimer sentReset bool + stopOnce sync.Once targetDefaultApplVerID string @@ -76,7 +77,10 @@ func (s *session) connect(msgIn <-chan fixIn, msgOut chan<- []byte) error { type stopReq struct{} func (s *session) stop() { - s.admin <- stopReq{} + //stop once + s.stopOnce.Do(func() { + s.admin <- stopReq{} + }) } type waitChan <-chan interface{} From 2dad0f040586fa32a081e47cc01aba55a9772251 Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Fri, 23 Dec 2022 11:56:48 +0400 Subject: [PATCH 13/47] Align session's ticker with round second Co-authored-by: Alexis Masson Signed-off-by: Sylvain Rabot --- session.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/session.go b/session.go index 331af0f0f..e2ee4344f 100644 --- a/session.go +++ b/session.go @@ -754,6 +754,14 @@ func (s *session) run() { } }) + + // Without this sleep the ticker will be aligned at the millisecond which + // corresponds to the creation of the session. If the session creation + // happened at 07:00:00.678 and the session StartTime is 07:30:00, any new + // connection received between 07:30:00.000 and 07:30:00.677 will be + // rejected. Aligning the ticker with a round second fixes that. + time.Sleep(time.Until(time.Now().Truncate(time.Second).Add(time.Second))) + ticker := time.NewTicker(time.Second) defer func() { From fb2a734823ef642e9d34653d41fa64544526e8c8 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Fri, 23 Dec 2022 20:47:29 -0600 Subject: [PATCH 14/47] Fix formatting and filestore order of operations --- .github/workflows/ci.yaml | 4 +- .golangci.yml | 2 - Makefile | 73 ++++++++----------- README.md | 59 ++++++++------- cmd/generate-fix/generate-fix.go | 1 - cmd/generate-fix/internal/template_helpers.go | 2 +- filestore.go | 4 +- mongostore.go | 6 +- store_test.go | 1 - 9 files changed, 68 insertions(+), 84 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 947b3325e..afe397103 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -37,8 +37,8 @@ jobs: env: GOLANGCI_LINT_VERSION: '1.46.2' GOLANGCI_LINT_SHA256: '242cd4f2d6ac0556e315192e8555784d13da5d1874e51304711570769c4f2b9b' - - name: Test style - run: make test-style + - name: Run Lint + run: make lint build: name: build diff --git a/.golangci.yml b/.golangci.yml index 15aa0a7b1..7d3a47ddb 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -7,7 +7,6 @@ run: linters: disable-all: true enable: - - deadcode - dupl - gofmt - goimports @@ -17,7 +16,6 @@ linters: - misspell - revive - unused - - varcheck - staticcheck linters-settings: diff --git a/Makefile b/Makefile index 9dffe9d3d..5caa90a69 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,3 @@ -GOBIN = $(shell go env GOBIN) -ifeq ($(GOBIN),) -GOBIN = $(shell go env GOPATH)/bin -endif -GOX = $(GOBIN)/gox -GOIMPORTS = $(GOBIN)/goimports -ARCH = $(shell uname -p) - -# ------------------------------------------------------------------------------ -# dependencies - -# If go install is run from inside the project directory it will add the -# dependencies to the go.mod file. To avoid that we change to a directory -# without a go.mod file when downloading the following dependencies - -$(GOX): - (cd /; GO111MODULE=on go install github.com/mitchellh/gox@latest) - -$(GOIMPORTS): - (cd /; GO111MODULE=on go install golang.org/x/tools/cmd/goimports@latest) - -# ------------------------------------------------------------------------------ all: vet test @@ -29,18 +7,8 @@ clean: generate: clean mkdir -p gen; cd gen; go run ../cmd/generate-fix/generate-fix.go -pkg-root=github.com/quickfixgo/quickfix/gen ../spec/*.xml -generate-dist: - cd ..; go run quickfix/cmd/generate-fix/generate-fix.go quickfix/spec/*.xml - -test-style: - GO111MODULE=on golangci-lint run - -.PHONY: format -format: $(GOIMPORTS) - GO111MODULE=on go list -f '{{.Dir}}' ./... | xargs $(GOIMPORTS) -w -local github.com/quickfixgo/quickfix - fmt: - go fmt `go list ./... | grep -v quickfix/gen` + gofmt -l -w -s $(shell find . -type f -name '*.go') vet: go vet `go list ./... | grep -v quickfix/gen` @@ -48,20 +16,20 @@ vet: test: MONGODB_TEST_CXN=mongodb://db:27017 go test -v -cover . ./datadictionary ./internal -build-src: - go build -v `go list ./...` - -build-test-srv: - cd _test; go build -o echo_server ./test-server/ +linters-install: + @golangci-lint --version >/dev/null 2>&1 || { \ + echo "installing linting tools..."; \ + curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.46.2; \ + } -build: build-src build-test-srv - -test-ci: - go test -v -cover . ./datadictionary ./internal +lint: linters-install + golangci-lint run -generate-ci: clean - mkdir -p gen; cd gen; go run ../cmd/generate-fix/generate-fix.go -pkg-root=github.com/quickfixgo/quickfix/gen ../spec/$(shell echo $(FIX_TEST) | tr '[:lower:]' '[:upper:]').xml; +# --------------------------------------------------------------- +# Targets related to running acceptance tests - +build-test-srv: + cd _test; go build -o echo_server ./test-server/ fix40: cd _test; ./runat.sh $@.cfg 5001 "definitions/server/$@/*.def" fix41: @@ -83,3 +51,20 @@ ACCEPT_SUITE=fix40 fix41 fix42 fix43 fix44 fix50 fix50sp1 fix50sp2 accept: $(ACCEPT_SUITE) .PHONY: test $(ACCEPT_SUITE) +# --------------------------------------------------------------- + +# --------------------------------------------------------------- +# These targets are specific to the Github CI Runner - + +build-src: + go build -v `go list ./...` + +build: build-src build-test-srv + +test-ci: + go test -v -cover . ./datadictionary ./internal + +generate-ci: clean + mkdir -p gen; cd gen; go run ../cmd/generate-fix/generate-fix.go -pkg-root=github.com/quickfixgo/quickfix/gen ../spec/$(shell echo $(FIX_TEST) | tr '[:lower:]' '[:upper:]').xml; + +# --------------------------------------------------------------- diff --git a/README.md b/README.md index 6626300fa..1a6d4cde0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -QuickFIX/Go -=========== +# QuickFIX/Go [![Build Status](https://github.com/quickfixgo/quickfix/workflows/CI/badge.svg)](https://github.com/quickfixgo/quickfix/actions) [![GoDoc](https://godoc.org/github.com/quickfixgo/quickfix?status.png)](https://godoc.org/github.com/quickfixgo/quickfix) [![Go Report Card](https://goreportcard.com/badge/github.com/quickfixgo/quickfix)](https://goreportcard.com/report/github.com/quickfixgo/quickfix) @@ -8,29 +7,28 @@ QuickFIX/Go Open Source [FIX Protocol](http://www.fixprotocol.org/) library implemented in Go -Getting Started and Documentation ---------------------------------- +## Getting Started and Documentation * [User Manual](http://quickfixgo.org/docs) * [API Documentation](https://godoc.org/github.com/quickfixgo/quickfix) -### Installation +## Installation To install QuickFIX/Go, use `go get`: ```sh -$ go get github.com/quickfixgo/quickfix +go get github.com/quickfixgo/quickfix ``` -### Staying up to date +## Staying up to date To update QuickFIX/Go to the latest version, use `go get -u github.com/quickfixgo/quickfix`. -### Example Apps +## Example Apps See [examples](https://github.com/quickfixgo/examples) for some simple examples of using QuickFIX/Go. -### FIX Message Generation +## FIX Message Generation QuickFIX/Go includes separate packages for tags, fields, enums, messages, and message components generated from the FIX 4.0 - FIX5.0SP2 specs. See: @@ -51,14 +49,17 @@ For most FIX applications, these generated resources are sufficient. Custom FIX Following installation, `generate-fix` is installed to `$GOPATH/bin/generate-fix`. Run `$GOPATH/bin/generate-fix --help` for usage instructions. -Developing QuickFIX/Go ----------------------- +## Developing QuickFIX/Go -If you wish to work on QuickFIX/Go itself, you will first need [Go](http://www.golang.org) installed and configured on your machine (version 1.13+ is preferred, but the minimum required version is 1.6). +If you wish to work on QuickFIX/Go itself, you will need [Docker](https://docs.docker.com/get-docker/) and [VSCode](https://code.visualstudio.com/download) on your machine. -Next, using [Git](https://git-scm.com/), clone the repository via `git clone git@github.com:quickfixgo/quickfix.git` +* Clone the repo and open it with VSCode with Docker running +* This repo comes with vscode devcontainer configs in `./.devcontainer/` +* Click the pop-up to re-open the project in the Dev Container +* This opens the project in a docker container pre-configured with everything you need -### Installing Dependencies + +## Installing Dependencies As of Go version 1.13, QuickFIX/Go uses [modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. You may require `GO111MODULE=on`. To install dependencies, run @@ -68,48 +69,50 @@ go mod download **Note:** No vendored dependencies are included in the QuickFIX/Go source. -### Build and Test +## Build and Test The default make target runs [go vet](https://godoc.org/golang.org/x/tools/cmd/vet) and unit tests. ```sh -$ make +make ``` If this exits with exit status 0, then everything is working! -### Generated Code +## Generated Code Generated code from the FIX40-FIX50SP2 specs are available as separate repos under the [QuickFIX/Go organization](https://github.com/quickfixgo). The source specifications for this generated code is located in `spec/`. Generated code can be identified by the `.generated.go` suffix. Any changes to generated code must be captured by changes to source in `cmd/generate-fix`. After making changes to the code generator source, run the following to re-generate the source ```sh -$ make generate-dist +make generate ``` If you are making changes to the generated code, please create Pull Requests for these changes for the affected repos. -### Acceptance Tests +## Acceptance Tests QuickFIX/Go has a comprehensive acceptance test suite covering the FIX protocol. These are the same tests used across all QuickFIX implementations. -QuickFIX/Go acceptance tests depend on ruby in path. +QuickFIX/Go acceptance tests depend on ruby in path, if you are using the dev container, it is already installed To run acceptance tests, - # generate code locally - make generate +```sh +# generate code locally +make generate - # build acceptance test rig - make build-test-srv +# build acceptance test rig +make build-test-srv - # run acceptance tests - make accept +# run acceptance tests +make accept +``` -### Dependencies +## Dependencies If you are developing QuickFIX/Go, there are a few tasks you might need to perform related to dependencies. -#### Adding/updating a dependency +### Adding/updating a dependency If you are adding or updating a dependency, you will need to update the `go.mod` and `go.sum` in the same Pull Request as the code that depends on it. You should do this in a separate commit from your code, as this makes PR review easier and Git history simpler to read in the future. diff --git a/cmd/generate-fix/generate-fix.go b/cmd/generate-fix/generate-fix.go index 27c5aa624..ae1749722 100644 --- a/cmd/generate-fix/generate-fix.go +++ b/cmd/generate-fix/generate-fix.go @@ -122,7 +122,6 @@ func main() { usage() } - args := flag.Args() if len(args) == 1 { dictpath := args[0] diff --git a/cmd/generate-fix/internal/template_helpers.go b/cmd/generate-fix/internal/template_helpers.go index 31fbac55d..e4dcce727 100644 --- a/cmd/generate-fix/internal/template_helpers.go +++ b/cmd/generate-fix/internal/template_helpers.go @@ -34,7 +34,7 @@ func checkIfTimeImportRequiredForFields(fTypes []*datadictionary.FieldType) (ok if vt, err = quickfixValueType(t); err != nil { return } - + if vt == "time.Time" { return true, nil } diff --git a/filestore.go b/filestore.go index 46a83e6b4..3b93db6e2 100644 --- a/filestore.go +++ b/filestore.go @@ -287,8 +287,6 @@ func (store *fileStore) SaveMessage(seqNum int, msg []byte) error { return fmt.Errorf("unable to write to file: %s: %s", store.headerFname, err.Error()) } - store.offsets[seqNum] = msgDef{offset: offset, size: len(msg)} - if _, err := store.bodyFile.Write(msg); err != nil { return fmt.Errorf("unable to write to file: %s: %s", store.bodyFname, err.Error()) } @@ -298,6 +296,8 @@ func (store *fileStore) SaveMessage(seqNum int, msg []byte) error { if err := store.headerFile.Sync(); err != nil { return fmt.Errorf("unable to flush file: %s: %s", store.headerFname, err.Error()) } + + store.offsets[seqNum] = msgDef{offset: offset, size: len(msg)} return nil } diff --git a/mongostore.go b/mongostore.go index a3dd8ada1..1bd32db7f 100644 --- a/mongostore.go +++ b/mongostore.go @@ -27,7 +27,7 @@ type mongoStore struct { db *mongo.Client messagesCollection string sessionsCollection string - allowTransactions bool + allowTransactions bool } // NewMongoStoreFactory returns a mongo-based implementation of MessageStoreFactory @@ -283,9 +283,9 @@ func (store *mongoStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg [ if err != nil { return err } - + next = store.cache.NextSenderMsgSeqNum() + 1 - + msgFilter = generateMessageFilter(&store.sessionID) sessionUpdate := generateMessageFilter(&store.sessionID) sessionUpdate.IncomingSeqNum = store.cache.NextTargetMsgSeqNum() diff --git a/store_test.go b/store_test.go index b8e6747fb..7f0f8eafc 100644 --- a/store_test.go +++ b/store_test.go @@ -113,7 +113,6 @@ func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) } - func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_AndIncrement_GetMessage() { s.Require().Nil(s.msgStore.SetNextSenderMsgSeqNum(420)) From c9661550ace668e4bdcce53488070614490235a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 24 Dec 2022 03:05:24 +0000 Subject: [PATCH 15/47] Bump golang.org/x/net from 0.2.0 to 0.4.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.2.0 to 0.4.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/compare/v0.2.0...v0.4.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7b6f670b1..952abfa45 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.8.1 go.mongodb.org/mongo-driver v1.11.1 - golang.org/x/net v0.2.0 + golang.org/x/net v0.4.0 ) require ( diff --git a/go.sum b/go.sum index 5b8965034..a1a76b93c 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From ec3714548814a70e5e0312c9ac3a5d5567273885 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Fri, 23 Dec 2022 21:20:40 -0600 Subject: [PATCH 16/47] Satisfy linter reqs --- acceptor.go | 11 +- application.go | 4 +- begin_string.go | 2 +- config/configuration.go | 2 +- config/doc.go | 309 ++++++++++++++++--------------- datadictionary/datadictionary.go | 76 ++++---- datadictionary/xml.go | 8 +- errors.go | 60 +++--- field.go | 16 +- field_map.go | 42 ++--- file_log.go | 4 +- fix_boolean.go | 4 +- fix_bytes.go | 2 +- fix_decimal.go | 2 +- fix_float.go | 4 +- fix_int.go | 8 +- fix_string.go | 2 +- fix_utc_timestamp.go | 6 +- initiator.go | 12 +- internal/event.go | 2 +- internal/session_settings.go | 2 +- internal/time_range.go | 20 +- log.go | 4 +- message.go | 30 +-- message_router.go | 12 +- msg_type.go | 2 +- null_log.go | 2 +- quickfix_test.go | 2 +- registry.go | 8 +- repeating_group.go | 28 +-- screen_log.go | 2 +- session_factory.go | 2 +- session_id.go | 2 +- session_rejects.go | 6 +- session_settings.go | 24 +-- session_state.go | 4 +- settings.go | 16 +- store.go | 6 +- tag.go | 6 +- tag_value.go | 2 +- tls.go | 2 +- validation.go | 16 +- validation_test.go | 12 +- 43 files changed, 401 insertions(+), 385 deletions(-) diff --git a/acceptor.go b/acceptor.go index 6482331d7..3d72ba20e 100644 --- a/acceptor.go +++ b/acceptor.go @@ -15,7 +15,7 @@ import ( "github.com/quickfixgo/quickfix/config" ) -//Acceptor accepts connections from FIX clients and manages the associated sessions. +// Acceptor accepts connections from FIX clients and manages the associated sessions. type Acceptor struct { app Application settings *Settings @@ -43,7 +43,7 @@ type ConnectionValidator interface { Validate(netConn net.Conn, session SessionID) error } -//Start accepting connections. +// Start accepting connections. func (a *Acceptor) Start() (err error) { socketAcceptHost := "" if a.settings.GlobalSettings().HasSetting(config.SocketAcceptHost) { @@ -112,7 +112,7 @@ func (a *Acceptor) Start() (err error) { return } -//Stop logs out existing sessions, close their connections, and stop accepting new connections. +// Stop logs out existing sessions, close their connections, and stop accepting new connections. func (a *Acceptor) Stop() { defer func() { _ = recover() // suppress sending on closed channel error @@ -141,7 +141,7 @@ func (a *Acceptor) RemoteAddr(sessionID SessionID) (net.Addr, bool) { return val, ok } -//NewAcceptor creates and initializes a new Acceptor. +// NewAcceptor creates and initializes a new Acceptor. func NewAcceptor(app Application, storeFactory MessageStoreFactory, settings *Settings, logFactory LogFactory) (a *Acceptor, err error) { a = &Acceptor{ app: app, @@ -394,7 +394,8 @@ LOOP: // Use it when you need a custom authentication logic that includes lower level interactions, // like mTLS auth or IP whitelistening. // To remove a previously set validator call it with a nil value: -// a.SetConnectionValidator(nil) +// +// a.SetConnectionValidator(nil) func (a *Acceptor) SetConnectionValidator(validator ConnectionValidator) { a.connectionValidator = validator } diff --git a/application.go b/application.go index e91ab1021..e7d76c60e 100644 --- a/application.go +++ b/application.go @@ -1,7 +1,7 @@ package quickfix -//Application interface should be implemented by FIX Applications. -//This is the primary interface for processing messages from a FIX Session. +// Application interface should be implemented by FIX Applications. +// This is the primary interface for processing messages from a FIX Session. type Application interface { //OnCreate notification of a session begin created. OnCreate(sessionID SessionID) diff --git a/begin_string.go b/begin_string.go index 74c2a3df5..b5d9f6f14 100644 --- a/begin_string.go +++ b/begin_string.go @@ -1,6 +1,6 @@ package quickfix -//FIX BeginString string values +// FIX BeginString string values const ( BeginStringFIX40 = "FIX.4.0" BeginStringFIX41 = "FIX.4.1" diff --git a/config/configuration.go b/config/configuration.go index d7280e4a3..2af864fd9 100644 --- a/config/configuration.go +++ b/config/configuration.go @@ -2,7 +2,7 @@ package config //NOTE: Additions to this file should be made to both config/doc.go and http://www.quickfixgo.org/docs/ -//Const configuration settings +// Const configuration settings const ( BeginString string = "BeginString" SenderCompID string = "SenderCompID" diff --git a/config/doc.go b/config/doc.go index 197844225..7da502416 100644 --- a/config/doc.go +++ b/config/doc.go @@ -1,264 +1,274 @@ /* Package config declares application and session settings for QuickFIX/Go -BeginString +# BeginString Version of FIX this session should use. Valid values: - FIXT.1.1 - FIX.4.4 - FIX.4.3 - FIX.4.2 - FIX.4.1 - FIX.4.0 + FIXT.1.1 + FIX.4.4 + FIX.4.3 + FIX.4.2 + FIX.4.1 + FIX.4.0 -SenderCompID +# SenderCompID Your ID as associated with this FIX session. Value is case-sensitive alpha-numeric string. -SenderSubID +# SenderSubID (Optional) Your subID as associated with this FIX session. Value is case-sensitive alpha-numeric string. -SenderLocationID +# SenderLocationID (Optional) Your locationID as associated with this FIX session. Value is case-sensitive alpha-numeric string. -TargetCompID +# TargetCompID Counter parties ID as associated with this FIX session. Value is case-sensitive alpha-numeric string. -TargetSubID +# TargetSubID (Optional) Counterparty's subID as associated with this FIX session. Value is case-sensitive alpha-numeric string. -TargetLocationID +# TargetLocationID (Optional) Counterparty's locationID as associated with this FIX session. Value is case-sensitive alpha-numeric string. -SessionQualifier +# SessionQualifier Additional qualifier to disambiguate otherwise identical sessions. Value is case-sensitive alpha-numeric string. -DefaultApplVerID +# DefaultApplVerID Required only for FIXT 1.1 (and newer). Ignored for earlier transport versions. Specifies the default application version ID for the session. This can either be the ApplVerID enum (see the ApplVerID field) or the BeginString for the default version. Valid Values: - FIX.5.0SP2 - FIX.5.0SP1 - FIX.5.0 - FIX.4.4 - FIX.4.3 - FIX.4.2 - FIX.4.1 - FIX.4.0 - 9 - 8 - 7 - 6 - 5 - 4 - 3 - 2 - -TimeZone + FIX.5.0SP2 + FIX.5.0SP1 + FIX.5.0 + FIX.4.4 + FIX.4.3 + FIX.4.2 + FIX.4.1 + FIX.4.0 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + +# TimeZone Time zone for this session; if specified, the session start and end will be converted from this zone to UTC. Valid Values: - IANA Time zone ID (America/New_York, Asia/Tokyo, Europe/London, etc.) - Local (The Zone on host) + IANA Time zone ID (America/New_York, Asia/Tokyo, Europe/London, etc.) + Local (The Zone on host) Defaults to UTC. -StartTime +# StartTime Time of day that this FIX session becomes activated. Valid Values: - time in the format of HH:MM:SS, time is represented in time zone configured by TimeZone + time in the format of HH:MM:SS, time is represented in time zone configured by TimeZone -EndTime +# EndTime Time of day that this FIX session becomes deactivated. Valid Values: - time in the format of HH:MM:SS, time is represented in time zone configured by TimeZone + time in the format of HH:MM:SS, time is represented in time zone configured by TimeZone -StartDay +# StartDay For week long sessions, the starting day of week for the session. Use in combination with StartTime. Valid Values: - Full day of week in English, or 3 letter abbreviation (i.e. Monday and Mon are valid) + Full day of week in English, or 3 letter abbreviation (i.e. Monday and Mon are valid) -EndDay +# EndDay For week long sessions, the ending day of week for the session. Use in combination with EndTime. Valid Values: - Full day of week in English, or 3 letter abbreviation (i.e. Monday and Mon are valid) + Full day of week in English, or 3 letter abbreviation (i.e. Monday and Mon are valid) -EnableLastMsgSeqNumProcessed +# EnableLastMsgSeqNumProcessed Add the last message sequence number processed in the header (optional tag 369). Valid Values: - Y - N + + Y + N Defaults to N. -ResendRequestChunkSize +# ResendRequestChunkSize Setting to limit the size of a resend request in case of missing messages. This is useful when the remote FIX engine does not allow to ask for more than n message for a ResendRequest. E.g. if the ResendRequestChunkSize is set to 5 and a gap of 7 messages is detected, a first resend request will be sent for 5 messages. When this gap has been filled, another resend request for 2 messages will be sent. If the ResendRequestChunkSize is set to 0, only one ResendRequest for all the missing messages will be sent. Value must be positive integer. Defaults to 0 (disables splitting). -ResetOnLogon +# ResetOnLogon Determines if sequence numbers should be reset when receiving a logon request. Acceptors only. Valid Values: - Y - N + + Y + N Defaults to N. -ResetOnLogout +# ResetOnLogout Determines if sequence numbers should be reset to 1 after a normal logout termination. Valid Values: - Y - N + + Y + N Defaults to N. -ResetOnDisconnect +# ResetOnDisconnect Determines if sequence numbers should be reset to 1 after an abnormal termination. Valid Values: - Y - N + + Y + N Defaults to N. -RefreshOnLogon +# RefreshOnLogon Determines if session state should be restored from persistence layer when logging on. Useful for creating hot failover sessions. Valid Values: - Y - N + + Y + N Defaults to N. -TimeStampPrecision +# TimeStampPrecision Determines precision for timestamps in (Orig)SendingTime fields that are sent out. Only available for FIX.4.2 and greater, FIX versions earlier than FIX.4.2 will use timestamp resolution in seconds. Valid Values: - SECONDS - MILLIS - MICROS - NANOS + + SECONDS + MILLIS + MICROS + NANOS Defaults to MILLIS. -Validation +# Validation The following settings are specific to message validation. -DataDictionary +# DataDictionary XML definition file for validating incoming FIX messages. If no DataDictionary is supplied, only basic message validation will be done. This setting should only be used with FIX transport versions older than FIXT.1.1. See TransportDataDictionary and AppDataDictionary for FIXT.1.1 settings. Value must be a valid XML data dictionary file. QuickFIX/Go comes with the following defaults in the spec directory - FIX44.xml - FIX43.xml - FIX42.xml - FIX41.xml - FIX40.xml + FIX44.xml + FIX43.xml + FIX42.xml + FIX41.xml + FIX40.xml -TransportDataDictionary +# TransportDataDictionary XML definition file for validating admin (transport) messages. This setting is only valid for FIXT.1.1 (or newer) sessions. See DataDictionary for older transport versions (FIX.4.0 - FIX.4.4) for additional information. Value must be a valid XML data dictionary file, QuickFIX/Go comes with the following defaults in the spec directory - FIXT1.1.xml + FIXT1.1.xml -AppDataDictionary +# AppDataDictionary XML definition file for validating application messages. This setting is only valid for FIXT.1.1 (or newer) sessions. See DataDictionary for older transport versions (FIX.4.0 - FIX.4.4) for additional information. This setting supports the possibility of a custom application data dictionary for each session. This setting would only be used with FIXT 1.1 and new transport protocols. This setting can be used as a prefix to specify multiple application dictionaries for the FIXT transport. For example: - DefaultApplVerID=FIX.4.2 - # For default application version ID - AppDataDictionary=FIX42.xml - # For nondefault application version ID - # Use BeginString suffix for app version - AppDataDictionary.FIX.4.4=FIX44.xml + DefaultApplVerID=FIX.4.2 + # For default application version ID + AppDataDictionary=FIX42.xml + # For nondefault application version ID + # Use BeginString suffix for app version + AppDataDictionary.FIX.4.4=FIX44.xml Value must be a valid XML data dictionary file. QuickFIX/Go comes with the following defaults in the spec directory - FIX50SP2.xml - FIX50SP1.xml - FIX50.xml - FIX44.xml - FIX43.xml - FIX42.xml - FIX41.xml - FIX40.xml + FIX50SP2.xml + FIX50SP1.xml + FIX50.xml + FIX44.xml + FIX43.xml + FIX42.xml + FIX41.xml + FIX40.xml -ValidateFieldsOutOfOrder +# ValidateFieldsOutOfOrder If set to N, fields that are out of order (i.e. body fields in the header, or header fields in the body) will not be rejected. Useful for connecting to systems which do not properly order fields. Valid Values: - Y - N + + Y + N Defaults to Y. -RejectInvalidMessage +# RejectInvalidMessage If RejectInvalidMessage is set to N, zero errors will be thrown on reception of message that fails data dictionary validation. Valid Values: - Y - N + + Y + N Defaults to Y. -CheckLatency +# CheckLatency If set to Y, messages must be received from the counterparty within a defined number of seconds. It is useful to turn this off if a system uses localtime for it's timestamps instead of GMT. Valid Values: - Y - N + + Y + N Defaults to Y. -MaxLatency +# MaxLatency If CheckLatency is set to Y, this defines the number of seconds latency allowed for a message to be processed. Value must be positive integer. Defaults to 120. -ReconnectInterval +# ReconnectInterval Time between reconnection attempts in seconds. Only used for initiators. Value must be positive integer. -Defaults to 30 +# Defaults to 30 -LogoutTimeout +# LogoutTimeout Session setting for logout timeout in seconds. Only used for initiators. Value must be positive integer. -Defaults to 2 +# Defaults to 2 -LogonTimeout +# LogonTimeout Session setting for logon timeout in seconds. Only used for initiators. Value must be positive integer. -Defaults to 10 +# Defaults to 10 -HeartBtInt +# HeartBtInt Heartbeat interval in seconds. Only used for initiators (unless HeartBtIntOverride is Y). Value must be positive integer. -HeartBtIntOverride +# HeartBtIntOverride If set to Y, will use the HeartBtInt interval rather than what the initiator dictates. Only used for acceptors. Valid Values: - Y - N + + Y + N Defaults to N. -SocketConnectPort +# SocketConnectPort Socket port for connecting to a session. Only used for initiators. Must be positive integer -SocketConnectHost +# SocketConnectHost Host to connect to. Only used for initiators. Value must be a valid IPv4 or IPv6 address or a domain name @@ -270,119 +280,124 @@ SocketConnectHost Alternate socket hosts for connecting to a session for failover, where n is a positive integer. (i.e.) SocketConnectHost1, SocketConnectHost2... must be consecutive and have a matching SocketConnectPort[n]. Value must be a valid IPv4 or IPv6 address or a domain name -SocketTimeout +# SocketTimeout Duration of timeout for TLS handshake. Only used for initiators. Example Values: - SocketTimeout=30s # 30 seconds - SocketTimeout=60m # 60 minutes + + SocketTimeout=30s # 30 seconds + SocketTimeout=60m # 60 minutes Defaults to 0(means nothing timeout). -SocketAcceptHost +# SocketAcceptHost Socket host address for listening on incoming connections, only used for acceptors. By default acceptors listen on all available interfaces. -SocketAcceptPort +# SocketAcceptPort Socket port for listening to incoming connections, only used for acceptors. Value must be a positive integer, valid open socket port. -SocketPrivateKeyFile +# SocketPrivateKeyFile Private key to use for secure TLS connections. Must be used with SocketCertificateFile. -SocketCertificateFile +# SocketCertificateFile Certificate to use for secure TLS connections. Must be used with SocketPrivateKeyFile. -SocketCAFile +# SocketCAFile Optional root CA to use for secure TLS connections. For acceptors, client certificates will be verified against this CA. For initiators, clients will use the CA to verify the server certificate. If not configurated, initiators will verify the server certificate using the host's root CA set. -SocketServerName +# SocketServerName The expected server name on a returned certificate, unless SocketInsecureSkipVerify is true. This is for the TLS Server Name Indication extension. Initiator only. -SocketMinimumTLSVersion +# SocketMinimumTLSVersion Specify the Minimum TLS version to use when creating a secure connection. The valid choices are SSL30, TLS10, TLS11, TLS12. Defaults to TLS12. -SocketUseSSL +# SocketUseSSL Use SSL for initiators even if client certificates are not present. If set to N or omitted, TLS will not be used if SocketPrivateKeyFile or SocketCertificateFile are not supplied. -ProxyType +# ProxyType Proxy type. Valid Values: - socks -ProxyHost + socks + +# ProxyHost -Proxy server IP address in the format of x.x.x.x or a domain name +# Proxy server IP address in the format of x.x.x.x or a domain name -ProxyPort +# ProxyPort -Proxy server port +# Proxy server port -ProxyUser +# ProxyUser -Proxy user +# Proxy user -ProxyPassword +# ProxyPassword -Proxy password +# Proxy password -UseTCPProxy +# UseTCPProxy Use TCP proxy for servers listening behind HAProxy of Amazon ELB load balancers. The server can then receive the address of the client instead of the load balancer's. Valid Values: - Y - N -PersistMessages + Y + N + +# PersistMessages If set to N, no messages will be persisted. This will force QuickFIX/Go to always send GapFills instead of resending messages. Use this if you know you never want to resend a message. Useful for market data streams. Valid Values: - Y - N + + Y + N Defaults to Y. -FileLogPath +# FileLogPath Directory to store logs. Value must be valid directory for storing files, application must have write access. -FileStorePath +# FileStorePath Directory to store sequence number and message files. Only used with FileStoreFactory. -MongoStoreConnection +# MongoStoreConnection The MongoDB connection URL to use (see https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo#Connect for more info). Only used with MongoStoreFactory. -MongoStoreDatabase +# MongoStoreDatabase The MongoDB-specific name of the database to use. Only used with MongoStoreFactory. -MongoStoreReplicaSet +# MongoStoreReplicaSet The MongoDB-specific name of the replica set to use. Optional, only used with MongoStoreFactory. -SQLStoreDriver +# SQLStoreDriver The name of the database driver to use (see https://github.com/golang/go/wiki/SQLDrivers for the list of available drivers). Only used with SqlStoreFactory. -SQLStoreDataSourceName +# SQLStoreDataSourceName The driver-specific data source name of the database to use. Only used with SqlStoreFactory. -SQLStoreConnMaxLifetime +# SQLStoreConnMaxLifetime SetConnMaxLifetime sets the maximum duration of time that a database connection may be reused (see https://golang.org/pkg/database/sql/#DB.SetConnMaxLifetime). Defaults to zero, which causes connections to be reused forever. Only used with SqlStoreFactory. If your database server has a config option to close inactive connections after some duration (e.g. MySQL "wait_timeout"), set SQLConnMaxLifetime to a value less than that duration. Example Values: - SQLConnMaxLifetime=14400s # 14400 seconds - SQLConnMaxLifetime=2h45m # 2 hours and 45 minutes + + SQLConnMaxLifetime=14400s # 14400 seconds + SQLConnMaxLifetime=2h45m # 2 hours and 45 minutes */ package config diff --git a/datadictionary/datadictionary.go b/datadictionary/datadictionary.go index ea93f6b25..b1dc8ef3f 100644 --- a/datadictionary/datadictionary.go +++ b/datadictionary/datadictionary.go @@ -1,4 +1,4 @@ -//Package datadictionary provides support for parsing and organizing FIX Data Dictionaries +// Package datadictionary provides support for parsing and organizing FIX Data Dictionaries package datadictionary import ( @@ -9,7 +9,7 @@ import ( "github.com/pkg/errors" ) -//DataDictionary models FIX messages, components, and fields. +// DataDictionary models FIX messages, components, and fields. type DataDictionary struct { FIXType string Major int @@ -23,20 +23,20 @@ type DataDictionary struct { Trailer *MessageDef } -//MessagePart can represent a Field, Repeating Group, or Component +// MessagePart can represent a Field, Repeating Group, or Component type MessagePart interface { Name() string Required() bool } -//messagePartWithFields is a MessagePart with multiple Fields +// messagePartWithFields is a MessagePart with multiple Fields type messagePartWithFields interface { MessagePart Fields() []*FieldDef RequiredFields() []*FieldDef } -//ComponentType is a grouping of fields. +// ComponentType is a grouping of fields. type ComponentType struct { name string parts []MessagePart @@ -45,7 +45,7 @@ type ComponentType struct { requiredParts []MessagePart } -//NewComponentType returns an initialized component type +// NewComponentType returns an initialized component type func NewComponentType(name string, parts []MessagePart) *ComponentType { comp := ComponentType{ name: name, @@ -77,37 +77,37 @@ func NewComponentType(name string, parts []MessagePart) *ComponentType { return &comp } -//Name returns the name of this component type +// Name returns the name of this component type func (c ComponentType) Name() string { return c.name } -//Fields returns all fields contained in this component. Includes fields -//encapsulated in components of this component +// Fields returns all fields contained in this component. Includes fields +// encapsulated in components of this component func (c ComponentType) Fields() []*FieldDef { return c.fields } -//RequiredFields returns those fields that are required for this component +// RequiredFields returns those fields that are required for this component func (c ComponentType) RequiredFields() []*FieldDef { return c.requiredFields } -//RequiredParts returns those parts that are required for this component +// RequiredParts returns those parts that are required for this component func (c ComponentType) RequiredParts() []MessagePart { return c.requiredParts } // Parts returns all parts in declaration order contained in this component func (c ComponentType) Parts() []MessagePart { return c.parts } -//TagSet is set for tags. +// TagSet is set for tags. type TagSet map[int]struct{} -//Add adds a tag to the tagset. +// Add adds a tag to the tagset. func (t TagSet) Add(tag int) { t[tag] = struct{}{} } -//Component is a Component as it appears in a given MessageDef +// Component is a Component as it appears in a given MessageDef type Component struct { *ComponentType required bool } -//NewComponent returns an initialized Component instance +// NewComponent returns an initialized Component instance func NewComponent(ct *ComponentType, required bool) *Component { return &Component{ ComponentType: ct, @@ -115,16 +115,16 @@ func NewComponent(ct *ComponentType, required bool) *Component { } } -//Required returns true if this component is required for the containing -//MessageDef +// Required returns true if this component is required for the containing +// MessageDef func (c Component) Required() bool { return c.required } -//Field models a field or repeating group in a message +// Field models a field or repeating group in a message type Field interface { Tag() int } -//FieldDef models a field belonging to a message. +// FieldDef models a field belonging to a message. type FieldDef struct { *FieldType required bool @@ -135,7 +135,7 @@ type FieldDef struct { requiredFields []*FieldDef } -//NewFieldDef returns an initialized FieldDef +// NewFieldDef returns an initialized FieldDef func NewFieldDef(fieldType *FieldType, required bool) *FieldDef { return &FieldDef{ FieldType: fieldType, @@ -143,7 +143,7 @@ func NewFieldDef(fieldType *FieldType, required bool) *FieldDef { } } -//NewGroupFieldDef returns an initialized FieldDef for a repeating group +// NewGroupFieldDef returns an initialized FieldDef for a repeating group func NewGroupFieldDef(fieldType *FieldType, required bool, parts []MessagePart) *FieldDef { field := FieldDef{ FieldType: fieldType, @@ -178,21 +178,21 @@ func NewGroupFieldDef(fieldType *FieldType, required bool, parts []MessagePart) return &field } -//Required returns true if this FieldDef is required for the containing -//MessageDef +// Required returns true if this FieldDef is required for the containing +// MessageDef func (f FieldDef) Required() bool { return f.required } -//IsGroup is true if the field is a repeating group. +// IsGroup is true if the field is a repeating group. func (f FieldDef) IsGroup() bool { return len(f.Fields) > 0 } -//RequiredParts returns those parts that are required for this FieldDef. IsGroup -//must return true +// RequiredParts returns those parts that are required for this FieldDef. IsGroup +// must return true func (f FieldDef) RequiredParts() []MessagePart { return f.requiredParts } -//RequiredFields returns those fields that are required for this FieldDef. IsGroup -//must return true +// RequiredFields returns those fields that are required for this FieldDef. IsGroup +// must return true func (f FieldDef) RequiredFields() []*FieldDef { return f.requiredFields } func (f FieldDef) childTags() []int { @@ -206,7 +206,7 @@ func (f FieldDef) childTags() []int { return tags } -//FieldType holds information relating to a field. Includes Tag, type, and enums, if defined. +// FieldType holds information relating to a field. Includes Tag, type, and enums, if defined. type FieldType struct { name string tag int @@ -214,7 +214,7 @@ type FieldType struct { Enums map[string]Enum } -//NewFieldType returns a pointer to an initialized FieldType +// NewFieldType returns a pointer to an initialized FieldType func NewFieldType(name string, tag int, fixType string) *FieldType { return &FieldType{ name: name, @@ -223,19 +223,19 @@ func NewFieldType(name string, tag int, fixType string) *FieldType { } } -//Name returns the name for this FieldType +// Name returns the name for this FieldType func (f FieldType) Name() string { return f.name } -//Tag returns the tag for this fieldType +// Tag returns the tag for this fieldType func (f FieldType) Tag() int { return f.tag } -//Enum is a container for value and description. +// Enum is a container for value and description. type Enum struct { Value string Description string } -//MessageDef can apply to header, trailer, or body of a FIX Message. +// MessageDef can apply to header, trailer, or body of a FIX Message. type MessageDef struct { Name string MsgType string @@ -249,10 +249,10 @@ type MessageDef struct { Tags TagSet } -//RequiredParts returns those parts that are required for this Message +// RequiredParts returns those parts that are required for this Message func (m MessageDef) RequiredParts() []MessagePart { return m.requiredParts } -//NewMessageDef returns a pointer to an initialized MessageDef +// NewMessageDef returns a pointer to an initialized MessageDef func NewMessageDef(name, msgType string, parts []MessagePart) *MessageDef { msg := MessageDef{ Name: name, @@ -299,7 +299,7 @@ func NewMessageDef(name, msgType string, parts []MessagePart) *MessageDef { return &msg } -//Parse loads and build a datadictionary instance from an xml file. +// Parse loads and build a datadictionary instance from an xml file. func Parse(path string) (*DataDictionary, error) { var xmlFile *os.File var err error @@ -312,7 +312,7 @@ func Parse(path string) (*DataDictionary, error) { return ParseSrc(xmlFile) } -//ParseSrc loads and build a datadictionary instance from an xml source. +// ParseSrc loads and build a datadictionary instance from an xml source. func ParseSrc(xmlSrc io.Reader) (*DataDictionary, error) { doc := new(XMLDoc) decoder := xml.NewDecoder(xmlSrc) diff --git a/datadictionary/xml.go b/datadictionary/xml.go index 7471a75bc..759a082f4 100644 --- a/datadictionary/xml.go +++ b/datadictionary/xml.go @@ -4,7 +4,7 @@ import ( "encoding/xml" ) -//XMLDoc is the unmarshalled root of a FIX Dictionary. +// XMLDoc is the unmarshalled root of a FIX Dictionary. type XMLDoc struct { Type string `xml:"type,attr"` Major string `xml:"major,attr"` @@ -27,7 +27,7 @@ type XMLComponent struct { Members []*XMLComponentMember `xml:",any"` } -//XMLField represents the fields/field xml element. +// XMLField represents the fields/field xml element. type XMLField struct { Number int `xml:"number,attr"` Name string `xml:"name,attr"` @@ -35,13 +35,13 @@ type XMLField struct { Values []*XMLValue `xml:"value"` } -//XMLValue represents the fields/field/value xml element. +// XMLValue represents the fields/field/value xml element. type XMLValue struct { Enum string `xml:"enum,attr"` Description string `xml:"description,attr"` } -//XMLComponentMember represents child elements of header, trailer, messages/message, and components/component elements +// XMLComponentMember represents child elements of header, trailer, messages/message, and components/component elements type XMLComponentMember struct { XMLName xml.Name Name string `xml:"name,attr"` diff --git a/errors.go b/errors.go index 19ca16e50..f69e9c287 100644 --- a/errors.go +++ b/errors.go @@ -5,10 +5,10 @@ import ( "fmt" ) -//ErrDoNotSend is a convenience error to indicate a DoNotSend in ToApp +// ErrDoNotSend is a convenience error to indicate a DoNotSend in ToApp var ErrDoNotSend = errors.New("Do Not Send") -//rejectReason enum values. +// rejectReason enum values. const ( rejectReasonInvalidTagNumber = 0 rejectReasonRequiredTagMissing = 1 @@ -27,7 +27,7 @@ const ( rejectReasonIncorrectNumInGroupCountForRepeatingGroup = 16 ) -//MessageRejectError is a type of error that can correlate to a message reject. +// MessageRejectError is a type of error that can correlate to a message reject. type MessageRejectError interface { error @@ -38,23 +38,23 @@ type MessageRejectError interface { IsBusinessReject() bool } -//RejectLogon indicates the application is rejecting permission to logon. Implements MessageRejectError +// RejectLogon indicates the application is rejecting permission to logon. Implements MessageRejectError type RejectLogon struct { Text string } func (e RejectLogon) Error() string { return e.Text } -//RefTagID implements MessageRejectError +// RefTagID implements MessageRejectError func (RejectLogon) RefTagID() *Tag { return nil } -//RejectReason implements MessageRejectError +// RejectReason implements MessageRejectError func (RejectLogon) RejectReason() int { return 0 } -//BusinessRejectRefID implements MessageRejectError +// BusinessRejectRefID implements MessageRejectError func (RejectLogon) BusinessRejectRefID() string { return "" } -//IsBusinessReject implements MessageRejectError +// IsBusinessReject implements MessageRejectError func (RejectLogon) IsBusinessReject() bool { return false } type messageRejectError struct { @@ -71,29 +71,29 @@ func (e messageRejectError) RejectReason() int { return e.rejectReason func (e messageRejectError) BusinessRejectRefID() string { return e.businessRejectRefID } func (e messageRejectError) IsBusinessReject() bool { return e.isBusinessReject } -//NewMessageRejectError returns a MessageRejectError with the given error message, reject reason, and optional reftagid +// NewMessageRejectError returns a MessageRejectError with the given error message, reject reason, and optional reftagid func NewMessageRejectError(err string, rejectReason int, refTagID *Tag) MessageRejectError { return messageRejectError{text: err, rejectReason: rejectReason, refTagID: refTagID} } -//NewBusinessMessageRejectError returns a MessageRejectError with the given error mesage, reject reason, and optional reftagid. -//Reject is treated as a business level reject +// NewBusinessMessageRejectError returns a MessageRejectError with the given error mesage, reject reason, and optional reftagid. +// Reject is treated as a business level reject func NewBusinessMessageRejectError(err string, rejectReason int, refTagID *Tag) MessageRejectError { return messageRejectError{text: err, rejectReason: rejectReason, refTagID: refTagID, isBusinessReject: true} } -//NewBusinessMessageRejectErrorWithRefID returns a MessageRejectError with the given error mesage, reject reason, refID, and optional reftagid. -//Reject is treated as a business level reject +// NewBusinessMessageRejectErrorWithRefID returns a MessageRejectError with the given error mesage, reject reason, refID, and optional reftagid. +// Reject is treated as a business level reject func NewBusinessMessageRejectErrorWithRefID(err string, rejectReason int, businessRejectRefID string, refTagID *Tag) MessageRejectError { return messageRejectError{text: err, rejectReason: rejectReason, refTagID: refTagID, businessRejectRefID: businessRejectRefID, isBusinessReject: true} } -//IncorrectDataFormatForValue returns an error indicating a field that cannot be parsed as the type required. +// IncorrectDataFormatForValue returns an error indicating a field that cannot be parsed as the type required. func IncorrectDataFormatForValue(tag Tag) MessageRejectError { return NewMessageRejectError("Incorrect data format for value", rejectReasonIncorrectDataFormatForValue, &tag) } -//repeatingGroupFieldsOutOfOrder returns an error indicating a problem parsing repeating groups fields +// repeatingGroupFieldsOutOfOrder returns an error indicating a problem parsing repeating groups fields func repeatingGroupFieldsOutOfOrder(tag Tag, reason string) MessageRejectError { if reason != "" { reason = fmt.Sprintf("Repeating group fields out of order (%s)", reason) @@ -103,73 +103,73 @@ func repeatingGroupFieldsOutOfOrder(tag Tag, reason string) MessageRejectError { return NewMessageRejectError(reason, rejectReasonRepeatingGroupFieldsOutOfOrder, &tag) } -//ValueIsIncorrect returns an error indicating a field with value that is not valid. +// ValueIsIncorrect returns an error indicating a field with value that is not valid. func ValueIsIncorrect(tag Tag) MessageRejectError { return NewMessageRejectError("Value is incorrect (out of range) for this tag", rejectReasonValueIsIncorrect, &tag) } -//ConditionallyRequiredFieldMissing indicates that the requested field could not be found in the FIX message. +// ConditionallyRequiredFieldMissing indicates that the requested field could not be found in the FIX message. func ConditionallyRequiredFieldMissing(tag Tag) MessageRejectError { return NewBusinessMessageRejectError(fmt.Sprintf("Conditionally Required Field Missing (%d)", tag), rejectReasonConditionallyRequiredFieldMissing, &tag) } -//valueIsIncorrectNoTag returns an error indicating a field with value that is not valid. -//FIXME: to be compliant with legacy tests, for certain value issues, do not include reftag? (11c_NewSeqNoLess) +// valueIsIncorrectNoTag returns an error indicating a field with value that is not valid. +// FIXME: to be compliant with legacy tests, for certain value issues, do not include reftag? (11c_NewSeqNoLess) func valueIsIncorrectNoTag() MessageRejectError { return NewMessageRejectError("Value is incorrect (out of range) for this tag", rejectReasonValueIsIncorrect, nil) } -//InvalidMessageType returns an error to indicate an invalid message type +// InvalidMessageType returns an error to indicate an invalid message type func InvalidMessageType() MessageRejectError { return NewMessageRejectError("Invalid MsgType", rejectReasonInvalidMsgType, nil) } -//UnsupportedMessageType returns an error to indicate an unhandled message. +// UnsupportedMessageType returns an error to indicate an unhandled message. func UnsupportedMessageType() MessageRejectError { return NewBusinessMessageRejectError("Unsupported Message Type", rejectReasonUnsupportedMessageType, nil) } -//TagNotDefinedForThisMessageType returns an error for an invalid tag appearing in a message. +// TagNotDefinedForThisMessageType returns an error for an invalid tag appearing in a message. func TagNotDefinedForThisMessageType(tag Tag) MessageRejectError { return NewMessageRejectError("Tag not defined for this message type", rejectReasonTagNotDefinedForThisMessageType, &tag) } -//tagAppearsMoreThanOnce return an error for multiple tags in a message not detected as a repeating group. +// tagAppearsMoreThanOnce return an error for multiple tags in a message not detected as a repeating group. func tagAppearsMoreThanOnce(tag Tag) MessageRejectError { return NewMessageRejectError("Tag appears more than once", rejectReasonTagAppearsMoreThanOnce, &tag) } -//RequiredTagMissing returns a validation error when a required field cannot be found in a message. +// RequiredTagMissing returns a validation error when a required field cannot be found in a message. func RequiredTagMissing(tag Tag) MessageRejectError { return NewMessageRejectError("Required tag missing", rejectReasonRequiredTagMissing, &tag) } -//incorrectNumInGroupCountForRepeatingGroup returns a validation error when the num in group value for a group does not match actual group size. +// incorrectNumInGroupCountForRepeatingGroup returns a validation error when the num in group value for a group does not match actual group size. func incorrectNumInGroupCountForRepeatingGroup(tag Tag) MessageRejectError { return NewMessageRejectError("Incorrect NumInGroup count for repeating group", rejectReasonIncorrectNumInGroupCountForRepeatingGroup, &tag) } -//tagSpecifiedOutOfRequiredOrder returns validation error when the group order does not match the spec. +// tagSpecifiedOutOfRequiredOrder returns validation error when the group order does not match the spec. func tagSpecifiedOutOfRequiredOrder(tag Tag) MessageRejectError { return NewMessageRejectError("Tag specified out of required order", rejectReasonTagSpecifiedOutOfRequiredOrder, &tag) } -//TagSpecifiedWithoutAValue returns a validation error for when a field has no value. +// TagSpecifiedWithoutAValue returns a validation error for when a field has no value. func TagSpecifiedWithoutAValue(tag Tag) MessageRejectError { return NewMessageRejectError("Tag specified without a value", rejectReasonTagSpecifiedWithoutAValue, &tag) } -//InvalidTagNumber returns a validation error for messages with invalid tags. +// InvalidTagNumber returns a validation error for messages with invalid tags. func InvalidTagNumber(tag Tag) MessageRejectError { return NewMessageRejectError("Invalid tag number", rejectReasonInvalidTagNumber, &tag) } -//compIDProblem creates a reject for msg where msg has invalid comp id values. +// compIDProblem creates a reject for msg where msg has invalid comp id values. func compIDProblem() MessageRejectError { return NewMessageRejectError("CompID problem", rejectReasonCompIDProblem, nil) } -//sendingTimeAccuracyProblem creates a reject for a msg with stale or invalid sending time. +// sendingTimeAccuracyProblem creates a reject for a msg with stale or invalid sending time. func sendingTimeAccuracyProblem() MessageRejectError { return NewMessageRejectError("SendingTime accuracy problem", rejectReasonSendingTimeAccuracyProblem, nil) } diff --git a/field.go b/field.go index 43b9e4d86..81a277cad 100644 --- a/field.go +++ b/field.go @@ -1,49 +1,49 @@ package quickfix -//FieldValueWriter is an interface for writing field values +// FieldValueWriter is an interface for writing field values type FieldValueWriter interface { //Write writes out the contents of the FieldValue to a []byte Write() []byte } -//FieldValueReader is an interface for reading field values +// FieldValueReader is an interface for reading field values type FieldValueReader interface { //Read reads the contents of the []byte into FieldValue. //Returns an error if there are issues in the data processing Read([]byte) error } -//The FieldValue interface is used to write/extract typed field values to/from raw bytes +// The FieldValue interface is used to write/extract typed field values to/from raw bytes type FieldValue interface { FieldValueWriter FieldValueReader } -//FieldWriter is an interface for a writing a field +// FieldWriter is an interface for a writing a field type FieldWriter interface { Tag() Tag FieldValueWriter } -//Field is the interface implemented by all typed Fields in a Message +// Field is the interface implemented by all typed Fields in a Message type Field interface { FieldWriter FieldValueReader } -//FieldGroupWriter is an interface for writing a FieldGroup +// FieldGroupWriter is an interface for writing a FieldGroup type FieldGroupWriter interface { Tag() Tag Write() []TagValue } -//FieldGroupReader is an interface for reading a FieldGroup +// FieldGroupReader is an interface for reading a FieldGroup type FieldGroupReader interface { Tag() Tag Read([]TagValue) ([]TagValue, error) } -//FieldGroup is the interface implemented by all typed Groups in a Message +// FieldGroup is the interface implemented by all typed Groups in a Message type FieldGroup interface { Tag() Tag Write() []TagValue diff --git a/field_map.go b/field_map.go index 4bf02e6ab..5d5f94269 100644 --- a/field_map.go +++ b/field_map.go @@ -7,7 +7,7 @@ import ( "time" ) -//field stores a slice of TagValues +// field stores a slice of TagValues type field []TagValue func fieldTag(f field) Tag { @@ -36,7 +36,7 @@ func (t tagSort) Len() int { return len(t.tags) } func (t tagSort) Swap(i, j int) { t.tags[i], t.tags[j] = t.tags[j], t.tags[i] } func (t tagSort) Less(i, j int) bool { return t.compare(t.tags[i], t.tags[j]) } -//FieldMap is a collection of fix fields that make up a fix message. +// FieldMap is a collection of fix fields that make up a fix message. type FieldMap struct { tagLookup map[Tag]field tagSort @@ -56,7 +56,7 @@ func (m *FieldMap) initWithOrdering(ordering tagOrder) { m.compare = ordering } -//Tags returns all of the Field Tags in this FieldMap +// Tags returns all of the Field Tags in this FieldMap func (m FieldMap) Tags() []Tag { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -69,12 +69,12 @@ func (m FieldMap) Tags() []Tag { return tags } -//Get parses out a field in this FieldMap. Returned reject may indicate the field is not present, or the field value is invalid. +// Get parses out a field in this FieldMap. Returned reject may indicate the field is not present, or the field value is invalid. func (m FieldMap) Get(parser Field) MessageRejectError { return m.GetField(parser.Tag(), parser) } -//Has returns true if the Tag is present in this FieldMap +// Has returns true if the Tag is present in this FieldMap func (m FieldMap) Has(tag Tag) bool { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -83,7 +83,7 @@ func (m FieldMap) Has(tag Tag) bool { return ok } -//GetField parses of a field with Tag tag. Returned reject may indicate the field is not present, or the field value is invalid. +// GetField parses of a field with Tag tag. Returned reject may indicate the field is not present, or the field value is invalid. func (m FieldMap) GetField(tag Tag, parser FieldValueReader) MessageRejectError { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -100,7 +100,7 @@ func (m FieldMap) GetField(tag Tag, parser FieldValueReader) MessageRejectError return nil } -//GetBytes is a zero-copy GetField wrapper for []bytes fields +// GetBytes is a zero-copy GetField wrapper for []bytes fields func (m FieldMap) GetBytes(tag Tag) ([]byte, MessageRejectError) { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -113,7 +113,7 @@ func (m FieldMap) GetBytes(tag Tag) ([]byte, MessageRejectError) { return f[0].value, nil } -//GetBool is a GetField wrapper for bool fields +// GetBool is a GetField wrapper for bool fields func (m FieldMap) GetBool(tag Tag) (bool, MessageRejectError) { var val FIXBoolean if err := m.GetField(tag, &val); err != nil { @@ -122,7 +122,7 @@ func (m FieldMap) GetBool(tag Tag) (bool, MessageRejectError) { return bool(val), nil } -//GetInt is a GetField wrapper for int fields +// GetInt is a GetField wrapper for int fields func (m FieldMap) GetInt(tag Tag) (int, MessageRejectError) { bytes, err := m.GetBytes(tag) if err != nil { @@ -137,7 +137,7 @@ func (m FieldMap) GetInt(tag Tag) (int, MessageRejectError) { return int(val), err } -//GetTime is a GetField wrapper for utc timestamp fields +// GetTime is a GetField wrapper for utc timestamp fields func (m FieldMap) GetTime(tag Tag) (t time.Time, err MessageRejectError) { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -155,7 +155,7 @@ func (m FieldMap) GetTime(tag Tag) (t time.Time, err MessageRejectError) { return val.Time, err } -//GetString is a GetField wrapper for string fields +// GetString is a GetField wrapper for string fields func (m FieldMap) GetString(tag Tag) (string, MessageRejectError) { var val FIXString if err := m.GetField(tag, &val); err != nil { @@ -164,7 +164,7 @@ func (m FieldMap) GetString(tag Tag) (string, MessageRejectError) { return string(val), nil } -//GetGroup is a Get function specific to Group Fields. +// GetGroup is a Get function specific to Group Fields. func (m FieldMap) GetGroup(parser FieldGroupReader) MessageRejectError { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -184,35 +184,35 @@ func (m FieldMap) GetGroup(parser FieldGroupReader) MessageRejectError { return nil } -//SetField sets the field with Tag tag +// SetField sets the field with Tag tag func (m *FieldMap) SetField(tag Tag, field FieldValueWriter) *FieldMap { return m.SetBytes(tag, field.Write()) } -//SetBytes sets bytes +// SetBytes sets bytes func (m *FieldMap) SetBytes(tag Tag, value []byte) *FieldMap { f := m.getOrCreate(tag) initField(f, tag, value) return m } -//SetBool is a SetField wrapper for bool fields +// SetBool is a SetField wrapper for bool fields func (m *FieldMap) SetBool(tag Tag, value bool) *FieldMap { return m.SetField(tag, FIXBoolean(value)) } -//SetInt is a SetField wrapper for int fields +// SetInt is a SetField wrapper for int fields func (m *FieldMap) SetInt(tag Tag, value int) *FieldMap { v := FIXInt(value) return m.SetBytes(tag, v.Write()) } -//SetString is a SetField wrapper for string fields +// SetString is a SetField wrapper for string fields func (m *FieldMap) SetString(tag Tag, value string) *FieldMap { return m.SetBytes(tag, []byte(value)) } -//Clear purges all fields from field map +// Clear purges all fields from field map func (m *FieldMap) Clear() { m.rwLock.Lock() defer m.rwLock.Unlock() @@ -223,7 +223,7 @@ func (m *FieldMap) Clear() { } } -//CopyInto overwrites the given FieldMap with this one +// CopyInto overwrites the given FieldMap with this one func (m *FieldMap) CopyInto(to *FieldMap) { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -266,14 +266,14 @@ func (m *FieldMap) getOrCreate(tag Tag) field { return f } -//Set is a setter for fields +// Set is a setter for fields func (m *FieldMap) Set(field FieldWriter) *FieldMap { f := m.getOrCreate(field.Tag()) initField(f, field.Tag(), field.Write()) return m } -//SetGroup is a setter specific to group fields +// SetGroup is a setter specific to group fields func (m *FieldMap) SetGroup(field FieldGroupWriter) *FieldMap { m.rwLock.Lock() defer m.rwLock.Unlock() diff --git a/file_log.go b/file_log.go index 02f27b001..52146f07e 100644 --- a/file_log.go +++ b/file_log.go @@ -35,8 +35,8 @@ type fileLogFactory struct { sessionLogPaths map[SessionID]string } -//NewFileLogFactory creates an instance of LogFactory that writes messages and events to file. -//The location of global and session log files is configured via FileLogPath. +// NewFileLogFactory creates an instance of LogFactory that writes messages and events to file. +// The location of global and session log files is configured via FileLogPath. func NewFileLogFactory(settings *Settings) (LogFactory, error) { logFactory := fileLogFactory{} diff --git a/fix_boolean.go b/fix_boolean.go index 5cf53b572..2d9bc57fb 100644 --- a/fix_boolean.go +++ b/fix_boolean.go @@ -4,10 +4,10 @@ import ( "errors" ) -//FIXBoolean is a FIX Boolean value, implements FieldValue. +// FIXBoolean is a FIX Boolean value, implements FieldValue. type FIXBoolean bool -//Bool converts the FIXBoolean value to bool +// Bool converts the FIXBoolean value to bool func (f FIXBoolean) Bool() bool { return bool(f) } func (f *FIXBoolean) Read(bytes []byte) error { diff --git a/fix_bytes.go b/fix_bytes.go index 5e3bb1300..8fb14d1a9 100644 --- a/fix_bytes.go +++ b/fix_bytes.go @@ -1,6 +1,6 @@ package quickfix -//FIXBytes is a generic FIX field value, implements FieldValue. Enables zero copy read from a FieldMap +// FIXBytes is a generic FIX field value, implements FieldValue. Enables zero copy read from a FieldMap type FIXBytes []byte func (f *FIXBytes) Read(bytes []byte) (err error) { diff --git a/fix_decimal.go b/fix_decimal.go index d6f8ab1cd..143e69d7a 100644 --- a/fix_decimal.go +++ b/fix_decimal.go @@ -2,7 +2,7 @@ package quickfix import "github.com/shopspring/decimal" -//FIXDecimal is a FIX Float Value that implements an arbitrary precision fixed-point decimal. Implements FieldValue +// FIXDecimal is a FIX Float Value that implements an arbitrary precision fixed-point decimal. Implements FieldValue type FIXDecimal struct { decimal.Decimal diff --git a/fix_float.go b/fix_float.go index 10122936a..28cafa576 100644 --- a/fix_float.go +++ b/fix_float.go @@ -5,10 +5,10 @@ import ( "strconv" ) -//FIXFloat is a FIX Float Value, implements FieldValue +// FIXFloat is a FIX Float Value, implements FieldValue type FIXFloat float64 -//Float64 converts the FIXFloat value to float64 +// Float64 converts the FIXFloat value to float64 func (f FIXFloat) Float64() float64 { return float64(f) } func (f *FIXFloat) Read(bytes []byte) error { diff --git a/fix_int.go b/fix_int.go index b3695116e..645884b95 100644 --- a/fix_int.go +++ b/fix_int.go @@ -14,7 +14,7 @@ const ( ascii9 = 57 ) -//atoi is similar to the function in strconv, but is tuned for ints appearing in FIX field types. +// atoi is similar to the function in strconv, but is tuned for ints appearing in FIX field types. func atoi(d []byte) (int, error) { if d[0] == asciiMinus { n, err := parseUInt(d[1:]) @@ -24,7 +24,7 @@ func atoi(d []byte) (int, error) { return parseUInt(d) } -//parseUInt is similar to the function in strconv, but is tuned for ints appearing in FIX field types. +// parseUInt is similar to the function in strconv, but is tuned for ints appearing in FIX field types. func parseUInt(d []byte) (n int, err error) { if len(d) == 0 { err = errors.New("empty bytes") @@ -43,10 +43,10 @@ func parseUInt(d []byte) (n int, err error) { return } -//FIXInt is a FIX Int Value, implements FieldValue +// FIXInt is a FIX Int Value, implements FieldValue type FIXInt int -//Int converts the FIXInt value to int +// Int converts the FIXInt value to int func (f FIXInt) Int() int { return int(f) } func (f *FIXInt) Read(bytes []byte) error { diff --git a/fix_string.go b/fix_string.go index bfa54ae06..39c2119a1 100644 --- a/fix_string.go +++ b/fix_string.go @@ -1,6 +1,6 @@ package quickfix -//FIXString is a FIX String Value, implements FieldValue +// FIXString is a FIX String Value, implements FieldValue type FIXString string func (f FIXString) String() string { diff --git a/fix_utc_timestamp.go b/fix_utc_timestamp.go index 82c2c2f7d..c6b685ca3 100644 --- a/fix_utc_timestamp.go +++ b/fix_utc_timestamp.go @@ -5,10 +5,10 @@ import ( "time" ) -//TimestampPrecision defines the precision used by FIXUTCTimestamp +// TimestampPrecision defines the precision used by FIXUTCTimestamp type TimestampPrecision int -//All TimestampPrecisions supported by FIX +// All TimestampPrecisions supported by FIX const ( Millis TimestampPrecision = iota Seconds @@ -16,7 +16,7 @@ const ( Nanos ) -//FIXUTCTimestamp is a FIX UTC Timestamp value, implements FieldValue +// FIXUTCTimestamp is a FIX UTC Timestamp value, implements FieldValue type FIXUTCTimestamp struct { time.Time Precision TimestampPrecision diff --git a/initiator.go b/initiator.go index 3b6672395..8426c7f26 100644 --- a/initiator.go +++ b/initiator.go @@ -10,7 +10,7 @@ import ( "golang.org/x/net/proxy" ) -//Initiator initiates connections and processes messages for all sessions. +// Initiator initiates connections and processes messages for all sessions. type Initiator struct { app Application settings *Settings @@ -24,7 +24,7 @@ type Initiator struct { sessionFactory } -//Start Initiator. +// Start Initiator. func (i *Initiator) Start() (err error) { i.stopChan = make(chan interface{}) @@ -50,7 +50,7 @@ func (i *Initiator) Start() (err error) { return } -//Stop Initiator. +// Stop Initiator. func (i *Initiator) Stop() { select { case <-i.stopChan: @@ -62,7 +62,7 @@ func (i *Initiator) Stop() { i.wg.Wait() } -//NewInitiator creates and initializes a new Initiator. +// NewInitiator creates and initializes a new Initiator. func NewInitiator(app Application, storeFactory MessageStoreFactory, appSettings *Settings, logFactory LogFactory) (*Initiator, error) { i := &Initiator{ app: app, @@ -92,7 +92,7 @@ func NewInitiator(app Application, storeFactory MessageStoreFactory, appSettings return i, nil } -//waitForInSessionTime returns true if the session is in session, false if the handler should stop +// waitForInSessionTime returns true if the session is in session, false if the handler should stop func (i *Initiator) waitForInSessionTime(session *session) bool { inSessionTime := make(chan interface{}) go func() { @@ -109,7 +109,7 @@ func (i *Initiator) waitForInSessionTime(session *session) bool { return true } -//waitForReconnectInterval returns true if a reconnect should be re-attempted, false if handler should stop +// waitForReconnectInterval returns true if a reconnect should be re-attempted, false if handler should stop func (i *Initiator) waitForReconnectInterval(reconnectInterval time.Duration) bool { select { case <-time.After(reconnectInterval): diff --git a/internal/event.go b/internal/event.go index 5c6af8db4..7e00cc2b8 100644 --- a/internal/event.go +++ b/internal/event.go @@ -1,6 +1,6 @@ package internal -//Event is an abstraction for session events +// Event is an abstraction for session events type Event int const ( diff --git a/internal/session_settings.go b/internal/session_settings.go index 7547c0fa6..b91d89a0d 100644 --- a/internal/session_settings.go +++ b/internal/session_settings.go @@ -2,7 +2,7 @@ package internal import "time" -//SessionSettings stores all of the configuration for a given session +// SessionSettings stores all of the configuration for a given session type SessionSettings struct { ResetOnLogon bool RefreshOnLogon bool diff --git a/internal/time_range.go b/internal/time_range.go index e69f2fd21..4b7f9d7c7 100644 --- a/internal/time_range.go +++ b/internal/time_range.go @@ -6,7 +6,7 @@ import ( "github.com/pkg/errors" ) -//TimeOfDay represents the time of day +// TimeOfDay represents the time of day type TimeOfDay struct { hour, minute, second int d time.Duration @@ -14,7 +14,7 @@ type TimeOfDay struct { const shortForm = "15:04:05" -//NewTimeOfDay returns a newly initialized TimeOfDay +// NewTimeOfDay returns a newly initialized TimeOfDay func NewTimeOfDay(hour, minute, second int) TimeOfDay { d := time.Duration(second)*time.Second + time.Duration(minute)*time.Minute + @@ -23,7 +23,7 @@ func NewTimeOfDay(hour, minute, second int) TimeOfDay { return TimeOfDay{hour: hour, minute: minute, second: second, d: d} } -//ParseTimeOfDay parses a TimeOfDay from a string in the format HH:MM:SS +// ParseTimeOfDay parses a TimeOfDay from a string in the format HH:MM:SS func ParseTimeOfDay(str string) (TimeOfDay, error) { t, err := time.Parse(shortForm, str) if err != nil { @@ -33,19 +33,19 @@ func ParseTimeOfDay(str string) (TimeOfDay, error) { return NewTimeOfDay(t.Clock()), nil } -//TimeRange represents a time band in a given time zone +// TimeRange represents a time band in a given time zone type TimeRange struct { startTime, endTime TimeOfDay startDay, endDay *time.Weekday loc *time.Location } -//NewUTCTimeRange returns a time range in UTC +// NewUTCTimeRange returns a time range in UTC func NewUTCTimeRange(start, end TimeOfDay) *TimeRange { return NewTimeRangeInLocation(start, end, time.UTC) } -//NewTimeRangeInLocation returns a time range in a given location +// NewTimeRangeInLocation returns a time range in a given location func NewTimeRangeInLocation(start, end TimeOfDay, loc *time.Location) *TimeRange { if loc == nil { panic("time: missing Location in call to NewTimeRangeInLocation") @@ -54,12 +54,12 @@ func NewTimeRangeInLocation(start, end TimeOfDay, loc *time.Location) *TimeRange return &TimeRange{startTime: start, endTime: end, loc: loc} } -//NewUTCWeekRange returns a weekly TimeRange +// NewUTCWeekRange returns a weekly TimeRange func NewUTCWeekRange(startTime, endTime TimeOfDay, startDay, endDay time.Weekday) *TimeRange { return NewWeekRangeInLocation(startTime, endTime, startDay, endDay, time.UTC) } -//NewWeekRangeInLocation returns a time range in a given location +// NewWeekRangeInLocation returns a time range in a given location func NewWeekRangeInLocation(startTime, endTime TimeOfDay, startDay, endDay time.Weekday, loc *time.Location) *TimeRange { r := NewTimeRangeInLocation(startTime, endTime, loc) r.startDay = &startDay @@ -120,7 +120,7 @@ func (r *TimeRange) isInWeekRange(t time.Time) bool { return true } -//IsInRange returns true if time t is within in the time range +// IsInRange returns true if time t is within in the time range func (r *TimeRange) IsInRange(t time.Time) bool { if r == nil { return true @@ -133,7 +133,7 @@ func (r *TimeRange) IsInRange(t time.Time) bool { return r.isInTimeRange(t) } -//IsInSameRange determines if two points in time are in the same time range +// IsInSameRange determines if two points in time are in the same time range func (r *TimeRange) IsInSameRange(t1, t2 time.Time) bool { if r == nil { return true diff --git a/log.go b/log.go index 6b1fa04bb..d346a5d7a 100644 --- a/log.go +++ b/log.go @@ -1,6 +1,6 @@ package quickfix -//Log is a generic interface for logging FIX messages and events. +// Log is a generic interface for logging FIX messages and events. type Log interface { //OnIncoming log incoming fix message OnIncoming([]byte) @@ -15,7 +15,7 @@ type Log interface { OnEventf(string, ...interface{}) } -//The LogFactory interface creates global and session specific Log instances +// The LogFactory interface creates global and session specific Log instances type LogFactory interface { //Create global log Create() (Log, error) diff --git a/message.go b/message.go index d76e5ca44..0a637346b 100644 --- a/message.go +++ b/message.go @@ -9,10 +9,10 @@ import ( "github.com/quickfixgo/quickfix/datadictionary" ) -//Header is first section of a FIX Message +// Header is first section of a FIX Message type Header struct{ FieldMap } -//in the message header, the first 3 tags in the message header must be 8,9,35 +// in the message header, the first 3 tags in the message header must be 8,9,35 func headerFieldOrdering(i, j Tag) bool { var ordering = func(t Tag) uint32 { switch t { @@ -40,20 +40,20 @@ func headerFieldOrdering(i, j Tag) bool { return i < j } -//Init initializes the Header instance +// Init initializes the Header instance func (h *Header) Init() { h.initWithOrdering(headerFieldOrdering) } -//Body is the primary application section of a FIX message +// Body is the primary application section of a FIX message type Body struct{ FieldMap } -//Init initializes the FIX message +// Init initializes the FIX message func (b *Body) Init() { b.init() } -//Trailer is the last section of a FIX message +// Trailer is the last section of a FIX message type Trailer struct{ FieldMap } // In the trailer, CheckSum (tag 10) must be last @@ -68,12 +68,12 @@ func trailerFieldOrdering(i, j Tag) bool { return i < j } -//Init initializes the FIX message +// Init initializes the FIX message func (t *Trailer) Init() { t.initWithOrdering(trailerFieldOrdering) } -//Message is a FIX Message abstraction. +// Message is a FIX Message abstraction. type Message struct { Header Header Trailer Trailer @@ -94,17 +94,17 @@ type Message struct { keepMessage bool } -//ToMessage returns the message itself +// ToMessage returns the message itself func (m *Message) ToMessage() *Message { return m } -//parseError is returned when bytes cannot be parsed as a FIX message. +// parseError is returned when bytes cannot be parsed as a FIX message. type parseError struct { OrigError string } func (e parseError) Error() string { return fmt.Sprintf("error parsing message: %s", e.OrigError) } -//NewMessage returns a newly initialized Message instance +// NewMessage returns a newly initialized Message instance func NewMessage() *Message { m := new(Message) m.Header.Init() @@ -130,12 +130,12 @@ func (m *Message) CopyInto(to *Message) { } } -//ParseMessage constructs a Message from a byte slice wrapping a FIX message. +// ParseMessage constructs a Message from a byte slice wrapping a FIX message. func ParseMessage(msg *Message, rawMessage *bytes.Buffer) (err error) { return ParseMessageWithDataDictionary(msg, rawMessage, nil, nil) } -//ParseMessageWithDataDictionary constructs a Message from a byte slice wrapping a FIX message using an optional session and application DataDictionary for reference. +// ParseMessageWithDataDictionary constructs a Message from a byte slice wrapping a FIX message using an optional session and application DataDictionary for reference. func ParseMessageWithDataDictionary( msg *Message, rawMessage *bytes.Buffer, @@ -287,7 +287,7 @@ func (m *Message) IsMsgTypeOf(msgType string) bool { return false } -//reverseRoute returns a message builder with routing header fields initialized as the reverse of this message. +// reverseRoute returns a message builder with routing header fields initialized as the reverse of this message. func (m *Message) reverseRoute() *Message { reverseMsg := NewMessage() @@ -362,7 +362,7 @@ func formatCheckSum(value int) string { return fmt.Sprintf("%03d", value) } -//Build constructs a []byte from a Message instance +// Build constructs a []byte from a Message instance func (m *Message) build() []byte { m.cook() diff --git a/message_router.go b/message_router.go index 8cc76bf73..03e57f867 100644 --- a/message_router.go +++ b/message_router.go @@ -5,7 +5,7 @@ type routeKey struct { MsgType string } -//FIX ApplVerID string values +// FIX ApplVerID string values const ( ApplVerIDFIX27 = "0" ApplVerIDFIX30 = "1" @@ -19,25 +19,25 @@ const ( ApplVerIDFIX50SP2 = "9" ) -//A MessageRoute is a function that can process a fromApp/fromAdmin callback +// A MessageRoute is a function that can process a fromApp/fromAdmin callback type MessageRoute func(msg *Message, sessionID SessionID) MessageRejectError -//A MessageRouter is a mutex for MessageRoutes +// A MessageRouter is a mutex for MessageRoutes type MessageRouter struct { routes map[routeKey]MessageRoute } -//NewMessageRouter returns an initialized MessageRouter instance +// 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. +// 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. +// 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, err := msg.Header.GetBytes(tagBeginString) if err != nil { diff --git a/msg_type.go b/msg_type.go index 03faed698..309f302f4 100644 --- a/msg_type.go +++ b/msg_type.go @@ -10,7 +10,7 @@ var msgTypeReject = []byte("3") var msgTypeSequenceReset = []byte("4") var msgTypeLogout = []byte("5") -//isAdminMessageType returns true if the message type is a session level message. +// isAdminMessageType returns true if the message type is a session level message. func isAdminMessageType(m []byte) bool { switch { case bytes.Equal(msgTypeHeartbeat, m), diff --git a/null_log.go b/null_log.go index 3d6f02ba1..786271c42 100644 --- a/null_log.go +++ b/null_log.go @@ -16,7 +16,7 @@ func (nullLogFactory) CreateSessionLog(sessionID SessionID) (Log, error) { return nullLog{}, nil } -//NewNullLogFactory creates an instance of LogFactory that returns no-op loggers. +// NewNullLogFactory creates an instance of LogFactory that returns no-op loggers. func NewNullLogFactory() LogFactory { return nullLogFactory{} } diff --git a/quickfix_test.go b/quickfix_test.go index 189aaf21f..575a28614 100644 --- a/quickfix_test.go +++ b/quickfix_test.go @@ -52,7 +52,7 @@ func (s *QuickFIXSuite) MessageEqualsBytes(expectedBytes []byte, msg *Message) { s.Equal(string(actualBytes), string(expectedBytes)) } -//MockStore wraps a memory store and mocks Refresh for convenience +// MockStore wraps a memory store and mocks Refresh for convenience type MockStore struct { mock.Mock memoryStore diff --git a/registry.go b/registry.go index 3c1fb2af8..ffbcd1914 100644 --- a/registry.go +++ b/registry.go @@ -10,12 +10,12 @@ var sessions = make(map[SessionID]*session) var errDuplicateSessionID = errors.New("Duplicate SessionID") var errUnknownSession = errors.New("Unknown session") -//Messagable is a Message or something that can be converted to a Message +// Messagable is a Message or something that can be converted to a Message type Messagable interface { ToMessage() *Message } -//Send determines the session to send Messagable using header fields BeginString, TargetCompID, SenderCompID +// Send determines the session to send Messagable using header fields BeginString, TargetCompID, SenderCompID func Send(m Messagable) (err error) { msg := m.ToMessage() var beginString FIXString @@ -39,7 +39,7 @@ func Send(m Messagable) (err error) { return SendToTarget(msg, sessionID) } -//SendToTarget sends a message based on the sessionID. Convenient for use in FromApp since it provides a session ID for incoming messages +// SendToTarget sends a message based on the sessionID. Convenient for use in FromApp since it provides a session ID for incoming messages func SendToTarget(m Messagable, sessionID SessionID) error { msg := m.ToMessage() session, ok := lookupSession(sessionID) @@ -50,7 +50,7 @@ func SendToTarget(m Messagable, sessionID SessionID) error { return session.queueForSend(msg) } -//UnregisterSession removes a session from the set of known sessions +// UnregisterSession removes a session from the set of known sessions func UnregisterSession(sessionID SessionID) error { sessionsLock.Lock() defer sessionsLock.Unlock() diff --git a/repeating_group.go b/repeating_group.go index 10b4150fc..173cfa116 100644 --- a/repeating_group.go +++ b/repeating_group.go @@ -6,7 +6,7 @@ import ( "strconv" ) -//GroupItem interface is used to construct repeating group templates +// GroupItem interface is used to construct repeating group templates type GroupItem interface { //Tag returns the tag identifying this GroupItem Tag() Tag @@ -38,15 +38,15 @@ func (t protoGroupElement) Read(tv []TagValue) ([]TagValue, error) { func (t protoGroupElement) Clone() GroupItem { return t } -//GroupElement returns a GroupItem made up of a single field +// GroupElement returns a GroupItem made up of a single field func GroupElement(tag Tag) GroupItem { return protoGroupElement{tag: tag} } -//GroupTemplate specifies the group item order for a RepeatingGroup +// GroupTemplate specifies the group item order for a RepeatingGroup type GroupTemplate []GroupItem -//Clone makes a copy of this GroupTemplate +// Clone makes a copy of this GroupTemplate func (gt GroupTemplate) Clone() GroupTemplate { clone := make(GroupTemplate, len(gt)) for i := range gt { @@ -56,17 +56,17 @@ func (gt GroupTemplate) Clone() GroupTemplate { return clone } -//Group is a group of fields occurring in a repeating group +// Group is a group of fields occurring in a repeating group type Group struct{ FieldMap } -//RepeatingGroup is a FIX Repeating Group type +// RepeatingGroup is a FIX Repeating Group type type RepeatingGroup struct { tag Tag template GroupTemplate groups []*Group } -//NewRepeatingGroup returns an initilized RepeatingGroup instance +// NewRepeatingGroup returns an initilized RepeatingGroup instance func NewRepeatingGroup(tag Tag, template GroupTemplate) *RepeatingGroup { return &RepeatingGroup{ tag: tag, @@ -74,12 +74,12 @@ func NewRepeatingGroup(tag Tag, template GroupTemplate) *RepeatingGroup { } } -//Tag returns the Tag for this repeating Group +// Tag returns the Tag for this repeating Group func (f RepeatingGroup) Tag() Tag { return f.tag } -//Clone makes a copy of this RepeatingGroup (tag, template) +// Clone makes a copy of this RepeatingGroup (tag, template) func (f RepeatingGroup) Clone() GroupItem { return &RepeatingGroup{ tag: f.tag, @@ -87,17 +87,17 @@ func (f RepeatingGroup) Clone() GroupItem { } } -//Len returns the number of Groups in this RepeatingGroup +// Len returns the number of Groups in this RepeatingGroup func (f RepeatingGroup) Len() int { return len(f.groups) } -//Get returns the ith group in this RepeatingGroup +// Get returns the ith group in this RepeatingGroup func (f RepeatingGroup) Get(i int) *Group { return f.groups[i] } -//Add appends a new group to the RepeatingGroup and returns the new Group +// Add appends a new group to the RepeatingGroup and returns the new Group func (f *RepeatingGroup) Add() *Group { g := new(Group) g.initWithOrdering(f.groupTagOrder()) @@ -106,8 +106,8 @@ func (f *RepeatingGroup) Add() *Group { return g } -//Write returns tagValues for all Items in the repeating group ordered by -//Group sequence and Group template order +// Write returns tagValues for all Items in the repeating group ordered by +// Group sequence and Group template order func (f RepeatingGroup) Write() []TagValue { tvs := make([]TagValue, 1) tvs[0].init(f.tag, []byte(strconv.Itoa(len(f.groups)))) diff --git a/screen_log.go b/screen_log.go index 0fcd4ebdb..e6271ecc0 100644 --- a/screen_log.go +++ b/screen_log.go @@ -40,7 +40,7 @@ func (screenLogFactory) CreateSessionLog(sessionID SessionID) (Log, error) { return log, nil } -//NewScreenLogFactory creates an instance of LogFactory that writes messages and events to stdout. +// NewScreenLogFactory creates an instance of LogFactory that writes messages and events to stdout. func NewScreenLogFactory() LogFactory { return screenLogFactory{} } diff --git a/session_factory.go b/session_factory.go index 8fc42d3c0..769e5084a 100644 --- a/session_factory.go +++ b/session_factory.go @@ -46,7 +46,7 @@ type sessionFactory struct { BuildInitiators bool } -//Creates Session, associates with internal session registry +// Creates Session, associates with internal session registry func (f sessionFactory) createSession( sessionID SessionID, storeFactory MessageStoreFactory, settings *SessionSettings, logFactory LogFactory, application Application, diff --git a/session_id.go b/session_id.go index 9ee621c52..c3ce615fe 100644 --- a/session_id.go +++ b/session_id.go @@ -7,7 +7,7 @@ type SessionID struct { BeginString, TargetCompID, TargetSubID, TargetLocationID, SenderCompID, SenderSubID, SenderLocationID, Qualifier string } -//IsFIXT returns true if the SessionID has a FIXT BeginString +// IsFIXT returns true if the SessionID has a FIXT BeginString func (s SessionID) IsFIXT() bool { return s.BeginString == BeginStringFIXT11 } diff --git a/session_rejects.go b/session_rejects.go index ba9e6ec23..2edfcd280 100644 --- a/session_rejects.go +++ b/session_rejects.go @@ -4,12 +4,12 @@ import ( "fmt" ) -//IncorrectBeginString is a message reject specific to incorrect begin strings. +// IncorrectBeginString is a message reject specific to incorrect begin strings. type incorrectBeginString struct{ messageRejectError } func (e incorrectBeginString) Error() string { return "Incorrect BeginString" } -//targetTooHigh is a MessageReject where the sequence number is larger than expected. +// targetTooHigh is a MessageReject where the sequence number is larger than expected. type targetTooHigh struct { messageRejectError ReceivedTarget int @@ -20,7 +20,7 @@ func (e targetTooHigh) Error() string { return fmt.Sprintf("MsgSeqNum too high, expecting %d but received %d", e.ExpectedTarget, e.ReceivedTarget) } -//targetTooLow is a MessageReject where the sequence number is less than expected. +// targetTooLow is a MessageReject where the sequence number is less than expected. type targetTooLow struct { messageRejectError ReceivedTarget int diff --git a/session_settings.go b/session_settings.go index 17889eccc..49afbcd7f 100644 --- a/session_settings.go +++ b/session_settings.go @@ -6,12 +6,12 @@ import ( "time" ) -//SessionSettings maps session settings to values with typed accessors. +// SessionSettings maps session settings to values with typed accessors. type SessionSettings struct { settings map[string]string } -//ConditionallyRequiredSetting indicates a missing setting +// ConditionallyRequiredSetting indicates a missing setting type ConditionallyRequiredSetting struct { Setting string } @@ -20,7 +20,7 @@ func (e ConditionallyRequiredSetting) Error() string { return fmt.Sprintf("Conditionally Required Setting: %v", e.Setting) } -//IncorrectFormatForSetting indicates a setting that is incorrectly formatted +// IncorrectFormatForSetting indicates a setting that is incorrectly formatted type IncorrectFormatForSetting struct { Setting, Value string Err error @@ -30,12 +30,12 @@ func (e IncorrectFormatForSetting) Error() string { return fmt.Sprintf("%q is invalid for %s", e.Value, e.Setting) } -//Init initializes or resets SessionSettings +// Init initializes or resets SessionSettings func (s *SessionSettings) Init() { s.settings = make(map[string]string) } -//NewSessionSettings returns a newly initialized SessionSettings instance +// NewSessionSettings returns a newly initialized SessionSettings instance func NewSessionSettings() *SessionSettings { s := &SessionSettings{} s.Init() @@ -43,7 +43,7 @@ func NewSessionSettings() *SessionSettings { return s } -//Set assigns a value to a setting on SessionSettings. +// Set assigns a value to a setting on SessionSettings. func (s *SessionSettings) Set(setting string, val string) { //lazy init if s.settings == nil { @@ -53,13 +53,13 @@ func (s *SessionSettings) Set(setting string, val string) { s.settings[setting] = val } -//HasSetting returns true if a setting is set, false if not +// HasSetting returns true if a setting is set, false if not func (s *SessionSettings) HasSetting(setting string) bool { _, ok := s.settings[setting] return ok } -//Setting is a settings string accessor. Returns an error if the setting is missing. +// Setting is a settings string accessor. Returns an error if the setting is missing. func (s *SessionSettings) Setting(setting string) (string, error) { val, ok := s.settings[setting] if !ok { @@ -69,7 +69,7 @@ func (s *SessionSettings) Setting(setting string) (string, error) { return val, nil } -//IntSetting returns the requested setting parsed as an int. Returns an errror if the setting is not set or cannot be parsed as an int. +// IntSetting returns the requested setting parsed as an int. Returns an errror if the setting is not set or cannot be parsed as an int. func (s *SessionSettings) IntSetting(setting string) (val int, err error) { stringVal, err := s.Setting(setting) @@ -84,8 +84,8 @@ func (s *SessionSettings) IntSetting(setting string) (val int, err error) { return } -//DurationSetting returns the requested setting parsed as a time.Duration. -//Returns an error if the setting is not set or cannot be parsed as a time.Duration. +// DurationSetting returns the requested setting parsed as a time.Duration. +// Returns an error if the setting is not set or cannot be parsed as a time.Duration. func (s *SessionSettings) DurationSetting(setting string) (val time.Duration, err error) { stringVal, err := s.Setting(setting) @@ -100,7 +100,7 @@ func (s *SessionSettings) DurationSetting(setting string) (val time.Duration, er return } -//BoolSetting returns the requested setting parsed as a boolean. Returns an error if the setting is not set or cannot be parsed as a bool. +// BoolSetting returns the requested setting parsed as a boolean. Returns an error if the setting is not set or cannot be parsed as a bool. func (s SessionSettings) BoolSetting(setting string) (bool, error) { stringVal, err := s.Setting(setting) diff --git a/session_state.go b/session_state.go index 55e341365..016cb3e8c 100644 --- a/session_state.go +++ b/session_state.go @@ -190,8 +190,8 @@ func handleStateError(s *session, err error) sessionState { return latentState{} } -//sessionState is the current state of the session state machine. The session state determines how the session responds to -//incoming messages, timeouts, and requests to send application messages. +// sessionState is the current state of the session state machine. The session state determines how the session responds to +// incoming messages, timeouts, and requests to send application messages. type sessionState interface { //FixMsgIn is called by the session on incoming messages from the counter party. The return type is the next session state //following message processing diff --git a/settings.go b/settings.go index 870cf3d71..f70bf9596 100644 --- a/settings.go +++ b/settings.go @@ -10,13 +10,13 @@ import ( "github.com/quickfixgo/quickfix/config" ) -//The Settings type represents a collection of global and session settings. +// The Settings type represents a collection of global and session settings. type Settings struct { globalSettings *SessionSettings sessionSettings map[SessionID]*SessionSettings } -//Init initializes or resets a Settings instance +// Init initializes or resets a Settings instance func (s *Settings) Init() { s.globalSettings = NewSessionSettings() s.sessionSettings = make(map[SessionID]*SessionSettings) @@ -28,7 +28,7 @@ func (s *Settings) lazyInit() { } } -//NewSettings creates a Settings instance +// NewSettings creates a Settings instance func NewSettings() *Settings { s := &Settings{} s.Init() @@ -75,8 +75,8 @@ func sessionIDFromSessionSettings(globalSettings *SessionSettings, sessionSettin return sessionID } -//ParseSettings creates and initializes a Settings instance with config parsed from a Reader. -//Returns error if the config is has parse errors +// ParseSettings creates and initializes a Settings instance with config parsed from a Reader. +// Returns error if the config is has parse errors func ParseSettings(reader io.Reader) (*Settings, error) { s := NewSettings() @@ -130,13 +130,13 @@ func ParseSettings(reader io.Reader) (*Settings, error) { return s, err } -//GlobalSettings are default setting inherited by all session settings. +// GlobalSettings are default setting inherited by all session settings. func (s *Settings) GlobalSettings() *SessionSettings { s.lazyInit() return s.globalSettings } -//SessionSettings return all session settings overlaying globalsettings. +// SessionSettings return all session settings overlaying globalsettings. func (s *Settings) SessionSettings() map[SessionID]*SessionSettings { allSessionSettings := make(map[SessionID]*SessionSettings) @@ -149,7 +149,7 @@ func (s *Settings) SessionSettings() map[SessionID]*SessionSettings { return allSessionSettings } -//AddSession adds Session Settings to Settings instance. Returns an error if session settings with duplicate sessionID has already been added +// AddSession adds Session Settings to Settings instance. Returns an error if session settings with duplicate sessionID has already been added func (s *Settings) AddSession(sessionSettings *SessionSettings) (SessionID, error) { s.lazyInit() diff --git a/store.go b/store.go index b743a46cc..0ad5123fa 100644 --- a/store.go +++ b/store.go @@ -6,7 +6,7 @@ import ( "github.com/pkg/errors" ) -//The MessageStore interface provides methods to record and retrieve messages for resend purposes +// The MessageStore interface provides methods to record and retrieve messages for resend purposes type MessageStore interface { NextSenderMsgSeqNum() int NextTargetMsgSeqNum() int @@ -29,7 +29,7 @@ type MessageStore interface { Close() error } -//The MessageStoreFactory interface is used by session to create a session specific message store +// The MessageStoreFactory interface is used by session to create a session specific message store type MessageStoreFactory interface { Create(sessionID SessionID) (MessageStore, error) } @@ -126,5 +126,5 @@ func (f memoryStoreFactory) Create(sessionID SessionID) (MessageStore, error) { return m, nil } -//NewMemoryStoreFactory returns a MessageStoreFactory instance that created in-memory MessageStores +// NewMemoryStoreFactory returns a MessageStoreFactory instance that created in-memory MessageStores func NewMemoryStoreFactory() MessageStoreFactory { return memoryStoreFactory{} } diff --git a/tag.go b/tag.go index 20fcda0b7..475c7316a 100644 --- a/tag.go +++ b/tag.go @@ -1,6 +1,6 @@ package quickfix -//Tag is a typed int representing a FIX tag +// Tag is a typed int representing a FIX tag type Tag int const ( @@ -61,7 +61,7 @@ const ( tagCheckSum Tag = 10 ) -//IsTrailer returns true if tag belongs in the message trailer +// IsTrailer returns true if tag belongs in the message trailer func (t Tag) IsTrailer() bool { switch t { case tagSignatureLength, tagSignature, tagCheckSum: @@ -70,7 +70,7 @@ func (t Tag) IsTrailer() bool { return false } -//IsHeader returns true if tag belongs in the message header +// IsHeader returns true if tag belongs in the message header func (t Tag) IsHeader() bool { switch t { case tagBeginString, diff --git a/tag_value.go b/tag_value.go index 762ea233a..75f532a85 100644 --- a/tag_value.go +++ b/tag_value.go @@ -6,7 +6,7 @@ import ( "strconv" ) -//TagValue is a low-level FIX field abstraction +// TagValue is a low-level FIX field abstraction type TagValue struct { tag Tag value []byte diff --git a/tls.go b/tls.go index e8a541c0b..62c7207f3 100644 --- a/tls.go +++ b/tls.go @@ -97,7 +97,7 @@ func loadTLSConfig(settings *SessionSettings) (tlsConfig *tls.Config, err error) return } -//defaultTLSConfig brought to you by https://github.com/gtank/cryptopasta/ +// defaultTLSConfig brought to you by https://github.com/gtank/cryptopasta/ func defaultTLSConfig() *tls.Config { return &tls.Config{ // Avoids most of the memorably-named TLS attacks diff --git a/validation.go b/validation.go index 2a3d61dd6..14f6f9f0d 100644 --- a/validation.go +++ b/validation.go @@ -4,19 +4,19 @@ import ( "github.com/quickfixgo/quickfix/datadictionary" ) -//Validator validates a FIX message +// Validator validates a FIX message type Validator interface { Validate(*Message) MessageRejectError } -//ValidatorSettings describe validation behavior +// ValidatorSettings describe validation behavior type ValidatorSettings struct { CheckFieldsOutOfOrder bool RejectInvalidMessage bool } -//Default configuration for message validation. -//See http://www.quickfixengine.org/quickfix/doc/html/configuration.html. +// Default configuration for message validation. +// See http://www.quickfixengine.org/quickfix/doc/html/configuration.html. var defaultValidatorSettings = ValidatorSettings{ CheckFieldsOutOfOrder: true, RejectInvalidMessage: true, @@ -33,7 +33,7 @@ type fixtValidator struct { settings ValidatorSettings } -//NewValidator creates a FIX message validator from the given data dictionaries +// NewValidator creates a FIX message validator from the given data dictionaries func NewValidator(settings ValidatorSettings, appDataDictionary, transportDataDictionary *datadictionary.DataDictionary) Validator { if transportDataDictionary != nil { return &fixtValidator{ @@ -48,7 +48,7 @@ func NewValidator(settings ValidatorSettings, appDataDictionary, transportDataDi } } -//Validate tests the message against the provided data dictionary. +// Validate tests the message against the provided data dictionary. func (v *fixValidator) Validate(msg *Message) MessageRejectError { if !msg.Header.Has(tagMsgType) { return RequiredTagMissing(tagMsgType) @@ -61,8 +61,8 @@ func (v *fixValidator) Validate(msg *Message) MessageRejectError { return validateFIX(v.dataDictionary, v.settings, msgType, msg) } -//Validate tests the message against the provided transport and app data dictionaries. -//If the message is an admin message, it will be validated against the transport data dictionary. +// Validate tests the message against the provided transport and app data dictionaries. +// If the message is an admin message, it will be validated against the transport data dictionary. func (v *fixtValidator) Validate(msg *Message) MessageRejectError { if !msg.Header.Has(tagMsgType) { return RequiredTagMissing(tagMsgType) diff --git a/validation_test.go b/validation_test.go index 8224c96c0..25a47802a 100644 --- a/validation_test.go +++ b/validation_test.go @@ -466,9 +466,9 @@ func tcTagAppearsMoreThanOnce() validateTest { tag := Tag(40) return validateTest{ - TestName: "Tag appears more than once", - Validator: validator, - MessageBytes: []byte("8=FIX.4.09=10735=D34=249=TW52=20060102-15:04:0556=ISLD11=ID21=140=140=254=138=20055=INTC60=20060102-15:04:0510=234"), + TestName: "Tag appears more than once", + Validator: validator, + MessageBytes: []byte("8=FIX.4.09=10735=D34=249=TW52=20060102-15:04:0556=ISLD11=ID21=140=140=254=138=20055=INTC60=20060102-15:04:0510=234"), ExpectedRejectReason: rejectReasonTagAppearsMoreThanOnce, ExpectedRefTagID: &tag, } @@ -479,9 +479,9 @@ func tcFloatValidation() validateTest { validator := NewValidator(defaultValidatorSettings, dict, nil) tag := Tag(38) return validateTest{ - TestName: "FloatValidation", - Validator: validator, - MessageBytes: []byte("8=FIX.4.29=10635=D34=249=TW52=20140329-22:38:4556=ISLD11=ID21=140=154=138=+200.0055=INTC60=20140329-22:38:4510=178"), + TestName: "FloatValidation", + Validator: validator, + MessageBytes: []byte("8=FIX.4.29=10635=D34=249=TW52=20140329-22:38:4556=ISLD11=ID21=140=154=138=+200.0055=INTC60=20140329-22:38:4510=178"), ExpectedRejectReason: rejectReasonIncorrectDataFormatForValue, ExpectedRefTagID: &tag, } From d06fa333e80d3dae28f49b100bbe02bc16c2e38b Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Fri, 23 Dec 2022 21:28:05 -0600 Subject: [PATCH 17/47] Bump linter version --- .github/workflows/ci.yaml | 4 +--- Makefile | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index afe397103..709a7468d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -30,13 +30,11 @@ jobs: - name: Install golangci-lint run: | curl -sSLO https://github.com/golangci/golangci-lint/releases/download/v$GOLANGCI_LINT_VERSION/golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64.tar.gz - shasum -a 256 golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64.tar.gz | grep "^$GOLANGCI_LINT_SHA256 " > /dev/null tar -xf golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64.tar.gz sudo mv golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64/golangci-lint /usr/local/bin/golangci-lint rm -rf golangci-lint-$GOLANGCI_LINT_VERSION-linux-amd64* env: - GOLANGCI_LINT_VERSION: '1.46.2' - GOLANGCI_LINT_SHA256: '242cd4f2d6ac0556e315192e8555784d13da5d1874e51304711570769c4f2b9b' + GOLANGCI_LINT_VERSION: '1.50.1' - name: Run Lint run: make lint diff --git a/Makefile b/Makefile index 5caa90a69..2e0799d43 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ test: linters-install: @golangci-lint --version >/dev/null 2>&1 || { \ echo "installing linting tools..."; \ - curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.46.2; \ + curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.50.1; \ } lint: linters-install From 7616a32e1e3a32d7a1b025c49c50f186e1c78344 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Tue, 3 Jan 2023 20:43:50 -0600 Subject: [PATCH 18/47] Adds v0.7.0 release notes --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcc635229..2aa4d96a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,37 @@ +## 0.7.0 (January 2, 2023) + +FEATURES + +* PersistMessages Config [GH 297] +* MaxLatency [GH 242] +* ResetOnDisconnect Configuration [GH 68] +* Support for High Precision Timestamps [GH 288] +* LogonTimeout [GH 295] +* LogoutTimeout [GH 296] +* Socks Proxy [GH 375] + +ENHANCEMENTS + +* Add SocketUseSSL parameter to allow SSL/TLS without client certs [GH 311] +* Support for RejectInvalidMessage configuration [GH 336] +* Add deep copy for Messages [GH 338] +* Add Go Module support [GH 340] +* Support timeout on ssl connection [GH 347, 349] +* Dynamic Sessions [GH 521] + + +BUG FIXES + +* header and trailer templates use rootpath [GH 302] +* Initiator stop panic if stop chan's already closed [GH 359] +* Connection closed when inbound logon has a too-low sequence number [GH 369] +* TLS server name config [GH 384] +* Fix concurrent map write [GH 436] +* Race condition during bilateral initial resend request [GH 439] +* Deadlock when disconnecting dynamic session [GH 524] + + + ## 0.6.0 (August 14, 2017) FEATURES From 7905df48534829913a32c506193a888b9c350f3f Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Wed, 4 Jan 2023 12:30:53 -0600 Subject: [PATCH 19/47] Amends v0.7.0 release notes --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aa4d96a3..b1bb9b03e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ ENHANCEMENTS * Add Go Module support [GH 340] * Support timeout on ssl connection [GH 347, 349] * Dynamic Sessions [GH 521] - +* Upgrade Mongo Driver to support transactions [GH 527] BUG FIXES @@ -29,7 +29,8 @@ BUG FIXES * Fix concurrent map write [GH 436] * Race condition during bilateral initial resend request [GH 439] * Deadlock when disconnecting dynamic session [GH 524] - +* Align session's ticker with round second [GH 533] +* Seqnum persist and increment fix [GH 528] ## 0.6.0 (August 14, 2017) From 8ed145d7243bdcdec4f367eecc55f5c7a405a25a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Jan 2023 00:07:55 +0000 Subject: [PATCH 20/47] Bump golang.org/x/net from 0.4.0 to 0.5.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.4.0 to 0.5.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 952abfa45..10cbdb8b1 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.8.1 go.mongodb.org/mongo-driver v1.11.1 - golang.org/x/net v0.4.0 + golang.org/x/net v0.5.0 ) require ( @@ -27,7 +27,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect golang.org/x/crypto v0.3.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/text v0.5.0 // indirect + golang.org/x/text v0.6.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index a1a76b93c..376aa7687 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -73,8 +73,8 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 124f989bd107dd8a67698e37cc6003765778ba12 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Tue, 17 Jan 2023 00:13:50 -0600 Subject: [PATCH 21/47] Update README.md --- README.md | 150 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 84 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 1a6d4cde0..350c7f6c9 100644 --- a/README.md +++ b/README.md @@ -2,74 +2,113 @@ [![Build Status](https://github.com/quickfixgo/quickfix/workflows/CI/badge.svg)](https://github.com/quickfixgo/quickfix/actions) [![GoDoc](https://godoc.org/github.com/quickfixgo/quickfix?status.png)](https://godoc.org/github.com/quickfixgo/quickfix) [![Go Report Card](https://goreportcard.com/badge/github.com/quickfixgo/quickfix)](https://goreportcard.com/report/github.com/quickfixgo/quickfix) -- Website: http://www.quickfixgo.org -- Mailing list: [Google Groups](https://groups.google.com/forum/#!forum/quickfixgo) - Open Source [FIX Protocol](http://www.fixprotocol.org/) library implemented in Go -## Getting Started and Documentation - -* [User Manual](http://quickfixgo.org/docs) -* [API Documentation](https://godoc.org/github.com/quickfixgo/quickfix) +## About +

QuickFIX/Go is a FIX Protocol Community implementation for the Go programming language.

+ +
    +
  • 100% free and open source with a liberal license
  • +
  • Supports FIX versions 4.0 - 5.0SP2
  • +
  • Runs on any hardware and operating system supported by Go (1.18+ required)
  • +
  • Spec driven run-time message validation
  • +
  • Spec driven code generation of type-safe FIX messages, fields, and repeating groups
  • +
  • Support for protocol customizations
  • +
  • Session state storage options: SQL, MongoDB, On-disk, or In-memory
  • +
  • Logging options: File, Screen
  • +
  • Failover and High Availability
  • +
  • Daily and weekly scheduling of session connections
  • +
  • Integrated support for SSL communicaitons
  • +
  • Automated unit and acceptance tests
  • +
  • Commercial Support available
  • +
+ +
+Sponsored by Connamara ## Installation -To install QuickFIX/Go, use `go get`: +With [Go module](https://github.com/golang/go/wiki/Modules) support, simply add the following import -```sh -go get github.com/quickfixgo/quickfix ``` +import "github.com/quickfixgo/quickfix" +``` + +to your code, and then `go [build|run|test]` will automatically fetch the necessary dependencies. -## Staying up to date +Otherwise, run the following Go command to install the `quickfix` package: -To update QuickFIX/Go to the latest version, use `go get -u github.com/quickfixgo/quickfix`. +```sh +go get -u github.com/quickfixgo/quickfix +``` -## Example Apps +## Getting Started -See [examples](https://github.com/quickfixgo/examples) for some simple examples of using QuickFIX/Go. +* [QuickFIX User Manual](http://quickfixgo.org/docs) +* [Go API Documentation](https://godoc.org/github.com/quickfixgo/quickfix) +* See [examples](https://github.com/quickfixgo/examples) for some simple examples of using QuickFIX/Go. -## FIX Message Generation +## FIX Messaging Model +To send and receive messages, your application will need a few additional packages. -QuickFIX/Go includes separate packages for tags, fields, enums, messages, and message components generated from the FIX 4.0 - FIX5.0SP2 specs. See: +QuickFIX/Go maintains separate packages for tags, fields, enums, messages, and message components auto-generated from the FIX 4.0 - FIX5.0SP2 XML specifications- -* [github.com/quickfixgo/tag](https://github.com/quickfixgo/tag) -* [github.com/quickfixgo/field](https://github.com/quickfixgo/field) -* [github.com/quickfixgo/enum](https://github.com/quickfixgo/enum) -* [github.com/quickfixgo/fix40](https://github.com/quickfixgo/fix40) -* [github.com/quickfixgo/fix41](https://github.com/quickfixgo/fix41) -* [github.com/quickfixgo/fix42](https://github.com/quickfixgo/fix42) -* [github.com/quickfixgo/fix43](https://github.com/quickfixgo/fix43) -* [github.com/quickfixgo/fix44](https://github.com/quickfixgo/fix44) -* [github.com/quickfixgo/fix50](https://github.com/quickfixgo/fix50) -* [github.com/quickfixgo/fix50sp1](https://github.com/quickfixgo/fix50sp1) -* [github.com/quickfixgo/fix50sp2](https://github.com/quickfixgo/fix50sp2) -* [github.com/quickfixgo/fixt11](https://github.com/quickfixgo/fixt11) +* [Tag](https://github.com/quickfixgo/tag) +* [Field](https://github.com/quickfixgo/field) +* [Enum](https://github.com/quickfixgo/enum) +* [FIX 4.0](https://github.com/quickfixgo/fix40) +* [FIX 4.1](https://github.com/quickfixgo/fix41) +* [FIX 4.2](https://github.com/quickfixgo/fix42) +* [FIX 4.3](https://github.com/quickfixgo/fix43) +* [FIX 4.4](https://github.com/quickfixgo/fix44) +* [FIX 5.0](https://github.com/quickfixgo/fix50) +* [FIX 5.0 SP1](https://github.com/quickfixgo/fix50sp1) +* [FIX 5.0 SP2](https://github.com/quickfixgo/fix50sp2) +* [FIXT 1.1](https://github.com/quickfixgo/fixt11) For most FIX applications, these generated resources are sufficient. Custom FIX applications may generate source specific to the FIX spec of that application using the `generate-fix` tool included with QuickFIX/Go. Following installation, `generate-fix` is installed to `$GOPATH/bin/generate-fix`. Run `$GOPATH/bin/generate-fix --help` for usage instructions. -## Developing QuickFIX/Go +## General Support +

Github Discussions

-If you wish to work on QuickFIX/Go itself, you will need [Docker](https://docs.docker.com/get-docker/) and [VSCode](https://code.visualstudio.com/download) on your machine. +

Our Github Discussions Board is free, public, and easily searchable. It’s the preferred method of user support from the QuickFIX/Go team. -* Clone the repo and open it with VSCode with Docker running -* This repo comes with vscode devcontainer configs in `./.devcontainer/` -* Click the pop-up to re-open the project in the Dev Container -* This opens the project in a docker container pre-configured with everything you need +

Please provide as much detail as you can when asking a question, and include relevant configurations and code snippets.

+

FIX Protocol

-## Installing Dependencies +

More information about the FIX protocol can be found at the FIX Protocol website. -As of Go version 1.13, QuickFIX/Go uses [modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. You may require `GO111MODULE=on`. To install dependencies, run +

Bugs and Issues

-```sh -go mod download -``` +

Bugs and issues can be submitted by anyone through our GitHub repository issues list.

+ +

Note: Please do not submit questions or help requests to the issues list. It is for bugs and issues. If you need help, please use the Discussions board as described above and you’ll be able to send your question to the entire community.

+ +

GitHub Issues

+ +

Please provide sample code, logs, and a description of the problem when the issue is submitted.

+ +

We will try to address new issues as quickly as possible, and we welcome contributions for bug fixes and new features!

+ +## Commercial Support +

Connamara Systems offers commercial support for developers who are integrating any of the QuickFIX implementations (Go, C++, Java, .NET). The support is offered in 10-hour bundles and grants developers access, via telephone or email, to the team that created QuickFIX/Go, QuickFIX/n, and are maintainers of QuickFIX.

-**Note:** No vendored dependencies are included in the QuickFIX/Go source. +

In addition to offering QuickFIX support, Connamara delivers Made-To-Measure Trading Solutions by bridging the gap between buy and build. By using internally developed trading platform components, Connamara delivers the best of off-the-shelf ISV solutions and custom application development. Coupled with Connamara’s unique licensing model, trading firms can get the best of both build and buy.

-## Build and Test + +## Contributing + +If you wish to work on QuickFIX/Go itself, you will need [Docker](https://docs.docker.com/get-docker/) and [VSCode](https://code.visualstudio.com/download) on your machine. + +* Clone the repo and open it with VSCode with Docker running +* This repo comes with vscode devcontainer configs in `./.devcontainer/` +* Click the pop-up to re-open the project in the Dev Container +* This opens the project in a docker container pre-configured with everything you need + +### Build and Test The default make target runs [go vet](https://godoc.org/golang.org/x/tools/cmd/vet) and unit tests. @@ -79,7 +118,7 @@ make If this exits with exit status 0, then everything is working! -## Generated Code +### Generated Code Generated code from the FIX40-FIX50SP2 specs are available as separate repos under the [QuickFIX/Go organization](https://github.com/quickfixgo). The source specifications for this generated code is located in `spec/`. Generated code can be identified by the `.generated.go` suffix. Any changes to generated code must be captured by changes to source in `cmd/generate-fix`. After making changes to the code generator source, run the following to re-generate the source @@ -89,7 +128,7 @@ make generate If you are making changes to the generated code, please create Pull Requests for these changes for the affected repos. -## Acceptance Tests +### Acceptance Tests QuickFIX/Go has a comprehensive acceptance test suite covering the FIX protocol. These are the same tests used across all QuickFIX implementations. @@ -108,27 +147,6 @@ make build-test-srv make accept ``` -## Dependencies - -If you are developing QuickFIX/Go, there are a few tasks you might need to perform related to dependencies. - -### Adding/updating a dependency - -If you are adding or updating a dependency, you will need to update the `go.mod` and `go.sum` in the same Pull Request as the code that depends on it. You should do this in a separate commit from your code, as this makes PR review easier and Git history simpler to read in the future. - -1. Add or update the dependency like usual: -```sh -go get -u github.com/foo/bar -``` -2. Update the module-related files: -```sh -go mod tidy -``` -3. Review the changes in git and commit them. - -Note that to specify a specific revision, you can manually edit the `go.mod` file and run `go mod tidy` - -Licensing ---------- +## Licensing -This software is available under the QuickFIX Software License. Please see the [LICENSE.txt](https://github.com/quickfixgo/quickfix/blob/master/LICENSE.txt) for the terms specified by the QuickFIX Software License. +This software is available under the QuickFIX Software License. Please see the [LICENSE.txt](https://github.com/quickfixgo/quickfix/blob/main/LICENSE.txt) for the terms specified by the QuickFIX Software License. From 9c874d8fb94a79d8365f7d570ce7427be0ed6928 Mon Sep 17 00:00:00 2001 From: Hyde Zhang Date: Fri, 24 Sep 2021 16:18:08 +0100 Subject: [PATCH 22/47] Fix repeating group read tags lost --- repeating_group.go | 1 + repeating_group_test.go | 2 ++ 2 files changed, 3 insertions(+) diff --git a/repeating_group.go b/repeating_group.go index 173cfa116..1cbbc8e2a 100644 --- a/repeating_group.go +++ b/repeating_group.go @@ -202,6 +202,7 @@ func (f *RepeatingGroup) Read(tv []TagValue) ([]TagValue, error) { group.rwLock.Lock() group.tagLookup[tvRange[0].tag] = tvRange + group.tags = append(group.tags, gi.Tag()) group.rwLock.Unlock() } diff --git a/repeating_group_test.go b/repeating_group_test.go index 448e39d6a..955e3b7da 100644 --- a/repeating_group_test.go +++ b/repeating_group_test.go @@ -185,6 +185,8 @@ func TestRepeatingGroup_Read(t *testing.T) { for _, expected := range test.expectedGroupTvs[g] { var actual FIXString require.Nil(t, group.GetField(expected.tag, &actual)) + require.NotNil(t, group.tags) + require.Equal(t, len(group.tags), len(group.tagLookup)) if !bytes.Equal(expected.value, []byte(actual)) { t.Errorf("%v, %v: expected %s, got %s", g, expected.tag, expected.value, actual) From 97461150fbecc974d0d435b9f3dff4d50c515fe6 Mon Sep 17 00:00:00 2001 From: Russell Scheerer Date: Thu, 1 Dec 2022 11:26:13 -0500 Subject: [PATCH 23/47] Add sessionId to global logs where possible --- acceptor.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acceptor.go b/acceptor.go index 3d72ba20e..656463cbe 100644 --- a/acceptor.go +++ b/acceptor.go @@ -298,7 +298,7 @@ func (a *Acceptor) handleConnection(netConn net.Conn) { // We have a session ID and a network connection. This seems to be a good place for any custom authentication logic. if a.connectionValidator != nil { if err := a.connectionValidator.Validate(netConn, sessID); err != nil { - a.globalLog.OnEventf("Unable to validate a connection %v", err.Error()) + a.globalLog.OnEventf("Unable to validate a connection for session %v: %v", sessID, err.Error()) return } } @@ -328,7 +328,7 @@ func (a *Acceptor) handleConnection(netConn net.Conn) { msgOut := make(chan []byte) if err := session.connect(msgIn, msgOut); err != nil { - a.globalLog.OnEventf("Unable to accept %v", err.Error()) + a.globalLog.OnEventf("Unable to accept session %v connection: %v", sessID, err.Error()) return } From f26aaade3055bb53265f00f44dfb375ae986f507 Mon Sep 17 00:00:00 2001 From: Lord Date: Thu, 21 May 2020 23:11:09 -0500 Subject: [PATCH 24/47] ignore data in xmldata field --- message.go | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/message.go b/message.go index 0a637346b..6945e2301 100644 --- a/message.go +++ b/message.go @@ -190,6 +190,8 @@ func ParseMessageWithDataDictionary( return } + prevTag := tagMsgType + msg.Header.add(msg.fields[fieldIndex : fieldIndex+1]) fieldIndex++ @@ -197,7 +199,11 @@ func ParseMessageWithDataDictionary( foundBody := false for { parsedFieldBytes = &msg.fields[fieldIndex] - rawBytes, err = extractField(parsedFieldBytes, rawBytes) + if prevTag == tagXMLDataLen { + rawBytes, err = extractXMLDataField(parsedFieldBytes, rawBytes) + } else { + rawBytes, err = extractField(parsedFieldBytes, rawBytes) + } if err != nil { return } @@ -220,6 +226,7 @@ func ParseMessageWithDataDictionary( msg.bodyBytes = rawBytes } + prevTag = parsedFieldBytes.tag fieldIndex++ } @@ -338,6 +345,30 @@ func extractSpecificField(field *TagValue, expectedTag Tag, buffer []byte) (remB return } +func extractXMLDataField(parsedFieldBytes *TagValue, buffer []byte) (remBytes []byte, err error) { + endIndex := bytes.IndexByte(buffer, '>') + if endIndex == -1 { + err = parseError{OrigError: "extractField: No Trailing Delim in " + string(buffer)} + remBytes = buffer + return + } + + endIndex = bytes.IndexByte(buffer[endIndex+1:], '>') + if endIndex == -1 { + err = parseError{OrigError: "extractField: No Trailing Delim in " + string(buffer)} + remBytes = buffer + return + } + + tempEndIndex := bytes.IndexByte(buffer[endIndex:], '\001') + endIndex += tempEndIndex + tempEndIndex = bytes.IndexByte(buffer[endIndex+1:], '\001') + endIndex += tempEndIndex + 1 + + err = parsedFieldBytes.parse(buffer[:endIndex+1]) + return buffer[(endIndex + 1):], err +} + func extractField(parsedFieldBytes *TagValue, buffer []byte) (remBytes []byte, err error) { endIndex := bytes.IndexByte(buffer, '\001') if endIndex == -1 { From 1ce30ebdce646424876ef299984bc090c5b4a719 Mon Sep 17 00:00:00 2001 From: Lord Date: Wed, 27 May 2020 15:37:07 -0500 Subject: [PATCH 25/47] Properly process CME XMLData for 35=n --- message.go | 34 +++++++++++++++------------------- message_test.go | 14 ++++++++++++-- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/message.go b/message.go index 6945e2301..5f185ed2f 100644 --- a/message.go +++ b/message.go @@ -190,7 +190,9 @@ func ParseMessageWithDataDictionary( return } - prevTag := tagMsgType + //prevTag := tagMsgType + xmlDataLen := 0 + xmlDataMsg := false msg.Header.add(msg.fields[fieldIndex : fieldIndex+1]) fieldIndex++ @@ -199,8 +201,10 @@ func ParseMessageWithDataDictionary( foundBody := false for { parsedFieldBytes = &msg.fields[fieldIndex] - if prevTag == tagXMLDataLen { - rawBytes, err = extractXMLDataField(parsedFieldBytes, rawBytes) + if xmlDataLen > 0 { + rawBytes, err = extractXMLDataField(parsedFieldBytes, rawBytes, xmlDataLen) + xmlDataLen = 0 + xmlDataMsg = true } else { rawBytes, err = extractField(parsedFieldBytes, rawBytes) } @@ -226,7 +230,10 @@ func ParseMessageWithDataDictionary( msg.bodyBytes = rawBytes } - prevTag = parsedFieldBytes.tag + //prevTag = parsedFieldBytes.tag + if parsedFieldBytes.tag == tagXMLDataLen { + xmlDataLen, _ = msg.Header.GetInt(tagXMLDataLen) + } fieldIndex++ } @@ -247,7 +254,7 @@ func ParseMessageWithDataDictionary( bodyLength, err := msg.Header.GetInt(tagBodyLength) if err != nil { err = parseError{OrigError: err.Error()} - } else if length != bodyLength { + } else if length != bodyLength && !xmlDataMsg { err = parseError{OrigError: fmt.Sprintf("Incorrect Message Length, expected %d, got %d", bodyLength, length)} } @@ -345,25 +352,14 @@ func extractSpecificField(field *TagValue, expectedTag Tag, buffer []byte) (remB return } -func extractXMLDataField(parsedFieldBytes *TagValue, buffer []byte) (remBytes []byte, err error) { - endIndex := bytes.IndexByte(buffer, '>') - if endIndex == -1 { - err = parseError{OrigError: "extractField: No Trailing Delim in " + string(buffer)} - remBytes = buffer - return - } - - endIndex = bytes.IndexByte(buffer[endIndex+1:], '>') +func extractXMLDataField(parsedFieldBytes *TagValue, buffer []byte, dataLen int) (remBytes []byte, err error) { + endIndex := bytes.IndexByte(buffer, '=') if endIndex == -1 { err = parseError{OrigError: "extractField: No Trailing Delim in " + string(buffer)} remBytes = buffer return } - - tempEndIndex := bytes.IndexByte(buffer[endIndex:], '\001') - endIndex += tempEndIndex - tempEndIndex = bytes.IndexByte(buffer[endIndex+1:], '\001') - endIndex += tempEndIndex + 1 + endIndex += dataLen + 1 err = parsedFieldBytes.parse(buffer[:endIndex+1]) return buffer[(endIndex + 1):], err diff --git a/message_test.go b/message_test.go index 40b063ca1..1a46a62d8 100644 --- a/message_test.go +++ b/message_test.go @@ -13,9 +13,9 @@ import ( func BenchmarkParseMessage(b *testing.B) { rawMsg := bytes.NewBufferString("8=FIX.4.29=10435=D34=249=TW52=20140515-19:49:56.65956=ISLD11=10021=140=154=155=TSLA60=00010101-00:00:00.00010=039") - var msg Message + msg := NewMessage() for i := 0; i < b.N; i++ { - _ = ParseMessage(&msg, rawMsg) + _ = ParseMessage(msg, rawMsg) } } @@ -32,6 +32,16 @@ func (s *MessageSuite) SetupTest() { s.msg = NewMessage() } +func TestXMLNonFIX(t *testing.T) { + rawMsg := bytes.NewBufferString("8=FIX.4.29=37235=n34=25512369=148152=20200522-07:05:33.75649=CME50=G56=OAEAAAN57=TRADE_CAPTURE143=US,IL212=261213=8=FIX.4.29=22535=BZ34=6549369=651852=20200522-07:05:33.74649=CME50=G56=9Q5000N57=DUMMY143=US,IL11=ACP159013113373460=20200522-07:05:33.734533=0893=Y1028=Y1300=991369=99612:325081373=31374=91375=15979=159013113373461769710=16710=245\"") + msg := NewMessage() + _ = ParseMessage(msg, rawMsg) + + if !msg.Header.Has(tagXMLData) { + t.Error("Expected xmldata tag") + } +} + func (s *MessageSuite) TestParseMessageEmpty() { rawMsg := bytes.NewBufferString("") From 8a2144a438445349de04c07d02fbb8bcb40df063 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Sun, 29 Jan 2023 19:18:12 -0600 Subject: [PATCH 26/47] Adds license info to src file headers and formats comments. --- .golangci.yml | 1 + LICENSE.txt => LICENSE | 2 +- accepter_test.go | 15 +++++ acceptor.go | 15 +++++ application.go | 29 +++++++--- begin_string.go | 17 +++++- cmd/generate-fix/generate-fix.go | 2 +- cmd/generate-fix/internal/globals.go | 6 +- cmd/generate-fix/internal/template_helpers.go | 2 +- config/configuration.go | 4 +- connection.go | 15 +++++ connection_internal_test.go | 15 +++++ datadictionary/datadictionary.go | 51 ++++++++--------- datadictionary/xml.go | 2 +- dialer.go | 15 +++++ dialer_test.go | 15 +++++ doc.go | 21 +++++-- errors.go | 41 ++++++++----- errors_test.go | 15 +++++ field.go | 37 ++++++++---- field_map.go | 57 ++++++++++++------- field_map_test.go | 15 +++++ file_log.go | 15 +++++ file_log_test.go | 15 +++++ filestore.go | 39 +++++++++---- filestore_test.go | 17 +++++- fileutil.go | 21 ++++++- fileutil_test.go | 15 +++++ fix_boolean.go | 17 +++++- fix_boolean_test.go | 15 +++++ fix_bytes.go | 17 +++++- fix_bytes_test.go | 15 +++++ fix_decimal.go | 19 ++++++- fix_decimal_test.go | 15 +++++ fix_float.go | 21 ++++++- fix_float_test.go | 15 +++++ fix_int.go | 23 ++++++-- fix_int_test.go | 15 +++++ fix_string.go | 17 +++++- fix_string_test.go | 15 +++++ fix_utc_timestamp.go | 25 ++++++-- fix_utc_timestamp_test.go | 15 +++++ in_session.go | 21 ++++++- in_session_test.go | 17 +++++- initiator.go | 23 ++++++-- internal/event.go | 10 ++-- internal/session_settings.go | 6 +- internal/time_range.go | 20 +++---- latent_state.go | 15 +++++ latent_state_test.go | 15 +++++ log.go | 29 +++++++--- logon_state.go | 15 +++++ logon_state_test.go | 21 ++++++- logout_state.go | 15 +++++ logout_state_test.go | 15 +++++ message.go | 57 ++++++++++++------- message_router.go | 23 ++++++-- message_router_test.go | 15 +++++ message_test.go | 19 ++++++- mongostore.go | 51 +++++++++++------ mongostore_test.go | 17 +++++- msg_type.go | 15 +++++ not_session_time.go | 15 +++++ not_session_time_test.go | 15 +++++ null_log.go | 15 +++++ parser.go | 23 ++++++-- parser_test.go | 15 +++++ pending_timeout.go | 15 +++++ pending_timeout_test.go | 15 +++++ quickfix_test.go | 17 +++++- registry.go | 23 ++++++-- repeating_group.go | 55 +++++++++++------- repeating_group_test.go | 15 +++++ resend_state.go | 19 ++++++- resend_state_test.go | 21 ++++++- screen_log.go | 15 +++++ session.go | 37 ++++++++---- session_factory.go | 21 ++++++- session_factory_test.go | 15 +++++ session_id.go | 19 ++++++- session_id_test.go | 15 +++++ session_rejects.go | 15 +++++ session_settings.go | 27 +++++++-- session_settings_test.go | 15 +++++ session_state.go | 33 ++++++++--- session_test.go | 41 ++++++++----- settings.go | 23 ++++++-- settings_test.go | 15 +++++ sqlstore.go | 39 +++++++++---- sqlstore_test.go | 17 +++++- store.go | 25 ++++++-- store_test.go | 19 ++++++- tag.go | 21 ++++++- tag_value.go | 17 +++++- tag_value_test.go | 15 +++++ tls.go | 15 +++++ tls_test.go | 15 +++++ validation.go | 25 ++++++-- validation_test.go | 50 +++++++++------- 99 files changed, 1652 insertions(+), 337 deletions(-) rename LICENSE.txt => LICENSE (95%) diff --git a/.golangci.yml b/.golangci.yml index 7d3a47ddb..cf2a5fff9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -17,6 +17,7 @@ linters: - revive - unused - staticcheck + - godot linters-settings: gofmt: diff --git a/LICENSE.txt b/LICENSE similarity index 95% rename from LICENSE.txt rename to LICENSE index d9eb36409..273a59dad 100644 --- a/LICENSE.txt +++ b/LICENSE @@ -1,6 +1,6 @@ The QuickFIX Software License, Version 1.0 -Copyright (c) 2001-2010 quickfixengine.org All rights +Copyright (c) 2001- quickfixengine.org All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/accepter_test.go b/accepter_test.go index 5e032cbb1..0d9f6487b 100644 --- a/accepter_test.go +++ b/accepter_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/acceptor.go b/acceptor.go index 656463cbe..879cdb17f 100644 --- a/acceptor.go +++ b/acceptor.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/application.go b/application.go index e7d76c60e..1d12419d3 100644 --- a/application.go +++ b/application.go @@ -1,26 +1,41 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix // Application interface should be implemented by FIX Applications. // This is the primary interface for processing messages from a FIX Session. type Application interface { - //OnCreate notification of a session begin created. + // OnCreate notification of a session begin created. OnCreate(sessionID SessionID) - //OnLogon notification of a session successfully logging on. + // OnLogon notification of a session successfully logging on. OnLogon(sessionID SessionID) - //OnLogout notification of a session logging off or disconnecting. + // OnLogout notification of a session logging off or disconnecting. OnLogout(sessionID SessionID) - //ToAdmin notification of admin message being sent to target. + // ToAdmin notification of admin message being sent to target. ToAdmin(message *Message, sessionID SessionID) - //ToApp notification of app message being sent to target. + // ToApp notification of app message being sent to target. ToApp(message *Message, sessionID SessionID) error - //FromAdmin notification of admin message being received from target. + // FromAdmin notification of admin message being received from target. FromAdmin(message *Message, sessionID SessionID) MessageRejectError - //FromApp notification of app message being received from target. + // FromApp notification of app message being received from target. FromApp(message *Message, sessionID SessionID) MessageRejectError } diff --git a/begin_string.go b/begin_string.go index b5d9f6f14..641ea7c6f 100644 --- a/begin_string.go +++ b/begin_string.go @@ -1,6 +1,21 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix -// FIX BeginString string values +// FIX BeginString string values. const ( BeginStringFIX40 = "FIX.4.0" BeginStringFIX41 = "FIX.4.1" diff --git a/cmd/generate-fix/generate-fix.go b/cmd/generate-fix/generate-fix.go index ae1749722..a24d39771 100644 --- a/cmd/generate-fix/generate-fix.go +++ b/cmd/generate-fix/generate-fix.go @@ -164,7 +164,7 @@ func main() { } switch pkg { - //uses fixt11 header/trailer + // Uses fixt11 header/trailer. case "fix50", "fix50sp1", "fix50sp2": default: waitGroup.Add(1) diff --git a/cmd/generate-fix/internal/globals.go b/cmd/generate-fix/internal/globals.go index 45e49467d..bf935b4db 100644 --- a/cmd/generate-fix/internal/globals.go +++ b/cmd/generate-fix/internal/globals.go @@ -14,7 +14,7 @@ var ( GlobalFieldTypes []*datadictionary.FieldType ) -//sort fieldtypes by name +// Sort fieldtypes by name. type byFieldName []*datadictionary.FieldType func (n byFieldName) Len() int { return len(n) } @@ -36,14 +36,14 @@ func BuildGlobalFieldTypes(specs []*datadictionary.DataDictionary) { for _, spec := range specs { for _, field := range spec.FieldTypeByTag { if oldField, ok := globalFieldTypesLookup[field.Name()]; ok { - //merge old enums with new + // Merge old enums with new. if len(oldField.Enums) > 0 && field.Enums == nil { field.Enums = make(map[string]datadictionary.Enum) } for enumVal, enum := range oldField.Enums { if _, ok := field.Enums[enumVal]; !ok { - //Verify an existing enum doesn't have the same description. Keep newer enum + // Verify an existing enum doesn't have the same description. Keep newer enum. okToKeepEnum := true for _, newEnum := range field.Enums { if newEnum.Description == enum.Description { diff --git a/cmd/generate-fix/internal/template_helpers.go b/cmd/generate-fix/internal/template_helpers.go index e4dcce727..932f4792b 100644 --- a/cmd/generate-fix/internal/template_helpers.go +++ b/cmd/generate-fix/internal/template_helpers.go @@ -306,7 +306,7 @@ func routerBeginString(spec *datadictionary.DataDictionary) (routerBeginString s routerBeginString = "FIXT.1.1" case spec.Major != 5 && spec.ServicePack == 0: routerBeginString = fmt.Sprintf("FIX.%v.%v", spec.Major, spec.Minor) - //ApplVerID enums + // ApplVerID enums. case spec.Major == 2: routerBeginString = "0" case spec.Major == 3: diff --git a/config/configuration.go b/config/configuration.go index 2af864fd9..431be8ea7 100644 --- a/config/configuration.go +++ b/config/configuration.go @@ -1,8 +1,8 @@ package config -//NOTE: Additions to this file should be made to both config/doc.go and http://www.quickfixgo.org/docs/ +// NOTE: Additions to this file should be made to both config/doc.go and http://www.quickfixgo.org/docs/ -// Const configuration settings +// Const configuration settings. const ( BeginString string = "BeginString" SenderCompID string = "SenderCompID" diff --git a/connection.go b/connection.go index 4e5768a36..c006560f4 100644 --- a/connection.go +++ b/connection.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import "io" diff --git a/connection_internal_test.go b/connection_internal_test.go index 54a9f347f..1ee4d13e8 100644 --- a/connection_internal_test.go +++ b/connection_internal_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/datadictionary/datadictionary.go b/datadictionary/datadictionary.go index b1dc8ef3f..9342b3dd5 100644 --- a/datadictionary/datadictionary.go +++ b/datadictionary/datadictionary.go @@ -23,13 +23,13 @@ type DataDictionary struct { Trailer *MessageDef } -// MessagePart can represent a Field, Repeating Group, or Component +// MessagePart can represent a Field, Repeating Group, or Component. type MessagePart interface { Name() string Required() bool } -// messagePartWithFields is a MessagePart with multiple Fields +// messagePartWithFields is a MessagePart with multiple Fields. type messagePartWithFields interface { MessagePart Fields() []*FieldDef @@ -45,7 +45,7 @@ type ComponentType struct { requiredParts []MessagePart } -// NewComponentType returns an initialized component type +// NewComponentType returns an initialized component type. func NewComponentType(name string, parts []MessagePart) *ComponentType { comp := ComponentType{ name: name, @@ -77,20 +77,20 @@ func NewComponentType(name string, parts []MessagePart) *ComponentType { return &comp } -// Name returns the name of this component type +// Name returns the name of this component type. func (c ComponentType) Name() string { return c.name } // Fields returns all fields contained in this component. Includes fields -// encapsulated in components of this component +// encapsulated in components of this component. func (c ComponentType) Fields() []*FieldDef { return c.fields } -// RequiredFields returns those fields that are required for this component +// RequiredFields returns those fields that are required for this component. func (c ComponentType) RequiredFields() []*FieldDef { return c.requiredFields } -// RequiredParts returns those parts that are required for this component +// RequiredParts returns those parts that are required for this component. func (c ComponentType) RequiredParts() []MessagePart { return c.requiredParts } -// Parts returns all parts in declaration order contained in this component +// Parts returns all parts in declaration order contained in this component. func (c ComponentType) Parts() []MessagePart { return c.parts } // TagSet is set for tags. @@ -101,13 +101,13 @@ func (t TagSet) Add(tag int) { t[tag] = struct{}{} } -// Component is a Component as it appears in a given MessageDef +// Component is a Component as it appears in a given MessageDef. type Component struct { *ComponentType required bool } -// NewComponent returns an initialized Component instance +// NewComponent returns an initialized Component instance. func NewComponent(ct *ComponentType, required bool) *Component { return &Component{ ComponentType: ct, @@ -116,10 +116,10 @@ func NewComponent(ct *ComponentType, required bool) *Component { } // Required returns true if this component is required for the containing -// MessageDef +// MessageDef. func (c Component) Required() bool { return c.required } -// Field models a field or repeating group in a message +// Field models a field or repeating group in a message. type Field interface { Tag() int } @@ -135,7 +135,7 @@ type FieldDef struct { requiredFields []*FieldDef } -// NewFieldDef returns an initialized FieldDef +// NewFieldDef returns an initialized FieldDef. func NewFieldDef(fieldType *FieldType, required bool) *FieldDef { return &FieldDef{ FieldType: fieldType, @@ -143,7 +143,7 @@ func NewFieldDef(fieldType *FieldType, required bool) *FieldDef { } } -// NewGroupFieldDef returns an initialized FieldDef for a repeating group +// NewGroupFieldDef returns an initialized FieldDef for a repeating group. func NewGroupFieldDef(fieldType *FieldType, required bool, parts []MessagePart) *FieldDef { field := FieldDef{ FieldType: fieldType, @@ -179,7 +179,7 @@ func NewGroupFieldDef(fieldType *FieldType, required bool, parts []MessagePart) } // Required returns true if this FieldDef is required for the containing -// MessageDef +// MessageDef. func (f FieldDef) Required() bool { return f.required } // IsGroup is true if the field is a repeating group. @@ -188,11 +188,11 @@ func (f FieldDef) IsGroup() bool { } // RequiredParts returns those parts that are required for this FieldDef. IsGroup -// must return true +// must return true. func (f FieldDef) RequiredParts() []MessagePart { return f.requiredParts } // RequiredFields returns those fields that are required for this FieldDef. IsGroup -// must return true +// must return true. func (f FieldDef) RequiredFields() []*FieldDef { return f.requiredFields } func (f FieldDef) childTags() []int { @@ -214,7 +214,7 @@ type FieldType struct { Enums map[string]Enum } -// NewFieldType returns a pointer to an initialized FieldType +// NewFieldType returns a pointer to an initialized FieldType. func NewFieldType(name string, tag int, fixType string) *FieldType { return &FieldType{ name: name, @@ -223,10 +223,10 @@ func NewFieldType(name string, tag int, fixType string) *FieldType { } } -// Name returns the name for this FieldType +// Name returns the name for this FieldType. func (f FieldType) Name() string { return f.name } -// Tag returns the tag for this fieldType +// Tag returns the tag for this fieldType. func (f FieldType) Tag() int { return f.tag } // Enum is a container for value and description. @@ -240,8 +240,7 @@ type MessageDef struct { Name string MsgType string Fields map[int]*FieldDef - //Parts are the MessageParts of contained in this MessageDef in declaration - //order + // Parts are the MessageParts of contained in this MessageDef in declaration order. Parts []MessagePart requiredParts []MessagePart @@ -249,10 +248,10 @@ type MessageDef struct { Tags TagSet } -// RequiredParts returns those parts that are required for this Message +// RequiredParts returns those parts that are required for this Message. func (m MessageDef) RequiredParts() []MessagePart { return m.requiredParts } -// NewMessageDef returns a pointer to an initialized MessageDef +// NewMessageDef returns a pointer to an initialized MessageDef. func NewMessageDef(name, msgType string, parts []MessagePart) *MessageDef { msg := MessageDef{ Name: name, @@ -283,8 +282,8 @@ func NewMessageDef(name, msgType string, parts []MessagePart) *MessageDef { switch pType := part.(type) { case messagePartWithFields: for _, f := range pType.Fields() { - //field if required in component is required in message only if - //component is required + // Field if required in component is required in message only if + // component is required. processField(f, pType.Required()) } diff --git a/datadictionary/xml.go b/datadictionary/xml.go index 759a082f4..a25e5b4e0 100644 --- a/datadictionary/xml.go +++ b/datadictionary/xml.go @@ -41,7 +41,7 @@ type XMLValue struct { Description string `xml:"description,attr"` } -// XMLComponentMember represents child elements of header, trailer, messages/message, and components/component elements +// XMLComponentMember represents child elements of header, trailer, messages/message, and components/component elements. type XMLComponentMember struct { XMLName xml.Name Name string `xml:"name,attr"` diff --git a/dialer.go b/dialer.go index 1eb28ad04..d1654aa31 100644 --- a/dialer.go +++ b/dialer.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/dialer_test.go b/dialer_test.go index 47bf79d08..5f8599c1e 100644 --- a/dialer_test.go +++ b/dialer_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/doc.go b/doc.go index 76f7b7b71..3d53535c3 100644 --- a/doc.go +++ b/doc.go @@ -1,6 +1,19 @@ -/* -Package quickfix is a full featured messaging engine for the FIX protocol. It is a 100% Go open source implementation of the popular C++ QuickFIX engine (http://quickfixengine.org). +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. -User manual and additional information available at http://quickfixgo.org -*/ +// Package quickfix is a full featured messaging engine for the FIX protocol. It is a 100% Go open source implementation of the popular C++ QuickFIX engine (http://quickfixengine.org). +// +// User manual and additional information available at https://quickfixgo.org package quickfix diff --git a/errors.go b/errors.go index f69e9c287..e9d120991 100644 --- a/errors.go +++ b/errors.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -5,7 +20,7 @@ import ( "fmt" ) -// ErrDoNotSend is a convenience error to indicate a DoNotSend in ToApp +// ErrDoNotSend is a convenience error to indicate a DoNotSend in ToApp. var ErrDoNotSend = errors.New("Do Not Send") // rejectReason enum values. @@ -31,30 +46,30 @@ const ( type MessageRejectError interface { error - //RejectReason, tag 373 for session rejects, tag 380 for business rejects. + // RejectReason, tag 373 for session rejects, tag 380 for business rejects. RejectReason() int BusinessRejectRefID() string RefTagID() *Tag IsBusinessReject() bool } -// RejectLogon indicates the application is rejecting permission to logon. Implements MessageRejectError +// RejectLogon indicates the application is rejecting permission to logon. Implements MessageRejectError. type RejectLogon struct { Text string } func (e RejectLogon) Error() string { return e.Text } -// RefTagID implements MessageRejectError +// RefTagID implements MessageRejectError. func (RejectLogon) RefTagID() *Tag { return nil } -// RejectReason implements MessageRejectError +// RejectReason implements MessageRejectError. func (RejectLogon) RejectReason() int { return 0 } -// BusinessRejectRefID implements MessageRejectError +// BusinessRejectRefID implements MessageRejectError. func (RejectLogon) BusinessRejectRefID() string { return "" } -// IsBusinessReject implements MessageRejectError +// IsBusinessReject implements MessageRejectError. func (RejectLogon) IsBusinessReject() bool { return false } type messageRejectError struct { @@ -71,19 +86,19 @@ func (e messageRejectError) RejectReason() int { return e.rejectReason func (e messageRejectError) BusinessRejectRefID() string { return e.businessRejectRefID } func (e messageRejectError) IsBusinessReject() bool { return e.isBusinessReject } -// NewMessageRejectError returns a MessageRejectError with the given error message, reject reason, and optional reftagid +// NewMessageRejectError returns a MessageRejectError with the given error message, reject reason, and optional reftagid. func NewMessageRejectError(err string, rejectReason int, refTagID *Tag) MessageRejectError { return messageRejectError{text: err, rejectReason: rejectReason, refTagID: refTagID} } // NewBusinessMessageRejectError returns a MessageRejectError with the given error mesage, reject reason, and optional reftagid. -// Reject is treated as a business level reject +// Reject is treated as a business level reject. func NewBusinessMessageRejectError(err string, rejectReason int, refTagID *Tag) MessageRejectError { return messageRejectError{text: err, rejectReason: rejectReason, refTagID: refTagID, isBusinessReject: true} } // NewBusinessMessageRejectErrorWithRefID returns a MessageRejectError with the given error mesage, reject reason, refID, and optional reftagid. -// Reject is treated as a business level reject +// Reject is treated as a business level reject. func NewBusinessMessageRejectErrorWithRefID(err string, rejectReason int, businessRejectRefID string, refTagID *Tag) MessageRejectError { return messageRejectError{text: err, rejectReason: rejectReason, refTagID: refTagID, businessRejectRefID: businessRejectRefID, isBusinessReject: true} } @@ -93,7 +108,7 @@ func IncorrectDataFormatForValue(tag Tag) MessageRejectError { return NewMessageRejectError("Incorrect data format for value", rejectReasonIncorrectDataFormatForValue, &tag) } -// repeatingGroupFieldsOutOfOrder returns an error indicating a problem parsing repeating groups fields +// repeatingGroupFieldsOutOfOrder returns an error indicating a problem parsing repeating groups fields. func repeatingGroupFieldsOutOfOrder(tag Tag, reason string) MessageRejectError { if reason != "" { reason = fmt.Sprintf("Repeating group fields out of order (%s)", reason) @@ -114,12 +129,12 @@ func ConditionallyRequiredFieldMissing(tag Tag) MessageRejectError { } // valueIsIncorrectNoTag returns an error indicating a field with value that is not valid. -// FIXME: to be compliant with legacy tests, for certain value issues, do not include reftag? (11c_NewSeqNoLess) +// FIXME: to be compliant with legacy tests, for certain value issues, do not include reftag? (11c_NewSeqNoLess). func valueIsIncorrectNoTag() MessageRejectError { return NewMessageRejectError("Value is incorrect (out of range) for this tag", rejectReasonValueIsIncorrect, nil) } -// InvalidMessageType returns an error to indicate an invalid message type +// InvalidMessageType returns an error to indicate an invalid message type. func InvalidMessageType() MessageRejectError { return NewMessageRejectError("Invalid MsgType", rejectReasonInvalidMsgType, nil) } diff --git a/errors_test.go b/errors_test.go index e612d3242..c5b77d9b6 100644 --- a/errors_test.go +++ b/errors_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/field.go b/field.go index 81a277cad..9dc00dac7 100644 --- a/field.go +++ b/field.go @@ -1,49 +1,64 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix -// FieldValueWriter is an interface for writing field values +// FieldValueWriter is an interface for writing field values. type FieldValueWriter interface { - //Write writes out the contents of the FieldValue to a []byte + // Write writes out the contents of the FieldValue to a `[]byte`. Write() []byte } -// FieldValueReader is an interface for reading field values +// FieldValueReader is an interface for reading field values. type FieldValueReader interface { - //Read reads the contents of the []byte into FieldValue. - //Returns an error if there are issues in the data processing + // Read reads the contents of the `[]byte` into FieldValue. + // Returns an error if there are issues in the data processing. Read([]byte) error } -// The FieldValue interface is used to write/extract typed field values to/from raw bytes +// The FieldValue interface is used to write/extract typed field values to/from raw bytes. type FieldValue interface { FieldValueWriter FieldValueReader } -// FieldWriter is an interface for a writing a field +// FieldWriter is an interface for a writing a field. type FieldWriter interface { Tag() Tag FieldValueWriter } -// Field is the interface implemented by all typed Fields in a Message +// Field is the interface implemented by all typed Fields in a Message. type Field interface { FieldWriter FieldValueReader } -// FieldGroupWriter is an interface for writing a FieldGroup +// FieldGroupWriter is an interface for writing a FieldGroup. type FieldGroupWriter interface { Tag() Tag Write() []TagValue } -// FieldGroupReader is an interface for reading a FieldGroup +// FieldGroupReader is an interface for reading a FieldGroup. type FieldGroupReader interface { Tag() Tag Read([]TagValue) ([]TagValue, error) } -// FieldGroup is the interface implemented by all typed Groups in a Message +// FieldGroup is the interface implemented by all typed Groups in a Message. type FieldGroup interface { Tag() Tag Write() []TagValue diff --git a/field_map.go b/field_map.go index 5d5f94269..e940790f5 100644 --- a/field_map.go +++ b/field_map.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -7,7 +22,7 @@ import ( "time" ) -// field stores a slice of TagValues +// field stores a slice of TagValues. type field []TagValue func fieldTag(f field) Tag { @@ -24,7 +39,7 @@ func writeField(f field, buffer *bytes.Buffer) { } } -// tagOrder true if tag i should occur before tag j +// tagOrder true if tag i should occur before tag j. type tagOrder func(i, j Tag) bool type tagSort struct { @@ -43,7 +58,7 @@ type FieldMap struct { rwLock *sync.RWMutex } -// ascending tags +// ascending tags. func normalFieldOrder(i, j Tag) bool { return i < j } func (m *FieldMap) init() { @@ -56,7 +71,7 @@ func (m *FieldMap) initWithOrdering(ordering tagOrder) { m.compare = ordering } -// Tags returns all of the Field Tags in this FieldMap +// Tags returns all of the Field Tags in this FieldMap. func (m FieldMap) Tags() []Tag { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -74,7 +89,7 @@ func (m FieldMap) Get(parser Field) MessageRejectError { return m.GetField(parser.Tag(), parser) } -// Has returns true if the Tag is present in this FieldMap +// Has returns true if the Tag is present in this FieldMap. func (m FieldMap) Has(tag Tag) bool { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -100,7 +115,7 @@ func (m FieldMap) GetField(tag Tag, parser FieldValueReader) MessageRejectError return nil } -// GetBytes is a zero-copy GetField wrapper for []bytes fields +// GetBytes is a zero-copy GetField wrapper for []bytes fields. func (m FieldMap) GetBytes(tag Tag) ([]byte, MessageRejectError) { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -113,7 +128,7 @@ func (m FieldMap) GetBytes(tag Tag) ([]byte, MessageRejectError) { return f[0].value, nil } -// GetBool is a GetField wrapper for bool fields +// GetBool is a GetField wrapper for bool fields. func (m FieldMap) GetBool(tag Tag) (bool, MessageRejectError) { var val FIXBoolean if err := m.GetField(tag, &val); err != nil { @@ -122,7 +137,7 @@ func (m FieldMap) GetBool(tag Tag) (bool, MessageRejectError) { return bool(val), nil } -// GetInt is a GetField wrapper for int fields +// GetInt is a GetField wrapper for int fields. func (m FieldMap) GetInt(tag Tag) (int, MessageRejectError) { bytes, err := m.GetBytes(tag) if err != nil { @@ -137,7 +152,7 @@ func (m FieldMap) GetInt(tag Tag) (int, MessageRejectError) { return int(val), err } -// GetTime is a GetField wrapper for utc timestamp fields +// GetTime is a GetField wrapper for utc timestamp fields. func (m FieldMap) GetTime(tag Tag) (t time.Time, err MessageRejectError) { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -155,7 +170,7 @@ func (m FieldMap) GetTime(tag Tag) (t time.Time, err MessageRejectError) { return val.Time, err } -// GetString is a GetField wrapper for string fields +// GetString is a GetField wrapper for string fields. func (m FieldMap) GetString(tag Tag) (string, MessageRejectError) { var val FIXString if err := m.GetField(tag, &val); err != nil { @@ -184,35 +199,35 @@ func (m FieldMap) GetGroup(parser FieldGroupReader) MessageRejectError { return nil } -// SetField sets the field with Tag tag +// SetField sets the field with Tag tag. func (m *FieldMap) SetField(tag Tag, field FieldValueWriter) *FieldMap { return m.SetBytes(tag, field.Write()) } -// SetBytes sets bytes +// SetBytes sets bytes. func (m *FieldMap) SetBytes(tag Tag, value []byte) *FieldMap { f := m.getOrCreate(tag) initField(f, tag, value) return m } -// SetBool is a SetField wrapper for bool fields +// SetBool is a SetField wrapper for bool fields. func (m *FieldMap) SetBool(tag Tag, value bool) *FieldMap { return m.SetField(tag, FIXBoolean(value)) } -// SetInt is a SetField wrapper for int fields +// SetInt is a SetField wrapper for int fields. func (m *FieldMap) SetInt(tag Tag, value int) *FieldMap { v := FIXInt(value) return m.SetBytes(tag, v.Write()) } -// SetString is a SetField wrapper for string fields +// SetString is a SetField wrapper for string fields. func (m *FieldMap) SetString(tag Tag, value string) *FieldMap { return m.SetBytes(tag, []byte(value)) } -// Clear purges all fields from field map +// Clear purges all fields from field map. func (m *FieldMap) Clear() { m.rwLock.Lock() defer m.rwLock.Unlock() @@ -223,7 +238,7 @@ func (m *FieldMap) Clear() { } } -// CopyInto overwrites the given FieldMap with this one +// CopyInto overwrites the given FieldMap with this one. func (m *FieldMap) CopyInto(to *FieldMap) { m.rwLock.RLock() defer m.rwLock.RUnlock() @@ -266,14 +281,14 @@ func (m *FieldMap) getOrCreate(tag Tag) field { return f } -// Set is a setter for fields +// Set is a setter for fields. func (m *FieldMap) Set(field FieldWriter) *FieldMap { f := m.getOrCreate(field.Tag()) initField(f, field.Tag(), field.Write()) return m } -// SetGroup is a setter specific to group fields +// SetGroup is a setter specific to group fields. func (m *FieldMap) SetGroup(field FieldGroupWriter) *FieldMap { m.rwLock.Lock() defer m.rwLock.Unlock() @@ -310,7 +325,7 @@ func (m FieldMap) total() int { for _, fields := range m.tagLookup { for _, tv := range fields { switch tv.tag { - case tagCheckSum: //tag does not contribute to total + case tagCheckSum: // Tag does not contribute to total. default: total += tv.total() } @@ -328,7 +343,7 @@ func (m FieldMap) length() int { for _, fields := range m.tagLookup { for _, tv := range fields { switch tv.tag { - case tagBeginString, tagBodyLength, tagCheckSum: //tags do not contribute to length + case tagBeginString, tagBodyLength, tagCheckSum: // Tags do not contribute to length. default: length += tv.length() } diff --git a/field_map_test.go b/field_map_test.go index f07f6f396..5d7da7041 100644 --- a/field_map_test.go +++ b/field_map_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/file_log.go b/file_log.go index 52146f07e..85eefab1d 100644 --- a/file_log.go +++ b/file_log.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/file_log_test.go b/file_log_test.go index 3358dc20a..b303ec290 100644 --- a/file_log_test.go +++ b/file_log_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/filestore.go b/filestore.go index 3b93db6e2..2a548cadb 100644 --- a/filestore.go +++ b/filestore.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -39,12 +54,12 @@ type fileStore struct { targetSeqNumsFile *os.File } -// NewFileStoreFactory returns a file-based implementation of MessageStoreFactory +// NewFileStoreFactory returns a file-based implementation of MessageStoreFactory. func NewFileStoreFactory(settings *Settings) MessageStoreFactory { return fileStoreFactory{settings: settings} } -// Create creates a new FileStore implementation of the MessageStore interface +// Create creates a new FileStore implementation of the MessageStore interface. func (f fileStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err error) { sessionSettings, ok := f.settings.SessionSettings()[sessionID] if !ok { @@ -82,7 +97,7 @@ func newFileStore(sessionID SessionID, dirname string) (*fileStore, error) { return store, nil } -// Reset deletes the store files and sets the seqnums back to 1 +// Reset deletes the store files and sets the seqnums back to 1. func (store *fileStore) Reset() error { if err := store.cache.Reset(); err != nil { return errors.Wrap(err, "cache reset") @@ -109,7 +124,7 @@ func (store *fileStore) Reset() error { return store.Refresh() } -// Refresh closes the store files and then reloads from them +// Refresh closes the store files and then reloads from them. func (store *fileStore) Refresh() (err error) { if err = store.cache.Reset(); err != nil { err = errors.Wrap(err, "cache reset") @@ -228,17 +243,17 @@ func (store *fileStore) setSeqNum(f *os.File, seqNum int) error { return nil } -// NextSenderMsgSeqNum returns the next MsgSeqNum that will be sent +// NextSenderMsgSeqNum returns the next MsgSeqNum that will be sent. func (store *fileStore) NextSenderMsgSeqNum() int { return store.cache.NextSenderMsgSeqNum() } -// NextTargetMsgSeqNum returns the next MsgSeqNum that should be received +// NextTargetMsgSeqNum returns the next MsgSeqNum that should be received. func (store *fileStore) NextTargetMsgSeqNum() int { return store.cache.NextTargetMsgSeqNum() } -// SetNextSenderMsgSeqNum sets the next MsgSeqNum that will be sent +// SetNextSenderMsgSeqNum sets the next MsgSeqNum that will be sent. func (store *fileStore) SetNextSenderMsgSeqNum(next int) error { if err := store.cache.SetNextSenderMsgSeqNum(next); err != nil { return errors.Wrap(err, "cache") @@ -246,7 +261,7 @@ func (store *fileStore) SetNextSenderMsgSeqNum(next int) error { return store.setSeqNum(store.senderSeqNumsFile, next) } -// SetNextTargetMsgSeqNum sets the next MsgSeqNum that should be received +// SetNextTargetMsgSeqNum sets the next MsgSeqNum that should be received. func (store *fileStore) SetNextTargetMsgSeqNum(next int) error { if err := store.cache.SetNextTargetMsgSeqNum(next); err != nil { return errors.Wrap(err, "cache") @@ -254,7 +269,7 @@ func (store *fileStore) SetNextTargetMsgSeqNum(next int) error { return store.setSeqNum(store.targetSeqNumsFile, next) } -// IncrNextSenderMsgSeqNum increments the next MsgSeqNum that will be sent +// IncrNextSenderMsgSeqNum increments the next MsgSeqNum that will be sent. func (store *fileStore) IncrNextSenderMsgSeqNum() error { if err := store.cache.IncrNextSenderMsgSeqNum(); err != nil { return errors.Wrap(err, "cache") @@ -262,7 +277,7 @@ func (store *fileStore) IncrNextSenderMsgSeqNum() error { return store.setSeqNum(store.senderSeqNumsFile, store.cache.NextSenderMsgSeqNum()) } -// IncrNextTargetMsgSeqNum increments the next MsgSeqNum that should be received +// IncrNextTargetMsgSeqNum increments the next MsgSeqNum that should be received. func (store *fileStore) IncrNextTargetMsgSeqNum() error { if err := store.cache.IncrNextTargetMsgSeqNum(); err != nil { return errors.Wrap(err, "cache") @@ -270,7 +285,7 @@ func (store *fileStore) IncrNextTargetMsgSeqNum() error { return store.setSeqNum(store.targetSeqNumsFile, store.cache.NextTargetMsgSeqNum()) } -// CreationTime returns the creation time of the store +// CreationTime returns the creation time of the store. func (store *fileStore) CreationTime() time.Time { return store.cache.CreationTime() } @@ -337,7 +352,7 @@ func (store *fileStore) GetMessages(beginSeqNum, endSeqNum int) ([][]byte, error return msgs, nil } -// Close closes the store's files +// Close closes the store's files. func (store *fileStore) Close() error { if err := closeFile(store.bodyFile); err != nil { return err diff --git a/filestore_test.go b/filestore_test.go index 56fc8ec68..3713ac8a9 100644 --- a/filestore_test.go +++ b/filestore_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -12,7 +27,7 @@ import ( "github.com/stretchr/testify/suite" ) -// FileStoreTestSuite runs all tests in the MessageStoreTestSuite against the FileStore implementation +// FileStoreTestSuite runs all tests in the MessageStoreTestSuite against the FileStore implementation. type FileStoreTestSuite struct { MessageStoreTestSuite fileStoreRootPath string diff --git a/fileutil.go b/fileutil.go index 5334f271c..0698a3a97 100644 --- a/fileutil.go +++ b/fileutil.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -32,7 +47,7 @@ func sessionIDFilenamePrefix(s SessionID) string { return strings.Join(fname, "-") } -// closeFile behaves like Close, except that no error is returned if the file does not exist +// closeFile behaves like Close, except that no error is returned if the file does not exist. func closeFile(f *os.File) error { if f != nil { if err := f.Close(); err != nil { @@ -44,7 +59,7 @@ func closeFile(f *os.File) error { return nil } -// removeFile behaves like os.Remove, except that no error is returned if the file does not exist +// removeFile behaves like os.Remove, except that no error is returned if the file does not exist. func removeFile(fname string) error { if err := os.Remove(fname); (err != nil) && !os.IsNotExist(err) { return errors.Wrapf(err, "remove %v", fname) @@ -52,7 +67,7 @@ func removeFile(fname string) error { return nil } -// openOrCreateFile opens a file for reading and writing, creating it if necessary +// openOrCreateFile opens a file for reading and writing, creating it if necessary. func openOrCreateFile(fname string, perm os.FileMode) (f *os.File, err error) { if f, err = os.OpenFile(fname, os.O_RDWR, perm); err != nil { if f, err = os.OpenFile(fname, os.O_RDWR|os.O_CREATE, perm); err != nil { diff --git a/fileutil_test.go b/fileutil_test.go index f634651df..0f9095364 100644 --- a/fileutil_test.go +++ b/fileutil_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/fix_boolean.go b/fix_boolean.go index 2d9bc57fb..73e4fc168 100644 --- a/fix_boolean.go +++ b/fix_boolean.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -7,7 +22,7 @@ import ( // FIXBoolean is a FIX Boolean value, implements FieldValue. type FIXBoolean bool -// Bool converts the FIXBoolean value to bool +// Bool converts the FIXBoolean value to bool. func (f FIXBoolean) Bool() bool { return bool(f) } func (f *FIXBoolean) Read(bytes []byte) error { diff --git a/fix_boolean_test.go b/fix_boolean_test.go index 150d8c0d6..c02747834 100644 --- a/fix_boolean_test.go +++ b/fix_boolean_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/fix_bytes.go b/fix_bytes.go index 8fb14d1a9..b998843c3 100644 --- a/fix_bytes.go +++ b/fix_bytes.go @@ -1,6 +1,21 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix -// FIXBytes is a generic FIX field value, implements FieldValue. Enables zero copy read from a FieldMap +// FIXBytes is a generic FIX field value, implements FieldValue. Enables zero copy read from a FieldMap. type FIXBytes []byte func (f *FIXBytes) Read(bytes []byte) (err error) { diff --git a/fix_bytes_test.go b/fix_bytes_test.go index 4dc94b56b..0855bdd16 100644 --- a/fix_bytes_test.go +++ b/fix_bytes_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/fix_decimal.go b/fix_decimal.go index 143e69d7a..a435c79fc 100644 --- a/fix_decimal.go +++ b/fix_decimal.go @@ -1,12 +1,27 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import "github.com/shopspring/decimal" -// FIXDecimal is a FIX Float Value that implements an arbitrary precision fixed-point decimal. Implements FieldValue +// FIXDecimal is a FIX Float Value that implements an arbitrary precision fixed-point decimal. Implements FieldValue. type FIXDecimal struct { decimal.Decimal - //Scale is the number of digits after the decimal point when Writing the field value as a FIX value + // Scale is the number of digits after the decimal point when Writing the field value as a FIX value. Scale int32 } diff --git a/fix_decimal_test.go b/fix_decimal_test.go index 1785d6e67..f6fc3d53c 100644 --- a/fix_decimal_test.go +++ b/fix_decimal_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/fix_float.go b/fix_float.go index 28cafa576..1d4b310c2 100644 --- a/fix_float.go +++ b/fix_float.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -5,10 +20,10 @@ import ( "strconv" ) -// FIXFloat is a FIX Float Value, implements FieldValue +// FIXFloat is a FIX Float Value, implements FieldValue. type FIXFloat float64 -// Float64 converts the FIXFloat value to float64 +// Float64 converts the FIXFloat value to float64. func (f FIXFloat) Float64() float64 { return float64(f) } func (f *FIXFloat) Read(bytes []byte) error { @@ -17,7 +32,7 @@ func (f *FIXFloat) Read(bytes []byte) error { return err } - //strconv allows values like "+100.00", which is not allowed for FIX float types + // `strconv` allows values like "+100.00", which is not allowed for FIX float types. for _, b := range bytes { if b != '.' && b != '-' && !isDecimal(b) { return fmt.Errorf("invalid value %v", string(bytes)) diff --git a/fix_float_test.go b/fix_float_test.go index b31bdbb60..6b75eaf11 100644 --- a/fix_float_test.go +++ b/fix_float_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/fix_int.go b/fix_int.go index 645884b95..6bd968003 100644 --- a/fix_int.go +++ b/fix_int.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -6,10 +21,10 @@ import ( ) const ( - //- + // ASCII - char. asciiMinus = 45 - //ascii numbers 0-9 + // ASCII numbers 0-9. ascii0 = 48 ascii9 = 57 ) @@ -43,10 +58,10 @@ func parseUInt(d []byte) (n int, err error) { return } -// FIXInt is a FIX Int Value, implements FieldValue +// FIXInt is a FIX Int Value, implements FieldValue. type FIXInt int -// Int converts the FIXInt value to int +// Int converts the FIXInt value to int. func (f FIXInt) Int() int { return int(f) } func (f *FIXInt) Read(bytes []byte) error { diff --git a/fix_int_test.go b/fix_int_test.go index 64142c045..caa9b7840 100644 --- a/fix_int_test.go +++ b/fix_int_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/fix_string.go b/fix_string.go index 39c2119a1..b4fe18a3d 100644 --- a/fix_string.go +++ b/fix_string.go @@ -1,6 +1,21 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix -// FIXString is a FIX String Value, implements FieldValue +// FIXString is a FIX String Value, implements FieldValue. type FIXString string func (f FIXString) String() string { diff --git a/fix_string_test.go b/fix_string_test.go index f2672f39e..c17a69d3c 100644 --- a/fix_string_test.go +++ b/fix_string_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/fix_utc_timestamp.go b/fix_utc_timestamp.go index c6b685ca3..ebd40cb06 100644 --- a/fix_utc_timestamp.go +++ b/fix_utc_timestamp.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -5,10 +20,10 @@ import ( "time" ) -// TimestampPrecision defines the precision used by FIXUTCTimestamp +// TimestampPrecision defines the precision used by FIXUTCTimestamp. type TimestampPrecision int -// All TimestampPrecisions supported by FIX +// All TimestampPrecisions supported by FIX. const ( Millis TimestampPrecision = iota Seconds @@ -16,7 +31,7 @@ const ( Nanos ) -// FIXUTCTimestamp is a FIX UTC Timestamp value, implements FieldValue +// FIXUTCTimestamp is a FIX UTC Timestamp value, implements FieldValue. type FIXUTCTimestamp struct { time.Time Precision TimestampPrecision @@ -31,12 +46,12 @@ const ( func (f *FIXUTCTimestamp) Read(bytes []byte) (err error) { switch len(bytes) { - //seconds + // Seconds. case 17: f.Time, err = time.Parse(utcTimestampSecondsFormat, string(bytes)) f.Precision = Seconds - //millis + // Millis. case 21: f.Time, err = time.Parse(utcTimestampMillisFormat, string(bytes)) f.Precision = Millis diff --git a/fix_utc_timestamp_test.go b/fix_utc_timestamp_test.go index b29039587..da2d0ecb9 100644 --- a/fix_utc_timestamp_test.go +++ b/fix_utc_timestamp_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix_test import ( diff --git a/in_session.go b/in_session.go index 3ca45d7bd..663e115a5 100644 --- a/in_session.go +++ b/in_session.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -145,7 +160,7 @@ func (state inSession) handleSequenceReset(session *session, msg *Message) (next return handleStateError(session, err) } case newSeqNo < expectedSeqNum: - //FIXME: to be compliant with legacy tests, do not include tag in reftagid? (11c_NewSeqNoLess) + // FIXME: to be compliant with legacy tests, do not include tag in reftagid? (11c_NewSeqNoLess). if err := session.doReject(msg, valueIsIncorrectNoTag()); err != nil { return handleStateError(session, err) } @@ -261,7 +276,7 @@ func (state inSession) processReject(session *session, msg *Message, rej Message var nextState resendState switch currentState := session.State.(type) { case resendState: - //assumes target too high reject already sent + // Assumes target too high reject already sent. nextState = currentState default: var err error @@ -275,7 +290,7 @@ func (state inSession) processReject(session *session, msg *Message, rej Message } nextState.messageStash[TypedError.ReceivedTarget] = msg - //do not reclaim stashed message + // Do not reclaim stashed message. msg.keepMessage = true return nextState diff --git a/in_session_test.go b/in_session_test.go index 80e827dec..aa9f87084 100644 --- a/in_session_test.go +++ b/in_session_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -318,7 +333,7 @@ func (s *InSessionTestSuite) TestFIXMsgInResendRequestDoNotSendApp() { s.MockApp.AssertNumberOfCalls(s.T(), "ToApp", 1) s.NextSenderMsgSeqNum(4) - //NOTE: a cheat here, need to reset mock + // NOTE: a cheat here, need to reset mock. s.MockApp = MockApp{} s.MockApp.On("FromAdmin").Return(nil) s.MockApp.On("ToApp").Return(ErrDoNotSend) diff --git a/initiator.go b/initiator.go index 8426c7f26..a3d64afc3 100644 --- a/initiator.go +++ b/initiator.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -29,7 +44,7 @@ func (i *Initiator) Start() (err error) { i.stopChan = make(chan interface{}) for sessionID, settings := range i.sessionSettings { - //TODO: move into session factory + // TODO: move into session factory. var tlsConfig *tls.Config if tlsConfig, err = loadTLSConfig(settings); err != nil { return @@ -54,7 +69,7 @@ func (i *Initiator) Start() (err error) { func (i *Initiator) Stop() { select { case <-i.stopChan: - //closed already + // Closed already. return default: } @@ -92,7 +107,7 @@ func NewInitiator(app Application, storeFactory MessageStoreFactory, appSettings return i, nil } -// waitForInSessionTime returns true if the session is in session, false if the handler should stop +// waitForInSessionTime returns true if the session is in session, false if the handler should stop. func (i *Initiator) waitForInSessionTime(session *session) bool { inSessionTime := make(chan interface{}) go func() { @@ -109,7 +124,7 @@ func (i *Initiator) waitForInSessionTime(session *session) bool { return true } -// waitForReconnectInterval returns true if a reconnect should be re-attempted, false if handler should stop +// waitForReconnectInterval returns true if a reconnect should be re-attempted, false if handler should stop. func (i *Initiator) waitForReconnectInterval(reconnectInterval time.Duration) bool { select { case <-time.After(reconnectInterval): diff --git a/internal/event.go b/internal/event.go index 7e00cc2b8..f737050d8 100644 --- a/internal/event.go +++ b/internal/event.go @@ -1,15 +1,15 @@ package internal -// Event is an abstraction for session events +// Event is an abstraction for session events. type Event int const ( - //PeerTimeout indicates the session peer has become unresponsive + // PeerTimeout indicates the session peer has become unresponsive. PeerTimeout Event = iota - //NeedHeartbeat indicates the session should send a heartbeat + // NeedHeartbeat indicates the session should send a heartbeat. NeedHeartbeat - //LogonTimeout indicates the peer has not sent a logon request + // LogonTimeout indicates the peer has not sent a logon request. LogonTimeout - //LogoutTimeout indicates the peer has not sent a logout request + // LogoutTimeout indicates the peer has not sent a logout request. LogoutTimeout ) diff --git a/internal/session_settings.go b/internal/session_settings.go index b91d89a0d..e003f54e4 100644 --- a/internal/session_settings.go +++ b/internal/session_settings.go @@ -2,7 +2,7 @@ package internal import "time" -// SessionSettings stores all of the configuration for a given session +// SessionSettings stores all of the configuration for a given session. type SessionSettings struct { ResetOnLogon bool RefreshOnLogon bool @@ -18,10 +18,10 @@ type SessionSettings struct { MaxLatency time.Duration DisableMessagePersist bool - //required on logon for FIX.T.1 messages + // Required on logon for FIX.T.1 messages. DefaultApplVerID string - //specific to initiators + // Specific to initiators. ReconnectInterval time.Duration LogoutTimeout time.Duration LogonTimeout time.Duration diff --git a/internal/time_range.go b/internal/time_range.go index 4b7f9d7c7..7c2ef10f6 100644 --- a/internal/time_range.go +++ b/internal/time_range.go @@ -6,7 +6,7 @@ import ( "github.com/pkg/errors" ) -// TimeOfDay represents the time of day +// TimeOfDay represents the time of day. type TimeOfDay struct { hour, minute, second int d time.Duration @@ -14,7 +14,7 @@ type TimeOfDay struct { const shortForm = "15:04:05" -// NewTimeOfDay returns a newly initialized TimeOfDay +// NewTimeOfDay returns a newly initialized TimeOfDay. func NewTimeOfDay(hour, minute, second int) TimeOfDay { d := time.Duration(second)*time.Second + time.Duration(minute)*time.Minute + @@ -23,7 +23,7 @@ func NewTimeOfDay(hour, minute, second int) TimeOfDay { return TimeOfDay{hour: hour, minute: minute, second: second, d: d} } -// ParseTimeOfDay parses a TimeOfDay from a string in the format HH:MM:SS +// ParseTimeOfDay parses a TimeOfDay from a string in the format HH:MM:SS. func ParseTimeOfDay(str string) (TimeOfDay, error) { t, err := time.Parse(shortForm, str) if err != nil { @@ -33,19 +33,19 @@ func ParseTimeOfDay(str string) (TimeOfDay, error) { return NewTimeOfDay(t.Clock()), nil } -// TimeRange represents a time band in a given time zone +// TimeRange represents a time band in a given time zone. type TimeRange struct { startTime, endTime TimeOfDay startDay, endDay *time.Weekday loc *time.Location } -// NewUTCTimeRange returns a time range in UTC +// NewUTCTimeRange returns a time range in UTC. func NewUTCTimeRange(start, end TimeOfDay) *TimeRange { return NewTimeRangeInLocation(start, end, time.UTC) } -// NewTimeRangeInLocation returns a time range in a given location +// NewTimeRangeInLocation returns a time range in a given location. func NewTimeRangeInLocation(start, end TimeOfDay, loc *time.Location) *TimeRange { if loc == nil { panic("time: missing Location in call to NewTimeRangeInLocation") @@ -54,12 +54,12 @@ func NewTimeRangeInLocation(start, end TimeOfDay, loc *time.Location) *TimeRange return &TimeRange{startTime: start, endTime: end, loc: loc} } -// NewUTCWeekRange returns a weekly TimeRange +// NewUTCWeekRange returns a weekly TimeRange. func NewUTCWeekRange(startTime, endTime TimeOfDay, startDay, endDay time.Weekday) *TimeRange { return NewWeekRangeInLocation(startTime, endTime, startDay, endDay, time.UTC) } -// NewWeekRangeInLocation returns a time range in a given location +// NewWeekRangeInLocation returns a time range in a given location. func NewWeekRangeInLocation(startTime, endTime TimeOfDay, startDay, endDay time.Weekday, loc *time.Location) *TimeRange { r := NewTimeRangeInLocation(startTime, endTime, loc) r.startDay = &startDay @@ -120,7 +120,7 @@ func (r *TimeRange) isInWeekRange(t time.Time) bool { return true } -// IsInRange returns true if time t is within in the time range +// IsInRange returns true if time t is within in the time range. func (r *TimeRange) IsInRange(t time.Time) bool { if r == nil { return true @@ -133,7 +133,7 @@ func (r *TimeRange) IsInRange(t time.Time) bool { return r.isInTimeRange(t) } -// IsInSameRange determines if two points in time are in the same time range +// IsInSameRange determines if two points in time are in the same time range. func (r *TimeRange) IsInSameRange(t1, t2 time.Time) bool { if r == nil { return true diff --git a/latent_state.go b/latent_state.go index e6e5bece4..133509c7b 100644 --- a/latent_state.go +++ b/latent_state.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import "github.com/quickfixgo/quickfix/internal" diff --git a/latent_state_test.go b/latent_state_test.go index db6e925b6..e3379a4e8 100644 --- a/latent_state_test.go +++ b/latent_state_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/log.go b/log.go index d346a5d7a..dbf6726fc 100644 --- a/log.go +++ b/log.go @@ -1,25 +1,40 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix // Log is a generic interface for logging FIX messages and events. type Log interface { - //OnIncoming log incoming fix message + // OnIncoming log incoming fix message. OnIncoming([]byte) - //OnOutgoing log outgoing fix message + // OnOutgoing log outgoing fix message. OnOutgoing([]byte) - //OnEvent log fix event + // OnEvent log fix event. OnEvent(string) - //OnEventf log fix event according to format specifier + // OnEventf log fix event according to format specifier. OnEventf(string, ...interface{}) } -// The LogFactory interface creates global and session specific Log instances +// The LogFactory interface creates global and session specific Log instances. type LogFactory interface { - //Create global log + // Create global log. Create() (Log, error) - //CreateSessionLog session specific log + // CreateSessionLog session specific log. CreateSessionLog(sessionID SessionID) (Log, error) } diff --git a/logon_state.go b/logon_state.go index d254b92b3..05c970838 100644 --- a/logon_state.go +++ b/logon_state.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/logon_state_test.go b/logon_state_test.go index cea45618b..96afc2e90 100644 --- a/logon_state_test.go +++ b/logon_state_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -83,7 +98,7 @@ func (s *LogonStateTestSuite) TestFixMsgInLogon() { s.MockApp.AssertExpectations(s.T()) s.State(inSession{}) - s.Equal(32*time.Second, s.session.HeartBtInt) //should be written from logon message + s.Equal(32*time.Second, s.session.HeartBtInt) // Should be written from logon message. s.False(s.session.HeartBtIntOverride) s.LastToAdminMessageSent() @@ -112,7 +127,7 @@ func (s *LogonStateTestSuite) TestFixMsgInLogonHeartBtIntOverride() { s.MockApp.AssertExpectations(s.T()) s.State(inSession{}) - s.Equal(time.Second, s.session.HeartBtInt) //should not have changed + s.Equal(time.Second, s.session.HeartBtInt) // Should not have changed. s.True(s.session.HeartBtIntOverride) s.LastToAdminMessageSent() @@ -309,7 +324,7 @@ func (s *LogonStateTestSuite) TestFixMsgInLogonSeqNumTooHigh() { s.State(resendState{}) s.NextTargetMsgSeqNum(1) - //session should send logon, and then queues resend request for send + // Session should send logon, and then queues resend request for send. s.MockApp.AssertNumberOfCalls(s.T(), "ToAdmin", 2) msgBytesSent, ok := s.Receiver.LastMessage() s.Require().True(ok) diff --git a/logout_state.go b/logout_state.go index 071512ce1..cee8e9bd8 100644 --- a/logout_state.go +++ b/logout_state.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import "github.com/quickfixgo/quickfix/internal" diff --git a/logout_state_test.go b/logout_state_test.go index 5b074f329..f414bc85f 100644 --- a/logout_state_test.go +++ b/logout_state_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/message.go b/message.go index 0a637346b..74294f07c 100644 --- a/message.go +++ b/message.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -9,10 +24,10 @@ import ( "github.com/quickfixgo/quickfix/datadictionary" ) -// Header is first section of a FIX Message +// Header is first section of a FIX Message. type Header struct{ FieldMap } -// in the message header, the first 3 tags in the message header must be 8,9,35 +// in the message header, the first 3 tags in the message header must be 8,9,35. func headerFieldOrdering(i, j Tag) bool { var ordering = func(t Tag) uint32 { switch t { @@ -40,23 +55,23 @@ func headerFieldOrdering(i, j Tag) bool { return i < j } -// Init initializes the Header instance +// Init initializes the Header instance. func (h *Header) Init() { h.initWithOrdering(headerFieldOrdering) } -// Body is the primary application section of a FIX message +// Body is the primary application section of a FIX message. type Body struct{ FieldMap } -// Init initializes the FIX message +// Init initializes the FIX message. func (b *Body) Init() { b.init() } -// Trailer is the last section of a FIX message +// Trailer is the last section of a FIX message. type Trailer struct{ FieldMap } -// In the trailer, CheckSum (tag 10) must be last +// In the trailer, CheckSum (tag 10) must be last. func trailerFieldOrdering(i, j Tag) bool { switch { case i == tagCheckSum: @@ -68,7 +83,7 @@ func trailerFieldOrdering(i, j Tag) bool { return i < j } -// Init initializes the FIX message +// Init initializes the FIX message. func (t *Trailer) Init() { t.initWithOrdering(trailerFieldOrdering) } @@ -79,22 +94,22 @@ type Message struct { Trailer Trailer Body Body - //ReceiveTime is the time that this message was read from the socket connection + // ReceiveTime is the time that this message was read from the socket connection. ReceiveTime time.Time rawMessage *bytes.Buffer - //slice of Bytes corresponding to the message body + // Slice of Bytes corresponding to the message body. bodyBytes []byte - //field bytes as they appear in the raw message + // Field bytes as they appear in the raw message. fields []TagValue - //flag is true if this message should not be returned to pool after use + // Flag is true if this message should not be returned to pool after use. keepMessage bool } -// ToMessage returns the message itself +// ToMessage returns the message itself. func (m *Message) ToMessage() *Message { return m } // parseError is returned when bytes cannot be parsed as a FIX message. @@ -104,7 +119,7 @@ type parseError struct { func (e parseError) Error() string { return fmt.Sprintf("error parsing message: %s", e.OrigError) } -// NewMessage returns a newly initialized Message instance +// NewMessage returns a newly initialized Message instance. func NewMessage() *Message { m := new(Message) m.Header.Init() @@ -149,7 +164,7 @@ func ParseMessageWithDataDictionary( rawBytes := rawMessage.Bytes() - //allocate fields in one chunk + // Allocate fields in one chunk. fieldCount := 0 for _, b := range rawBytes { if b == '\001' { @@ -169,7 +184,7 @@ func ParseMessageWithDataDictionary( fieldIndex := 0 - //message must start with begin string, body length, msg type + // Message must start with begin string, body length, msg type. if rawBytes, err = extractSpecificField(&msg.fields[fieldIndex], tagBeginString, rawBytes); err != nil { return } @@ -223,7 +238,7 @@ func ParseMessageWithDataDictionary( fieldIndex++ } - //body length would only be larger than trailer if fields out of order + // Body length would only be larger than trailer if fields out of order. if len(msg.bodyBytes) > len(trailerBytes) { msg.bodyBytes = msg.bodyBytes[:len(msg.bodyBytes)-len(trailerBytes)] } @@ -231,7 +246,7 @@ func ParseMessageWithDataDictionary( length := 0 for _, field := range msg.fields { switch field.tag { - case tagBeginString, tagBodyLength, tagCheckSum: //tags do not contribute to length + case tagBeginString, tagBodyLength, tagCheckSum: // Tags do not contribute to length. default: length += field.length() } @@ -274,7 +289,7 @@ func isTrailerField(tag Tag, dataDict *datadictionary.DataDictionary) bool { return ok } -// MsgType returns MsgType (tag 35) field's value +// MsgType returns MsgType (tag 35) field's value. func (m *Message) MsgType() (string, MessageRejectError) { return m.Header.GetString(tagMsgType) } @@ -313,7 +328,7 @@ func (m *Message) reverseRoute() *Message { copy(tagDeliverToCompID, tagOnBehalfOfCompID) copy(tagDeliverToSubID, tagOnBehalfOfSubID) - //tags added in 4.1 + // Tags added in 4.1. var beginString FIXString if m.Header.GetField(tagBeginString, &beginString) == nil { if string(beginString) != BeginStringFIX40 { @@ -362,7 +377,7 @@ func formatCheckSum(value int) string { return fmt.Sprintf("%03d", value) } -// Build constructs a []byte from a Message instance +// Build constructs a []byte from a Message instance. func (m *Message) build() []byte { m.cook() diff --git a/message_router.go b/message_router.go index 03e57f867..c640f3e4d 100644 --- a/message_router.go +++ b/message_router.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix type routeKey struct { @@ -5,7 +20,7 @@ type routeKey struct { MsgType string } -// FIX ApplVerID string values +// FIX ApplVerID string values. const ( ApplVerIDFIX27 = "0" ApplVerIDFIX30 = "1" @@ -19,15 +34,15 @@ const ( ApplVerIDFIX50SP2 = "9" ) -// A MessageRoute is a function that can process a fromApp/fromAdmin callback +// A MessageRoute is a function that can process a fromApp/fromAdmin callback. type MessageRoute func(msg *Message, sessionID SessionID) MessageRejectError -// A MessageRouter is a mutex for MessageRoutes +// A MessageRouter is a mutex for MessageRoutes. type MessageRouter struct { routes map[routeKey]MessageRoute } -// NewMessageRouter returns an initialized MessageRouter instance +// NewMessageRouter returns an initialized MessageRouter instance. func NewMessageRouter() *MessageRouter { return &MessageRouter{routes: make(map[routeKey]MessageRoute)} } diff --git a/message_router_test.go b/message_router_test.go index 93779b464..b2e7b59f5 100644 --- a/message_router_test.go +++ b/message_router_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/message_test.go b/message_test.go index 40b063ca1..97a8f3f05 100644 --- a/message_test.go +++ b/message_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -83,7 +98,7 @@ func (s *MessageSuite) TestParseMessageWithDataDictionary() { } func (s *MessageSuite) TestParseOutOfOrder() { - //allow fields out of order, save for validation + // Allow fields out of order, save for validation. rawMsg := bytes.NewBufferString("8=FIX.4.09=8135=D11=id21=338=10040=154=155=MSFT34=249=TW52=20140521-22:07:0956=ISLD10=250") s.Nil(ParseMessage(s.msg, rawMsg)) } @@ -159,7 +174,7 @@ func (s *MessageSuite) TestReverseRouteIgnoreEmpty() { } func (s *MessageSuite) TestReverseRouteFIX40() { - //onbehalfof/deliverto location id not supported in fix 4.0 + // The onbehalfof/deliverto location id not supported in fix 4.0. s.Nil(ParseMessage(s.msg, bytes.NewBufferString("8=FIX.4.09=17135=D34=249=TW50=KK52=20060102-15:04:0556=ISLD57=AP144=BB115=JCD116=CS128=MG129=CB142=JV143=RY145=BH11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=123"))) builder := s.msg.reverseRoute() diff --git a/mongostore.go b/mongostore.go index 1bd32db7f..c9bc37ac2 100644 --- a/mongostore.go +++ b/mongostore.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -30,12 +45,12 @@ type mongoStore struct { allowTransactions bool } -// NewMongoStoreFactory returns a mongo-based implementation of MessageStoreFactory +// NewMongoStoreFactory returns a mongo-based implementation of MessageStoreFactory. func NewMongoStoreFactory(settings *Settings) MessageStoreFactory { return NewMongoStoreFactoryPrefixed(settings, "") } -// NewMongoStoreFactoryPrefixed returns a mongo-based implementation of MessageStoreFactory, with prefix on collections +// NewMongoStoreFactoryPrefixed returns a mongo-based implementation of MessageStoreFactory, with prefix on collections. func NewMongoStoreFactoryPrefixed(settings *Settings, collectionsPrefix string) MessageStoreFactory { return mongoStoreFactory{ settings: settings, @@ -44,7 +59,7 @@ func NewMongoStoreFactoryPrefixed(settings *Settings, collectionsPrefix string) } } -// Create creates a new MongoStore implementation of the MessageStore interface +// Create creates a new MongoStore implementation of the MessageStore interface. func (f mongoStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err error) { sessionSettings, ok := f.settings.SessionSettings()[sessionID] if !ok { @@ -109,14 +124,14 @@ func generateMessageFilter(s *SessionID) (messageFilter *mongoQuickFixEntryData) } type mongoQuickFixEntryData struct { - //Message specific data + // Message specific data. Msgseq int `bson:"msgseq,omitempty"` Message []byte `bson:"message,omitempty"` - //Session specific data + // Session specific data. CreationTime time.Time `bson:"creation_time,omitempty"` IncomingSeqNum int `bson:"incoming_seq_num,omitempty"` OutgoingSeqNum int `bson:"outgoing_seq_num,omitempty"` - //Indexed data + // Indexed data. BeginString string `bson:"begin_string"` SessionQualifier string `bson:"session_qualifier"` SenderCompID string `bson:"sender_comp_id"` @@ -127,7 +142,7 @@ type mongoQuickFixEntryData struct { TargetLocID string `bson:"target_loc_id"` } -// Reset deletes the store records and sets the seqnums back to 1 +// Reset deletes the store records and sets the seqnums back to 1. func (store *mongoStore) Reset() error { msgFilter := generateMessageFilter(&store.sessionID) _, err := store.db.Database(store.mongoDatabase).Collection(store.messagesCollection).DeleteMany(context.Background(), msgFilter) @@ -149,7 +164,7 @@ func (store *mongoStore) Reset() error { return err } -// Refresh reloads the store from the database +// Refresh reloads the store from the database. func (store *mongoStore) Refresh() error { if err := store.cache.Reset(); err != nil { return err @@ -194,17 +209,17 @@ func (store *mongoStore) populateCache() error { return nil } -// NextSenderMsgSeqNum returns the next MsgSeqNum that will be sent +// NextSenderMsgSeqNum returns the next MsgSeqNum that will be sent. func (store *mongoStore) NextSenderMsgSeqNum() int { return store.cache.NextSenderMsgSeqNum() } -// NextTargetMsgSeqNum returns the next MsgSeqNum that should be received +// NextTargetMsgSeqNum returns the next MsgSeqNum that should be received. func (store *mongoStore) NextTargetMsgSeqNum() int { return store.cache.NextTargetMsgSeqNum() } -// SetNextSenderMsgSeqNum sets the next MsgSeqNum that will be sent +// SetNextSenderMsgSeqNum sets the next MsgSeqNum that will be sent. func (store *mongoStore) SetNextSenderMsgSeqNum(next int) error { msgFilter := generateMessageFilter(&store.sessionID) sessionUpdate := generateMessageFilter(&store.sessionID) @@ -217,7 +232,7 @@ func (store *mongoStore) SetNextSenderMsgSeqNum(next int) error { return store.cache.SetNextSenderMsgSeqNum(next) } -// SetNextTargetMsgSeqNum sets the next MsgSeqNum that should be received +// SetNextTargetMsgSeqNum sets the next MsgSeqNum that should be received. func (store *mongoStore) SetNextTargetMsgSeqNum(next int) error { msgFilter := generateMessageFilter(&store.sessionID) sessionUpdate := generateMessageFilter(&store.sessionID) @@ -230,7 +245,7 @@ func (store *mongoStore) SetNextTargetMsgSeqNum(next int) error { return store.cache.SetNextTargetMsgSeqNum(next) } -// IncrNextSenderMsgSeqNum increments the next MsgSeqNum that will be sent +// IncrNextSenderMsgSeqNum increments the next MsgSeqNum that will be sent. func (store *mongoStore) IncrNextSenderMsgSeqNum() error { if err := store.cache.IncrNextSenderMsgSeqNum(); err != nil { return errors.Wrap(err, "cache incr") @@ -238,7 +253,7 @@ func (store *mongoStore) IncrNextSenderMsgSeqNum() error { return store.SetNextSenderMsgSeqNum(store.cache.NextSenderMsgSeqNum()) } -// IncrNextTargetMsgSeqNum increments the next MsgSeqNum that should be received +// IncrNextTargetMsgSeqNum increments the next MsgSeqNum that should be received. func (store *mongoStore) IncrNextTargetMsgSeqNum() error { if err := store.cache.IncrNextTargetMsgSeqNum(); err != nil { return errors.Wrap(err, "cache incr") @@ -246,7 +261,7 @@ func (store *mongoStore) IncrNextTargetMsgSeqNum() error { return store.SetNextTargetMsgSeqNum(store.cache.NextTargetMsgSeqNum()) } -// CreationTime returns the creation time of the store +// CreationTime returns the creation time of the store. func (store *mongoStore) CreationTime() time.Time { return store.cache.CreationTime() } @@ -307,7 +322,7 @@ func (store *mongoStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg [ func (store *mongoStore) GetMessages(beginSeqNum, endSeqNum int) (msgs [][]byte, err error) { msgFilter := generateMessageFilter(&store.sessionID) - //Marshal into database form + // Marshal into database form. msgFilterBytes, err := bson.Marshal(msgFilter) if err != nil { return @@ -317,7 +332,7 @@ func (store *mongoStore) GetMessages(beginSeqNum, endSeqNum int) (msgs [][]byte, if err != nil { return } - //Modify the query to use a range for the sequence filter + // Modify the query to use a range for the sequence filter. seqFilter["msgseq"] = bson.M{ "$gte": beginSeqNum, "$lte": endSeqNum, @@ -339,7 +354,7 @@ func (store *mongoStore) GetMessages(beginSeqNum, endSeqNum int) (msgs [][]byte, return } -// Close closes the store's database connection +// Close closes the store's database connection. func (store *mongoStore) Close() error { if store.db != nil { err := store.db.Disconnect(context.Background()) diff --git a/mongostore_test.go b/mongostore_test.go index 32682b65d..4a8089f1c 100644 --- a/mongostore_test.go +++ b/mongostore_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -11,7 +26,7 @@ import ( "github.com/stretchr/testify/suite" ) -// MongoStoreTestSuite runs all tests in the MessageStoreTestSuite against the MongoStore implementation +// MongoStoreTestSuite runs all tests in the MessageStoreTestSuite against the MongoStore implementation. type MongoStoreTestSuite struct { MessageStoreTestSuite } diff --git a/msg_type.go b/msg_type.go index 309f302f4..823d9a752 100644 --- a/msg_type.go +++ b/msg_type.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import "bytes" diff --git a/not_session_time.go b/not_session_time.go index 2e3b04c3d..058159b99 100644 --- a/not_session_time.go +++ b/not_session_time.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import "github.com/quickfixgo/quickfix/internal" diff --git a/not_session_time_test.go b/not_session_time_test.go index 21a2c8f22..736e8efc9 100644 --- a/not_session_time_test.go +++ b/not_session_time_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/null_log.go b/null_log.go index 786271c42..106dcae42 100644 --- a/null_log.go +++ b/null_log.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix type nullLog struct{} diff --git a/parser.go b/parser.go index 13b992d03..a3ec73993 100644 --- a/parser.go +++ b/parser.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -12,7 +27,7 @@ const ( ) type parser struct { - //buffer is a slice of bigBuffer + // Buffer is a slice of bigBuffer. bigBuffer, buffer []byte reader io.Reader lastRead time.Time @@ -26,16 +41,16 @@ func (p *parser) readMore() (int, error) { if len(p.buffer) == cap(p.buffer) { var newBuffer []byte switch { - //initialize the parser + // Initialize the parser. case len(p.bigBuffer) == 0: p.bigBuffer = make([]byte, defaultBufSize) newBuffer = p.bigBuffer[0:0] - //shift buffer back to the start of bigBuffer + // Shift buffer back to the start of bigBuffer. case 2*len(p.buffer) <= len(p.bigBuffer): newBuffer = p.bigBuffer[0:len(p.buffer)] - //reallocate big buffer with enough space to shift buffer + // Reallocate big buffer with enough space to shift buffer. default: p.bigBuffer = make([]byte, 2*len(p.buffer)) newBuffer = p.bigBuffer[0:len(p.buffer)] diff --git a/parser_test.go b/parser_test.go index 533691986..34bca808d 100644 --- a/parser_test.go +++ b/parser_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/pending_timeout.go b/pending_timeout.go index 87154dddd..170af8a57 100644 --- a/pending_timeout.go +++ b/pending_timeout.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import "github.com/quickfixgo/quickfix/internal" diff --git a/pending_timeout_test.go b/pending_timeout_test.go index 1ad845d89..954a79c7c 100644 --- a/pending_timeout_test.go +++ b/pending_timeout_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/quickfix_test.go b/quickfix_test.go index 575a28614..beb8792bc 100644 --- a/quickfix_test.go +++ b/quickfix_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -52,7 +67,7 @@ func (s *QuickFIXSuite) MessageEqualsBytes(expectedBytes []byte, msg *Message) { s.Equal(string(actualBytes), string(expectedBytes)) } -// MockStore wraps a memory store and mocks Refresh for convenience +// MockStore wraps a memory store and mocks Refresh for convenience. type MockStore struct { mock.Mock memoryStore diff --git a/registry.go b/registry.go index ffbcd1914..180bc8035 100644 --- a/registry.go +++ b/registry.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -10,12 +25,12 @@ var sessions = make(map[SessionID]*session) var errDuplicateSessionID = errors.New("Duplicate SessionID") var errUnknownSession = errors.New("Unknown session") -// Messagable is a Message or something that can be converted to a Message +// Messagable is a Message or something that can be converted to a Message. type Messagable interface { ToMessage() *Message } -// Send determines the session to send Messagable using header fields BeginString, TargetCompID, SenderCompID +// Send determines the session to send Messagable using header fields BeginString, TargetCompID, SenderCompID. func Send(m Messagable) (err error) { msg := m.ToMessage() var beginString FIXString @@ -39,7 +54,7 @@ func Send(m Messagable) (err error) { return SendToTarget(msg, sessionID) } -// SendToTarget sends a message based on the sessionID. Convenient for use in FromApp since it provides a session ID for incoming messages +// SendToTarget sends a message based on the sessionID. Convenient for use in FromApp since it provides a session ID for incoming messages. func SendToTarget(m Messagable, sessionID SessionID) error { msg := m.ToMessage() session, ok := lookupSession(sessionID) @@ -50,7 +65,7 @@ func SendToTarget(m Messagable, sessionID SessionID) error { return session.queueForSend(msg) } -// UnregisterSession removes a session from the set of known sessions +// UnregisterSession removes a session from the set of known sessions. func UnregisterSession(sessionID SessionID) error { sessionsLock.Lock() defer sessionsLock.Unlock() diff --git a/repeating_group.go b/repeating_group.go index 1cbbc8e2a..853cc7d35 100644 --- a/repeating_group.go +++ b/repeating_group.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -6,20 +21,20 @@ import ( "strconv" ) -// GroupItem interface is used to construct repeating group templates +// GroupItem interface is used to construct repeating group templates. type GroupItem interface { - //Tag returns the tag identifying this GroupItem + // Tag returns the tag identifying this GroupItem. Tag() Tag - //Read Parameter to Read is tagValues. For most fields, only the first tagValue will be required. - //The length of the slice extends from the tagValue mapped to the field to be read through the - //following fields. This can be useful for GroupItems made up of repeating groups. + // Read Parameter to Read is tagValues. For most fields, only the first tagValue will be required. + // The length of the slice extends from the tagValue mapped to the field to be read through the + // following fields. This can be useful for GroupItems made up of repeating groups. // - //The Read function returns the remaining tagValues not processed by the GroupItem. If there was a - //problem reading the field, an error may be returned + // The Read function returns the remaining tagValues not processed by the GroupItem. If there was a + // problem reading the field, an error may be returned. Read([]TagValue) ([]TagValue, error) - //Clone makes a copy of this GroupItem + // Clone makes a copy of this GroupItem. Clone() GroupItem } @@ -38,15 +53,15 @@ func (t protoGroupElement) Read(tv []TagValue) ([]TagValue, error) { func (t protoGroupElement) Clone() GroupItem { return t } -// GroupElement returns a GroupItem made up of a single field +// GroupElement returns a GroupItem made up of a single field. func GroupElement(tag Tag) GroupItem { return protoGroupElement{tag: tag} } -// GroupTemplate specifies the group item order for a RepeatingGroup +// GroupTemplate specifies the group item order for a RepeatingGroup. type GroupTemplate []GroupItem -// Clone makes a copy of this GroupTemplate +// Clone makes a copy of this GroupTemplate. func (gt GroupTemplate) Clone() GroupTemplate { clone := make(GroupTemplate, len(gt)) for i := range gt { @@ -56,17 +71,17 @@ func (gt GroupTemplate) Clone() GroupTemplate { return clone } -// Group is a group of fields occurring in a repeating group +// Group is a group of fields occurring in a repeating group. type Group struct{ FieldMap } -// RepeatingGroup is a FIX Repeating Group type +// RepeatingGroup is a FIX Repeating Group type. type RepeatingGroup struct { tag Tag template GroupTemplate groups []*Group } -// NewRepeatingGroup returns an initilized RepeatingGroup instance +// NewRepeatingGroup returns an initilized RepeatingGroup instance. func NewRepeatingGroup(tag Tag, template GroupTemplate) *RepeatingGroup { return &RepeatingGroup{ tag: tag, @@ -74,12 +89,12 @@ func NewRepeatingGroup(tag Tag, template GroupTemplate) *RepeatingGroup { } } -// Tag returns the Tag for this repeating Group +// Tag returns the Tag for this repeating Group. func (f RepeatingGroup) Tag() Tag { return f.tag } -// Clone makes a copy of this RepeatingGroup (tag, template) +// Clone makes a copy of this RepeatingGroup (tag, template). func (f RepeatingGroup) Clone() GroupItem { return &RepeatingGroup{ tag: f.tag, @@ -87,17 +102,17 @@ func (f RepeatingGroup) Clone() GroupItem { } } -// Len returns the number of Groups in this RepeatingGroup +// Len returns the number of Groups in this RepeatingGroup. func (f RepeatingGroup) Len() int { return len(f.groups) } -// Get returns the ith group in this RepeatingGroup +// Get returns the ith group in this RepeatingGroup. func (f RepeatingGroup) Get(i int) *Group { return f.groups[i] } -// Add appends a new group to the RepeatingGroup and returns the new Group +// Add appends a new group to the RepeatingGroup and returns the new Group. func (f *RepeatingGroup) Add() *Group { g := new(Group) g.initWithOrdering(f.groupTagOrder()) @@ -107,7 +122,7 @@ func (f *RepeatingGroup) Add() *Group { } // Write returns tagValues for all Items in the repeating group ordered by -// Group sequence and Group template order +// Group sequence and Group template order. func (f RepeatingGroup) Write() []TagValue { tvs := make([]TagValue, 1) tvs[0].init(f.tag, []byte(strconv.Itoa(len(f.groups)))) diff --git a/repeating_group_test.go b/repeating_group_test.go index 955e3b7da..abd316d78 100644 --- a/repeating_group_test.go +++ b/repeating_group_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/resend_state.go b/resend_state.go index d07559b82..8a46e36e3 100644 --- a/resend_state.go +++ b/resend_state.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import "github.com/quickfixgo/quickfix/internal" @@ -17,8 +32,8 @@ func (s resendState) Timeout(session *session, event internal.Event) (nextState case inSession: nextState = s case pendingTimeout: - //wrap pendingTimeout in resend. prevents us falling back to inSession if recovering - //from pendingTimeout + // Wrap pendingTimeout in resend. prevents us falling back to inSession if recovering + // from pendingTimeout. nextState = pendingTimeout{s} } diff --git a/resend_state_test.go b/resend_state_test.go index 4d8184a9d..093660d85 100644 --- a/resend_state_test.go +++ b/resend_state_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -61,7 +76,7 @@ func (s *resendStateTestSuite) TestTimeoutUnchangedNeedHeartbeat() { func (s *resendStateTestSuite) TestFixMsgIn() { s.session.State = inSession{} - //in session expects seq number 1, send too high + // In session expects seq number 1, send too high. s.MessageFactory.SetNextSeqNum(2) s.MockApp.On("ToAdmin") @@ -98,7 +113,7 @@ func (s *resendStateTestSuite) TestFixMsgIn() { func (s *resendStateTestSuite) TestFixMsgInSequenceReset() { s.session.State = inSession{} - //in session expects seq number 1, send too high + // In session expects seq number 1, send too high. s.MessageFactory.SetNextSeqNum(3) s.MockApp.On("ToAdmin") @@ -130,7 +145,7 @@ func (s *resendStateTestSuite) TestFixMsgInResendChunk() { s.session.State = inSession{} s.ResendRequestChunkSize = 2 - //in session expects seq number 1, send too high + // In session expects seq number 1, send too high. s.MessageFactory.SetNextSeqNum(4) s.MockApp.On("ToAdmin") diff --git a/screen_log.go b/screen_log.go index e6271ecc0..c17d67ecb 100644 --- a/screen_log.go +++ b/screen_log.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/session.go b/session.go index f539d285a..e3a89b07c 100644 --- a/session.go +++ b/session.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -11,7 +26,7 @@ import ( "github.com/quickfixgo/quickfix/internal" ) -// The Session is the primary FIX abstraction for message communication +// The Session is the primary FIX abstraction for message communication. type session struct { store MessageStore @@ -21,10 +36,10 @@ type session struct { messageOut chan<- []byte messageIn <-chan fixIn - //application messages are queued up for send here + // Application messages are queued up for send here. toSend [][]byte - //mutex for access to toSend + // Mutex for access to toSend. sendMutex sync.Mutex sessionEvent chan internal.Event @@ -77,7 +92,7 @@ func (s *session) connect(msgIn <-chan fixIn, msgOut chan<- []byte) error { type stopReq struct{} func (s *session) stop() { - //stop once + // Stop once. s.stopOnce.Do(func() { s.admin <- stopReq{} }) @@ -208,7 +223,7 @@ func (s *session) resend(msg *Message) bool { return s.application.ToApp(msg, s.sessionID) == nil } -// queueForSend will validate, persist, and queue the message for send +// queueForSend will validate, persist, and queue the message for send. func (s *session) queueForSend(msg *Message) error { s.sendMutex.Lock() defer s.sendMutex.Unlock() @@ -228,7 +243,7 @@ func (s *session) queueForSend(msg *Message) error { return nil } -// send will validate, persist, queue the message. If the session is logged on, send all messages in the queue +// send will validate, persist, queue the message. If the session is logged on, send all messages in the queue. func (s *session) send(msg *Message) error { return s.sendInReplyTo(msg, nil) } @@ -251,7 +266,7 @@ func (s *session) sendInReplyTo(msg *Message, inReplyTo *Message) error { return nil } -// dropAndReset will drop the send queue and reset the message store +// dropAndReset will drop the send queue and reset the message store. func (s *session) dropAndReset() error { s.sendMutex.Lock() defer s.sendMutex.Unlock() @@ -396,7 +411,7 @@ func (s *session) sendResendRequest(beginSeq, endSeq int) (nextState resendState } func (s *session) handleLogon(msg *Message) error { - //Grab default app ver id from fixt.1.1 logon + // Grab default app ver id from fixt.1.1 logon. if s.sessionID.BeginString == BeginStringFIXT11 { var targetApplVerID FIXString @@ -642,7 +657,7 @@ func (s *session) doReject(msg *Message, rej MessageRejectError) error { default: reply.Body.SetField(tagSessionRejectReason, FIXInt(rej.RejectReason())) case rej.RejectReason() > rejectReasonInvalidMsgType && s.sessionID.BeginString == BeginStringFIX42: - //fix42 knows up to invalid msg type + // Fix42 knows up to invalid msg type. } if refTagID := rej.RefTagID(); refTagID != nil { @@ -743,14 +758,14 @@ func (s *session) run() { var stopChan = make(chan struct{}) s.stateTimer = internal.NewEventTimer(func() { select { - //deadlock in write to chan s.sessionEvent after s.Stopped()==true and end of loop session.go:766 because no reader of chan s.sessionEvent + // Deadlock in write to chan s.sessionEvent after s.Stopped()==true and end of loop session.go:766 because no reader of chan s.sessionEvent. case s.sessionEvent <- internal.NeedHeartbeat: case <-stopChan: } }) s.peerTimer = internal.NewEventTimer(func() { select { - //deadlock in write to chan s.sessionEvent after s.Stopped()==true and end of loop session.go:766 because no reader of chan s.sessionEvent + // Deadlock in write to chan s.sessionEvent after s.Stopped()==true and end of loop session.go:766 because no reader of chan s.sessionEvent. case s.sessionEvent <- internal.PeerTimeout: case <-stopChan: } diff --git a/session_factory.go b/session_factory.go index 769e5084a..3a6be68a5 100644 --- a/session_factory.go +++ b/session_factory.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -42,11 +57,11 @@ var applVerIDLookup = map[string]string{ } type sessionFactory struct { - //True if building sessions that initiate logon + // True if building sessions that initiate logon. BuildInitiators bool } -// Creates Session, associates with internal session registry +// Creates Session, associates with internal session registry. func (f sessionFactory) createSession( sessionID SessionID, storeFactory MessageStoreFactory, settings *SessionSettings, logFactory LogFactory, application Application, @@ -92,7 +107,7 @@ func (f sessionFactory) newSession( s.DefaultApplVerID = applVerID } - //If the transport or app data dictionary setting is set, the other also needs to be set. + // If the transport or app data dictionary setting is set, the other also needs to be set. if settings.HasSetting(config.TransportDataDictionary) || settings.HasSetting(config.AppDataDictionary) { var transportDataDictionaryPath, appDataDictionaryPath string if transportDataDictionaryPath, err = settings.Setting(config.TransportDataDictionary); err != nil { diff --git a/session_factory_test.go b/session_factory_test.go index a86cfe369..db99302f1 100644 --- a/session_factory_test.go +++ b/session_factory_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/session_id.go b/session_id.go index c3ce615fe..c4dfb3513 100644 --- a/session_id.go +++ b/session_id.go @@ -1,13 +1,28 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import "bytes" -// SessionID is a unique identifier of a Session +// SessionID is a unique identifier of a Session. type SessionID struct { BeginString, TargetCompID, TargetSubID, TargetLocationID, SenderCompID, SenderSubID, SenderLocationID, Qualifier string } -// IsFIXT returns true if the SessionID has a FIXT BeginString +// IsFIXT returns true if the SessionID has a FIXT BeginString. func (s SessionID) IsFIXT() bool { return s.BeginString == BeginStringFIXT11 } diff --git a/session_id_test.go b/session_id_test.go index 6c5eae3b2..3ea9a22e8 100644 --- a/session_id_test.go +++ b/session_id_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/session_rejects.go b/session_rejects.go index 2edfcd280..4ea16b61e 100644 --- a/session_rejects.go +++ b/session_rejects.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/session_settings.go b/session_settings.go index 49afbcd7f..323ac6234 100644 --- a/session_settings.go +++ b/session_settings.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -11,7 +26,7 @@ type SessionSettings struct { settings map[string]string } -// ConditionallyRequiredSetting indicates a missing setting +// ConditionallyRequiredSetting indicates a missing setting. type ConditionallyRequiredSetting struct { Setting string } @@ -20,7 +35,7 @@ func (e ConditionallyRequiredSetting) Error() string { return fmt.Sprintf("Conditionally Required Setting: %v", e.Setting) } -// IncorrectFormatForSetting indicates a setting that is incorrectly formatted +// IncorrectFormatForSetting indicates a setting that is incorrectly formatted. type IncorrectFormatForSetting struct { Setting, Value string Err error @@ -30,12 +45,12 @@ func (e IncorrectFormatForSetting) Error() string { return fmt.Sprintf("%q is invalid for %s", e.Value, e.Setting) } -// Init initializes or resets SessionSettings +// Init initializes or resets SessionSettings. func (s *SessionSettings) Init() { s.settings = make(map[string]string) } -// NewSessionSettings returns a newly initialized SessionSettings instance +// NewSessionSettings returns a newly initialized SessionSettings instance. func NewSessionSettings() *SessionSettings { s := &SessionSettings{} s.Init() @@ -45,7 +60,7 @@ func NewSessionSettings() *SessionSettings { // Set assigns a value to a setting on SessionSettings. func (s *SessionSettings) Set(setting string, val string) { - //lazy init + // Lazy init. if s.settings == nil { s.Init() } @@ -53,7 +68,7 @@ func (s *SessionSettings) Set(setting string, val string) { s.settings[setting] = val } -// HasSetting returns true if a setting is set, false if not +// HasSetting returns true if a setting is set, false if not. func (s *SessionSettings) HasSetting(setting string) bool { _, ok := s.settings[setting] return ok diff --git a/session_settings_test.go b/session_settings_test.go index 34687ae2c..7fa9a94ad 100644 --- a/session_settings_test.go +++ b/session_settings_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/session_state.go b/session_state.go index 016cb3e8c..230ac8613 100644 --- a/session_state.go +++ b/session_state.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -193,29 +208,29 @@ func handleStateError(s *session, err error) sessionState { // sessionState is the current state of the session state machine. The session state determines how the session responds to // incoming messages, timeouts, and requests to send application messages. type sessionState interface { - //FixMsgIn is called by the session on incoming messages from the counter party. The return type is the next session state - //following message processing + // FixMsgIn is called by the session on incoming messages from the counter party. + // The return type is the next session state following message processing. FixMsgIn(*session, *Message) (nextState sessionState) - //Timeout is called by the session on a timeout event. + // Timeout is called by the session on a timeout event. Timeout(*session, internal.Event) (nextState sessionState) - //IsLoggedOn returns true if state is logged on an in session, false otherwise + // IsLoggedOn returns true if state is logged on an in session, false otherwise. IsLoggedOn() bool - //IsConnected returns true if the state is connected + // IsConnected returns true if the state is connected. IsConnected() bool - //IsSessionTime returns true if the state is in session time + // IsSessionTime returns true if the state is in session time. IsSessionTime() bool - //ShutdownNow terminates the session state immediately + // ShutdownNow terminates the session state immediately. ShutdownNow(*session) - //Stop triggers a clean stop + // Stop triggers a clean stop. Stop(*session) (nextState sessionState) - //Stringer debugging convenience + // Stringer debugging convenience. fmt.Stringer } diff --git a/session_test.go b/session_test.go index 293b94805..457b5edd3 100644 --- a/session_test.go +++ b/session_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -70,7 +85,7 @@ func (s *SessionSuite) TestInsertSendingTime() { Precision TimestampPrecision ExpectedPrecision TimestampPrecision }{ - {BeginStringFIX40, Millis, Seconds}, //config is ignored for fix < 4.2 + {BeginStringFIX40, Millis, Seconds}, // Config is ignored for fix < 4.2. {BeginStringFIX41, Millis, Seconds}, {BeginStringFIX42, Millis, Millis}, @@ -170,7 +185,7 @@ func (s *SessionSuite) TestCheckTargetTooHigh() { s.Require().NotNil(err, "sequence number too high should return an error") s.IsType(targetTooHigh{}, err) - //spot on + // Spot on. msg.Header.SetField(tagMsgSeqNum, FIXInt(45)) s.Nil(s.session.checkTargetTooHigh(msg)) } @@ -217,13 +232,13 @@ func (s *SessionSuite) TestCheckTargetTooLow() { s.Require().NotNil(err, "sequence number is required") s.Equal(rejectReasonRequiredTagMissing, err.RejectReason()) - //too low + // Too low. msg.Header.SetField(tagMsgSeqNum, FIXInt(43)) err = s.session.checkTargetTooLow(msg) s.NotNil(err, "sequence number too low should return error") s.IsType(targetTooLow{}, err) - //spot on + // Spot on. msg.Header.SetField(tagMsgSeqNum, FIXInt(45)) s.Nil(s.session.checkTargetTooLow(msg)) } @@ -238,34 +253,34 @@ func (s *SessionSuite) TestShouldSendReset() { NextTargetMsgSeqNum int Expected bool }{ - {BeginStringFIX40, true, false, false, 1, 1, false}, //ResetSeqNumFlag not available < fix41 + {BeginStringFIX40, true, false, false, 1, 1, false}, // ResetSeqNumFlag not available < fix41. - {BeginStringFIX41, true, false, false, 1, 1, true}, //session must be configured to reset on logon + {BeginStringFIX41, true, false, false, 1, 1, true}, // Session must be configured to reset on logon. {BeginStringFIX42, true, false, false, 1, 1, true}, {BeginStringFIX43, true, false, false, 1, 1, true}, {BeginStringFIX44, true, false, false, 1, 1, true}, {BeginStringFIXT11, true, false, false, 1, 1, true}, - {BeginStringFIX41, false, true, false, 1, 1, true}, //or disconnect + {BeginStringFIX41, false, true, false, 1, 1, true}, // Or disconnect. {BeginStringFIX42, false, true, false, 1, 1, true}, {BeginStringFIX43, false, true, false, 1, 1, true}, {BeginStringFIX44, false, true, false, 1, 1, true}, {BeginStringFIXT11, false, true, false, 1, 1, true}, - {BeginStringFIX41, false, false, true, 1, 1, true}, //or logout + {BeginStringFIX41, false, false, true, 1, 1, true}, // Or logout. {BeginStringFIX42, false, false, true, 1, 1, true}, {BeginStringFIX43, false, false, true, 1, 1, true}, {BeginStringFIX44, false, false, true, 1, 1, true}, {BeginStringFIXT11, false, false, true, 1, 1, true}, - {BeginStringFIX41, true, true, false, 1, 1, true}, //or combo + {BeginStringFIX41, true, true, false, 1, 1, true}, // Or combo. {BeginStringFIX42, false, true, true, 1, 1, true}, {BeginStringFIX43, true, false, true, 1, 1, true}, {BeginStringFIX44, true, true, true, 1, 1, true}, - {BeginStringFIX41, false, false, false, 1, 1, false}, //or will not be set + {BeginStringFIX41, false, false, false, 1, 1, false}, // Or will not be set. - {BeginStringFIX41, true, false, false, 1, 10, false}, //session seq numbers should be reset at the time of check + {BeginStringFIX41, true, false, false, 1, 10, false}, // Session seq numbers should be reset at the time of check. {BeginStringFIX42, true, false, false, 2, 1, false}, {BeginStringFIX43, true, false, false, 14, 100, false}, } @@ -930,7 +945,7 @@ func (suite *SessionSendTestSuite) TestDropAndSendDropsQueue() { suite.MessageType(string(msgTypeLogon), msg) suite.FieldEquals(tagMsgSeqNum, 3, msg.Header) - //only one message sent + // Only one message sent. suite.LastToAdminMessageSent() suite.NoMessageSent() } @@ -952,7 +967,7 @@ func (suite *SessionSendTestSuite) TestDropAndSendDropsQueueWithReset() { suite.MessageType(string(msgTypeLogon), msg) suite.FieldEquals(tagMsgSeqNum, 1, msg.Header) - //only one message sent + // Only one message sent. suite.LastToAdminMessageSent() suite.NoMessageSent() } diff --git a/settings.go b/settings.go index f70bf9596..f457f9e2f 100644 --- a/settings.go +++ b/settings.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -16,7 +31,7 @@ type Settings struct { sessionSettings map[SessionID]*SessionSettings } -// Init initializes or resets a Settings instance +// Init initializes or resets a Settings instance. func (s *Settings) Init() { s.globalSettings = NewSessionSettings() s.sessionSettings = make(map[SessionID]*SessionSettings) @@ -28,7 +43,7 @@ func (s *Settings) lazyInit() { } } -// NewSettings creates a Settings instance +// NewSettings creates a Settings instance. func NewSettings() *Settings { s := &Settings{} s.Init() @@ -76,7 +91,7 @@ func sessionIDFromSessionSettings(globalSettings *SessionSettings, sessionSettin } // ParseSettings creates and initializes a Settings instance with config parsed from a Reader. -// Returns error if the config is has parse errors +// Returns error if the config is has parse errors. func ParseSettings(reader io.Reader) (*Settings, error) { s := NewSettings() @@ -149,7 +164,7 @@ func (s *Settings) SessionSettings() map[SessionID]*SessionSettings { return allSessionSettings } -// AddSession adds Session Settings to Settings instance. Returns an error if session settings with duplicate sessionID has already been added +// AddSession adds Session Settings to Settings instance. Returns an error if session settings with duplicate sessionID has already been added. func (s *Settings) AddSession(sessionSettings *SessionSettings) (SessionID, error) { s.lazyInit() diff --git a/settings_test.go b/settings_test.go index 9ce568e50..9ac8d9dcb 100644 --- a/settings_test.go +++ b/settings_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/sqlstore.go b/sqlstore.go index d0b1c5162..6ff8ac225 100644 --- a/sqlstore.go +++ b/sqlstore.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -45,12 +60,12 @@ func postgresPlaceholder(i int) string { return fmt.Sprintf("$%d", i+1) } -// NewSQLStoreFactory returns a sql-based implementation of MessageStoreFactory +// NewSQLStoreFactory returns a sql-based implementation of MessageStoreFactory. func NewSQLStoreFactory(settings *Settings) MessageStoreFactory { return sqlStoreFactory{settings: settings} } -// Create creates a new SQLStore implementation of the MessageStore interface +// Create creates a new SQLStore implementation of the MessageStore interface. func (f sqlStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err error) { sessionSettings, ok := f.settings.SessionSettings()[sessionID] if !ok { @@ -106,7 +121,7 @@ func newSQLStore(sessionID SessionID, driver string, dataSourceName string, conn return store, nil } -// Reset deletes the store records and sets the seqnums back to 1 +// Reset deletes the store records and sets the seqnums back to 1. func (store *sqlStore) Reset() error { s := store.sessionID _, err := store.db.Exec(sqlString(`DELETE FROM messages @@ -137,7 +152,7 @@ func (store *sqlStore) Reset() error { return err } -// Refresh reloads the store from the database +// Refresh reloads the store from the database. func (store *sqlStore) Refresh() error { if err := store.cache.Reset(); err != nil { return err @@ -194,17 +209,17 @@ func (store *sqlStore) populateCache() error { return err } -// NextSenderMsgSeqNum returns the next MsgSeqNum that will be sent +// NextSenderMsgSeqNum returns the next MsgSeqNum that will be sent. func (store *sqlStore) NextSenderMsgSeqNum() int { return store.cache.NextSenderMsgSeqNum() } -// NextTargetMsgSeqNum returns the next MsgSeqNum that should be received +// NextTargetMsgSeqNum returns the next MsgSeqNum that should be received. func (store *sqlStore) NextTargetMsgSeqNum() int { return store.cache.NextTargetMsgSeqNum() } -// SetNextSenderMsgSeqNum sets the next MsgSeqNum that will be sent +// SetNextSenderMsgSeqNum sets the next MsgSeqNum that will be sent. func (store *sqlStore) SetNextSenderMsgSeqNum(next int) error { s := store.sessionID _, err := store.db.Exec(sqlString(`UPDATE sessions SET outgoing_seqnum = ? @@ -220,7 +235,7 @@ func (store *sqlStore) SetNextSenderMsgSeqNum(next int) error { return store.cache.SetNextSenderMsgSeqNum(next) } -// SetNextTargetMsgSeqNum sets the next MsgSeqNum that should be received +// SetNextTargetMsgSeqNum sets the next MsgSeqNum that should be received. func (store *sqlStore) SetNextTargetMsgSeqNum(next int) error { s := store.sessionID _, err := store.db.Exec(sqlString(`UPDATE sessions SET incoming_seqnum = ? @@ -236,7 +251,7 @@ func (store *sqlStore) SetNextTargetMsgSeqNum(next int) error { return store.cache.SetNextTargetMsgSeqNum(next) } -// IncrNextSenderMsgSeqNum increments the next MsgSeqNum that will be sent +// IncrNextSenderMsgSeqNum increments the next MsgSeqNum that will be sent. func (store *sqlStore) IncrNextSenderMsgSeqNum() error { if err := store.cache.IncrNextSenderMsgSeqNum(); err != nil { return errors.Wrap(err, "cache incr next") @@ -244,7 +259,7 @@ func (store *sqlStore) IncrNextSenderMsgSeqNum() error { return store.SetNextSenderMsgSeqNum(store.cache.NextSenderMsgSeqNum()) } -// IncrNextTargetMsgSeqNum increments the next MsgSeqNum that should be received +// IncrNextTargetMsgSeqNum increments the next MsgSeqNum that should be received. func (store *sqlStore) IncrNextTargetMsgSeqNum() error { if err := store.cache.IncrNextTargetMsgSeqNum(); err != nil { return errors.Wrap(err, "cache incr next") @@ -252,7 +267,7 @@ func (store *sqlStore) IncrNextTargetMsgSeqNum() error { return store.SetNextTargetMsgSeqNum(store.cache.NextTargetMsgSeqNum()) } -// CreationTime returns the creation time of the store +// CreationTime returns the creation time of the store. func (store *sqlStore) CreationTime() time.Time { return store.cache.CreationTime() } @@ -350,7 +365,7 @@ func (store *sqlStore) GetMessages(beginSeqNum, endSeqNum int) ([][]byte, error) return msgs, nil } -// Close closes the store's database connection +// Close closes the store's database connection. func (store *sqlStore) Close() error { if store.db != nil { store.db.Close() diff --git a/sqlstore_test.go b/sqlstore_test.go index da2c8a5a4..512c951fc 100644 --- a/sqlstore_test.go +++ b/sqlstore_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -16,7 +31,7 @@ import ( "github.com/stretchr/testify/suite" ) -// SqlStoreTestSuite runs all tests in the MessageStoreTestSuite against the SqlStore implementation +// SqlStoreTestSuite runs all tests in the MessageStoreTestSuite against the SqlStore implementation. type SQLStoreTestSuite struct { MessageStoreTestSuite sqlStoreRootPath string diff --git a/store.go b/store.go index 0ad5123fa..c56e1896e 100644 --- a/store.go +++ b/store.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -6,7 +21,7 @@ import ( "github.com/pkg/errors" ) -// The MessageStore interface provides methods to record and retrieve messages for resend purposes +// The MessageStore interface provides methods to record and retrieve messages for resend purposes. type MessageStore interface { NextSenderMsgSeqNum() int NextTargetMsgSeqNum() int @@ -29,7 +44,7 @@ type MessageStore interface { Close() error } -// The MessageStoreFactory interface is used by session to create a session specific message store +// The MessageStoreFactory interface is used by session to create a session specific message store. type MessageStoreFactory interface { Create(sessionID SessionID) (MessageStore, error) } @@ -80,12 +95,12 @@ func (store *memoryStore) Reset() error { } func (store *memoryStore) Refresh() error { - //nop, nothing to refresh + // NOP, nothing to refresh. return nil } func (store *memoryStore) Close() error { - //nop, nothing to close + // NOP, nothing to close. return nil } @@ -126,5 +141,5 @@ func (f memoryStoreFactory) Create(sessionID SessionID) (MessageStore, error) { return m, nil } -// NewMemoryStoreFactory returns a MessageStoreFactory instance that created in-memory MessageStores +// NewMemoryStoreFactory returns a MessageStoreFactory instance that created in-memory MessageStores. func NewMemoryStoreFactory() MessageStoreFactory { return memoryStoreFactory{} } diff --git a/store_test.go b/store_test.go index 7f0f8eafc..075b3fd6c 100644 --- a/store_test.go +++ b/store_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -9,13 +24,13 @@ import ( "github.com/stretchr/testify/suite" ) -// MessageStoreTestSuite is the suite of all tests that should be run against all MessageStore implementations +// MessageStoreTestSuite is the suite of all tests that should be run against all MessageStore implementations. type MessageStoreTestSuite struct { suite.Suite msgStore MessageStore } -// MemoryStoreTestSuite runs all tests in the MessageStoreTestSuite against the MemoryStore implementation +// MemoryStoreTestSuite runs all tests in the MessageStoreTestSuite against the MemoryStore implementation. type MemoryStoreTestSuite struct { MessageStoreTestSuite } diff --git a/tag.go b/tag.go index 475c7316a..01b28356f 100644 --- a/tag.go +++ b/tag.go @@ -1,6 +1,21 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix -// Tag is a typed int representing a FIX tag +// Tag is a typed int representing a FIX tag. type Tag int const ( @@ -61,7 +76,7 @@ const ( tagCheckSum Tag = 10 ) -// IsTrailer returns true if tag belongs in the message trailer +// IsTrailer returns true if tag belongs in the message trailer. func (t Tag) IsTrailer() bool { switch t { case tagSignatureLength, tagSignature, tagCheckSum: @@ -70,7 +85,7 @@ func (t Tag) IsTrailer() bool { return false } -// IsHeader returns true if tag belongs in the message header +// IsHeader returns true if tag belongs in the message header. func (t Tag) IsHeader() bool { switch t { case tagBeginString, diff --git a/tag_value.go b/tag_value.go index 75f532a85..6e721862f 100644 --- a/tag_value.go +++ b/tag_value.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -6,7 +21,7 @@ import ( "strconv" ) -// TagValue is a low-level FIX field abstraction +// TagValue is a low-level FIX field abstraction. type TagValue struct { tag Tag value []byte diff --git a/tag_value_test.go b/tag_value_test.go index 48883ed85..2c9ccc811 100644 --- a/tag_value_test.go +++ b/tag_value_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/tls.go b/tls.go index 62c7207f3..a86a49129 100644 --- a/tls.go +++ b/tls.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/tls_test.go b/tls_test.go index 9274b95dd..0bae6cd54 100644 --- a/tls_test.go +++ b/tls_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( diff --git a/validation.go b/validation.go index 14f6f9f0d..427fadacb 100644 --- a/validation.go +++ b/validation.go @@ -1,15 +1,30 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( "github.com/quickfixgo/quickfix/datadictionary" ) -// Validator validates a FIX message +// Validator validates a FIX message. type Validator interface { Validate(*Message) MessageRejectError } -// ValidatorSettings describe validation behavior +// ValidatorSettings describe validation behavior. type ValidatorSettings struct { CheckFieldsOutOfOrder bool RejectInvalidMessage bool @@ -33,7 +48,7 @@ type fixtValidator struct { settings ValidatorSettings } -// NewValidator creates a FIX message validator from the given data dictionaries +// NewValidator creates a FIX message validator from the given data dictionaries. func NewValidator(settings ValidatorSettings, appDataDictionary, transportDataDictionary *datadictionary.DataDictionary) Validator { if transportDataDictionary != nil { return &fixtValidator{ @@ -209,13 +224,13 @@ func validateVisitGroupField(fieldDef *datadictionary.FieldDef, fieldStack []Tag for len(fieldStack) > 0 { - //start of repeating group + // Start of repeating group. if int(fieldStack[0].tag) == fieldDef.Fields[0].Tag() { childDefs = fieldDef.Fields groupCount++ } - //group complete + // Group complete. if len(childDefs) == 0 { break } diff --git a/validation_test.go b/validation_test.go index 25a47802a..da0e65f2b 100644 --- a/validation_test.go +++ b/validation_test.go @@ -1,3 +1,18 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + package quickfix import ( @@ -66,13 +81,13 @@ func TestValidate(t *testing.T) { switch { case reject.RefTagID() == nil && test.ExpectedRefTagID == nil: - //ok, expected and actual ref tag not set + // OK, expected and actual ref tag not set. case reject.RefTagID() != nil && test.ExpectedRefTagID == nil: t.Errorf("%v: Unexpected RefTag '%v'", test.TestName, *reject.RefTagID()) case reject.RefTagID() == nil && test.ExpectedRefTagID != nil: t.Errorf("%v: Expected RefTag '%v'", test.TestName, *test.ExpectedRefTagID) case *reject.RefTagID() == *test.ExpectedRefTagID: - //ok, tags equal + // OK, tags equal. default: t.Errorf("%v: Expected RefTag '%v' got '%v'", test.TestName, *test.ExpectedRefTagID, *reject.RefTagID()) } @@ -193,7 +208,7 @@ func tcTagNotDefinedForMessage() validateTest { } func tcTagIsDefinedForMessage() validateTest { - //compare to tcTagIsNotDefinedForMessage + // Compare to `tcTagIsNotDefinedForMessage`. dict, _ := datadictionary.Parse("spec/FIX43.xml") validator := NewValidator(defaultValidatorSettings, dict, nil) validMsg := createFIX43NewOrderSingle() @@ -227,9 +242,7 @@ func tcFieldNotFoundBody() validateTest { SetField(Tag(38), FIXString("A")) tag := Tag(40) - //ord type is required - //invalidMsg1.Body.SetField(Tag(40), "A")) - + // Ord type is required. invalidMsg1.Body.SetField(Tag(40), "A")). msgBytes := invalidMsg1.build() return validateTest{ @@ -259,9 +272,8 @@ func tcFieldNotFoundHeader() validateTest { SetField(tagSenderCompID, FIXString("0")). SetField(tagTargetCompID, FIXString("0")). SetField(tagMsgSeqNum, FIXString("0")) - //sending time is required - //invalidMsg2.Header.FieldMap.SetField(tag.SendingTime, "0")) + // Sending time is required. invalidMsg2.Header.FieldMap.SetField(tag.SendingTime, "0")). tag := tagSendingTime msgBytes := invalidMsg2.build() @@ -348,7 +360,7 @@ func tcTagSpecifiedOutOfRequiredOrderHeader() validateTest { builder := createFIX40NewOrderSingle() tag := tagOnBehalfOfCompID - //should be in header + // Should be in header. builder.Body.SetField(tag, FIXString("CWB")) msgBytes := builder.build() @@ -367,7 +379,7 @@ func tcTagSpecifiedOutOfRequiredOrderTrailer() validateTest { builder := createFIX40NewOrderSingle() tag := tagSignature - //should be in trailer + // Should be in trailer. builder.Body.SetField(tag, FIXString("SIG")) msgBytes := builder.build() @@ -428,7 +440,7 @@ func tcTagSpecifiedOutOfRequiredOrderDisabledHeader() validateTest { builder := createFIX40NewOrderSingle() tag := tagOnBehalfOfCompID - //should be in header + // Should be in header. builder.Body.SetField(tag, FIXString("CWB")) msgBytes := builder.build() @@ -448,7 +460,7 @@ func tcTagSpecifiedOutOfRequiredOrderDisabledTrailer() validateTest { builder := createFIX40NewOrderSingle() tag := tagSignature - //should be in trailer + // Should be in trailer. builder.Body.SetField(tag, FIXString("SIG")) msgBytes := builder.build() @@ -524,27 +536,27 @@ func TestValidateVisitField(t *testing.T) { expectReject bool expectedRejectReason int }{ - //non-repeating + // Non-repeating. {expectedRemFields: 0, fieldDef: fieldDef0, fields: []TagValue{field}}, - //single field group + // Single field group. {expectedRemFields: 0, fieldDef: groupFieldDef, fields: []TagValue{groupID, repField1}}, - //multiple field group + // Multiple field group. {expectedRemFields: 0, fieldDef: groupFieldDef, fields: []TagValue{groupID, repField1, repField2}}, - //test with trailing tag not in group + // Test with trailing tag not in group. {expectedRemFields: 1, fieldDef: groupFieldDef, fields: []TagValue{groupID, repField1, repField2, field}}, - //repeats + // Repeats. {expectedRemFields: 1, fieldDef: groupFieldDef, fields: []TagValue{groupID2, repField1, repField2, repField1, repField2, field}}, - //REJECT: group size declared > actual group size + // REJECT: group size declared > actual group size. {expectReject: true, fieldDef: groupFieldDef, fields: []TagValue{groupID3, repField1, repField2, repField1, repField2, field}, @@ -555,7 +567,7 @@ func TestValidateVisitField(t *testing.T) { fields: []TagValue{groupID3, repField1, repField1, field}, expectedRejectReason: rejectReasonIncorrectNumInGroupCountForRepeatingGroup, }, - //REJECT: group size declared < actual group size + // REJECT: group size declared < actual group size. {expectReject: true, fieldDef: groupFieldDef, fields: []TagValue{groupID, repField1, repField2, repField1, repField2, field}, From 0f9a0059d461351fc45fce55e13bb0c52b332e00 Mon Sep 17 00:00:00 2001 From: Andrey Kuznetsov Date: Wed, 7 Mar 2018 23:25:37 +0300 Subject: [PATCH 27/47] set targetSubID to session --- registry.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/registry.go b/registry.go index 180bc8035..747578a19 100644 --- a/registry.go +++ b/registry.go @@ -49,7 +49,10 @@ func Send(m Messagable) (err error) { return nil } - sessionID := SessionID{BeginString: string(beginString), TargetCompID: string(targetCompID), SenderCompID: string(senderCompID)} + var targetSubID FIXString + msg.Header.GetField(tagTargetSubID, &targetSubID) + + sessionID := SessionID{BeginString: string(beginString), TargetCompID: string(targetCompID), SenderCompID: string(senderCompID), TargetSubID: string(targetSubID)} return SendToTarget(msg, sessionID) } From 831392f017a0930837732c95d6468280410bb7b8 Mon Sep 17 00:00:00 2001 From: Matt Rasband <2184696+mattrasband@users.noreply.github.com> Date: Fri, 3 Jun 2022 08:43:38 -0600 Subject: [PATCH 28/47] Allow stores to fall back to global settings for dynamic sessions * Dynamic sessions are not added to the settings until after the session factory has created the sessions. In this scenario the filestore and sqlstore are unable to get the settings and fail to create the various message stores. Often these settings are set globally so we should try falling back before failing to create the message store. --- filestore.go | 10 +++++++++- sqlstore.go | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/filestore.go b/filestore.go index 2a548cadb..e0766fd08 100644 --- a/filestore.go +++ b/filestore.go @@ -61,10 +61,18 @@ func NewFileStoreFactory(settings *Settings) MessageStoreFactory { // Create creates a new FileStore implementation of the MessageStore interface. func (f fileStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err error) { + globalSettings := f.settings.GlobalSettings() + dynamicSessions, _ := globalSettings.BoolSetting(config.DynamicSessions) + sessionSettings, ok := f.settings.SessionSettings()[sessionID] if !ok { - return nil, fmt.Errorf("unknown session: %v", sessionID) + if dynamicSessions { + sessionSettings = globalSettings + } else { + return nil, fmt.Errorf("unknown session: %v", sessionID) + } } + dirname, err := sessionSettings.Setting(config.FileStorePath) if err != nil { return nil, err diff --git a/sqlstore.go b/sqlstore.go index 6ff8ac225..5e492be2c 100644 --- a/sqlstore.go +++ b/sqlstore.go @@ -67,10 +67,18 @@ func NewSQLStoreFactory(settings *Settings) MessageStoreFactory { // Create creates a new SQLStore implementation of the MessageStore interface. func (f sqlStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err error) { + globalSettings := f.settings.GlobalSettings() + dynamicSessions, _ := globalSettings.BoolSetting(config.DynamicSessions) + sessionSettings, ok := f.settings.SessionSettings()[sessionID] if !ok { - return nil, fmt.Errorf("unknown session: %v", sessionID) + if dynamicSessions { + sessionSettings = globalSettings + } else { + return nil, fmt.Errorf("unknown session: %v", sessionID) + } } + sqlDriver, err := sessionSettings.Setting(config.SQLStoreDriver) if err != nil { return nil, err From 0dd076e88623a3a1b4a54266ada1412f3815437c Mon Sep 17 00:00:00 2001 From: Matt Rasband <2184696+mattrasband@users.noreply.github.com> Date: Fri, 3 Jun 2022 08:50:21 -0600 Subject: [PATCH 29/47] Include mongostore in fixes to #484 --- mongostore.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mongostore.go b/mongostore.go index c9bc37ac2..290cdc236 100644 --- a/mongostore.go +++ b/mongostore.go @@ -61,9 +61,16 @@ func NewMongoStoreFactoryPrefixed(settings *Settings, collectionsPrefix string) // Create creates a new MongoStore implementation of the MessageStore interface. func (f mongoStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err error) { + globalSettings := f.settings.GlobalSettings() + dynamicSessions, _ := globalSettings.BoolSetting(config.DynamicSessions) + sessionSettings, ok := f.settings.SessionSettings()[sessionID] if !ok { - return nil, fmt.Errorf("unknown session: %v", sessionID) + if dynamicSessions { + sessionSettings = globalSettings + } else { + return nil, fmt.Errorf("unknown session: %v", sessionID) + } } mongoConnectionURL, err := sessionSettings.Setting(config.MongoStoreConnection) if err != nil { From 111c2093bac07c0f13e63647005ac515f4d847ba Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Mon, 30 Jan 2023 22:18:02 -0600 Subject: [PATCH 30/47] Clean-up unused --- message.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/message.go b/message.go index efe964395..6fd769186 100644 --- a/message.go +++ b/message.go @@ -205,7 +205,6 @@ func ParseMessageWithDataDictionary( return } - //prevTag := tagMsgType xmlDataLen := 0 xmlDataMsg := false @@ -245,7 +244,6 @@ func ParseMessageWithDataDictionary( msg.bodyBytes = rawBytes } - //prevTag = parsedFieldBytes.tag if parsedFieldBytes.tag == tagXMLDataLen { xmlDataLen, _ = msg.Header.GetInt(tagXMLDataLen) } From a18c8897b5004dc50e54a86329126e9f34b2f717 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Mon, 30 Jan 2023 23:56:51 -0600 Subject: [PATCH 31/47] Revert and fix send message session registry --- fix_string_test.go | 2 ++ registry.go | 8 ++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/fix_string_test.go b/fix_string_test.go index c17a69d3c..4f3712333 100644 --- a/fix_string_test.go +++ b/fix_string_test.go @@ -44,6 +44,8 @@ func TestFIXStringRead(t *testing.T) { expectError bool }{ {[]byte("blah"), "blah", false}, + {nil, "", false}, + {[]byte(""), "", false}, } for _, test := range tests { diff --git a/registry.go b/registry.go index 747578a19..291d44bee 100644 --- a/registry.go +++ b/registry.go @@ -45,14 +45,10 @@ func Send(m Messagable) (err error) { var senderCompID FIXString if err := msg.Header.GetField(tagSenderCompID, &senderCompID); err != nil { - - return nil + return err } - var targetSubID FIXString - msg.Header.GetField(tagTargetSubID, &targetSubID) - - sessionID := SessionID{BeginString: string(beginString), TargetCompID: string(targetCompID), SenderCompID: string(senderCompID), TargetSubID: string(targetSubID)} + sessionID := SessionID{BeginString: string(beginString), TargetCompID: string(targetCompID), SenderCompID: string(senderCompID)} return SendToTarget(msg, sessionID) } From 1f4e57093df54e957b5c92a8413d11522d6e64a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 01:36:37 +0000 Subject: [PATCH 32/47] Bump github.com/stretchr/testify from 1.8.1 to 1.8.2 Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.2. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.2) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 10cbdb8b1..30a566aaa 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 github.com/pkg/errors v0.9.1 github.com/shopspring/decimal v1.3.1 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.2 go.mongodb.org/mongo-driver v1.11.1 golang.org/x/net v0.5.0 ) diff --git a/go.sum b/go.sum index 376aa7687..bfabda208 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= From 06a24e1e2ce6cd13be0db1d02daa86b2d11dc239 Mon Sep 17 00:00:00 2001 From: Sai G Date: Tue, 28 Feb 2023 17:10:49 -0500 Subject: [PATCH 33/47] Remove tag from field map --- field_map.go | 8 ++++++++ field_map_test.go | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/field_map.go b/field_map.go index e940790f5..17903ed17 100644 --- a/field_map.go +++ b/field_map.go @@ -227,6 +227,14 @@ func (m *FieldMap) SetString(tag Tag, value string) *FieldMap { return m.SetBytes(tag, []byte(value)) } +// Remove removes a tag from field map +func (m *FieldMap) Remove(tag Tag) { + m.rwLock.Lock() + defer m.rwLock.Unlock() + + delete(m.tagLookup, tag) +} + // Clear purges all fields from field map. func (m *FieldMap) Clear() { m.rwLock.Lock() diff --git a/field_map_test.go b/field_map_test.go index 5d7da7041..0e9078734 100644 --- a/field_map_test.go +++ b/field_map_test.go @@ -190,3 +190,15 @@ func TestFieldMap_CopyInto(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "a", s) } + +func TestFieldMap_Remove(t *testing.T) { + var fMap FieldMap + fMap.init() + + fMap.SetField(1, FIXString("hello")) + fMap.SetField(2, FIXString("world")) + + fMap.Remove(1) + assert.False(t, fMap.Has(1)) + assert.True(t, fMap.Has(2)) +} From d1ac11dfcef04c2630353abf20800b147c62e0e5 Mon Sep 17 00:00:00 2001 From: Sai G Date: Tue, 28 Feb 2023 17:24:18 -0500 Subject: [PATCH 34/47] fix linter failure --- field_map.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/field_map.go b/field_map.go index 17903ed17..18216f81c 100644 --- a/field_map.go +++ b/field_map.go @@ -227,7 +227,7 @@ func (m *FieldMap) SetString(tag Tag, value string) *FieldMap { return m.SetBytes(tag, []byte(value)) } -// Remove removes a tag from field map +// Remove removes a tag from field map. func (m *FieldMap) Remove(tag Tag) { m.rwLock.Lock() defer m.rwLock.Unlock() From 65ca3790cc5ce48ebdff2fae2b33d9689dd627cf Mon Sep 17 00:00:00 2001 From: Neal Patel Date: Mon, 6 Mar 2023 13:33:36 -0800 Subject: [PATCH 35/47] Add message.Bytes() to avoid string conversion --- message.go | 9 ++++++++- message_test.go | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/message.go b/message.go index 6fd769186..63dca9043 100644 --- a/message.go +++ b/message.go @@ -272,7 +272,6 @@ func ParseMessageWithDataDictionary( } return - } func isHeaderField(tag Tag, dataDict *datadictionary.DataDictionary) bool { @@ -390,6 +389,14 @@ func extractField(parsedFieldBytes *TagValue, buffer []byte) (remBytes []byte, e return buffer[(endIndex + 1):], err } +func (m *Message) Bytes() []byte { + if m.rawMessage != nil { + return m.rawMessage.Bytes() + } + + return m.build() +} + func (m *Message) String() string { if m.rawMessage != nil { return m.rawMessage.String() diff --git a/message_test.go b/message_test.go index 7c5557b9b..9bb223751 100644 --- a/message_test.go +++ b/message_test.go @@ -222,12 +222,14 @@ func (s *MessageSuite) TestCopyIntoMessage() { s.Nil(ParseMessage(s.msg, bytes.NewBufferString(newMsgString))) s.True(s.msg.IsMsgTypeOf("A")) s.Equal(s.msg.String(), newMsgString) + s.Equal(string(s.msg.Bytes()), newMsgString) // clear the source buffer also msgBuf.Reset() s.True(dest.IsMsgTypeOf("D")) s.Equal(dest.String(), renderedString) + s.Equal(string(dest.Bytes()), renderedString) } func checkFieldInt(s *MessageSuite, fields FieldMap, tag, expected int) { From 0e376c451883c23ae1e0e82cab11331adaf09e45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Apr 2023 00:57:53 +0000 Subject: [PATCH 36/47] Bump golang.org/x/net from 0.5.0 to 0.9.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.5.0 to 0.9.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/compare/v0.5.0...v0.9.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 10cbdb8b1..ba85909c4 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.8.1 go.mongodb.org/mongo-driver v1.11.1 - golang.org/x/net v0.5.0 + golang.org/x/net v0.9.0 ) require ( @@ -27,7 +27,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect golang.org/x/crypto v0.3.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/text v0.9.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 376aa7687..d821ac2b7 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -73,8 +73,8 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From b6691d8fed1f6285fa5319b3691bc0e44baadf0c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 May 2023 00:58:03 +0000 Subject: [PATCH 37/47] Bump go.mongodb.org/mongo-driver from 1.11.1 to 1.11.6 Bumps [go.mongodb.org/mongo-driver](https://github.com/mongodb/mongo-go-driver) from 1.11.1 to 1.11.6. - [Release notes](https://github.com/mongodb/mongo-go-driver/releases) - [Commits](https://github.com/mongodb/mongo-go-driver/compare/v1.11.1...v1.11.6) --- updated-dependencies: - dependency-name: go.mongodb.org/mongo-driver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 10cbdb8b1..d3b7bcff2 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.8.1 - go.mongodb.org/mongo-driver v1.11.1 + go.mongodb.org/mongo-driver v1.11.6 golang.org/x/net v0.5.0 ) diff --git a/go.sum b/go.sum index 376aa7687..df339f816 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= -go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8= -go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= +go.mongodb.org/mongo-driver v1.11.6 h1:XM7G6PjiGAO5betLF13BIa5TlLUUE3uJ/2Ox3Lz1K+o= +go.mongodb.org/mongo-driver v1.11.6/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= From a02cb5144189b138eca02a5a578708ab1c60272f Mon Sep 17 00:00:00 2001 From: Adam Krieg Date: Tue, 2 Nov 2021 16:50:10 -0400 Subject: [PATCH 38/47] Add support for QuickfixJ option FileStoreSync which controls whether we wait until the write hits the filesystem for each write --- config/configuration.go | 1 + filestore.go | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/config/configuration.go b/config/configuration.go index 431be8ea7..1d70f75c7 100644 --- a/config/configuration.go +++ b/config/configuration.go @@ -50,6 +50,7 @@ const ( HeartBtIntOverride string = "HeartBtIntOverride" FileLogPath string = "FileLogPath" FileStorePath string = "FileStorePath" + FileStoreSync string = "FileStoreSync" SQLStoreDriver string = "SQLStoreDriver" SQLStoreDataSourceName string = "SQLStoreDataSourceName" SQLStoreConnMaxLifetime string = "SQLStoreConnMaxLifetime" diff --git a/filestore.go b/filestore.go index e0766fd08..120ba83c0 100644 --- a/filestore.go +++ b/filestore.go @@ -52,6 +52,7 @@ type fileStore struct { sessionFile *os.File senderSeqNumsFile *os.File targetSeqNumsFile *os.File + fileSync bool } // NewFileStoreFactory returns a file-based implementation of MessageStoreFactory. @@ -77,10 +78,19 @@ func (f fileStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, er if err != nil { return nil, err } - return newFileStore(sessionID, dirname) + var fsync bool + if sessionSettings.HasSetting(config.FileStoreSync) { + fsync, err = sessionSettings.BoolSetting(config.FileStoreSync) + if err != nil { + return nil, err + } + } else { + fsync = true //existing behavior is to fsync writes + } + return newFileStore(sessionID, dirname, fsync) } -func newFileStore(sessionID SessionID, dirname string) (*fileStore, error) { +func newFileStore(sessionID SessionID, dirname string, fileSync bool) (*fileStore, error) { if err := os.MkdirAll(dirname, os.ModePerm); err != nil { return nil, err } @@ -96,6 +106,7 @@ func newFileStore(sessionID SessionID, dirname string) (*fileStore, error) { sessionFname: path.Join(dirname, fmt.Sprintf("%s.%s", sessionPrefix, "session")), senderSeqNumsFname: path.Join(dirname, fmt.Sprintf("%s.%s", sessionPrefix, "senderseqnums")), targetSeqNumsFname: path.Join(dirname, fmt.Sprintf("%s.%s", sessionPrefix, "targetseqnums")), + fileSync: fileSync, } if err := store.Refresh(); err != nil { @@ -232,8 +243,10 @@ func (store *fileStore) setSession() error { if _, err := store.sessionFile.Write(data); err != nil { return fmt.Errorf("unable to write to file: %s: %s", store.sessionFname, err.Error()) } - if err := store.sessionFile.Sync(); err != nil { - return fmt.Errorf("unable to flush file: %s: %s", store.sessionFname, err.Error()) + if store.fileSync { + if err := store.sessionFile.Sync(); err != nil { + return fmt.Errorf("unable to flush file: %s: %s", store.sessionFname, err.Error()) + } } return nil } @@ -245,8 +258,10 @@ func (store *fileStore) setSeqNum(f *os.File, seqNum int) error { if _, err := fmt.Fprintf(f, "%019d", seqNum); err != nil { return fmt.Errorf("unable to write to file: %s: %s", f.Name(), err.Error()) } - if err := f.Sync(); err != nil { - return fmt.Errorf("unable to flush file: %s: %s", f.Name(), err.Error()) + if store.fileSync { + if err := f.Sync(); err != nil { + return fmt.Errorf("unable to flush file: %s: %s", f.Name(), err.Error()) + } } return nil } @@ -313,11 +328,13 @@ func (store *fileStore) SaveMessage(seqNum int, msg []byte) error { if _, err := store.bodyFile.Write(msg); err != nil { return fmt.Errorf("unable to write to file: %s: %s", store.bodyFname, err.Error()) } - if err := store.bodyFile.Sync(); err != nil { - return fmt.Errorf("unable to flush file: %s: %s", store.bodyFname, err.Error()) - } - if err := store.headerFile.Sync(); err != nil { - return fmt.Errorf("unable to flush file: %s: %s", store.headerFname, err.Error()) + if store.fileSync { + if err := store.bodyFile.Sync(); err != nil { + return fmt.Errorf("unable to flush file: %s: %s", store.bodyFname, err.Error()) + } + if err := store.headerFile.Sync(); err != nil { + return fmt.Errorf("unable to flush file: %s: %s", store.headerFname, err.Error()) + } } store.offsets[seqNum] = msgDef{offset: offset, size: len(msg)} From a353cb0fc9b9743b86199888194d407b687f30ef Mon Sep 17 00:00:00 2001 From: Adam Krieg Date: Tue, 31 Aug 2021 16:49:24 -0400 Subject: [PATCH 39/47] Prevent staleness check from happening during replay, which can necesssarily involve receiving old messages --- resend_state_test.go | 30 ++++++++++++++++++++++++++++++ session.go | 10 +++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/resend_state_test.go b/resend_state_test.go index 093660d85..88a2ee8de 100644 --- a/resend_state_test.go +++ b/resend_state_test.go @@ -17,6 +17,7 @@ package quickfix import ( "testing" + "time" "github.com/stretchr/testify/suite" @@ -189,3 +190,32 @@ func (s *resendStateTestSuite) TestFixMsgInResendChunk() { s.FieldEquals(tagBeginSeqNo, 3, s.MockApp.lastToAdmin.Body) s.FieldEquals(tagEndSeqNo, 0, s.MockApp.lastToAdmin.Body) } + +//TestFixMsgResendWithOldSendingTime Tests that we suspend staleness checks during replay +//as a replayed message may be arbitrarily old +func (s *resendStateTestSuite) TestFixMsgResendWithOldSendingTime() { + s.session.State = inSession{} + s.ResendRequestChunkSize = 2 + + //in session expects seq number 1, send too high + s.MessageFactory.SetNextSeqNum(4) + s.MockApp.On("ToAdmin") + + msgSeqNum4 := s.NewOrderSingle() + s.fixMsgIn(s.session, msgSeqNum4) + + s.MockApp.AssertExpectations(s.T()) + s.State(resendState{}) + s.LastToAdminMessageSent() + s.MessageType(string(msgTypeResendRequest), s.MockApp.lastToAdmin) + s.FieldEquals(tagBeginSeqNo, 1, s.MockApp.lastToAdmin.Body) + s.FieldEquals(tagEndSeqNo, 2, s.MockApp.lastToAdmin.Body) + s.NextTargetMsgSeqNum(1) + + msgSeqNum5 := s.NewOrderSingle() + //set the sending time far enough in the past to trip the staleness check + msgSeqNum5.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now().Add(-s.MaxLatency)}) + s.fixMsgIn(s.session, msgSeqNum5) + s.State(resendState{}) + s.NextTargetMsgSeqNum(1) +} diff --git a/session.go b/session.go index e3a89b07c..ab53935e5 100644 --- a/session.go +++ b/session.go @@ -516,10 +516,14 @@ func (s *session) verifySelect(msg *Message, checkTooHigh bool, checkTooLow bool return reject } - if reject := s.checkSendingTime(msg); reject != nil { - return reject + switch s.stateMachine.State.(type) { + case resendState: + //Don't check staleness of a replay + default: + if reject := s.checkSendingTime(msg); reject != nil { + return reject + } } - if checkTooLow { if reject := s.checkTargetTooLow(msg); reject != nil { return reject From 6dbde4ab7d80d12e14ec1a8b243334bd894aaf36 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Sun, 7 May 2023 22:00:40 -0500 Subject: [PATCH 40/47] Update resend_state_test.go --- resend_state_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resend_state_test.go b/resend_state_test.go index 88a2ee8de..d6bd0eb50 100644 --- a/resend_state_test.go +++ b/resend_state_test.go @@ -191,13 +191,13 @@ func (s *resendStateTestSuite) TestFixMsgInResendChunk() { s.FieldEquals(tagEndSeqNo, 0, s.MockApp.lastToAdmin.Body) } -//TestFixMsgResendWithOldSendingTime Tests that we suspend staleness checks during replay -//as a replayed message may be arbitrarily old +// TestFixMsgResendWithOldSendingTime tests that we suspend staleness checks during replay +// as a replayed message may be arbitrarily old. func (s *resendStateTestSuite) TestFixMsgResendWithOldSendingTime() { s.session.State = inSession{} s.ResendRequestChunkSize = 2 - //in session expects seq number 1, send too high + // In session expects seq number 1, send too high. s.MessageFactory.SetNextSeqNum(4) s.MockApp.On("ToAdmin") @@ -213,7 +213,7 @@ func (s *resendStateTestSuite) TestFixMsgResendWithOldSendingTime() { s.NextTargetMsgSeqNum(1) msgSeqNum5 := s.NewOrderSingle() - //set the sending time far enough in the past to trip the staleness check + // Set the sending time far enough in the past to trip the staleness check. msgSeqNum5.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now().Add(-s.MaxLatency)}) s.fixMsgIn(s.session, msgSeqNum5) s.State(resendState{}) From 3ce9479197a8f43fa301fbe43dc3864d4b761d43 Mon Sep 17 00:00:00 2001 From: Tiger Lee Date: Thu, 17 Sep 2020 17:47:46 +0800 Subject: [PATCH 41/47] Avoid to block thread while write to a nil channel if session disconnected during sendBytes, session.messageOut may be set to nil before write in session.onDisconnect() --- session.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/session.go b/session.go index ab53935e5..b359245e2 100644 --- a/session.go +++ b/session.go @@ -367,6 +367,11 @@ func (s *session) EnqueueBytesAndSend(msg []byte) { } func (s *session) sendBytes(msg []byte) { + if s.messageOut == nil { + s.log.OnEventf("Failed to send: disconnected") + return + } + s.log.OnOutgoing(msg) s.messageOut <- msg s.stateTimer.Reset(s.HeartBtInt) From 982d831d7e099e3e7f23b9d5bef87558f420787f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 May 2023 00:57:43 +0000 Subject: [PATCH 42/47] Bump golang.org/x/net from 0.9.0 to 0.10.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.9.0 to 0.10.0. - [Commits](https://github.com/golang/net/compare/v0.9.0...v0.10.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b79d1f433..abfef601e 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.8.2 go.mongodb.org/mongo-driver v1.11.6 - golang.org/x/net v0.9.0 + golang.org/x/net v0.10.0 ) require ( diff --git a/go.sum b/go.sum index e7408ef38..42a8a9100 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From f275c045b8e1c79413c753644ac393de8717c88b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 00:57:49 +0000 Subject: [PATCH 43/47] Bump github.com/stretchr/testify from 1.8.2 to 1.8.4 Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.4. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.4) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index abfef601e..d26261e24 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 github.com/pkg/errors v0.9.1 github.com/shopspring/decimal v1.3.1 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.4 go.mongodb.org/mongo-driver v1.11.6 golang.org/x/net v0.10.0 ) diff --git a/go.sum b/go.sum index 42a8a9100..3576f3a2a 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= From 679ec50a70f0124c89c30ac3d8d5ee30f661f2dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jun 2023 00:59:18 +0000 Subject: [PATCH 44/47] Bump github.com/mattn/go-sqlite3 from 1.14.16 to 1.14.17 Bumps [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) from 1.14.16 to 1.14.17. - [Release notes](https://github.com/mattn/go-sqlite3/releases) - [Commits](https://github.com/mattn/go-sqlite3/compare/v1.14.16...v1.14.17) --- updated-dependencies: - dependency-name: github.com/mattn/go-sqlite3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index abfef601e..4cf256c31 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a - github.com/mattn/go-sqlite3 v1.14.16 + github.com/mattn/go-sqlite3 v1.14.17 github.com/pkg/errors v0.9.1 github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.8.2 diff --git a/go.sum b/go.sum index 42a8a9100..c30c84da2 100644 --- a/go.sum +++ b/go.sum @@ -19,8 +19,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= +github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v64GQ= github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= From 60dde0588fa69688b56c594f5cd5bd3bed77fde5 Mon Sep 17 00:00:00 2001 From: Alexandre Thibault Date: Tue, 1 Aug 2023 14:15:48 +0200 Subject: [PATCH 45/47] Check RejectInvalidMessage on FIXT validation Signed-off-by: Alexandre Thibault --- .../14i_RepeatingGroupCountNotEqual.def | 4 +- .../14i_RepeatingGroupCountNotEqual.def | 4 +- validation.go | 12 +- validation_test.go | 424 ++++++++++++++++++ 4 files changed, 435 insertions(+), 9 deletions(-) diff --git a/_test/definitions/server/fix50sp1/14i_RepeatingGroupCountNotEqual.def b/_test/definitions/server/fix50sp1/14i_RepeatingGroupCountNotEqual.def index e223b0410..5fce36436 100644 --- a/_test/definitions/server/fix50sp1/14i_RepeatingGroupCountNotEqual.def +++ b/_test/definitions/server/fix50sp1/14i_RepeatingGroupCountNotEqual.def @@ -11,7 +11,7 @@ E8=FIXT.1.19=6735=A34=149=ISLD52=00000000-00:00:00.00056=TW98=0108=2113 #------------------------ #New order message with incorrect repeating group "count". NoTradingSessions (386) -I8=FIXT.1.135=D34=249=TW52=