├── go ├── BSDmakefile ├── src │ ├── restincl │ │ ├── restin.ini │ │ ├── README │ │ ├── Makefile │ │ ├── viewsupp.go │ │ ├── fileupload.go │ │ └── transactions.go │ ├── exutil │ │ ├── Makefile │ │ ├── stopwatch.go │ │ └── caroots.go │ ├── tcpgatesv │ │ ├── Makefile │ │ ├── xatmipool.go │ │ ├── outseq.go │ │ ├── netin.go │ │ ├── periodic.go │ │ └── atmiout.go │ ├── Makefile │ ├── restoutsv │ │ ├── Makefile │ │ ├── periodic.go │ │ ├── jsonerror.go │ │ ├── xatmipool.go │ │ └── viewsupp.go │ └── ubftab │ │ └── Makefile └── Makefile ├── tests ├── 01_restin │ ├── binary.test.response │ ├── binary.test.request │ ├── BSDmakefile │ ├── runtime │ │ ├── bin │ │ │ ├── testsv │ │ │ ├── trancl │ │ │ ├── transv │ │ │ └── restincl │ │ ├── static │ │ │ ├── other.txt │ │ │ └── index.html │ │ ├── ubftab │ │ │ └── test.fd │ │ ├── viewdir │ │ │ └── restin.V │ │ └── conf │ │ │ ├── gencert.sh │ │ │ └── ndrxconfig.xml │ ├── src │ │ ├── viewdir │ │ │ ├── Makefile │ │ │ └── restin.v_in │ │ ├── Makefile │ │ ├── trancl │ │ │ └── Makefile │ │ ├── transv │ │ │ ├── Makefile │ │ │ └── transv.go │ │ ├── testsv │ │ │ ├── Makefile │ │ │ ├── textsv.go │ │ │ ├── binary.go │ │ │ ├── regexp.go │ │ │ ├── cookies.go │ │ │ ├── jsonsv.go │ │ │ ├── fileupload.go │ │ │ └── viewsv.go │ │ └── ubftab │ │ │ ├── Makefile │ │ │ └── test.fd │ └── Makefile ├── 02_tcpgatesv │ ├── src │ │ ├── exutil │ │ ├── Makefile │ │ ├── testcl │ │ │ └── Makefile │ │ ├── testsv │ │ │ ├── Makefile │ │ │ └── seqtest.go │ │ └── ubftab │ │ │ ├── Makefile │ │ │ └── test.fd │ ├── BSDmakefile │ ├── runtime │ │ ├── bin │ │ │ ├── testcl │ │ │ ├── testsv │ │ │ └── tcpgatesv │ │ ├── ubftab │ │ │ └── test.fd │ │ └── conf │ │ │ ├── gencert.sh │ │ │ └── ndrxconfig.xml │ └── Makefile ├── 03_restout │ ├── BSDmakefile │ ├── runtime │ │ ├── bin │ │ │ ├── testcl │ │ │ ├── bigmsgsv │ │ │ ├── restincl │ │ │ ├── testsv │ │ │ └── restoutsv │ │ ├── ubftab │ │ │ └── test.fd │ │ ├── viewdir │ │ ├── conf │ │ │ ├── debug.ini │ │ │ ├── gencert.sh │ │ │ ├── ndrxconfig.xml │ │ │ ├── restin.ini │ │ │ └── restout.ini │ │ └── test.ud │ ├── src │ │ ├── viewdir │ │ ├── Makefile │ │ ├── testcl │ │ │ ├── Makefile │ │ │ └── testcl.go │ │ ├── bigmsgsv │ │ │ ├── Makefile │ │ │ └── testsv.go │ │ └── ubftab │ │ │ ├── Makefile │ │ │ └── test.fd │ └── Makefile ├── Makefile └── run.sh ├── doc ├── restinout_tutor_1.dia ├── restinout_tutor_1.png ├── pers_sync_net_to_ex.dia ├── pers_sync_net_to_ex.png ├── nonpers_sync_ex_to_net.dia ├── nonpers_sync_ex_to_net.png ├── nonpers_sync_net_to_ex.dia ├── nonpers_sync_net_to_ex.png ├── pers_async_net_to_ex_w_corr.dia ├── pers_async_net_to_ex_w_corr.png ├── pers_sync_ex_to_net_connid.dia ├── pers_sync_ex_to_net_connid.png ├── Makefile ├── pers_async_ex_to_net_wo_corr.dia ├── pers_async_ex_to_net_wo_corr.png ├── pers_async_net_to_ex_wo_corr.dia ├── pers_async_net_to_ex_wo_corr.png ├── manpage │ └── Makefile └── Mdoc ├── Makefile ├── .gitignore ├── pkg ├── README └── CMakeLists.txt └── README.md /go/BSDmakefile: -------------------------------------------------------------------------------- 1 | all clean: 2 | gmake $@ 3 | -------------------------------------------------------------------------------- /tests/01_restin/binary.test.response: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /tests/01_restin/binary.test.request: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/src/exutil: -------------------------------------------------------------------------------- 1 | ../../../go/src/exutil -------------------------------------------------------------------------------- /tests/01_restin/BSDmakefile: -------------------------------------------------------------------------------- 1 | all clean: 2 | gmake $@ 3 | -------------------------------------------------------------------------------- /tests/01_restin/runtime/bin/testsv: -------------------------------------------------------------------------------- 1 | ../../src/testsv/testsv -------------------------------------------------------------------------------- /tests/01_restin/runtime/bin/trancl: -------------------------------------------------------------------------------- 1 | ../../src/trancl/trancl -------------------------------------------------------------------------------- /tests/01_restin/runtime/bin/transv: -------------------------------------------------------------------------------- 1 | ../../src/transv/transv -------------------------------------------------------------------------------- /tests/03_restout/BSDmakefile: -------------------------------------------------------------------------------- 1 | all clean: 2 | gmake $@ 3 | -------------------------------------------------------------------------------- /tests/03_restout/runtime/bin/testcl: -------------------------------------------------------------------------------- 1 | ../../src/testcl/testcl -------------------------------------------------------------------------------- /tests/03_restout/src/viewdir: -------------------------------------------------------------------------------- 1 | ../../01_restin/src/viewdir/ -------------------------------------------------------------------------------- /tests/01_restin/runtime/static/other.txt: -------------------------------------------------------------------------------- 1 | Some other file 2 | -------------------------------------------------------------------------------- /tests/01_restin/runtime/ubftab/test.fd: -------------------------------------------------------------------------------- 1 | ../../src/ubftab/test.fd -------------------------------------------------------------------------------- /tests/02_tcpgatesv/BSDmakefile: -------------------------------------------------------------------------------- 1 | all clean: 2 | gmake $@ 3 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/runtime/bin/testcl: -------------------------------------------------------------------------------- 1 | ../../src/testcl/testcl -------------------------------------------------------------------------------- /tests/02_tcpgatesv/runtime/bin/testsv: -------------------------------------------------------------------------------- 1 | ../../src/testsv/testsv -------------------------------------------------------------------------------- /tests/03_restout/runtime/ubftab/test.fd: -------------------------------------------------------------------------------- 1 | ../../src/ubftab/test.fd -------------------------------------------------------------------------------- /tests/03_restout/runtime/viewdir: -------------------------------------------------------------------------------- 1 | ../../01_restin/src/viewdir -------------------------------------------------------------------------------- /tests/01_restin/runtime/viewdir/restin.V: -------------------------------------------------------------------------------- 1 | ../../src/viewdir/restin.V -------------------------------------------------------------------------------- /tests/02_tcpgatesv/runtime/ubftab/test.fd: -------------------------------------------------------------------------------- 1 | ../../src/ubftab/test.fd -------------------------------------------------------------------------------- /tests/03_restout/runtime/bin/bigmsgsv: -------------------------------------------------------------------------------- 1 | ../../src/bigmsgsv/bigmsgsv -------------------------------------------------------------------------------- /tests/01_restin/runtime/bin/restincl: -------------------------------------------------------------------------------- 1 | ../../../../go/src/restincl/restincl -------------------------------------------------------------------------------- /tests/03_restout/runtime/bin/restincl: -------------------------------------------------------------------------------- 1 | ../../../../go/src/restincl/restincl -------------------------------------------------------------------------------- /tests/03_restout/runtime/bin/testsv: -------------------------------------------------------------------------------- 1 | ../../../01_restin/src/testsv/testsv -------------------------------------------------------------------------------- /go/src/restincl/restin.ini: -------------------------------------------------------------------------------- 1 | ../../../tests/01_restin/runtime/conf/restin.ini -------------------------------------------------------------------------------- /tests/02_tcpgatesv/runtime/bin/tcpgatesv: -------------------------------------------------------------------------------- 1 | ../../../../go/src/tcpgatesv/tcpgatesv -------------------------------------------------------------------------------- /tests/03_restout/runtime/bin/restoutsv: -------------------------------------------------------------------------------- 1 | ../../../../go/src/restoutsv/restoutsv -------------------------------------------------------------------------------- /doc/restinout_tutor_1.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/restinout_tutor_1.dia -------------------------------------------------------------------------------- /doc/restinout_tutor_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/restinout_tutor_1.png -------------------------------------------------------------------------------- /doc/pers_sync_net_to_ex.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_sync_net_to_ex.dia -------------------------------------------------------------------------------- /doc/pers_sync_net_to_ex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_sync_net_to_ex.png -------------------------------------------------------------------------------- /doc/nonpers_sync_ex_to_net.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/nonpers_sync_ex_to_net.dia -------------------------------------------------------------------------------- /doc/nonpers_sync_ex_to_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/nonpers_sync_ex_to_net.png -------------------------------------------------------------------------------- /doc/nonpers_sync_net_to_ex.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/nonpers_sync_net_to_ex.dia -------------------------------------------------------------------------------- /doc/nonpers_sync_net_to_ex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/nonpers_sync_net_to_ex.png -------------------------------------------------------------------------------- /tests/01_restin/runtime/static/index.html: -------------------------------------------------------------------------------- 1 |
This is title
Hello world 2 | -------------------------------------------------------------------------------- /doc/pers_async_net_to_ex_w_corr.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_async_net_to_ex_w_corr.dia -------------------------------------------------------------------------------- /doc/pers_async_net_to_ex_w_corr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_async_net_to_ex_w_corr.png -------------------------------------------------------------------------------- /doc/pers_sync_ex_to_net_connid.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_sync_ex_to_net_connid.dia -------------------------------------------------------------------------------- /doc/pers_sync_ex_to_net_connid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_sync_ex_to_net_connid.png -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | $(MAKE) -f Mdoc 3 | $(MAKE) -C manpage 4 | clean: 5 | $(MAKE) -f Mdoc clean 6 | $(MAKE) -C manpage clean 7 | -------------------------------------------------------------------------------- /doc/pers_async_ex_to_net_wo_corr.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_async_ex_to_net_wo_corr.dia -------------------------------------------------------------------------------- /doc/pers_async_ex_to_net_wo_corr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_async_ex_to_net_wo_corr.png -------------------------------------------------------------------------------- /doc/pers_async_net_to_ex_wo_corr.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_async_net_to_ex_wo_corr.dia -------------------------------------------------------------------------------- /doc/pers_async_net_to_ex_wo_corr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/endurox-dev/endurox-connect/HEAD/doc/pers_async_net_to_ex_wo_corr.png -------------------------------------------------------------------------------- /go/src/restincl/README: -------------------------------------------------------------------------------- 1 | Create an atmi client, read from socket, pipe done via channel to pool. 2 | For config use NDRX_CCTAG env as sub-section. 3 | -------------------------------------------------------------------------------- /go/Makefile: -------------------------------------------------------------------------------- 1 | export GOPATH=$(shell pwd) 2 | export GO111MODULE=auto 3 | 4 | all: 5 | $(MAKE) -C src 6 | 7 | clean: 8 | rm -rf pkg bin 9 | $(MAKE) -C src clean 10 | 11 | 12 | .PHONY: clean all 13 | -------------------------------------------------------------------------------- /tests/03_restout/runtime/conf/debug.ini: -------------------------------------------------------------------------------- 1 | [@debug] 2 | testcl= ndrx=3 ubf=1 tp=3 file=${NDRX_APPHOME}/log/testcl.log threaded=y 3 | testsv= ndrx=3 ubf=1 tp=3 file=${NDRX_APPHOME}/log/testsv.log threaded=y 4 | 5 | -------------------------------------------------------------------------------- /tests/03_restout/runtime/test.ud: -------------------------------------------------------------------------------- 1 | SRVCNM JUERRORS 2 | T_CHAR_FLD A 3 | T_SHORT_FLD 123 4 | T_LONG_FLD 444444444 5 | T_FLOAT_FLD 1.33 6 | T_DOUBLE_FLD 4444.3333 7 | T_STRING_FLD HELLO 8 | T_CARRAY_FLD WORLD 9 | 10 | -------------------------------------------------------------------------------- /tests/01_restin/src/viewdir/Makefile: -------------------------------------------------------------------------------- 1 | 2 | unexport VIEWDIR 3 | unexport VIEWFILES 4 | 5 | .DEFAULT_GOAL := restin.V 6 | 7 | restin.V: restin.v_in 8 | viewc -n restin.v_in 9 | 10 | 11 | clean: 12 | -rm *.V 13 | -------------------------------------------------------------------------------- /tests/01_restin/Makefile: -------------------------------------------------------------------------------- 1 | export GOPATH=$(shell pwd) 2 | export GO111MODULE=auto 3 | 4 | all: 5 | $(MAKE) -C src 6 | 7 | clean: 8 | rm -rf pkg bin 9 | $(MAKE) -C src clean 10 | 11 | 12 | 13 | .PHONY: clean all 14 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/Makefile: -------------------------------------------------------------------------------- 1 | export GOPATH=$(shell pwd) 2 | export GO111MODULE=auto 3 | 4 | all: 5 | $(MAKE) -C src 6 | 7 | clean: 8 | rm -rf pkg bin 9 | $(MAKE) -C src clean 10 | 11 | 12 | 13 | .PHONY: clean all 14 | -------------------------------------------------------------------------------- /tests/03_restout/Makefile: -------------------------------------------------------------------------------- 1 | export GOPATH=$(shell pwd) 2 | export GO111MODULE=auto 3 | 4 | all: 5 | $(MAKE) -C src 6 | 7 | clean: 8 | rm -rf pkg bin 9 | $(MAKE) -C src clean 10 | 11 | 12 | 13 | .PHONY: clean all 14 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | # Do recursive builds 2 | all: 3 | $(MAKE) -C 01_restin 4 | $(MAKE) -C 02_tcpgatesv 5 | $(MAKE) -C 03_restout 6 | 7 | clean: 8 | $(MAKE) -C 01_restin clean 9 | $(MAKE) -C 02_tcpgatesv clean 10 | $(MAKE) -C 03_restout clean 11 | 12 | .PHONY: clean all 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | .PHONY: all pkg clean doc 4 | 5 | 6 | # Do recursive builds 7 | all: 8 | $(MAKE) -C go 9 | $(MAKE) -C tests 10 | cd pkg && cmake . 11 | 12 | clean: 13 | $(MAKE) -C tests clean 14 | $(MAKE) -C go clean 15 | 16 | doc: 17 | $(MAKE) -C doc 18 | 19 | pkg: all 20 | cd pkg && cpack 21 | 22 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/src/Makefile: -------------------------------------------------------------------------------- 1 | # Do recursive builds 2 | all: 3 | go get -u github.com/endurox-dev/endurox-go && cd github.com/endurox-dev/endurox-go && git checkout v8.0 4 | $(MAKE) -C ubftab 5 | $(MAKE) -C testsv 6 | $(MAKE) -C testcl 7 | 8 | clean: 9 | $(MAKE) -C ubftab clean 10 | $(MAKE) -C testsv clean 11 | $(MAKE) -C testcl clean 12 | 13 | .PHONY: clean all 14 | -------------------------------------------------------------------------------- /tests/03_restout/src/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go get -u github.com/endurox-dev/endurox-go && cd github.com/endurox-dev/endurox-go && git checkout v8.0 3 | $(MAKE) -C ubftab 4 | $(MAKE) -C testcl 5 | $(MAKE) -C viewdir 6 | $(MAKE) -C bigmsgsv 7 | 8 | clean: 9 | $(MAKE) -C ubftab clean 10 | $(MAKE) -C testcl clean 11 | $(MAKE) -C viewdir clean 12 | $(MAKE) -C bigmsgsv clean 13 | 14 | 15 | .PHONY: clean all 16 | 17 | -------------------------------------------------------------------------------- /go/src/exutil/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 4 | 5 | LIBRARY=exutil 6 | LDFLAGS= 7 | 8 | VERSION=1.0.0 9 | BUILD_TIME=`date +%FT%T%z` 10 | 11 | .DEFAULT_GOAL: $(LIBRARY) 12 | 13 | $(LIBRARY): $(SOURCES) 14 | go build ${LDFLAGS} -o ${LIBRARY} *.go 15 | go install ${LDFLAGS} ./... 16 | 17 | .PHONY: clean 18 | clean: 19 | if [ -f ${LIBRARY} ] ; then rm ${LIBRARY} ; fi 20 | 21 | -------------------------------------------------------------------------------- /tests/01_restin/src/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | go get -u github.com/endurox-dev/endurox-go && cd github.com/endurox-dev/endurox-go && git checkout v8.0 3 | $(MAKE) -C ubftab 4 | $(MAKE) -C testsv 5 | $(MAKE) -C transv 6 | $(MAKE) -C trancl 7 | $(MAKE) -C viewdir 8 | 9 | clean: 10 | $(MAKE) -C ubftab clean 11 | $(MAKE) -C testsv clean 12 | $(MAKE) -C transv clean 13 | $(MAKE) -C trancl clean 14 | $(MAKE) -C viewdir clean 15 | 16 | 17 | .PHONY: clean all 18 | -------------------------------------------------------------------------------- /go/src/tcpgatesv/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 4 | 5 | BINARY=tcpgatesv 6 | LDFLAGS= 7 | 8 | VERSION=1.0.0 9 | BUILD_TIME=`date +%FT%T%z` 10 | 11 | .DEFAULT_GOAL: $(BINARY) 12 | 13 | $(BINARY): $(SOURCES) 14 | go build ${LDFLAGS} -o ${BINARY} *.go 15 | 16 | .PHONY: install 17 | install: 18 | go install ${LDFLAGS} ./... 19 | 20 | .PHONY: clean 21 | clean: 22 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 23 | -------------------------------------------------------------------------------- /tests/01_restin/src/trancl/Makefile: -------------------------------------------------------------------------------- 1 | SOURCEDIR=. 2 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 3 | 4 | BINARY=trancl 5 | LDFLAGS= 6 | 7 | VERSION=1.0.0 8 | BUILD_TIME=`date +%FT%T%z` 9 | 10 | .DEFAULT_GOAL: $(BINARY) 11 | 12 | $(BINARY): $(SOURCES) 13 | go build ${LDFLAGS} -o ${BINARY} *.go 14 | 15 | .PHONY: install 16 | install: 17 | go install ${LDFLAGS} ./... 18 | 19 | .PHONY: clean 20 | clean: 21 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 22 | -------------------------------------------------------------------------------- /tests/01_restin/src/transv/Makefile: -------------------------------------------------------------------------------- 1 | SOURCEDIR=. 2 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 3 | 4 | BINARY=transv 5 | LDFLAGS= 6 | 7 | VERSION=1.0.0 8 | BUILD_TIME=`date +%FT%T%z` 9 | 10 | .DEFAULT_GOAL: $(BINARY) 11 | 12 | $(BINARY): $(SOURCES) 13 | go build ${LDFLAGS} -o ${BINARY} *.go 14 | 15 | .PHONY: install 16 | install: 17 | go install ${LDFLAGS} ./... 18 | 19 | .PHONY: clean 20 | clean: 21 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 22 | -------------------------------------------------------------------------------- /tests/01_restin/src/testsv/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 4 | 5 | BINARY=testsv 6 | LDFLAGS= 7 | 8 | VERSION=1.0.0 9 | BUILD_TIME=`date +%FT%T%z` 10 | 11 | .DEFAULT_GOAL: $(BINARY) 12 | 13 | $(BINARY): $(SOURCES) 14 | go build ${LDFLAGS} -o ${BINARY} *.go 15 | 16 | .PHONY: install 17 | install: 18 | go install ${LDFLAGS} ./... 19 | 20 | .PHONY: clean 21 | clean: 22 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 23 | -------------------------------------------------------------------------------- /tests/03_restout/src/testcl/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 4 | 5 | BINARY=testcl 6 | LDFLAGS= 7 | 8 | VERSION=1.0.0 9 | BUILD_TIME=`date +%FT%T%z` 10 | 11 | .DEFAULT_GOAL: $(BINARY) 12 | 13 | $(BINARY): $(SOURCES) 14 | go build ${LDFLAGS} -o ${BINARY} *.go 15 | 16 | .PHONY: install 17 | install: 18 | go install ${LDFLAGS} ./... 19 | 20 | .PHONY: clean 21 | clean: 22 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 23 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/src/testcl/Makefile: -------------------------------------------------------------------------------- 1 | SOURCEDIR=. 2 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 3 | 4 | BINARY=testcl 5 | LDFLAGS= 6 | 7 | VERSION=1.0.0 8 | BUILD_TIME=`date +%FT%T%z` 9 | 10 | .DEFAULT_GOAL: $(BINARY) 11 | 12 | $(BINARY): $(SOURCES) 13 | go build ${LDFLAGS} -o ${BINARY} *.go 14 | 15 | .PHONY: install 16 | install: 17 | go install ${LDFLAGS} ./... 18 | 19 | .PHONY: clean 20 | 21 | clean: 22 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 23 | -------------------------------------------------------------------------------- /tests/03_restout/src/bigmsgsv/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 4 | 5 | BINARY=bigmsgsv 6 | LDFLAGS= 7 | 8 | VERSION=1.0.0 9 | BUILD_TIME=`date +%FT%T%z` 10 | 11 | .DEFAULT_GOAL: $(BINARY) 12 | 13 | $(BINARY): $(SOURCES) 14 | go build ${LDFLAGS} -o ${BINARY} *.go 15 | 16 | .PHONY: install 17 | install: 18 | go install ${LDFLAGS} ./... 19 | 20 | .PHONY: clean 21 | clean: 22 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 23 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/src/testsv/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 4 | 5 | BINARY=testsv 6 | #LDFLAGS=-race 7 | LDFLAGS= 8 | 9 | VERSION=1.0.0 10 | BUILD_TIME=`date +%FT%T%z` 11 | 12 | .DEFAULT_GOAL: $(BINARY) 13 | 14 | $(BINARY): $(SOURCES) 15 | go build ${LDFLAGS} -o ${BINARY} *.go 16 | 17 | .PHONY: install 18 | install: 19 | go install ${LDFLAGS} ./... 20 | 21 | .PHONY: clean 22 | clean: 23 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 24 | -------------------------------------------------------------------------------- /go/src/Makefile: -------------------------------------------------------------------------------- 1 | # Do recursive builds 2 | all: 3 | go get -u github.com/endurox-dev/endurox-go && cd github.com/endurox-dev/endurox-go && git checkout v8.0 4 | $(MAKE) -C ubftab 5 | $(MAKE) -C exutil 6 | $(MAKE) -C restincl 7 | $(MAKE) -C restoutsv 8 | $(MAKE) -C tcpgatesv 9 | 10 | clean: 11 | - rm -rf github.com/endurox-dev 12 | $(MAKE) -C ubftab clean 13 | $(MAKE) -C exutil clean 14 | $(MAKE) -C restincl clean 15 | $(MAKE) -C restoutsv clean 16 | $(MAKE) -C tcpgatesv clean 17 | 18 | .PHONY: clean 19 | -------------------------------------------------------------------------------- /go/src/restincl/Makefile: -------------------------------------------------------------------------------- 1 | SOURCEDIR=. 2 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 3 | 4 | BINARY=restincl 5 | 6 | VERSION=1.0.0 7 | BUILD_TIME=`date +%FT%T%z` 8 | 9 | #LDFLAGS=-ldflags "-X github.com/ariejan/roll/core.Version=${VERSION} -X github.com/ariejan/roll/core.BuildTime=${BUILD_TIME}" 10 | 11 | .DEFAULT_GOAL: $(BINARY) 12 | 13 | $(BINARY): $(SOURCES) 14 | go build ${LDFLAGS} -o ${BINARY} *.go 15 | 16 | .PHONY: install 17 | install: 18 | go install ${LDFLAGS} ./... 19 | 20 | .PHONY: clean 21 | clean: 22 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 23 | -------------------------------------------------------------------------------- /go/src/restoutsv/Makefile: -------------------------------------------------------------------------------- 1 | SOURCEDIR=. 2 | SOURCES := $(shell find $(SOURCEDIR) -name '*.go') 3 | 4 | BINARY=restoutsv 5 | 6 | VERSION=1.0.0 7 | BUILD_TIME=`date +%FT%T%z` 8 | 9 | #LDFLAGS=-ldflags "-X github.com/ariejan/roll/core.Version=${VERSION} -X github.com/ariejan/roll/core.BuildTime=${BUILD_TIME}" 10 | 11 | .DEFAULT_GOAL: $(BINARY) 12 | 13 | $(BINARY): $(SOURCES) 14 | go build ${LDFLAGS} -o ${BINARY} *.go 15 | 16 | .PHONY: install 17 | install: 18 | go install ${LDFLAGS} ./... 19 | 20 | .PHONY: clean 21 | clean: 22 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 23 | -------------------------------------------------------------------------------- /go/src/ubftab/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.fd') 4 | SOURCES += Exfields 5 | 6 | OUTPUT = $(addsuffix .go, $(SOURCES)) 7 | 8 | comma:= , 9 | empty:= 10 | space:= $(empty) $(empty) 11 | 12 | export FIELDTBLS=$(subst $(space),$(comma),$(SOURCES)) 13 | export FLDTBLDIR=$(shell pwd) 14 | 15 | $(info $$SOURCES is [${SOURCES}]) 16 | $(info $$OUTPUT is [${OUTPUT}]) 17 | $(info $$FIELDTBLS is [${FIELDTBLS}]) 18 | 19 | PACKAGE=ubftab 20 | 21 | .DEFAULT_GOAL: $(OUTPUT) 22 | LDFLAGS= 23 | 24 | $(OUTPUT): $(SOURCES) 25 | mkfldhdr -m1 -p${PACKAGE} 26 | go build ${LDFLAGS} -o ${PACKAGE} *.go 27 | go install ${LDFLAGS} ./... 28 | 29 | .PHONY: clean 30 | clean: 31 | - rm *.go ${PACKAGE} 32 | -------------------------------------------------------------------------------- /tests/01_restin/src/ubftab/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.fd') 4 | SOURCES += Exfields 5 | 6 | OUTPUT = $(addsuffix .go, $(SOURCES)) 7 | 8 | comma:= , 9 | empty:= 10 | space:= $(empty) $(empty) 11 | 12 | export FIELDTBLS=$(subst $(space),$(comma),$(SOURCES)) 13 | export FLDTBLDIR=$(shell pwd) 14 | 15 | $(info $$SOURCES is [${SOURCES}]) 16 | $(info $$OUTPUT is [${OUTPUT}]) 17 | $(info $$FIELDTBLS is [${FIELDTBLS}]) 18 | 19 | PACKAGE=ubftab 20 | 21 | .DEFAULT_GOAL: $(OUTPUT) 22 | LDFLAGS= 23 | 24 | $(OUTPUT): $(SOURCES) 25 | mkfldhdr -m1 -p${PACKAGE} 26 | go build ${LDFLAGS} -o ${PACKAGE} *.go 27 | go install ${LDFLAGS} ./... 28 | 29 | .PHONY: clean 30 | clean: 31 | - rm *.go 32 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/src/ubftab/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.fd') 4 | SOURCES += Exfields 5 | 6 | OUTPUT = $(addsuffix .go, $(SOURCES)) 7 | 8 | comma:= , 9 | empty:= 10 | space:= $(empty) $(empty) 11 | 12 | export FIELDTBLS=$(subst $(space),$(comma),$(SOURCES)) 13 | export FLDTBLDIR=$(shell pwd) 14 | 15 | $(info $$SOURCES is [${SOURCES}]) 16 | $(info $$OUTPUT is [${OUTPUT}]) 17 | $(info $$FIELDTBLS is [${FIELDTBLS}]) 18 | 19 | PACKAGE=ubftab 20 | 21 | .DEFAULT_GOAL: $(OUTPUT) 22 | LDFLAGS= 23 | 24 | $(OUTPUT): $(SOURCES) 25 | mkfldhdr -m1 -p${PACKAGE} 26 | go build ${LDFLAGS} -o ${PACKAGE} *.go 27 | go install ${LDFLAGS} ./... 28 | 29 | .PHONY: clean 30 | clean: 31 | - rm *.go 32 | -------------------------------------------------------------------------------- /tests/03_restout/src/ubftab/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCEDIR=. 3 | SOURCES := $(shell find $(SOURCEDIR) -name '*.fd') 4 | SOURCES += Exfields 5 | 6 | OUTPUT = $(addsuffix .go, $(SOURCES)) 7 | 8 | comma:= , 9 | empty:= 10 | space:= $(empty) $(empty) 11 | 12 | export FIELDTBLS=$(subst $(space),$(comma),$(SOURCES)) 13 | export FLDTBLDIR=$(shell pwd) 14 | 15 | $(info $$SOURCES is [${SOURCES}]) 16 | $(info $$OUTPUT is [${OUTPUT}]) 17 | $(info $$FIELDTBLS is [${FIELDTBLS}]) 18 | 19 | PACKAGE=ubftab 20 | 21 | .DEFAULT_GOAL: $(OUTPUT) 22 | LDFLAGS= 23 | 24 | $(OUTPUT): $(SOURCES) 25 | mkfldhdr -m1 -p${PACKAGE} 26 | go build ${LDFLAGS} -o ${PACKAGE} *.go 27 | go install ${LDFLAGS} ./... 28 | 29 | .PHONY: clean 30 | clean: 31 | - rm *.go 32 | -------------------------------------------------------------------------------- /tests/01_restin/src/testsv/textsv.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import atmi "github.com/endurox-dev/endurox-go" 4 | 5 | //Text service 6 | //@param ac ATMI Context 7 | //@param svc Service call information 8 | func TEXTSV(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 9 | 10 | ret := SUCCEED 11 | 12 | //Get UBF Handler 13 | sb, _ := ac.CastToString(&svc.Data) 14 | 15 | //Return to the caller 16 | defer func() { 17 | if SUCCEED == ret { 18 | ac.TpReturn(atmi.TPSUCCESS, 0, sb, 0) 19 | } else { 20 | ac.TpReturn(atmi.TPFAIL, 0, sb, 0) 21 | } 22 | }() 23 | 24 | ac.TpLogWarn("Got string request...") 25 | 26 | ac.TpLogInfo("Got text: [%s]", sb.GetString()) 27 | 28 | sb.SetString("Hello from EnduroX") 29 | 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /tests/01_restin/src/testsv/binary.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | atmi "github.com/endurox-dev/endurox-go" 5 | ) 6 | 7 | //Binary service 8 | //@param ac ATMI Context 9 | //@param svc Service call information 10 | func BINARYSV(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 11 | 12 | ret := SUCCEED 13 | 14 | //Get UBF Handler 15 | bb, _ := ac.CastToCarray(&svc.Data) 16 | 17 | //Return to the caller 18 | defer func() { 19 | if SUCCEED == ret { 20 | ac.TpReturn(atmi.TPSUCCESS, 0, bb, 0) 21 | } else { 22 | ac.TpReturn(atmi.TPFAIL, 0, bb, 0) 23 | } 24 | }() 25 | 26 | bb.GetBytes() 27 | ac.TpLogDump(atmi.LOG_INFO, "Got binary request buffer", 28 | bb.GetBytes(), len(bb.GetBytes())) 29 | 30 | bb.SetBytes([]byte{9,8,7,6,5,4,3,2,1,0}) 31 | 32 | ac.TpLogDump(atmi.LOG_INFO, "Responding with buffer", bb.GetBytes(), 33 | len(bb.GetBytes())) 34 | 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /tests/01_restin/src/viewdir/restin.v_in: -------------------------------------------------------------------------------- 1 | VIEW REQUEST1 2 | #type cname fbname count flag size null 3 | 4 | short tshort1 - 1 - - - 5 | long tlong1 - 1 - - - 6 | string tstring1 - 3 - 18 - 7 | 8 | # Response 9 | int rspcode - 1 - - - 10 | string rspmessage - 1 - 255 - 11 | 12 | END 13 | 14 | # 15 | # This do not have resposne fields inside 16 | # 17 | VIEW REQUEST2 18 | #type cname fbname count flag size null 19 | 20 | short tshort2 - 1 - - - 21 | long tlong2 - 1 - - - 22 | string tstring2 - 1 - 20 - 23 | 24 | END 25 | 26 | # 27 | # Pure resposne object, and short response message field to test trucate 28 | # 29 | VIEW RSPV 30 | #type cname fbname count flag size null 31 | int rspcode - 1 - - - 32 | string rspmessage - 1 - 4 - 33 | END 34 | 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | go/pkg/ 2 | go/src/exutil/exutil 3 | go/src/github.com/ 4 | go/src/restincl/restincl 5 | go/src/restoutsv/restoutsv 6 | go/src/tcpgatesv/tcpgatesv 7 | go/src/ubftab/Exfields.go 8 | go/src/ubftab/ubftab 9 | pkg/CMakeCache.txt 10 | pkg/CMakeFiles/ 11 | pkg/CPackConfig.cmake 12 | pkg/CPackSourceConfig.cmake 13 | pkg/Makefile 14 | pkg/cmake_install.cmake 15 | tests/01_restin/pkg/ 16 | tests/01_restin/src/github.com/ 17 | tests/01_restin/src/testsv/testsv 18 | tests/01_restin/src/ubftab/Exfields.go 19 | tests/01_restin/src/ubftab/test.fd.go 20 | tests/01_restin/src/ubftab/ubftab 21 | tests/02_tcpgatesv/pkg/ 22 | tests/02_tcpgatesv/src/github.com/ 23 | tests/02_tcpgatesv/src/testcl/testcl 24 | tests/02_tcpgatesv/src/testsv/testsv 25 | tests/02_tcpgatesv/src/ubftab/Exfields.go 26 | tests/02_tcpgatesv/src/ubftab/test.fd.go 27 | tests/02_tcpgatesv/src/ubftab/ubftab 28 | tests/03_restout/pkg/ 29 | tests/03_restout/src/github.com/ 30 | tests/03_restout/src/testcl/testcl 31 | tests/03_restout/src/ubftab/Exfields.go 32 | tests/03_restout/src/ubftab/test.fd.go 33 | tests/03_restout/src/ubftab/ubftab 34 | -------------------------------------------------------------------------------- /tests/01_restin/src/testsv/regexp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import atmi "github.com/endurox-dev/endurox-go" 4 | 5 | //Regexp UBF service 6 | //@param ac ATMI Context 7 | //@param svc Service call information 8 | func REGEXP(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 9 | 10 | ret := SUCCEED 11 | 12 | //Get UBF Handler 13 | ub, _ := ac.CastToUBF(&svc.Data) 14 | 15 | //Return to the caller 16 | defer func() { 17 | if SUCCEED == ret { 18 | ac.TpReturn(atmi.TPSUCCESS, 0, ub, 0) 19 | } else { 20 | ac.TpReturn(atmi.TPFAIL, 0, ub, 0) 21 | } 22 | }() 23 | 24 | ac.TpLogInfo("Got UBF: [%v]", ub) 25 | 26 | return 27 | } 28 | 29 | //Regexp JSON service 30 | //@param ac ATMI Context 31 | //@param svc Service call information 32 | func REGEXPJSON(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 33 | 34 | ret := SUCCEED 35 | 36 | //Get UBF Handler 37 | jb, _ := ac.CastToJSON(&svc.Data) 38 | 39 | //Return to the caller 40 | defer func() { 41 | if SUCCEED == ret { 42 | ac.TpReturn(atmi.TPSUCCESS, 0, jb, 0) 43 | } else { 44 | ac.TpReturn(atmi.TPFAIL, 0, jb, 0) 45 | } 46 | }() 47 | 48 | ac.TpLogInfo("Got json: [%v]", jb) 49 | 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/runtime/conf/gencert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Generate test CA, Client cert, Server Cert 5 | # 6 | 7 | TEST_HOSTNAME=`hostname` 8 | echo "Host name is [$TEST_HOSTNAME]" 9 | 10 | set -x 11 | 12 | echo "subjectAltName=DNS:$TEST_HOSTNAME" > altsubj.ext 13 | 14 | # Generate root CA 15 | openssl req -nodes -x509 -newkey rsa:2048 -keyout ca.key -out ca.crt -subj "/C=LV/ST=RIGA/L=Riga/O=Endurox_CA/OU=root/CN=$TEST_HOSTNAME/emailAddress=test@mavimax.com" 16 | 17 | # Generate server cert 18 | openssl req -nodes -newkey rsa:2048 -keyout server.key -out server.csr -subj "/C=LV/ST=RIGA/L=Riga/O=Endurox_SV/OU=root/CN=$TEST_HOSTNAME/emailAddress=test@mavimax.com" 19 | 20 | # Sign server cert 21 | openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -extfile altsubj.ext 22 | 23 | # Generate client cert 24 | openssl req -nodes -newkey rsa:2048 -keyout client.key -out client.csr -subj "/C=LV/ST=RIGA/L=Riga/O=Endurox_CL/OU=root/CN=$TEST_HOSTNAME/emailAddress=test@mavimax.com" 25 | 26 | # Sign client cert 27 | openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAserial ca.srl -out client.crt -extfile altsubj.ext 28 | 29 | -------------------------------------------------------------------------------- /tests/01_restin/src/ubftab/test.fd: -------------------------------------------------------------------------------- 1 | 2 | $#ifndef __TEST_FD 3 | $#define __TEST_FD 4 | 5 | *base 6000 6 | 7 | 8 | T_CHAR_FLD 11 char - 1 Chart test field 1 9 | T_CHAR_2_FLD 12 char - 1 Chart test field 2 10 | T_SHORT_FLD 21 short - 1 Short test field 1 11 | T_SHORT_2_FLD 22 short - 1 Short test field 2 12 | T_LONG_FLD 31 long - 1 Long test field 1 13 | T_LONG_2_FLD 32 long - 1 Long test field 2 14 | T_FLOAT_FLD 41 float - 1 Float test field 1 15 | T_FLOAT_2_FLD 42 float - 1 Float test field 2 16 | T_FLOAT_3_FLD 43 float - 1 Float test field 3 17 | T_DOUBLE_FLD 51 double - 1 Double test field 1 18 | T_DOUBLE_2_FLD 52 double - 1 Double test field 2 19 | T_DOUBLE_3_FLD 53 double - 1 Double test field 3 20 | T_DOUBLE_4_FLD 54 double - 1 Double test field 4 21 | T_STRING_FLD 61 string - 1 String test field 1 22 | T_STRING_2_FLD 62 string - 1 String test field 2 23 | T_STRING_3_FLD 63 string - 1 String test field 3 24 | T_STRING_4_FLD 64 string - 1 String test field 4 25 | T_STRING_5_FLD 65 string - 1 String test field 5 26 | T_STRING_6_FLD 66 string - 1 String test field 6 27 | T_STRING_7_FLD 67 string - 1 String test field 7 28 | T_STRING_8_FLD 68 string - 1 String test field 8 29 | T_STRING_9_FLD 69 string - 1 String test field 9 30 | T_STRING_10_FLD 10 string - 1 String test field 10 31 | T_CARRAY_FLD 81 carray - 1 Carray test field 1 32 | T_CARRAY_2_FLD 82 carray - 1 Carray test field 2 33 | 34 | 35 | $#endif 36 | -------------------------------------------------------------------------------- /tests/03_restout/src/ubftab/test.fd: -------------------------------------------------------------------------------- 1 | 2 | $#ifndef __TEST_FD 3 | $#define __TEST_FD 4 | 5 | *base 6000 6 | 7 | 8 | T_CHAR_FLD 11 char - 1 Chart test field 1 9 | T_CHAR_2_FLD 12 char - 1 Chart test field 2 10 | T_SHORT_FLD 21 short - 1 Short test field 1 11 | T_SHORT_2_FLD 22 short - 1 Short test field 2 12 | T_LONG_FLD 31 long - 1 Long test field 1 13 | T_LONG_2_FLD 32 long - 1 Long test field 2 14 | T_FLOAT_FLD 41 float - 1 Float test field 1 15 | T_FLOAT_2_FLD 42 float - 1 Float test field 2 16 | T_FLOAT_3_FLD 43 float - 1 Float test field 3 17 | T_DOUBLE_FLD 51 double - 1 Double test field 1 18 | T_DOUBLE_2_FLD 52 double - 1 Double test field 2 19 | T_DOUBLE_3_FLD 53 double - 1 Double test field 3 20 | T_DOUBLE_4_FLD 54 double - 1 Double test field 4 21 | T_STRING_FLD 61 string - 1 String test field 1 22 | T_STRING_2_FLD 62 string - 1 String test field 2 23 | T_STRING_3_FLD 63 string - 1 String test field 3 24 | T_STRING_4_FLD 64 string - 1 String test field 4 25 | T_STRING_5_FLD 65 string - 1 String test field 5 26 | T_STRING_6_FLD 66 string - 1 String test field 6 27 | T_STRING_7_FLD 67 string - 1 String test field 7 28 | T_STRING_8_FLD 68 string - 1 String test field 8 29 | T_STRING_9_FLD 69 string - 1 String test field 9 30 | T_STRING_10_FLD 10 string - 1 String test field 10 31 | T_CARRAY_FLD 81 carray - 1 Carray test field 1 32 | T_CARRAY_2_FLD 82 carray - 1 Carray test field 2 33 | 34 | 35 | $#endif 36 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/src/ubftab/test.fd: -------------------------------------------------------------------------------- 1 | 2 | $#ifndef __TEST_FD 3 | $#define __TEST_FD 4 | 5 | *base 6000 6 | 7 | 8 | T_CHAR_FLD 11 char - 1 Chart test field 1 9 | T_CHAR_2_FLD 12 char - 1 Chart test field 2 10 | T_SHORT_FLD 21 short - 1 Short test field 1 11 | T_SHORT_2_FLD 22 short - 1 Short test field 2 12 | T_LONG_FLD 31 long - 1 Long test field 1 13 | T_LONG_2_FLD 32 long - 1 Long test field 2 14 | T_FLOAT_FLD 41 float - 1 Float test field 1 15 | T_FLOAT_2_FLD 42 float - 1 Float test field 2 16 | T_FLOAT_3_FLD 43 float - 1 Float test field 3 17 | T_DOUBLE_FLD 51 double - 1 Double test field 1 18 | T_DOUBLE_2_FLD 52 double - 1 Double test field 2 19 | T_DOUBLE_3_FLD 53 double - 1 Double test field 3 20 | T_DOUBLE_4_FLD 54 double - 1 Double test field 4 21 | T_STRING_FLD 61 string - 1 String test field 1 22 | T_STRING_2_FLD 62 string - 1 String test field 2 23 | T_STRING_3_FLD 63 string - 1 String test field 3 24 | T_STRING_4_FLD 64 string - 1 String test field 4 25 | T_STRING_5_FLD 65 string - 1 String test field 5 26 | T_STRING_6_FLD 66 string - 1 String test field 6 27 | T_STRING_7_FLD 67 string - 1 String test field 7 28 | T_STRING_8_FLD 68 string - 1 String test field 8 29 | T_STRING_9_FLD 69 string - 1 String test field 9 30 | T_STRING_10_FLD 10 string - 1 String test field 10 31 | T_CARRAY_FLD 81 carray - 1 Carray test field 1 32 | T_CARRAY_2_FLD 82 carray - 1 Carray test field 2 33 | 34 | 35 | $#endif 36 | -------------------------------------------------------------------------------- /pkg/README: -------------------------------------------------------------------------------- 1 | Using cmake as pacakge generator 2 | 3 | Releases: 4 | 5 | 6 | 2.0.0 - Completed restin/restout/tcpgate 7 | 2.1.2 - Fixes of Bug #200, Bug #201 8 | 2.1.3 - Feature #204 9 | 2.1.4 - View support in restincl 10 | 2.2.1 - (development version) Bug #225, works on restout view support 11 | 2.2.2 - (stable version) Bug #227 12 | 2.3.0 - Support for big message size 13 | 2.4.0 - Support for message length offset and keep header - Feature #273 14 | 2.4.2 - Feature #278 - provide compiled connection id to status service 15 | 2.4.3 - Feature #289 - print in log file caller ip address from which restin got call 16 | 2.4.5 - Works on Bug #285 (in progress) 17 | 2.4.6 - Finished Bug #285 18 | 2.4.8 - Fixed #305 19 | 2.4.10 - Implemented Feature #340 20 | 2.4.12 - Fixed Bug #356 21 | 2.4.14 - Implemented Feature #384 - static content serving 22 | 2.4.16 - Feature #377 - ext mode (in/out filters) 23 | 2.4.18 - Bug #461 24 | 2.4.20 - Updates on ext mode processing now body is loaded into EX_IF_REQDATA/EX_IF_RSPDATA fields 25 | 2.4.22 - Feature #509 - added EX_IF_METHOD for ext (web method post/get, etc..) 26 | 2.4.24 - Feature #531 - Optmizations (linger flag, less data array compies, quicker copies) 27 | 2.4.26 - Feature #596 - tls support in tcpgatesv 28 | 2.4.28 - Bug #607 - tcpgatesv if invalid tls_ca_roots is given, no error is returned 29 | 2.4.30 - Feature #606 - file upload 30 | 2.5.0 - Feature #640 - transactions API 31 | 8.0.0 - Building against endurox-go@v8.0, Support #754, Bug #757 32 | 8.0.2 - Bug #770, Support #780 33 | 8.0.4 - Bug #800 34 | 2.5.2 - Bug #770 35 | -------------------------------------------------------------------------------- /tests/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # @(#) Integration tests 5 | # 6 | 7 | # have some limits... 8 | ulimit -n 50000 9 | ulimit -c unlimited 10 | 11 | # Load other config... stack size, etc 12 | source ~/ndrx_home 13 | 14 | # 15 | # Temporary fix for Support #754 16 | # 17 | export GODEBUG="asyncpreemptoff=1" 18 | 19 | > ./test.out 20 | # Have some terminal output... 21 | tail -f test.out & 22 | 23 | ( 24 | M_tests=0 25 | M_ok=0 26 | M_fail=0 27 | 28 | run_test () { 29 | 30 | test=$1 31 | M_tests=$((M_tests + 1)) 32 | echo "*** RUNNING [$test]" 33 | 34 | pushd . 35 | cd $test 36 | ./run.sh 37 | ret=$? 38 | popd 39 | 40 | echo "*** RESULT [$test] $ret" 41 | 42 | if [[ $ret -eq 0 ]]; then 43 | M_ok=$((M_ok + 1)) 44 | else 45 | M_fail=$((M_fail + 1)) 46 | fi 47 | } 48 | 49 | run_test "01_restin" 50 | run_test "02_tcpgatesv" 51 | run_test "03_restout" 52 | 53 | ################################################################################ 54 | # Print results in out file 55 | # use temp file to avoid plotting to the same file which are are grepping... 56 | ################################################################################ 57 | grep RESULT test.out >test.out.tmp 58 | cat test.out.tmp 59 | rm test.out.tmp 60 | ################################################################################ 61 | 62 | echo "*** SUMMARY $M_tests tests executed. $M_ok passes, $M_fail failures" 63 | 64 | # wait for tail to pick the change 65 | sleep 5 66 | xadmin killall tail 67 | 68 | exit $M_fail 69 | 70 | ) > test.out 2>&1 71 | 72 | -------------------------------------------------------------------------------- /tests/01_restin/src/testsv/cookies.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "ubftab" 5 | 6 | atmi "github.com/endurox-dev/endurox-go" 7 | ) 8 | 9 | //Cookies UBF service 10 | //@param ac ATMI Context 11 | //@param svc Service call information 12 | func COOKIES(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 13 | 14 | ret := SUCCEED 15 | 16 | //Get UBF Handler 17 | ub, _ := ac.CastToUBF(&svc.Data) 18 | 19 | //Return to the caller 20 | defer func() { 21 | if SUCCEED == ret { 22 | ac.TpReturn(atmi.TPSUCCESS, 0, ub, 0) 23 | } else { 24 | ac.TpReturn(atmi.TPFAIL, 0, ub, 0) 25 | } 26 | }() 27 | 28 | //Resize buffer, to have some more space 29 | if err := ub.TpRealloc(1024); err != nil { 30 | ac.TpLogError("TpRealloc() Got error: %d:[%s]\n", err.Code(), err.Message()) 31 | ret = FAIL 32 | return 33 | } 34 | 35 | //Print the buffer to stdout 36 | ub.TpLogPrintUBF(atmi.LOG_DEBUG, "Incoming request:") 37 | 38 | ac.TpLogDebug("Set Header & Cookies data") 39 | 40 | ub.BAdd(ubftab.EX_IF_RSPHN, "Accept-Language") 41 | ub.BAdd(ubftab.EX_IF_RSPHV, "EN-US") 42 | 43 | ub.BAdd(ubftab.EX_IF_RSPHN, "Last-Modified") 44 | ub.BAdd(ubftab.EX_IF_RSPHV, "Tue, 31 Aug 2063 23:59:59 GMT") 45 | 46 | // Set Cookie data 47 | ub.BAdd(ubftab.EX_IF_RSPCN, "RspCookie") 48 | ub.BAdd(ubftab.EX_IF_RSPCV, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq") 49 | ub.BAdd(ubftab.EX_IF_RSPCPATH, "/cookie/path") 50 | ub.BAdd(ubftab.EX_IF_RSPCDOMAIN, "localhost.com") 51 | ub.BAdd(ubftab.EX_IF_RSPCEXPIRES, "Thu, 08 Nov 2018 10:13:34 GMT") 52 | ub.BAdd(ubftab.EX_IF_RSPCMAXAGE, "3600") 53 | ub.BAdd(ubftab.EX_IF_RSPCSECURE, "AAA") 54 | ub.BAdd(ubftab.EX_IF_RSPCHTTPONLY, "true") 55 | 56 | ac.TpLogInfo("Got UBF: [%v]", ub) 57 | 58 | return 59 | } 60 | -------------------------------------------------------------------------------- /tests/03_restout/runtime/conf/gencert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bash shell script for generating self-signed certs. Run this in a folder, as it 4 | # generates a few files. Large portions of this script were taken from the 5 | # following artcile: 6 | # 7 | # http://usrportage.de/archives/919-Batch-generating-SSL-certificates.html 8 | # 9 | # Additional alterations by: Brad Landers 10 | # Date: 2012-01-27 11 | 12 | # Script accepts a single argument, the fqdn for the cert 13 | DOMAIN="$1" 14 | if [ -z "$DOMAIN" ]; then 15 | echo "Usage: $(basename $0) " 16 | exit 11 17 | fi 18 | 19 | fail_if_error() { 20 | [ $1 != 0 ] && { 21 | unset PASSPHRASE 22 | exit 10 23 | } 24 | } 25 | 26 | # Generate a passphrase 27 | #export PASSPHRASE=$(head -c 500 /dev/urandom | tr -dc a-z0-9A-Z | head -c 128; echo) 28 | export PASSPHRASE=ABCDEFABCDEF 29 | 30 | # Certificate details; replace items in angle brackets with your own info 31 | subj=" 32 | C=US 33 | ST=CA 34 | O=TEST 35 | localityName=NY 36 | commonName=$DOMAIN 37 | organizationalUnitName=EX 38 | emailAddress=test@example.com 39 | " 40 | 41 | # Generate the server private key 42 | openssl genrsa -des3 -out $DOMAIN.key -passout env:PASSPHRASE 2048 43 | fail_if_error $? 44 | 45 | # Generate the CSR 46 | openssl req \ 47 | -new \ 48 | -batch \ 49 | -subj "$(echo -n "$subj" | tr "\n" "/")" \ 50 | -key $DOMAIN.key \ 51 | -out $DOMAIN.csr \ 52 | -passin env:PASSPHRASE 53 | fail_if_error $? 54 | cp $DOMAIN.key $DOMAIN.key.org 55 | fail_if_error $? 56 | 57 | # Strip the password so we don't have to type it every time we restart Apache 58 | openssl rsa -in $DOMAIN.key.org -out $DOMAIN.key -passin env:PASSPHRASE 59 | fail_if_error $? 60 | 61 | # Generate the cert (good for 10 years) 62 | openssl x509 -req -days 3650 -in $DOMAIN.csr -signkey $DOMAIN.key -out $DOMAIN.crt 63 | fail_if_error $? 64 | 65 | -------------------------------------------------------------------------------- /tests/01_restin/runtime/conf/gencert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bash shell script for generating self-signed certs. Run this in a folder, as it 4 | # generates a few files. Large portions of this script were taken from the 5 | # following artcile: 6 | # 7 | # http://usrportage.de/archives/919-Batch-generating-SSL-certificates.html 8 | # 9 | # Additional alterations by: Brad Landers 10 | # Date: 2012-01-27 11 | 12 | # Script accepts a single argument, the fqdn for the cert 13 | DOMAIN="$1" 14 | if [ -z "$DOMAIN" ]; then 15 | echo "Usage: $(basename $0) " 16 | exit 11 17 | fi 18 | 19 | fail_if_error() { 20 | [ $1 != 0 ] && { 21 | unset PASSPHRASE 22 | exit 10 23 | } 24 | } 25 | 26 | echo "OPENSSL USED: " 27 | which openssl 28 | echo "OPENSSL END" 29 | 30 | # Generate a passphrase 31 | #export PASSPHRASE=$(head -c 500 /dev/urandom | tr -dc a-z0-9A-Z | head -c 128; echo) 32 | export PASSPHRASE=ABCDEFABCDEF 33 | echo "PASSPHRASE: [$PASSPHRASE]" 34 | 35 | # Certificate details; replace items in angle brackets with your own info 36 | subj=" 37 | C=US 38 | ST=CA 39 | O=TEST 40 | localityName=NY 41 | commonName=$DOMAIN 42 | organizationalUnitName=EX 43 | emailAddress=test@example.com 44 | " 45 | 46 | # Generate the server private key 47 | openssl genrsa -des3 -out $DOMAIN.key -passout env:PASSPHRASE 2048 48 | fail_if_error $? 49 | 50 | # Generate the CSR 51 | openssl req \ 52 | -new \ 53 | -batch \ 54 | -subj "$(echo -n "$subj" | tr "\n" "/")" \ 55 | -key $DOMAIN.key \ 56 | -out $DOMAIN.csr \ 57 | -passin env:PASSPHRASE 58 | fail_if_error $? 59 | cp $DOMAIN.key $DOMAIN.key.org 60 | fail_if_error $? 61 | 62 | # Strip the password so we don't have to type it every time we restart Apache 63 | openssl rsa -in $DOMAIN.key.org -out $DOMAIN.key -passin env:PASSPHRASE 64 | fail_if_error $? 65 | 66 | # Generate the cert (good for 10 years) 67 | openssl x509 -req -days 3650 -in $DOMAIN.csr -signkey $DOMAIN.key -out $DOMAIN.crt 68 | fail_if_error $? 69 | 70 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/src/testsv/seqtest.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | u "ubftab" 5 | 6 | atmi "github.com/endurox-dev/endurox-go" 7 | ) 8 | 9 | var Msequence byte = 0 10 | 11 | var Mmsgs int64 = 0 //messages received 12 | 13 | //Test message sequence (seqin/seqout) 14 | //@param ac ATMI Context 15 | //@param svc Service call information 16 | func SEQTEST(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 17 | 18 | ret := SUCCEED 19 | 20 | //Return to the caller 21 | defer func() { 22 | 23 | ac.TpLogCloseReqFile() 24 | if SUCCEED == ret { 25 | ac.TpReturn(atmi.TPSUCCESS, 0, &svc.Data, 0) 26 | } else { 27 | ac.TpReturn(atmi.TPFAIL, 0, &svc.Data, 0) 28 | } 29 | }() 30 | 31 | //Get UBF Handler 32 | ub, _ := ac.CastToUBF(&svc.Data) 33 | 34 | //Print the buffer to stdout 35 | //fmt.Println("Incoming request:") 36 | ub.TpLogPrintUBF(atmi.LOG_DEBUG, "TESTSVC: Incoming request:") 37 | 38 | ba, err := ub.BGetByteArr(u.EX_NETDATA, 0) 39 | 40 | if err != nil { 41 | ac.TpLogError("TESTERROR Failed to get EX_NETDATA: %s", err.Message()) 42 | ret = FAIL 43 | return 44 | } 45 | 46 | if ba[0] != Msequence { 47 | 48 | ac.TpLogError("TESTERROR: Expected %d got %d", Msequence, ba[0]) 49 | 50 | } 51 | 52 | Mmsgs++; 53 | Msequence++ 54 | 55 | return 56 | } 57 | 58 | //Return number of messages sequenced 59 | func SEQRES(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 60 | 61 | ret := SUCCEED 62 | 63 | //Return to the caller 64 | defer func() { 65 | 66 | ac.TpLogCloseReqFile() 67 | if SUCCEED == ret { 68 | ac.TpReturn(atmi.TPSUCCESS, 0, &svc.Data, 0) 69 | } else { 70 | ac.TpReturn(atmi.TPFAIL, 0, &svc.Data, 0) 71 | } 72 | }() 73 | 74 | //Get UBF Handler 75 | ub, _ := ac.CastToUBF(&svc.Data) 76 | 77 | used, _ := ub.BUsed() 78 | 79 | //Resize buffer, to have some more space 80 | if err := ub.TpRealloc(used + 1024); err != nil { 81 | ac.TpLogError("TpRealloc() Got error: %d:[%s]\n", err.Code(), err.Message()) 82 | ret = FAIL 83 | return 84 | } 85 | 86 | if err := ub.BChg(u.T_LONG_FLD, 0, Mmsgs); nil != err { 87 | ac.TpLogError("Failed to set T_LONG_FLD: %s", err.Message()) 88 | ret = FAIL 89 | return 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /tests/01_restin/src/testsv/jsonsv.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | atmi "github.com/endurox-dev/endurox-go" 7 | ) 8 | 9 | type TestJSONMsg struct { 10 | StringField string `json:"StringField"` 11 | StringField2 string `json:"StringField2"` 12 | NumField int `json:"NumField"` 13 | NumField2 int `json:"NumField2"` 14 | BoolField bool `json:"BoolField"` 15 | BoolField2 bool `json:"BoolField2"` 16 | } 17 | 18 | //JSON Service, we will receive JSON block 19 | //@param ac ATMI Context 20 | //@param svc Service call information 21 | func JSONSV(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 22 | 23 | var msg TestJSONMsg 24 | ret := SUCCEED 25 | 26 | //Get UBF Handler 27 | jb, _ := ac.CastToJSON(&svc.Data) 28 | 29 | //Return to the caller 30 | defer func() { 31 | if SUCCEED == ret { 32 | ac.TpReturn(atmi.TPSUCCESS, 0, jb, 0) 33 | } else { 34 | ac.TpReturn(atmi.TPFAIL, 0, jb, 0) 35 | } 36 | }() 37 | 38 | ac.TpLogWarn("Got json request...") 39 | 40 | //Resize buffer, to have some more space to return data in 41 | if err := jb.TpRealloc(1024); err != nil { 42 | ac.TpLogError("TpRealloc() Got error: %d:[%s]\n", 43 | err.Code(), err.Message()) 44 | ret = FAIL 45 | return 46 | } 47 | 48 | ac.TpLogDump(atmi.LOG_INFO, "Got request buffer", 49 | jb.GetJSON(), len(jb.GetJSON())) 50 | //Umarshal the data, copy to *2 and marshal back to buffer 51 | jerr := json.Unmarshal(jb.GetJSON(), &msg) 52 | if jerr != nil { 53 | ac.TpLogError("Unmarshal: %s", jerr) 54 | ret = FAIL 55 | return 56 | } 57 | msg.StringField2 = msg.StringField 58 | msg.BoolField2 = msg.BoolField 59 | msg.NumField2 = msg.NumField 60 | 61 | val, jerr := json.Marshal(msg) 62 | if jerr != nil { 63 | ac.TpLogError("Marshal: %s", jerr) 64 | ret = FAIL 65 | return 66 | } 67 | 68 | ac.TpLogDump(atmi.LOG_INFO, "Built response", val, len(val)) 69 | 70 | //Set the data in return buffer 71 | if err := jb.SetJSON(val); err != nil { 72 | ac.TpLogError("Failed to return json buffer %s", err.Message()) 73 | ret = FAIL 74 | return 75 | } 76 | 77 | ac.TpLogDump(atmi.LOG_INFO, "Responding with buffer", jb.GetJSON(), len(jb.GetJSON())) 78 | 79 | return 80 | } 81 | -------------------------------------------------------------------------------- /doc/manpage/Makefile: -------------------------------------------------------------------------------- 1 | ## 2 | ## @brief Enduro/X Addons (connectivity) module documentation 3 | ## 4 | ## @file Makefile 5 | ## 6 | ## ----------------------------------------------------------------------------- 7 | ## Enduro/X Middleware Platform for Distributed Transaction Processing 8 | ## Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | ## Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | ## This software is released under one of the following licenses: 11 | ## AGPL or Mavimax's license for commercial use. 12 | ## ----------------------------------------------------------------------------- 13 | ## AGPL license: 14 | ## 15 | ## This program is free software; you can redistribute it and/or modify it under 16 | ## the terms of the GNU Affero General Public License, version 3 as published 17 | ## by the Free Software Foundation; 18 | ## 19 | ## This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | ## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | ## PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | ## for more details. 23 | ## 24 | ## You should have received a copy of the GNU Affero General Public License along 25 | ## with this program; if not, write to the Free Software Foundation, Inc., 26 | ## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | ## 28 | ## ----------------------------------------------------------------------------- 29 | ## A commercial use license is available from Mavimax, Ltd 30 | ## contact@mavimax.com 31 | ## ----------------------------------------------------------------------------- 32 | ## 33 | 34 | A2X := $(shell a2x --version 2> /dev/null) 35 | 36 | SOURCE_DOCS :=$(shell ls -1 *.adoc) 37 | DOCS := $(patsubst %.adoc, %.8, $(SOURCE_DOCS)) 38 | 39 | .DEFAULT_GOAL := all 40 | 41 | check_asciidoc: 42 | @type a2x >/dev/null 2>&1 || echo "Missing asciidoc - docs will not built" 43 | 44 | all: check_asciidoc $(DOCS) 45 | 46 | # 47 | # Do not remove images 48 | # 49 | .SECONDARY: $(GRAPHS) 50 | 51 | 52 | # 53 | # Build the document 54 | # So translate the % document and use $% 55 | # 56 | %.8: %.adoc 57 | a2x -D. --format=manpage $< 58 | a2x -D. --format=xhtml $< 59 | 60 | clean: 61 | rm -f *.8 *.html *.css 62 | 63 | .PHONY: clean all 64 | 65 | 66 | 67 | # vim: set ts=4 sw=4 et smartindent: 68 | -------------------------------------------------------------------------------- /tests/03_restout/src/bigmsgsv/testsv.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | u "ubftab" 8 | 9 | atmi "github.com/endurox-dev/endurox-go" 10 | ) 11 | 12 | const ( 13 | SUCCEED = 0 14 | FAIL = -1 15 | ) 16 | 17 | //BIGMSG service 18 | func BIGMSG(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 19 | 20 | ret := SUCCEED 21 | 22 | //Get UBF Handler 23 | ub, _ := ac.CastToUBF(&svc.Data) 24 | 25 | //Print the buffer to stdout 26 | //fmt.Println("Incoming request:") 27 | //ub.TpLogPrintUBF(atmi.LOG_DEBUG, "Incoming request:") 28 | ac.TpLogInfo("BIGMSG got call!") 29 | 30 | //Set some field 31 | testdata, err := ub.BGetByteArr(u.T_CARRAY_FLD, 0) 32 | 33 | if err != nil { 34 | fmt.Printf("Bchg() Got error: %d:[%s]\n", err.Code(), err.Message()) 35 | ret = FAIL 36 | goto out 37 | } 38 | 39 | for i := 0; i < len(testdata); i++ { 40 | if testdata[i] != byte((i+1)%255) { 41 | ac.TpLogError("TESTERROR: Error at index %d expected %d got: %d", 42 | i, (i+2)%255, testdata[i]) 43 | ret = FAIL 44 | goto out 45 | } 46 | 47 | testdata[i] = byte((i + 2) % 255) 48 | } 49 | 50 | ac.TpLogInfo("About set test data!") 51 | 52 | if err := ub.BChg(u.T_CARRAY_FLD, 0, testdata); err != nil { 53 | ac.TpLogError("TESTERROR ! Bchg() 2 Got error: %d:[%s]", err.Code(), err.Message()) 54 | ret = FAIL 55 | goto out 56 | } 57 | 58 | out: 59 | //Return to the caller 60 | if SUCCEED == ret { 61 | ac.TpReturn(atmi.TPSUCCESS, 0, ub, 0) 62 | } else { 63 | ac.TpReturn(atmi.TPFAIL, 0, ub, 0) 64 | } 65 | return 66 | } 67 | 68 | //Server init, called when process is booted 69 | //@param ac ATMI Context 70 | func Init(ac *atmi.ATMICtx) int { 71 | 72 | ac.TpLogWarn("Doing server init...") 73 | 74 | if err := ac.TpAdvertise("BIGMSG", "BIGMSG", BIGMSG); err != nil { 75 | fmt.Println(err) 76 | return atmi.FAIL 77 | } 78 | 79 | return atmi.SUCCEED 80 | } 81 | 82 | //Server shutdown 83 | //@param ac ATMI Context 84 | func Uninit(ac *atmi.ATMICtx) { 85 | ac.TpLogWarn("Server is shutting down...") 86 | } 87 | 88 | //Executable main entry point 89 | func main() { 90 | //Have some context 91 | ac, err := atmi.NewATMICtx() 92 | 93 | if nil != err { 94 | fmt.Fprintf(os.Stderr, "Failed to allocate new context: %s", err) 95 | os.Exit(atmi.FAIL) 96 | } else { 97 | //Run as server 98 | ac.TpRun(Init, Uninit) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /go/src/exutil/stopwatch.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Simple stopwatch implementation 3 | * 4 | * @file stopwatch.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package exutil 34 | 35 | import ( 36 | "time" 37 | ) 38 | 39 | //Get UTC milliseconds since epoch 40 | //@return epoch milliseconds 41 | func GetEpochMillis() int64 { 42 | now := time.Now() 43 | nanos := now.UnixNano() 44 | millis := nanos / 1000000 45 | 46 | return millis 47 | } 48 | 49 | //About incoming & outgoing messages: 50 | type StopWatch struct { 51 | start int64 //Timestamp messag sent 52 | } 53 | 54 | //Reset the stopwatch 55 | func (s *StopWatch) Reset() { 56 | s.start = GetEpochMillis() 57 | } 58 | 59 | //Get delta milliseconds 60 | //@return time spent in milliseconds 61 | func (s *StopWatch) GetDeltaMillis() int64 { 62 | return GetEpochMillis() - s.start 63 | } 64 | 65 | //Get delta seconds of the stopwatch 66 | //@return return seconds spent 67 | func (s *StopWatch) GetDetlaSec() int64 { 68 | return (GetEpochMillis() - s.start) / 1000 69 | } 70 | /* vim: set ts=4 sw=4 et smartindent: */ 71 | -------------------------------------------------------------------------------- /doc/Mdoc: -------------------------------------------------------------------------------- 1 | ## 2 | ## @brief Enduro/X Addons (connectivity) module documentation 3 | ## 4 | ## @file Mdoc 5 | ## 6 | ## ----------------------------------------------------------------------------- 7 | ## Enduro/X Middleware Platform for Distributed Transaction Processing 8 | ## Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | ## Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | ## This software is released under one of the following licenses: 11 | ## AGPL or Mavimax's license for commercial use. 12 | ## ----------------------------------------------------------------------------- 13 | ## AGPL license: 14 | ## 15 | ## This program is free software; you can redistribute it and/or modify it under 16 | ## the terms of the GNU Affero General Public License, version 3 as published 17 | ## by the Free Software Foundation; 18 | ## 19 | ## This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | ## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | ## PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | ## for more details. 23 | ## 24 | ## You should have received a copy of the GNU Affero General Public License along 25 | ## with this program; if not, write to the Free Software Foundation, Inc., 26 | ## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | ## 28 | ## ----------------------------------------------------------------------------- 29 | ## A commercial use license is available from Mavimax, Ltd 30 | ## contact@mavimax.com 31 | ## ----------------------------------------------------------------------------- 32 | ## 33 | 34 | A2X := $(shell a2x --version 2> /dev/null) 35 | 36 | SOURCE_DOCS :=$(shell ls -1 *.adoc) 37 | DOCS := $(patsubst %.adoc, %.html, $(SOURCE_DOCS)) 38 | 39 | SOURCES_GRAPHS :=$(shell ls -1 *.dia) 40 | GRAPHS := $(patsubst %.dia, %.png, $(SOURCES_GRAPHS)) 41 | 42 | $(info $$SOURCES_GRAPHS is [${SOURCES_GRAPHS}]) 43 | $(info $$GRAPHS is [${GRAPHS}]) 44 | 45 | .DEFAULT_GOAL := all 46 | 47 | check_asciidoc: 48 | @type a2x >/dev/null 2>&1 || echo "Missing asciidoc - docs will not built" 49 | 50 | check_dia: 51 | @type dia >/dev/null 2>&1 || echo "Missing asciidoc - docs will not built" 52 | 53 | all: check_asciidoc check_dia $(DOCS) 54 | 55 | # 56 | # Do not remove images 57 | # 58 | .SECONDARY: $(GRAPHS) 59 | 60 | 61 | # 62 | # Build the images 63 | # Images shall go to "images" folder 64 | # and later shall be copied to "out"/images 65 | # 66 | %.png: %.dia 67 | dia --size=800x --filter=png -e $@ -t png $< 68 | 69 | # 70 | # Build the document 71 | # So translate the % document and use $% 72 | # 73 | %.html: %.adoc $(GRAPHS) 74 | a2x -D. -f xhtml $< 75 | 76 | clean: 77 | rm -f *.html *.css *.xml *.png 78 | 79 | .PHONY: clean all 80 | 81 | 82 | 83 | # vim: set ts=4 sw=4 et smartindent: 84 | -------------------------------------------------------------------------------- /go/src/restoutsv/periodic.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Enduro/X periodic service polling callback (using for echo advertise) 3 | * 4 | * @file periodic.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | atmi "github.com/endurox-dev/endurox-go" 37 | ) 38 | 39 | //Run scheduled tasks for advertise/unadvertise 40 | //@param ac ATMI Context (server main) 41 | //@return SUCCEED 0, or -1 FAIL 42 | func Periodic(ac *atmi.ATMICtx) int { 43 | 44 | ret := atmi.SUCCEED 45 | 46 | ac.TpLogDebug("Periodic()") 47 | 48 | MadvertiseLock.Lock() 49 | 50 | //Loop over the all services and check the required actions 51 | for _, v := range Mservices { 52 | 53 | if v.echoSchedAdv { 54 | 55 | ac.TpLogInfo("periodic: [%s] needs to be advertised", 56 | v.Svc) 57 | 58 | if errA := v.Advertise(ac); errA != nil { 59 | 60 | ac.TpLogError("Failed to advertise [%s]: %s", 61 | v.Svc, errA.Error()) 62 | 63 | return FAIL 64 | } 65 | 66 | } else if v.echoSchedUnAdv { 67 | 68 | ac.TpLogInfo("periodic: [%s] needs to be unadvertised", 69 | v.Svc) 70 | if errA := v.Unadvertise(ac); errA != nil { 71 | 72 | ac.TpLogError("Failed to unadvertise [%s]: %s", 73 | v.Svc, errA.Error()) 74 | 75 | return FAIL 76 | } 77 | } 78 | } 79 | 80 | MadvertiseLock.Unlock() 81 | 82 | return ret 83 | } 84 | /* vim: set ts=4 sw=4 et smartindent: */ 85 | -------------------------------------------------------------------------------- /go/src/exutil/caroots.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief CA Root handler 3 | * 4 | * @file caroots.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package exutil 34 | 35 | import ( 36 | "crypto/x509" 37 | "fmt" 38 | "io/ioutil" 39 | "strings" 40 | 41 | atmi "github.com/endurox-dev/endurox-go" 42 | ) 43 | 44 | var MRootCAs *x509.CertPool = nil //Loaded root cer 45 | 46 | //Load root certificate authorities from configured string 47 | func LoadRootCAs(ac *atmi.ATMICtx, carootsfiles string) error { 48 | 49 | //Split by ; 50 | certs := strings.Replace(carootsfiles, " ", "", -1) 51 | certs = strings.Replace(carootsfiles, "\t", "", -1) 52 | 53 | crt_arr := strings.Split(certs, ";") 54 | crt_num := len(crt_arr) 55 | 56 | MRootCAs = x509.NewCertPool() 57 | 58 | for i := 0; i < crt_num; i++ { 59 | 60 | ac.TpLogInfo("Loading root CA: %s", crt_arr[i]) 61 | 62 | caCert, err := ioutil.ReadFile(crt_arr[i]) 63 | if err != nil { 64 | ac.TpLogError("Failed to read CA root cert [%s]: %s", crt_arr[i], err) 65 | return fmt.Errorf("Failed to read CA root cert [%s]: %s", crt_arr[i], err) 66 | } 67 | if !MRootCAs.AppendCertsFromPEM(caCert) { 68 | ac.TpLogError("Failed to load/parse CA root cert [%s]", crt_arr[i]) 69 | return fmt.Errorf("Failed to load/parse CA root cert [%s]", crt_arr[i]) 70 | } 71 | } 72 | 73 | ac.TpLogInfo("Roots loaded OK") 74 | return nil 75 | 76 | } 77 | 78 | /* vim: set ts=4 sw=4 et smartindent: */ 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # endurox-connect 2 | Enduro/X Connectivity packages 3 | 4 | This module adds ability to expose to outer world Enduro/X services. It is bi-directional interface, providing: 5 | 6 | * Incoming from network http/rest compatibility. This process allows to configure web route and map them to internal XATMI services. The configuration is extensible and there are several data conversion formats available. 7 | * Outgoing to network http/rest compatibility. 8 | * Generic two-way tcp/ip driver for IoT device connectivity. 9 | 10 | Release binaries may be found here: https://www.mavimax.com/downloads 11 | 12 | ## Build & test status 13 | 14 | | OS | Status | OS | Status |OS | Status | 15 | |----------|:-------------:|----------|:-------------:|----------|:-------------:| 16 | |RHEL/Oracle Linux 8| [![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-ol8)](http://www.silodev.com:9090/jenkins/job/endurox-connect-ol8/) | Centos 6|[![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-centos6)](http://www.silodev.com:9090/jenkins/job/endurox-connect-centos6/)|FreeBSD 11|[![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-freebsd11)](http://www.silodev.com:9090/jenkins/job/endurox-connect-freebsd11/)| 17 | |Oracle Linux 7|[![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-ol7)](http://www.silodev.com:9090/jenkins/job/endurox-connect-ol7/)|OSX 11.4|[![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-osx11_4)](http://www.silodev.com:9090/jenkins/job/endurox-connect-osx11_4/)|raspbian10_arv7l|[![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-raspbian10_arv7l)](http://www.silodev.com:9090/jenkins/job/endurox-connect-raspbian10_arv7l/)| 18 | |SLES 12|[![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-sles12)](http://www.silodev.com:9090/jenkins/job/endurox-connect-sles12/)|SLES 15|[![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-sles15)](http://www.silodev.com:9090/jenkins/job/endurox-connect-sles15/)|Ubuntu 14.04| [![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-ubuntu14)](http://www.silodev.com:9090/jenkins/job/endurox-connect-ubuntu14/)| 19 | |Ubuntu 18.04| [![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-ubuntu18)](http://www.silodev.com:9090/jenkins/job/endurox-connect-ubuntu18/)|AIX 7.2| [![Build Status](http://www.silodev.com:9090/jenkins/buildStatus/icon?job=endurox-connect-aix7_2)](http://www.silodev.com:9090/jenkins/job/endurox-connect-aix7_2/)| 20 | 21 | 22 | # Releases 23 | 24 | - Version 8.0.0 released on 09/01/2022 (stable) Support #754, Bug #757 25 | - Version 8.0.2 released on 07/04/2022 (stable) Bug #770, Support #780 26 | - Version 2.5.2 released on 07/04/2022 (stable) Bug #770 27 | - Version 8.0.4 released on 07/03/2023 (stable) Bug #800 28 | - Version 2.5.4 released on 03/04/2024 (stable) Bug #828 29 | - Version 8.0.6 released on 03/04/2024 (stable) Bug #828 30 | - Version 2.5.6 marked on 22/09/2024 (stable) Feature #846 31 | - Version 8.0.6 marked on 22/09/2024 (stable) Feature #846 32 | -------------------------------------------------------------------------------- /go/src/restoutsv/jsonerror.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Parse the incoming json message and read the fields cotnaining json string & Number 3 | * This will use Enduro/X provided Exparson package. Due to fact that there are 4 | * problems with golang to dynamicall parse the string & number in one step. 5 | * 6 | * @file jsonerror.go 7 | */ 8 | /* ----------------------------------------------------------------------------- 9 | * Enduro/X Middleware Platform for Distributed Transaction Processing 10 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 11 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 12 | * This software is released under one of the following licenses: 13 | * AGPL or Mavimax's license for commercial use. 14 | * ----------------------------------------------------------------------------- 15 | * AGPL license: 16 | * 17 | * This program is free software; you can redistribute it and/or modify it under 18 | * the terms of the GNU Affero General Public License, version 3 as published 19 | * by the Free Software Foundation; 20 | * 21 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 22 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 23 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 24 | * for more details. 25 | * 26 | * You should have received a copy of the GNU Affero General Public License along 27 | * with this program; if not, write to the Free Software Foundation, Inc., 28 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29 | * 30 | * ----------------------------------------------------------------------------- 31 | * A commercial use license is available from Mavimax, Ltd 32 | * contact@mavimax.com 33 | * ----------------------------------------------------------------------------- 34 | */ 35 | package main 36 | 37 | import ( 38 | "unsafe" 39 | "errors" 40 | atmi "github.com/endurox-dev/endurox-go" 41 | ) 42 | 43 | /* 44 | #cgo pkg-config: atmisrvinteg 45 | 46 | #include 47 | #include 48 | */ 49 | import "C" 50 | 51 | //Get the JSON error fields (if they are present) 52 | //@param ac ATMI context 53 | //@param json JSON block recevied from network 54 | //@return , , ATMIError (if set to nil, all other are present) 55 | func JSONErrorGet(ac *atmi.ATMICtx, json *string, jcodefld string, jmessagefld string) (int, string, error) { 56 | 57 | c_codefld := C.CString(jcodefld) 58 | defer C.free(unsafe.Pointer(c_codefld)) 59 | 60 | c_jmessagefld := C.CString(jmessagefld) 61 | defer C.free(unsafe.Pointer(c_jmessagefld)) 62 | 63 | c_buffer := C.CString(*json) 64 | defer C.free(unsafe.Pointer(c_buffer)) 65 | 66 | root_value := C.exjson_parse_string_with_comments(c_buffer); 67 | defer C.exjson_value_free(root_value); 68 | 69 | if nil==root_value { 70 | return FAIL, "", errors.New("Invalid JSON (1)!"); 71 | } 72 | 73 | root_object := C.exjson_value_get_object(root_value); 74 | 75 | if nil==root_object { 76 | return FAIL, "", errors.New("Invalid JSON (2)!"); 77 | } 78 | 79 | if (nil!=root_object) { 80 | 81 | codeVal:=C.exjson_object_dotget_number(root_object, c_codefld) 82 | messageVal:=C.exjson_object_get_string(root_object, c_jmessagefld) 83 | 84 | errs:=C.GoString(messageVal) 85 | 86 | if errs=="" { 87 | ac.TpLogInfo("No error string in response"); 88 | } 89 | 90 | return int(C.int(codeVal)), C.GoString(messageVal), nil 91 | } 92 | 93 | return FAIL, "", errors.New("Invalid JSON (3)"); 94 | } 95 | /* vim: set ts=4 sw=4 et smartindent: */ 96 | -------------------------------------------------------------------------------- /go/src/tcpgatesv/xatmipool.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Pool of XATMI sessions 3 | * 4 | * @file xatmipool.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | "sync" 37 | 38 | atmi "github.com/endurox-dev/endurox-go" 39 | ) 40 | 41 | type XATMIPool struct { 42 | //freechansync *sync.Mutex //We need to lock the freechan 43 | freechan chan int //List of free channels submitted by wokers 44 | ctxs []*atmi.ATMICtx //List of contexts 45 | nrWorkers int //Number of contexts 46 | 47 | } 48 | 49 | var MinXPool XATMIPool //In XATMI pool 50 | var MoutXPool XATMIPool //Out XATMI pool 51 | 52 | var MXDispatcher = &sync.Mutex{} 53 | 54 | //Initialize out pool 55 | //@param ac ATMI contexts 56 | //@param pool XATMI pool 57 | //@return error in case of error or nil if ok 58 | func initPool(ac *atmi.ATMICtx, pool *XATMIPool) error { 59 | 60 | pool.freechan = make(chan int, pool.nrWorkers) 61 | 62 | //pool.freechansync = &sync.Mutex{} 63 | 64 | for i := 0; i < pool.nrWorkers; i++ { 65 | 66 | ctx, err := atmi.NewATMICtx() 67 | 68 | if err != nil { 69 | ac.TpLogError("Failed to create context: %s", err.Message()) 70 | return err 71 | } 72 | 73 | if err := ctx.TpInit(); nil != err { 74 | ac.TpLogError("Failed to tpinit: %s", err.Error()) 75 | return err 76 | } 77 | 78 | pool.ctxs = append(pool.ctxs, ctx) 79 | 80 | //Submit the free ATMI context 81 | pool.freechan <- i 82 | } 83 | return nil 84 | } 85 | 86 | //Close the open xatmi contexts 87 | //@param ac XATMI contexts 88 | //@param pool XATMI pool 89 | func deInitPoll(ac *atmi.ATMICtx, pool *XATMIPool) { 90 | 91 | for i := 0; i < pool.nrWorkers; i++ { 92 | nr := <-pool.freechan 93 | 94 | ac.TpLogWarn("Terminating %d context", nr) 95 | pool.ctxs[nr].TpTerm() 96 | pool.ctxs[nr].FreeATMICtx() 97 | } 98 | } 99 | 100 | //Return the free X context 101 | func getFreeXChan(ac *atmi.ATMICtx, pool *XATMIPool) int { 102 | //Should we use locking here? 103 | //WHY? 104 | //pool.freechansync.Lock() 105 | 106 | nr := <-pool.freechan 107 | 108 | //pool.freechansync.Unlock() 109 | 110 | ac.TpLogInfo("Got free XATMI out object id=%d ", nr) 111 | 112 | return nr 113 | } 114 | 115 | /* vim: set ts=4 sw=4 et smartindent: */ 116 | -------------------------------------------------------------------------------- /go/src/restoutsv/xatmipool.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Pool of XATMI sessions 3 | * 4 | * @file xatmipool.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | "sync" 37 | 38 | atmi "github.com/endurox-dev/endurox-go" 39 | ) 40 | 41 | type XATMIPool struct { 42 | freechansync *sync.Mutex //We need to lock the freechan 43 | freechan chan int //List of free channels submitted by wokers 44 | ctxs []*atmi.ATMICtx //List of contexts 45 | nrWorkers int //Number of contexts 46 | 47 | } 48 | 49 | var MoutXPool XATMIPool //Out XATMI pool 50 | 51 | var MXDispatcher = &sync.Mutex{} 52 | 53 | //Initialize out pool 54 | //@param ac ATMI contexts 55 | //@param pool XATMI pool 56 | //@return error in case of error or nil if ok 57 | func initPool(ac *atmi.ATMICtx, pool *XATMIPool) atmi.ATMIError { 58 | 59 | pool.freechan = make(chan int, pool.nrWorkers) 60 | 61 | pool.freechansync = &sync.Mutex{} 62 | 63 | for i := 0; i < pool.nrWorkers; i++ { 64 | 65 | ctx, err := atmi.NewATMICtx() 66 | 67 | if err != nil { 68 | ac.TpLogError("Failed to create context: %s", err.Message()) 69 | return err 70 | } 71 | 72 | //Causes auto-init to kill the last-call object 73 | if err := ctx.TpInit(); nil != err { 74 | ac.TpLogError("Failed to tpinit: %s", err.Error()) 75 | return err 76 | } 77 | 78 | pool.ctxs = append(pool.ctxs, ctx) 79 | 80 | //Submit the free ATMI context 81 | pool.freechan <- i 82 | } 83 | return nil 84 | } 85 | 86 | //Close the open xatmi contexts 87 | //@param ac XATMI contexts 88 | //@param pool XATMI pool 89 | func deInitPoll(ac *atmi.ATMICtx, pool *XATMIPool) { 90 | 91 | for i := 0; i < pool.nrWorkers; i++ { 92 | nr := <-pool.freechan 93 | 94 | ac.TpLogWarn("Terminating %d context", nr) 95 | pool.ctxs[nr].TpTerm() 96 | pool.ctxs[nr].FreeATMICtx() 97 | } 98 | } 99 | 100 | //Return the free X context 101 | func getFreeXChan(ac *atmi.ATMICtx, pool *XATMIPool) int { 102 | //Should we use locking here? 103 | 104 | pool.freechansync.Lock() 105 | 106 | nr := <-pool.freechan 107 | 108 | pool.freechansync.Unlock() 109 | 110 | ac.TpLogInfo("Got free XATMI out object id=%d ", nr) 111 | 112 | return nr 113 | } 114 | /* vim: set ts=4 sw=4 et smartindent: */ 115 | -------------------------------------------------------------------------------- /tests/01_restin/src/transv/transv.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Transaction queue interface service. This will add message to queue 3 | * and read message from queue. The caller via restincl will control the transactions 4 | * and thus add/gets should follow the transactional nature. 5 | * 6 | * @file transv.go 7 | */ 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | "ubftab" 14 | 15 | atmi "github.com/endurox-dev/endurox-go" 16 | ) 17 | 18 | //Add message to queue 19 | //@param ac ATMI Context 20 | //@param svc Service call information 21 | func QADD(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 22 | 23 | ret := atmi.SUCCEED 24 | 25 | var qctl atmi.TPQCTL 26 | //Get UBF Handler 27 | ub, _ := ac.CastToUBF(&svc.Data) 28 | 29 | //Return to the caller 30 | defer func() { 31 | 32 | ac.TpLogCloseReqFile() 33 | if atmi.SUCCEED == ret { 34 | ac.TpReturn(atmi.TPSUCCESS, 0, ub, 0) 35 | } else { 36 | ac.TpReturn(atmi.TPFAIL, 0, ub, 0) 37 | } 38 | }() 39 | 40 | //Print the buffer to stdout 41 | ub.TpLogPrintUBF(atmi.LOG_DEBUG, "Incoming request:") 42 | 43 | //Enqueue the string 44 | if err := ac.TpEnqueue("QSPACE1", "MYQ1", &qctl, ub, 0); nil != err { 45 | fmt.Printf("TpEnqueue() failed: ATMI Error %d:[%s]\n", err.Code(), err.Message()) 46 | ret = atmi.FAIL 47 | return 48 | } 49 | 50 | return 51 | } 52 | 53 | //Get message from queue 54 | //@param ac ATMI Context 55 | //@param svc Service call information 56 | func QGET(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 57 | 58 | var qctl atmi.TPQCTL 59 | 60 | ret := atmi.SUCCEED 61 | //Get UBF Handler 62 | ub, _ := ac.CastToUBF(&svc.Data) 63 | 64 | //Return to the caller 65 | defer func() { 66 | 67 | ac.TpLogCloseReqFile() 68 | if atmi.SUCCEED == ret { 69 | ac.TpReturn(atmi.TPSUCCESS, 0, ub, 0) 70 | } else { 71 | ac.TpReturn(atmi.TPFAIL, 0, ub, 0) 72 | } 73 | }() 74 | 75 | //Resize buffer, to have some more space 76 | used, _ := ub.BUsed() 77 | if err := ub.TpRealloc(used + 1024); err != nil { 78 | ac.TpLogError("TpRealloc() Got error: %d:[%s]\n", err.Code(), err.Message()) 79 | ret = atmi.FAIL 80 | return 81 | } 82 | 83 | //Get the msg 84 | if err := ac.TpDequeue("QSPACE1", "MYQ1", &qctl, &svc.Data, 0); nil != err { 85 | fmt.Printf("TpDequeue() failed: ATMI Error %d:[%s]\n", err.Code(), err.Message()) 86 | ret = atmi.FAIL 87 | 88 | //Load the error code of Q 89 | ub.BChg(ubftab.T_LONG_2_FLD, 0, err.Code()) 90 | 91 | return 92 | } 93 | 94 | return 95 | } 96 | 97 | //TXFAIL generate fail (note that this is process in transaction context) 98 | //@param ac ATMI Context 99 | //@param svc Service call information 100 | func TXFAIL(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 101 | 102 | ac.TpReturn(atmi.TPFAIL, 0, &svc.Data, 0) 103 | 104 | return 105 | } 106 | 107 | //Server init, called when process is booted 108 | //@param ac ATMI Context 109 | func Init(ac *atmi.ATMICtx) int { 110 | 111 | ac.TpLogWarn("Doing server init...") 112 | 113 | if err := ac.TpAdvertise("QADD", "QADD", QADD); err != nil { 114 | fmt.Println(err) 115 | return atmi.FAIL 116 | } 117 | 118 | if err := ac.TpAdvertise("QGET", "QGET", QGET); err != nil { 119 | fmt.Println(err) 120 | return atmi.FAIL 121 | } 122 | 123 | if err := ac.TpAdvertise("TXFAIL", "TXFAIL", TXFAIL); err != nil { 124 | fmt.Println(err) 125 | return atmi.FAIL 126 | } 127 | 128 | if err := ac.TpOpen(); err != nil { 129 | ac.TpLogError("Failed to tpopen: %s", err.Error()) 130 | return atmi.FAIL 131 | } 132 | 133 | return atmi.SUCCEED 134 | } 135 | 136 | //Server shutdown 137 | //@param ac ATMI Context 138 | func Uninit(ac *atmi.ATMICtx) { 139 | ac.TpLogWarn("Server is shutting down...") 140 | ac.TpClose() 141 | } 142 | 143 | //Executable main entry point 144 | func main() { 145 | //Have some context 146 | ac, err := atmi.NewATMICtx() 147 | 148 | if nil != err { 149 | fmt.Fprintf(os.Stderr, "Failed to allocate new context: %s", err) 150 | os.Exit(atmi.FAIL) 151 | } else { 152 | //Run as server 153 | ac.TpRun(Init, Uninit) 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /tests/01_restin/runtime/conf/ndrxconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 12 | 1 13 | 14 | 17 | 5 18 | 19 | 22 | 1 23 | 24 | 27 | 1 28 | 29 | 32 | 5 33 | 34 | 37 | 38 | 42 | 20 43 | 44 | 45 | 50 | Y 51 | 52 | 53 | 54 | 55 | 1 56 | 2 57 | 58 | 61 | 1 62 | 63 | 67 | 2 68 | 69 | 72 | 10 73 | 74 | 79 | 30 80 | 81 | 85 | 3 86 | 87 | 91 | 1 92 | 93 | 94 | 95 | 96 | 2 97 | 2 98 | 1 99 | -e ${NDRX_APPHOME}/log/cconfsrv.log -r 100 | 101 | 102 | 2 103 | 2 104 | 20 105 | -e ${NDRX_APPHOME}/log/tpevsrv.log -r 106 | 107 | 108 | 1 109 | 1 110 | TRAN 111 | 200 112 | -e ${NDRX_APPHOME}/log/tmsrv-rm1.log -r -- -t1 -l${NDRX_APPHOME}/tmlogs/rm2 113 | 114 | 115 | 1 116 | 1 117 | 240 118 | TMQ 119 | -e ${NDRX_APPHOME}/log/tmsrv-rm1.log -r -- -t1 -l${NDRX_APPHOME}/tmlogs/rm2 120 | 121 | 122 | 1 123 | 1 124 | 300 125 | TMQ 126 | -e ${NDRX_APPHOME}/log/tmqueue-rm2.log -r -- -s1 127 | 128 | 129 | 1 130 | 1 131 | 2000 132 | -e ${NDRX_APPHOME}/log/testsv.log -r 133 | 134 | 135 | 1 136 | 1 137 | 2020 138 | TRAN 139 | -e ${NDRX_APPHOME}/log/transv.log -r 140 | 141 | 142 | 1 143 | 1 144 | 9999 145 | -e ${NDRX_APPHOME}/log/cpmsrv.log -r -- -k3 -i1 146 | 147 | 148 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /go/src/restoutsv/viewsupp.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief View support routines 3 | * 4 | * @file viewsupp.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | "fmt" 37 | 38 | atmi "github.com/endurox-dev/endurox-go" 39 | ) 40 | 41 | //Install error code in the view, Note max allowed error message size is 1024 bytes 42 | //including EOS 43 | //@param buf VIEW buffer 44 | //@param code error code to install 45 | //@param msg error message to install 46 | //@return nil on OK, UBF error on failure 47 | func VIEWInstallError(buf *atmi.TypedVIEW, view string, view_code_fld string, 48 | code int, view_msg_fld string, msg string) atmi.UBFError { 49 | 50 | //Check the length of the message field 51 | 52 | _, _, _, dim_size, _, errU := buf.BVOccur(view_msg_fld) 53 | 54 | if nil != errU { 55 | buf.Buf.Ctx.TpLogError("Failed to get %s.%s infos: %s", 56 | view, view_msg_fld, errU.Error()) 57 | return errU 58 | } 59 | 60 | buf.Buf.Ctx.TpLogInfo("message field dim size: %d", dim_size) 61 | //Conver message to bytes: 62 | 63 | byteStr := []byte(msg) 64 | 65 | //+1 for C EOS 66 | if int64(len(byteStr)+1) > dim_size { 67 | byteStr = byteStr[0 : dim_size-1] //1 for EOS 68 | } 69 | 70 | if errU := buf.BVChg(view_code_fld, 0, code); nil != errU { 71 | buf.Buf.Ctx.TpLogError("Failed to test/set code in resposne %s.[%s] to [%d]: %s", 72 | view, view_code_fld, code, errU.Error()) 73 | return errU 74 | } 75 | 76 | if errU := buf.BVChg(view_msg_fld, 0, byteStr); nil != errU { 77 | buf.Buf.Ctx.TpLogError("Failed to test/set message in resposne %s.[%s] to [%d]: %s", 78 | view, view_msg_fld, string(byteStr), errU.Error()) 79 | return errU 80 | } 81 | 82 | return nil 83 | } 84 | 85 | //Validate view service 86 | //@param ac ATMI Service context 87 | //@param s Service context 88 | //@return error in case of err or nil 89 | func VIEWValidateService(ac *atmi.ATMICtx, s *ServiceMap) error { 90 | 91 | //Set not NULL flag 92 | if s.View_notnull { 93 | ac.TpLogInfo("VIEWs in responses will contain non NULL fields only " + 94 | "(according to view file)") 95 | s.View_flags |= atmi.BVACCESS_NOTNULL 96 | } 97 | 98 | if ERRORS_JSON2VIEW == s.Errors_int && 99 | (s.Errfmt_view_code == "" || s.Errfmt_view_msg == "") { 100 | return fmt.Errorf("For json2view errors parameters 'errfmt_view_code' and " + 101 | "'errfmt_view_msg' must be defined") 102 | } 103 | 104 | return nil 105 | } 106 | 107 | //Reset view error 108 | //@param ac ATMI Context 109 | //@param s service map 110 | //@param v typed view 111 | //@return in case of error ATMI error or nil 112 | func VIEWResetEchoError(ac *atmi.ATMICtx, s *ServiceMap, v *atmi.TypedVIEW) atmi.ATMIError { 113 | 114 | if s.Errors_int == ERRORS_JSON2VIEW { 115 | errU := VIEWInstallError(s.echoVIEW, s.echoVIEW.BVName(), s.Errfmt_view_code, 116 | atmi.TPMINVAL, s.Errfmt_view_msg, "SUCCEED") 117 | if nil != errU { 118 | ac.TpLogError("Failed to install response in echo view: %s", 119 | errU.Error()) 120 | return atmi.NewCustomATMIError(atmi.TPEINVAL, fmt.Sprintf("Failed to install "+ 121 | "response in echo view: %s", errU.Error())) 122 | } 123 | } 124 | 125 | return nil 126 | } 127 | /* vim: set ts=4 sw=4 et smartindent: */ 128 | -------------------------------------------------------------------------------- /tests/03_restout/runtime/conf/ndrxconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 12 | 1 13 | 14 | 17 | 5 18 | 19 | 22 | 1 23 | 24 | 27 | 1 28 | 29 | 32 | 5 33 | 34 | 37 | 38 | 42 | 20 43 | 44 | 45 | 50 | Y 51 | 52 | 53 | 54 | 55 | 1 56 | 2 57 | 58 | 61 | 1 62 | 63 | 67 | 2 68 | 69 | 72 | 10 73 | 74 | 79 | 20 80 | 81 | 85 | 3 86 | 87 | 91 | 1 92 | 93 | 94 | 95 | 96 | 2 97 | 2 98 | 1 99 | -e ${NDRX_APPHOME}/log/cconfsrv.log -r 100 | 101 | 102 | 2 103 | 2 104 | 20 105 | -e ${NDRX_APPHOME}/log/tpevsrv.log -r 106 | 107 | 108 | 3 109 | 3 110 | 40 111 | RM1TMQ 112 | -e ${NDRX_APPHOME}/log/tmsrv-rm1.log -r -- -t1 -l${NDRX_APPHOME}/tmlogs/rm1 113 | 114 | 115 | 1 116 | 1 117 | 60 118 | RM1TMQ 119 | -e ${NDRX_APPHOME}/log/tmqueue-rm1.log -r -- -s1 120 | 121 | 122 | 1 123 | 1 124 | 150 125 | -e ${NDRX_APPHOME}/log/tpbridge_2.log -r 126 | -f -n2 -r -i 172.0.0.1 -p 21003 -tA -z30 127 | 128 | 129 | 3 130 | 3 131 | 2000 132 | -e ${NDRX_APPHOME}/log/testsv.log -r 133 | 134 | 135 | 1 136 | 1 137 | 2050 138 | -e ${NDRX_APPHOME}/log/bigmsgsv.log -r 139 | 140 | 141 | 1 142 | 1 143 | 2100 144 | y 145 | -e ${NDRX_APPHOME}/log/restoutsv.log -r 146 | 1 147 | 148 | 149 | 1 150 | 1 151 | 2200 152 | y 153 | -e ${NDRX_APPHOME}/log/restoutsv_bigmsg.log -r 154 | bigmsg 155 | 156 | 157 | 1 158 | 1 159 | 9999 160 | -e ${NDRX_APPHOME}/log/cpmsrv.log -r -- -k3 -i1 161 | 162 | 163 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /go/src/tcpgatesv/outseq.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Outgiong (Ex->Net) message sequencing 3 | * 4 | * @file outseq.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | "sync" 37 | 38 | atmi "github.com/endurox-dev/endurox-go" 39 | ) 40 | 41 | //ATMI Out message dispatching block 42 | //note that if this is second message in structure then "nr" is invalid 43 | type ATMIOutBlock struct { 44 | id int64 45 | nr int 46 | pool *XATMIPool 47 | ctxData *atmi.TPSRVCTXDATA 48 | buf *atmi.TypedUBF 49 | cd int 50 | } 51 | 52 | var MSeqOutMutex = &sync.Mutex{} //For out message sequencing 53 | var MSeqOutCond = sync.NewCond(MSeqOutMutex) 54 | var MNrMessages = 0 //Number of messages enqueued 55 | var MSeqOutMsgs map[int64][]*ATMIOutBlock 56 | 57 | /* 58 | //Get next work load block 59 | //@param id connect id 60 | //@return Message out or nil (EOF) 61 | func XATMIDispatchCallNext(id int64) *ATMIOutBlock { 62 | //Assume current is done, extract next if have so... 63 | var ret *ATMIOutBlock = nil 64 | //Lock the queues 65 | MSeqOutMutex.Lock() 66 | 67 | MSeqOutMsgs[id] = append(MSeqOutMsgs[id][:0], MSeqOutMsgs[id][1:]...) 68 | 69 | if len(MSeqOutMsgs[id]) == 0 { 70 | MSeqOutMsgs[id] = nil 71 | } 72 | 73 | if nil != MSeqOutMsgs[id] { 74 | ret = MSeqOutMsgs[id][0] 75 | } 76 | 77 | MSeqOutMutex.Unlock() 78 | 79 | return ret 80 | } 81 | */ 82 | 83 | //Process messages in loop for given connection id 84 | //@param[in] id connection id 85 | func XATMIDispatchCallRunner(id int64, block *ATMIOutBlock) { 86 | 87 | //var nextBlock *ATMIOutBlock 88 | 89 | nrOurs := block.nr 90 | pool := block.pool //pool shall no change here amog the enqueued objects 91 | 92 | /* 93 | for nextBlock = block; nil != nextBlock; nextBlock = XATMIDispatchCallNext(id) { 94 | XATMIDispatchCall(nextBlock.pool, nrOurs, 95 | nextBlock.ctxData, nextBlock.buf, nextBlock.cd, false) 96 | } 97 | */ 98 | 99 | for { 100 | /* read block */ 101 | MSeqOutMutex.Lock() 102 | 103 | if len(MSeqOutMsgs[id]) == 0 { 104 | MSeqOutMsgs[id] = nil 105 | MSeqOutMutex.Unlock() 106 | break 107 | } 108 | block = MSeqOutMsgs[id][0] 109 | MSeqOutMutex.Unlock() 110 | 111 | XATMIDispatchCall(block.pool, nrOurs, 112 | block.ctxData, block.buf, block.cd, false) 113 | 114 | /* delete block */ 115 | MSeqOutMutex.Lock() 116 | MSeqOutMsgs[id] = MSeqOutMsgs[id][1:] 117 | MNrMessages-- 118 | MSeqOutCond.Signal() 119 | MSeqOutMutex.Unlock() 120 | } 121 | 122 | //Free up the chan 123 | pool.freechan <- nrOurs 124 | } 125 | 126 | //Sequenced message dispatching 127 | //@param id connection id, either compiled or simple, up to user 128 | //@param pool XATMI pool 129 | //@param nr thread number in pool 130 | //@param ctxData context data 131 | //@param buf call buffer 132 | //@param cd call descriptor (XATMI) 133 | func XATMIDispatchCallSeq(id int64, pool *XATMIPool, nr int, ctxData *atmi.TPSRVCTXDATA, 134 | buf *atmi.TypedUBF, cd int) { 135 | 136 | //Lock the queues 137 | MSeqOutMutex.Lock() 138 | 139 | //let threads to complete. 140 | if MNrMessages >= MWorkersOut { 141 | //wait on cond.. 142 | MSeqOutCond.Wait() 143 | } 144 | 145 | startNew := false 146 | 147 | block := ATMIOutBlock{id: id, pool: pool, nr: nr, ctxData: ctxData, buf: buf, cd: cd} 148 | 149 | if nil == MSeqOutMsgs[id] { 150 | startNew = true 151 | } 152 | MSeqOutMsgs[id] = append(MSeqOutMsgs[id], &block) 153 | 154 | MNrMessages++ 155 | if startNew { 156 | go XATMIDispatchCallRunner(id, &block) 157 | } else { 158 | //We shall release the channel as runner will work with his chan 159 | pool.freechan <- nr 160 | } 161 | 162 | MSeqOutMutex.Unlock() 163 | 164 | } 165 | 166 | /* vim: set ts=4 sw=4 et smartindent: */ 167 | -------------------------------------------------------------------------------- /tests/01_restin/src/testsv/fileupload.go: -------------------------------------------------------------------------------- 1 | /** 2 | * File upload handler 3 | */ 4 | package main 5 | 6 | import ( 7 | "os/exec" 8 | "strings" 9 | u "ubftab" 10 | 11 | atmi "github.com/endurox-dev/endurox-go" 12 | ) 13 | 14 | const ( 15 | SUCCEED = 0 16 | FAIL = -1 17 | ) 18 | 19 | //Check if the failure is due to internal workings 20 | //Check the error code that it matches 21 | //If so return message "DIS" 22 | func UPLDERR(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 23 | 24 | ret := SUCCEED 25 | 26 | //Get UBF Handler 27 | ub, _ := ac.CastToUBF(&svc.Data) 28 | ac.TpLogSetReqFile(ub, "", "") 29 | //Return to the caller 30 | defer func() { 31 | 32 | ub.TpLogPrintUBF(atmi.LOG_DEBUG, "Returning:") 33 | 34 | ac.TpLogCloseReqFile() 35 | if SUCCEED == ret { 36 | ac.TpReturn(atmi.TPSUCCESS, 0, ub, 0) 37 | } else { 38 | ac.TpReturn(atmi.TPFAIL, 0, ub, 0) 39 | } 40 | }() 41 | 42 | tperrno, _ := ub.BGetInt(u.EX_IF_ECODE, 0) 43 | tperrsrc, _ := ub.BGetString(u.EX_IF_ERRSRC, 0) 44 | tpstrerror, _ := ub.BGetString(u.EX_IF_EMSG, 0) 45 | 46 | ac.TpLogDebug("Got error tperrno: %d src: %s msg: %s", tperrno, tperrsrc, tpstrerror) 47 | 48 | if tperrno == atmi.TPEOS && tperrsrc == "R" { 49 | //This is OK condition, set the message 50 | ub.BChg(u.EX_IF_RSPDATA, 0, "DISK FAILURE") 51 | } else { 52 | ub.BChg(u.EX_IF_RSPDATA, 0, "OTHER FAILURE: "+tperrsrc) 53 | } 54 | 55 | //Set return code OK 56 | 57 | ub.BChg(u.EX_NETRCODE, 0, "200") 58 | 59 | } 60 | 61 | //This will receive the files on disk, perform the checksum 62 | //And will return \n on reply body 63 | func FILEUPLOAD(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 64 | 65 | ret := SUCCEED 66 | var reply string 67 | //Get UBF Handler 68 | ub, _ := ac.CastToUBF(&svc.Data) 69 | 70 | ac.TpLogSetReqFile(ub, "", "") 71 | 72 | //Return to the caller 73 | defer func() { 74 | 75 | ub.TpLogPrintUBF(atmi.LOG_DEBUG, "Response buf:") 76 | ac.TpLogCloseReqFile() 77 | if SUCCEED == ret { 78 | ac.TpReturn(atmi.TPSUCCESS, 0, ub, 0) 79 | } else { 80 | ac.TpReturn(atmi.TPFAIL, 0, ub, 0) 81 | } 82 | }() 83 | 84 | //Print the buffer to stdout 85 | ub.TpLogPrintUBF(atmi.LOG_DEBUG, "Incoming request:") 86 | 87 | //Loop over the buffer... we will mark file No 1.ac 88 | 89 | occs, errU := ub.BOccur(u.EX_IF_REQFILEDISK) 90 | 91 | if nil != errU { 92 | ac.TpLogError("TESTERROR: Error reading EX_IF_REQFILEDISK") 93 | ret = FAIL 94 | return 95 | } 96 | 97 | if occs < 3 { 98 | ac.TpLogError("TESTERROR: Expected atleast 3 occs (got %d)", occs) 99 | ret = FAIL 100 | return 101 | } 102 | 103 | //Resize buffer, to have some more space 104 | used, _ := ub.BUsed() 105 | if err := ub.TpRealloc(used + 1024); err != nil { 106 | ac.TpLogError("TpRealloc() Got error: %d:[%s]\n", err.Code(), err.Message()) 107 | ret = FAIL 108 | return 109 | } 110 | 111 | //If occs==3, the we leave first file on disk 112 | //In other cases all files from disk must be deleted 113 | 114 | //Process each of the files... 115 | for i := 0; i < occs; i++ { 116 | 117 | if 3 == occs { 118 | //Set the keep flag 119 | if 2 == i { 120 | ub.BChg(u.EX_IF_RSPFILEACTION, i, "K") 121 | } else { 122 | ub.BChg(u.EX_IF_RSPFILEACTION, i, "D") 123 | } 124 | } else { 125 | //Having other occs, just delete (default) 126 | } 127 | 128 | //Get the file on disk 129 | diskname, errU := ub.BGetString(u.EX_IF_REQFILEDISK, i) 130 | if nil != errU { 131 | ac.TpLogError("Failed to get EX_IF_REQFILEDISK[%d]: %s", i, errU.Error()) 132 | ret = FAIL 133 | return 134 | } 135 | ac.TpLogInfo("File name on disk is: [%s]", diskname) 136 | 137 | //Get the file name at user side 138 | fname, errU := ub.BGetString(u.EX_IF_REQFILENAME, i) 139 | if nil != errU { 140 | ac.TpLogError("Failed to get EX_IF_REQFILENAME[%d]: %s", i, errU.Error()) 141 | ret = FAIL 142 | return 143 | } 144 | ac.TpLogInfo("Form file name (user side): [%s]", fname) 145 | 146 | //Get the mime 147 | mime, errU := ub.BGetString(u.EX_IF_REQFILEMIME, i) 148 | if nil != errU { 149 | ac.TpLogError("Failed to get EX_IF_REQFILEMIME[%d]: %s", i, errU.Error()) 150 | ret = FAIL 151 | return 152 | } 153 | ac.TpLogInfo("Mime: [%s]", mime) 154 | 155 | //Get the form field name 156 | formname, errU := ub.BGetString(u.EX_IF_REQFILEFORM, i) 157 | if nil != errU { 158 | ac.TpLogError("Failed to get EX_IF_REQFILEFORM[%d]: %s", i, errU.Error()) 159 | ret = FAIL 160 | return 161 | } 162 | ac.TpLogInfo("Form field: [%s]", formname) 163 | 164 | //Disk file name shall be different that user 165 | //this is nature of the test 166 | if diskname == fname { 167 | ac.TpLogError("Disk file name [%s] shall not match the logical upload file name [%s] at occ %d", 168 | diskname, fname, i) 169 | ret = FAIL 170 | return 171 | } 172 | 173 | cmd := exec.Command("cksum", diskname) 174 | out, err := cmd.Output() 175 | 176 | if err != nil { 177 | ac.TpLogError("Failed to get checksum for [%s]: %s", diskname, err.Error()) 178 | ret = FAIL 179 | return 180 | } 181 | 182 | strout := strings.Replace(string(out), diskname, fname, -1) 183 | reply += (strout + "\n") 184 | 185 | } 186 | 187 | //Get the chekcsum 188 | ac.TpLogInfo("Reply: [%s]", reply) 189 | //Load the reply 190 | if errU := ub.BChg(u.EX_IF_RSPDATA, 0, reply); nil != errU { 191 | ac.TpLogError("TpRealloc() Got error: %d:[%s]", errU.Code(), errU.Message()) 192 | ret = FAIL 193 | return 194 | } 195 | 196 | return 197 | } 198 | -------------------------------------------------------------------------------- /tests/01_restin/src/testsv/viewsv.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import atmi "github.com/endurox-dev/endurox-go" 4 | 5 | //VIEW service 6 | //@param ac ATMI Context 7 | //@param svc Service call information 8 | func VIEWSV1(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 9 | 10 | ret := FAIL 11 | 12 | //Get UBF Handler 13 | v, _ := ac.CastToVIEW(&svc.Data) 14 | 15 | //Return to the caller 16 | defer func() { 17 | if SUCCEED == ret { 18 | ac.TpReturn(atmi.TPSUCCESS, 0, v, 0) 19 | } else { 20 | ac.TpReturn(atmi.TPFAIL, 0, v, 0) 21 | } 22 | }() 23 | 24 | //Test data received 25 | tshort1, errU := v.BVGetInt16("tshort1", 0, 0) 26 | ac.TpAssertEqualPanic(errU, nil, "tshort1=> must be nil") 27 | ac.TpAssertEqualPanic(tshort1, 5, "tshort1 value") 28 | 29 | tlong1, errU := v.BVGetInt64("tlong1", 0, 0) 30 | ac.TpAssertEqualPanic(errU, nil, "tlong1=> must be nil") 31 | ac.TpAssertEqualPanic(tlong1, 77777, "tlong1 value") 32 | 33 | tstring1, errU := v.BVGetString("tstring1", 1, 0) 34 | ac.TpAssertEqualPanic(errU, nil, "tstring1=> must be nil") 35 | ac.TpAssertEqualPanic(tstring1, "INCOMING TEST", "tstring1 value") 36 | 37 | //Set response data 38 | 39 | if errU = v.BVChg("tshort1", 0, 8); nil != errU { 40 | ac.TpLogError("Failed to set tshort1: %s", errU.Error()) 41 | return 42 | } 43 | 44 | if errU = v.BVChg("tlong1", 0, 11111); nil != errU { 45 | ac.TpLogError("Failed to set tlong1: %s", errU.Error()) 46 | return 47 | } 48 | 49 | if errU = v.BVChg("tstring1", 0, "HELLO RESPONSE"); nil != errU { 50 | ac.TpLogError("Failed to set tstring1: %s", errU.Error()) 51 | return 52 | } 53 | 54 | ret = SUCCEED 55 | 56 | return 57 | } 58 | 59 | //VIEW service - return different view W/O RSP 60 | //@param ac ATMI Context 61 | //@param svc Service call information 62 | func VIEWSV2(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 63 | 64 | ret := SUCCEED 65 | 66 | //Get UBF Handler 67 | v, _ := ac.CastToVIEW(&svc.Data) 68 | 69 | //Return to the caller 70 | defer func() { 71 | if SUCCEED == ret { 72 | ac.TpReturn(atmi.TPSUCCESS, 0, v, 0) 73 | } else { 74 | ac.TpReturn(atmi.TPFAIL, 0, v, 0) 75 | } 76 | }() 77 | 78 | //Test data received 79 | tshort1, errU := v.BVGetInt16("tshort1", 0, 0) 80 | ac.TpAssertEqualPanic(errU, nil, "tshort1=> must be nil") 81 | 82 | tlong1, errU := v.BVGetInt64("tlong1", 0, 0) 83 | ac.TpAssertEqualPanic(errU, nil, "tlong1=> must be nil") 84 | 85 | tstring1, errU := v.BVGetString("tstring1", 1, 0) 86 | ac.TpAssertEqualPanic(errU, nil, "tstring1=> must be nil") 87 | 88 | v2, errA := ac.NewVIEW("REQUEST2", 0) 89 | ac.TpAssertEqualPanic(errA, nil, "Request2: errA must be nil") 90 | 91 | errU = v2.BVChg("tshort2", 0, tshort1) 92 | ac.TpAssertEqualPanic(errU, nil, "Request2: tshort2") 93 | 94 | errU = v2.BVChg("tlong2", 0, tlong1) 95 | ac.TpAssertEqualPanic(errU, nil, "Request2: tlong2") 96 | 97 | errU = v2.BVChg("tstring2", 0, tstring1) 98 | ac.TpAssertEqualPanic(errU, nil, "Request2: tstring2") 99 | 100 | v = v2 101 | 102 | return 103 | } 104 | 105 | //VIEW service - Failure service, with different buffer 106 | //@param ac ATMI Context 107 | //@param svc Service call information 108 | func VIEWFAIL(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 109 | 110 | //Get UBF Handler 111 | v, _ := ac.CastToVIEW(&svc.Data) 112 | 113 | //Return to the caller 114 | defer func() { 115 | ac.TpReturn(atmi.TPFAIL, 0, v, 0) 116 | }() 117 | 118 | //Test data received 119 | tshort1, errU := v.BVGetInt16("tshort1", 0, 0) 120 | ac.TpAssertEqualPanic(errU, nil, "tshort1=> must be nil") 121 | 122 | tlong1, errU := v.BVGetInt64("tlong1", 0, 0) 123 | ac.TpAssertEqualPanic(errU, nil, "tlong1=> must be nil") 124 | 125 | tstring1, errU := v.BVGetString("tstring1", 1, 0) 126 | ac.TpAssertEqualPanic(errU, nil, "tstring1=> must be nil") 127 | 128 | v2, errA := ac.NewVIEW("REQUEST2", 0) 129 | ac.TpAssertEqualPanic(errA, nil, "Request2: errA must be nil") 130 | 131 | errU = v2.BVChg("tshort2", 0, tshort1) 132 | ac.TpAssertEqualPanic(errU, nil, "Request2: tshort2") 133 | 134 | errU = v2.BVChg("tlong2", 0, tlong1) 135 | ac.TpAssertEqualPanic(errU, nil, "Request2: tlong2") 136 | 137 | errU = v2.BVChg("tstring2", 0, tstring1) 138 | ac.TpAssertEqualPanic(errU, nil, "Request2: tstring2") 139 | 140 | v = v2 141 | 142 | return 143 | } 144 | 145 | //VIEW service, FAIL2 146 | //@param ac ATMI Context 147 | //@param svc Service call information 148 | func VIEWFAIL2(ac *atmi.ATMICtx, svc *atmi.TPSVCINFO) { 149 | 150 | //Get UBF Handler 151 | v, _ := ac.CastToVIEW(&svc.Data) 152 | 153 | //Return to the caller 154 | defer func() { 155 | ac.TpReturn(atmi.TPFAIL, 0, v, 0) 156 | }() 157 | 158 | //Test data received 159 | tshort1, errU := v.BVGetInt16("tshort1", 0, 0) 160 | ac.TpAssertEqualPanic(errU, nil, "tshort1=> must be nil") 161 | ac.TpAssertEqualPanic(tshort1, 5, "tshort1 value") 162 | 163 | tlong1, errU := v.BVGetInt64("tlong1", 0, 0) 164 | ac.TpAssertEqualPanic(errU, nil, "tlong1=> must be nil") 165 | ac.TpAssertEqualPanic(tlong1, 77777, "tlong1 value") 166 | 167 | tstring1, errU := v.BVGetString("tstring1", 1, 0) 168 | ac.TpAssertEqualPanic(errU, nil, "tstring1=> must be nil") 169 | ac.TpAssertEqualPanic(tstring1, "INCOMING TEST", "tstring1 value") 170 | 171 | //Set response data 172 | 173 | if errU = v.BVChg("tshort1", 0, 8); nil != errU { 174 | ac.TpLogError("Failed to set tshort1: %s", errU.Error()) 175 | return 176 | } 177 | 178 | if errU = v.BVChg("tlong1", 0, 11111); nil != errU { 179 | ac.TpLogError("Failed to set tlong1: %s", errU.Error()) 180 | return 181 | } 182 | 183 | if errU = v.BVChg("tstring1", 0, "HELLO RESPONSE"); nil != errU { 184 | ac.TpLogError("Failed to set tstring1: %s", errU.Error()) 185 | return 186 | } 187 | 188 | return 189 | } 190 | -------------------------------------------------------------------------------- /tests/03_restout/runtime/conf/restin.ini: -------------------------------------------------------------------------------- 1 | # 2 | # JSON UBF test, sync 3 | # 4 | [@restin/1] 5 | debug= ndrx=3 tp=3 ubf=0 iflags=detailed threaded=y 6 | port=8080 7 | ip=0.0.0.0 8 | gencore=1 9 | # 10 | # Defaults: conv=json2ubf 11 | # async - call service in async way, if submitted ok, just reply back with ok 12 | # 13 | # Hmm we could use same format for definding defaults... 14 | defaults={"errors":"http" 15 | ,"reqlogsvc": "GETFILE" 16 | ,"noreqfilersp": true 17 | } 18 | 19 | ################################################################################ 20 | # JSON2UBF test cases, JSON2UBF error codes 21 | ################################################################################ 22 | /jubfjue_ok={"svc":"DATASV1", "notime":false, "conv":"json2ubf", "errors":"json2ubf", "async":false} 23 | 24 | # This will return server error 25 | /jubfjue_fail={"svc":"FAILSV1", "notime":false, "conv":"json2ubf", "errors":"json2ubf", "async":false} 26 | 27 | # Time-out 28 | /jubfjue_tout={"svc":"LONGOP", "notime":false, "conv":"json2ubf", "errors":"json2ubf", "async":false} 29 | ################################################################################ 30 | # JSON2UBF, http error codes 31 | ################################################################################ 32 | /jubfhte_ok={"svc":"DATASV1", "notime":false, "conv":"json2ubf", "errors":"http", "async":false} 33 | 34 | # This will return server error 35 | /jubfhte_fail={"svc":"FAILSV1", "notime":false, "conv":"json2ubf", "errors":"http", "async":false} 36 | 37 | # Time-out 38 | /jubfhte_tout={"svc":"LONGOP", "notime":false, "conv":"json2ubf", "errors":"http", "async":false} 39 | ################################################################################ 40 | 41 | ################################################################################ 42 | # STRING, text error codes 43 | ################################################################################ 44 | /textte_ok={"svc":"TEXTSV", "notime":false, "conv":"text", "errors":"text", "async":false} 45 | 46 | # This will return server error 47 | /textte_fail={"svc":"FAILSV1", "notime":false, "conv":"text", "errors":"text", "async":false} 48 | ################################################################################ 49 | # JSON, json error fields 50 | ################################################################################ 51 | # Test JSON buffer format 52 | /jsonje_ok={"svc":"JSONSV", "conv":"json", "errors":"json"} 53 | # Test JSON buffer format, no error fields: 54 | /jsonje_okns={"svc":"JSONSV", "conv":"json", "errors":"json", "errfmt_json_onsucc":false} 55 | # Asyn json 56 | /jsonje_okasync={"svc":"JSONSV", "conv":"json", "errors":"json", "async":true} 57 | # Test JSON errors 58 | /jsonje_fail={ 59 | "svc":"FAILSV1" 60 | ,"conv":"json" 61 | ,"errors":"json" 62 | ,"errfmt_json_msg":"\"message\":\"%s\"" 63 | ,"errfmt_json_code":"\"code\":%d" 64 | } 65 | ################################################################################ 66 | # Carray buffer, ok 67 | ################################################################################ 68 | /rawte_ok={"svc":"BINARYSV", "conv":"raw", "errors":"text", "async":false} 69 | # Carray buffer, fail 70 | /rawte_fail={"svc":"FAILSV1", "conv":"raw", "errors":"text", "async":false} 71 | ################################################################################ 72 | # ECHO, JSON2UBF 73 | ################################################################################ 74 | /echo_json2ubf={"notime":false, "errors":"json2ubf", "echo":true} 75 | ################################################################################ 76 | # ECHO, JSON 77 | ################################################################################ 78 | /echo_json={"notime":false, "errors":"json", "echo":true} 79 | # Have some test for JSON http errors: 80 | /dep_jsonhte={"svc":"JSONSV", "conv":"json", "errors":"http"} 81 | ################################################################################ 82 | # ECHO, STRING 83 | ################################################################################ 84 | /echo_string={"notime":false, "conv": "text", "errors":"text", "echo":true} 85 | # Have some test for JSON http errors: 86 | /dep_stringhte={"svc":"TEXTSV", "conv":"text", "errors":"http"} 87 | ################################################################################ 88 | # ECHO, RAW 89 | ################################################################################ 90 | /echo_raw={"svc":"BINARYSV", "conv":"raw", "errors":"text", "async":false, "echo":true} 91 | /dep_rawhte={"svc":"BINARYSV", "conv":"raw", "errors":"http", "async":false} 92 | 93 | ################################################################################ 94 | # VIEW tests 95 | ################################################################################ 96 | 97 | # 98 | # Response with response view, ubf2view errors 99 | # 100 | /viewerr/ok={"svc":"VIEWSV1", "conv":"json2view", "errors":"json2view", 101 | "errfmt_view_msg":"rspmessage", "errfmt_view_code":"rspcode", "errfmt_view_onsucc":true, 102 | "errfmt_view_rsp":"RSPV"} 103 | 104 | # Failed service with ubf2view 105 | /viewerr/fail={"svc":"VIEWFAIL2" 106 | , "conv":"json2view" 107 | , "errors":"json2view" 108 | , "errfmt_view_msg":"rspmessage" 109 | , "errfmt_view_code":"rspcode" 110 | , "errfmt_view_onsucc":false 111 | , "errfmt_view_rsp":"RSPV"} 112 | 113 | # Time-out 114 | /viewerr/tout={"svc":"LONGOP2" 115 | , "notime":false 116 | , "conv":"json2view" 117 | , "errors":"json2view" 118 | , "errfmt_view_msg":"rspmessage" 119 | , "errfmt_view_code":"rspcode" 120 | , "errfmt_view_onsucc":false 121 | , "errfmt_view_rsp":"RSPV"} 122 | 123 | # View http errors, OK 124 | /viewhttp/ok={"svc":"VIEWSV1", "conv":"json2view", "errors":"http"} 125 | 126 | # View http errors, FAIL 127 | /viewhttp/fail={"svc":"VIEWFAIL2", "conv":"json2view", "errors":"http"} 128 | 129 | # Echo test for view 130 | /echo_json2view={"notime":false 131 | , "conv":"json2view" 132 | , "errors":"json2view" 133 | , "errfmt_view_onsucc":true 134 | , "errfmt_view_msg":"rspmessage" 135 | , "errfmt_view_code":"rspcode" 136 | , "echo":true} 137 | 138 | # 139 | # TLS tests 140 | # 141 | [@restin/1/TLS] 142 | tls_enable=1 143 | tls_cert_file=${NDRX_APPHOME}/conf/localhost.crt 144 | tls_key_file=${NDRX_APPHOME}/conf/localhost.key 145 | 146 | 147 | # 148 | # JSON UBF test, sync 149 | # 150 | [@restin/bigmsg] 151 | debug= ndrx=4 tp=4 ubf=0 iflags=detailed threaded=y 152 | port=8181 153 | ip=0.0.0.0 154 | gencore=1 155 | # 156 | # Defaults: conv=json2ubf 157 | # async - call service in async way, if submitted ok, just reply back with ok 158 | # 159 | # Hmm we could use same format for definding defaults... 160 | defaults={"errors":"http" 161 | ,"reqlogsvc": "GETFILE" 162 | ,"noreqfilersp": true 163 | } 164 | 165 | # Test case for big messages (1M) 166 | /bigmsg={"svc":"BIGMSG", "notime":false, "conv":"json2ubf", "errors":"json2ubf", "async":false} 167 | 168 | -------------------------------------------------------------------------------- /go/src/restincl/viewsupp.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief View support 3 | * 4 | * @file viewsupp.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | "fmt" 37 | 38 | atmi "github.com/endurox-dev/endurox-go" 39 | ) 40 | 41 | //Install error code in the view, Note max allowed error message size is 1024 bytes 42 | //including EOS 43 | //@param buf VIEW buffer 44 | //@param code error code to install 45 | //@param msg error message to install 46 | //@return nil on OK, UBF error on failure 47 | func VIEWInstallError(buf *atmi.TypedVIEW, view string, view_code_fld string, 48 | code int, view_msg_fld string, msg string) atmi.UBFError { 49 | 50 | //Check the length of the message field 51 | 52 | _, _, _, dim_size, _, errU := buf.BVOccur(view_msg_fld) 53 | 54 | if nil != errU { 55 | buf.Buf.Ctx.TpLogError("Failed to get %s.%s infos: %s", 56 | view, view_msg_fld, errU.Error()) 57 | return errU 58 | } 59 | 60 | buf.Buf.Ctx.TpLogInfo("message field dim size: %d", dim_size) 61 | //Conver message to bytes: 62 | 63 | byteStr := []byte(msg) 64 | 65 | //+1 for C EOS 66 | if int64(len(byteStr)+1) > dim_size { 67 | byteStr = byteStr[0 : dim_size-1] //1 for EOS 68 | } 69 | 70 | if errU := buf.BVChg(view_code_fld, 0, code); nil != errU { 71 | buf.Buf.Ctx.TpLogError("Failed to test/set code in resposne %s.[%s] to [%d]: %s", 72 | view, view_code_fld, code, errU.Error()) 73 | return errU 74 | } 75 | 76 | if errU := buf.BVChg(view_msg_fld, 0, byteStr); nil != errU { 77 | buf.Buf.Ctx.TpLogError("Failed to test/set message in resposne %s.[%s] to [%d]: %s", 78 | view, view_msg_fld, string(byteStr), errU.Error()) 79 | return errU 80 | } 81 | 82 | return nil 83 | } 84 | 85 | //Validate view service settings 86 | //@param ac ATMI context 87 | //@param svc Service map 88 | //@return error or nil 89 | func VIEWSvcValidateSettings(ac *atmi.ATMICtx, svc *ServiceMap) error { 90 | 91 | //Set not NULL flag 92 | if svc.View_notnull { 93 | ac.TpLogInfo("VIEWs in responses will contain non NULL fields only " + 94 | "(according to view file)") 95 | svc.View_flags |= atmi.BVACCESS_NOTNULL 96 | } 97 | 98 | if svc.Errors_int != ERRORS_JSON2VIEW { 99 | return nil //Nothing to validate 100 | } 101 | 102 | //For async calls we need response object 103 | if svc.Asynccall && !svc.Asyncecho && svc.Errfmt_view_rsp == "" { 104 | err := fmt.Errorf("Tag 'errfmt_view_rsp' must set in case if 'async' " + 105 | "is set and 'asyncecho' is not set") 106 | ac.TpLogError(err.Error()) 107 | return err 108 | } 109 | 110 | //Error fields must be present 111 | ac.TpLogInfo("Errfmt_view_msg=[%s] Errfmt_view_code=[%s]", 112 | svc.Errfmt_view_msg, svc.Errfmt_view_code) 113 | if "" == svc.Errfmt_view_msg || "" == svc.Errfmt_view_code { 114 | err := fmt.Errorf("Tags 'errfmt_view_code' and 'errfmt_view_msg' " + 115 | "must be present in case of 'json2view' errors") 116 | ac.TpLogError(err.Error()) 117 | return err 118 | } 119 | 120 | //If response goes first, the response view must be set 121 | if svc.Errfmt_view_rsp_first && "" == svc.Errfmt_view_rsp { 122 | err := fmt.Errorf("If responding with response view first " + 123 | "('errfmt_view_rsp_first' true), tag 'errfmt_view_rsp' must be set") 124 | ac.TpLogError(err.Error()) 125 | return err 126 | } 127 | 128 | //Test the response object if have one. 129 | 130 | ac.TpLogInfo("Testing view: %s setting code in %s and message in %s", 131 | svc.Errfmt_view_rsp, svc.Errfmt_view_code, 132 | svc.Errfmt_view_msg) 133 | 134 | if svc.Errfmt_view_rsp != "" { 135 | buf, errA := ac.NewVIEW(svc.Errfmt_view_rsp, 0) 136 | 137 | if nil != errA { 138 | err := fmt.Errorf("Failed to alloc VIEW/[%s]: %s", 139 | svc.Errfmt_view_rsp, errA.Error()) 140 | ac.TpLogError(err.Error()) 141 | return err 142 | } 143 | 144 | errA = VIEWInstallError(buf, svc.Errfmt_view_rsp, 145 | svc.Errfmt_view_code, 0, svc.Errfmt_view_msg, 146 | "SUCCEED") 147 | } 148 | 149 | return nil 150 | } 151 | 152 | //Generate response from view configured 153 | //@param ac ATMI Context 154 | //@param svc Servic map 155 | //@param atmiErr ATMI error to put in response 156 | //@return In case of error return [] 157 | func VIEWGenDefaultResponse(ac *atmi.ATMICtx, svc *ServiceMap, atmiErr atmi.ATMIError) []byte { 158 | //In this case response VIEW buffer must be set. 159 | 160 | if nil == atmiErr { 161 | atmiErr = atmi.NewCustomATMIError(atmi.TPMINVAL, "SUCCEED") 162 | } 163 | bufv, errA := ac.NewVIEW(svc.Errfmt_view_rsp, 0) 164 | 165 | if nil != errA { 166 | ac.TpLogError("Failed to alloc VIEW/[%s] - dropping response: %s", 167 | svc.Errfmt_view_rsp, errA.Error()) 168 | ac.UserLog("Failed to alloc VIEW/[%s] - dropping response: %s", 169 | svc.Errfmt_view_rsp, errA.Error()) 170 | return []byte("{}") 171 | } 172 | 173 | if errU := VIEWInstallError(bufv, svc.Errfmt_view_rsp, 174 | svc.Errfmt_view_code, atmiErr.Code(), svc.Errfmt_view_msg, 175 | atmiErr.Message()); nil != errU { 176 | 177 | ac.TpLogError("Failed to set viewe response - dropping: %s", 178 | atmiErr.Message()) 179 | 180 | ac.UserLog("Failed to set view response - dropping: %s", 181 | atmiErr.Message()) 182 | 183 | return []byte("{}") 184 | 185 | } 186 | 187 | //The resposne view contains all field no matter of the non-null setting 188 | ret, err1 := bufv.TpVIEWToJSON(0) 189 | 190 | if nil == err1 { 191 | //Generate the resposne buffer... 192 | rsp := []byte(ret) 193 | 194 | return rsp 195 | 196 | } else { 197 | ac.TpLogError("Failed to convert VIEW to JSON - dropping response: %s", 198 | err1.Error()) 199 | 200 | ac.UserLog("Failed to convert VIEW to JSON - dropping response: %s", 201 | err1.Error()) 202 | 203 | return nil 204 | } 205 | } 206 | /* vim: set ts=4 sw=4 et smartindent: */ 207 | -------------------------------------------------------------------------------- /go/src/restincl/fileupload.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief File upload handler (multi-part form) 3 | * 4 | * @file fileupload.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | "fmt" 37 | "io" 38 | "io/ioutil" 39 | "mime/multipart" 40 | "net/http" 41 | "os" 42 | "strings" 43 | "ubftab" 44 | 45 | atmi "github.com/endurox-dev/endurox-go" 46 | ) 47 | 48 | const ( 49 | FILES_FLAG_KEEP = "K" //Keep the files after the upload service finish 50 | FILES_FLAG_DELETE = "D" //Delete the file (RFU) 51 | ) 52 | 53 | //This is used to strack 54 | //additional request details 55 | //Including list of files uploaded 56 | type RequestContext struct { 57 | errSrc string 58 | fileList []string 59 | } 60 | 61 | //Prepare file upload (request part, download & prepare the UBF buffer) 62 | //@param ac ATMI Context 63 | //@param bufu ATMI buffer (must be UBF) for EXT processing 64 | //@param svc Target service 65 | //@param req HTTP request obj 66 | //@param rctx request context attributes 67 | //@return ATMI error or nil 68 | func handleFileUploadReq(ac *atmi.ATMICtx, bufu *atmi.TypedUBF, svc *ServiceMap, 69 | r *http.Request, rctx *RequestContext) atmi.ATMIError { 70 | 71 | var n int 72 | var err error 73 | var occ = 0 74 | // define pointers for the multipart reader and its parts 75 | var mr *multipart.Reader 76 | var part *multipart.Part 77 | 78 | ac.TpLogInfo("Receiving file upload...") 79 | 80 | if mr, err = r.MultipartReader(); err != nil { 81 | 82 | ac.TpLogError("Failed to open multi-part reader: %s", err.Error()) 83 | return atmi.NewCustomATMIError(atmi.TPESYSTEM, fmt.Sprintf( 84 | "Failed to open multi-part reader: %s", err.Error())) 85 | } 86 | 87 | // buffer to be used for reading bytes from files 88 | chunk := make([]byte, 4096) 89 | 90 | for { 91 | var tempfile *os.File 92 | var filesize int 93 | var uploaded bool 94 | 95 | if part, err = mr.NextPart(); err != nil { 96 | if err != io.EOF { 97 | ac.TpLogError("Error while fetching next part: %s", err.Error()) 98 | return atmi.NewCustomATMIError(atmi.TPESYSTEM, 99 | fmt.Sprintf("Error while fetching next part: %s", err.Error())) 100 | 101 | } else { 102 | ac.TpLogInfo("Multipart upload OK") 103 | return nil 104 | } 105 | } 106 | 107 | ac.TpLogDebug("Uploaded filename occ=%d: %s", occ, part.FileName()) 108 | ac.TpLogDebug("Uploaded mimetype occ=%d: %s", occ, part.Header) 109 | 110 | //Add the file names to the buffer 111 | if errU := bufu.BAdd(ubftab.EX_IF_REQFILENAME, part.FileName()); nil != errU { 112 | ac.TpLogError("Failed to add EX_IF_REQFILENAME[%d]: %s", occ, errU.Error()) 113 | return atmi.NewCustomATMIError(atmi.TPESYSTEM, 114 | fmt.Sprintf("Failed to add EX_IF_REQFILENAME[%d]: %s", occ, errU.Error())) 115 | } 116 | 117 | if errU := bufu.BAdd(ubftab.EX_IF_REQFILEFORM, part.FormName()); nil != errU { 118 | ac.TpLogError("Failed to add EX_IF_REQFILEFORM[%d]: %s", occ, errU.Error()) 119 | return atmi.NewCustomATMIError(atmi.TPESYSTEM, 120 | fmt.Sprintf("Failed to add EX_IF_REQFILEFORM[%d]: %s", occ, errU.Error())) 121 | } 122 | 123 | if errU := bufu.BAdd(ubftab.EX_IF_REQFILEMIME, part.Header.Get("Content-Type")); nil != errU { 124 | ac.TpLogError("Failed to add EX_IF_REQFILEMIME[%d]: %s", occ, errU.Error()) 125 | return atmi.NewCustomATMIError(atmi.TPESYSTEM, 126 | fmt.Sprintf("Failed to add EX_IF_REQFILEMIME[%d]: %s", occ, errU.Error())) 127 | } 128 | 129 | //Add the file name to received rctx 130 | 131 | tempfile, err = ioutil.TempFile(svc.Tempdir, fmt.Sprintf("%s-%s", progsection, M_cctag)) 132 | if err != nil { 133 | return atmi.NewCustomATMIError(atmi.TPEOS, 134 | fmt.Sprintf("Error while creating temp file: %s", err.Error())) 135 | } 136 | 137 | ac.TpLogInfo("Got file name for file occ %d: %s", occ, tempfile.Name()) 138 | rctx.fileList = append(rctx.fileList, tempfile.Name()) 139 | 140 | if errU := bufu.BAdd(ubftab.EX_IF_REQFILEDISK, tempfile.Name()); nil != errU { 141 | ac.TpLogError("Failed to add EX_IF_REQFILEDISK[%d]: %s", occ, errU.Error()) 142 | return atmi.NewCustomATMIError(atmi.TPESYSTEM, 143 | fmt.Sprintf("Failed to add EX_IF_REQFILEDISK[%d]: %s", occ, errU.Error())) 144 | } 145 | 146 | defer tempfile.Close() 147 | 148 | // Read all parts of the file & write off to disk... 149 | for !uploaded { 150 | if n, err = part.Read(chunk); err != nil { 151 | if err != io.EOF { 152 | ac.TpLogError("Error reading chunk: %s", err.Error()) 153 | return atmi.NewCustomATMIError(atmi.TPESYSTEM, 154 | fmt.Sprintf("Error reading chunk: %s", err.Error())) 155 | } 156 | uploaded = true 157 | } 158 | 159 | if n, err = tempfile.Write(chunk[:n]); err != nil { 160 | ac.TpLogError("Error writing chunk to [%s]: %s", tempfile.Name(), err.Error()) 161 | return atmi.NewCustomATMIError(atmi.TPEOS, 162 | fmt.Sprintf("Error writing chunk [%s] to: %s", tempfile.Name(), err.Error())) 163 | } 164 | filesize += n 165 | } 166 | 167 | ac.TpLogInfo("Uploaded file [%s] size: %d bytes", tempfile.Name(), filesize) 168 | 169 | occ++ 170 | } 171 | 172 | } 173 | 174 | //Handle response after the file processed 175 | //@param ac ATMI Context 176 | //@param ubfu UBF buffer used for request handling 177 | //@param service definition 178 | //@param rctx request boject 179 | //@return ATMI error if any 180 | func handleFileUploadRsp(ac *atmi.ATMICtx, bufu *atmi.TypedUBF, svc *ServiceMap, 181 | rctx *RequestContext) atmi.ATMIError { 182 | 183 | for i, s := range rctx.fileList { 184 | 185 | //Check the action by index 186 | 187 | action, _ := bufu.BGetString(ubftab.EX_IF_RSPFILEACTION, i) 188 | 189 | if strings.Contains(action, FILES_FLAG_KEEP) { 190 | ac.TpLogInfo("Keeping file [%s] (occ %d)", s, i) 191 | } else { 192 | ac.TpLogInfo("Removing file [%s] (occ %d)", s, i) 193 | os.Remove(s) 194 | } 195 | } 196 | 197 | return nil 198 | } 199 | 200 | /* vim: set ts=4 sw=4 et smartindent: */ 201 | -------------------------------------------------------------------------------- /tests/03_restout/runtime/conf/restout.ini: -------------------------------------------------------------------------------- 1 | # additional view settings... 2 | [@global] 3 | VIEWDIR=${NDRX_APPHOME}/viewdir 4 | VIEWFILES=restin.V 5 | 6 | [@restout/1] 7 | # Enduro/X debug string setup 8 | debug = tp=3 ndrx=3 iflags=detailed file= threaded=y 9 | gencore=1 10 | workers=5 11 | scan_time=7 12 | # 13 | # Defaults: conv=json2ubf 14 | # async - call service in async way, if submitted ok, just reply back with ok 15 | # 16 | 17 | # MOVED DOWN FOR SECON-PASS CONFIG TEST 18 | #defaults={"urlbase":"https://localhost:8080" 19 | # ,"errors":"http" 20 | # ,"noreqfilersp": true 21 | # ,"sslinsecure": true 22 | # } 23 | 24 | ################################################################################ 25 | # JSON2UBF test case - jue (json2ubf err) 26 | ################################################################################ 27 | service JUBFJUE_OK={ 28 | "url":"/jubfjue_ok" 29 | ,"errors":"json2ubf" 30 | ,"timeout":5 31 | } 32 | 33 | service JUBFJUE_FAIL={ 34 | "url":"/jubfjue_fail" 35 | ,"errors":"json2ubf" 36 | ,"timeout":5 37 | } 38 | 39 | service JUBFJUE_TOUT={ 40 | "url":"/jubfjue_tout" 41 | ,"errors":"json2ubf" 42 | ,"timeout":1 43 | } 44 | 45 | # No such service - http 404 46 | service JUBFJUE_NENT={ 47 | "url":"/jubfjue_nent" 48 | ,"errors":"json2ubf" 49 | ,"timeout":1 50 | } 51 | ################################################################################ 52 | # JSON2UBF test case - http errors 53 | ################################################################################ 54 | service JUBFHTE_OK={ 55 | "url":"/jubfhte_ok" 56 | ,"errors":"http" 57 | ,"timeout":5 58 | } 59 | 60 | service JUBFHTE_FAIL={ 61 | "url":"/jubfhte_fail" 62 | ,"errors":"http" 63 | ,"timeout":5 64 | } 65 | 66 | service JUBFHTE_TOUT={ 67 | "url":"/jubfhte_tout" 68 | ,"errors":"http" 69 | ,"timeout":1 70 | } 71 | # 404 72 | service JUBFHTE_NENT={ 73 | "url":"/jubfhte_nent" 74 | ,"errors":"http" 75 | ,"timeout":1 76 | } 77 | # 404 - remapped to tout 78 | service JUBFHTE_NENT_13={ 79 | "url":"/jubfhte_nent" 80 | ,"errors":"http" 81 | ,"timeout":1 82 | ,"errors_fmt_http_map":"200:0,404:13,*:11" 83 | } 84 | 85 | ################################################################################ 86 | # TEXT test case - text errors 87 | ################################################################################ 88 | 89 | service TEXTTE_OK={ 90 | "url":"/textte_ok" 91 | ,"errors":"text" 92 | ,"timeout":5 93 | } 94 | 95 | service TEXTTE_FAIL={ 96 | "url":"/textte_fail" 97 | ,"errors":"text" 98 | ,"timeout":5 99 | } 100 | 101 | ################################################################################ 102 | # JSON test case - json errors 103 | ################################################################################ 104 | 105 | service JSONJE_OK={ 106 | "url":"/jsonje_ok" 107 | ,"errors":"json" 108 | ,"timeout":5 109 | } 110 | 111 | service JSONJE_OKNS={ 112 | "url":"/jsonje_okns" 113 | ,"errors":"json" 114 | ,"timeout":5 115 | ,"errfmt_json_onsucc":false 116 | } 117 | 118 | service JSONJE_OKASYNC={ 119 | "url":"/jsonje_okasync" 120 | ,"errors":"json" 121 | ,"timeout":5 122 | } 123 | 124 | service JSONJE_FAIL={ 125 | "url":"/jsonje_fail" 126 | ,"errors":"json" 127 | ,"timeout":5 128 | ,"errfmt_json_msg":"message" 129 | ,"errfmt_json_code":"code" 130 | } 131 | 132 | ################################################################################ 133 | # RAW test case - text errors 134 | ################################################################################ 135 | 136 | service RAWTE_OK={ 137 | "url":"/rawte_ok" 138 | ,"errors":"text" 139 | ,"timeout":5 140 | } 141 | 142 | service RAWTE_FAIL={ 143 | "url":"/rawte_fail" 144 | ,"errors":"text" 145 | ,"timeout":5 146 | } 147 | 148 | ################################################################################ 149 | # ECHO tests, JSON2UBF 150 | ################################################################################ 151 | 152 | # This echo host 153 | service ECHO_JSON2UBF={ 154 | "url":"/echo_json2ubf" 155 | ,"errors":"json2ubf" 156 | ,"echo":true 157 | ,"echo_time":1 158 | ,"echo_max_fail":2 159 | ,"echo_min_ok":3 160 | ,"echo_conv":"json2ubf" 161 | ,"echo_data":"{\"T_STRING_FLD\":\"Some echo data...\"}" 162 | } 163 | 164 | # This depends on echo host ECHO_JSON2UBF 165 | # once it is up, the service DEP_JSON2UBF should be advertised 166 | service DEP_JSON2UBF={ 167 | "url":"/jubfjue_ok" 168 | ,"errors":"json2ubf" 169 | ,"timeout":5 170 | ,"depends_on":"ECHO_JSON2UBF" 171 | } 172 | 173 | service DEP_JSON2UBF2={ 174 | "url":"/jubfjue_ok" 175 | ,"errors":"json2ubf" 176 | ,"timeout":5 177 | ,"depends_on":"ECHO_JSON2UBF" 178 | } 179 | 180 | ################################################################################ 181 | # ECHO tests, JSON 182 | ################################################################################ 183 | # This echo host 184 | service ECHO_JSON={ 185 | "url":"/echo_json" 186 | ,"errors":"json" 187 | ,"echo":true 188 | ,"echo_time":1 189 | ,"echo_max_fail":2 190 | ,"echo_min_ok":3 191 | ,"echo_conv":"json" 192 | ,"echo_data":"{\"StringField\":\"Hello Echo\"}" 193 | } 194 | 195 | service DEP_JSON={ 196 | "url":"/dep_jsonhte" 197 | ,"errors":"http" 198 | ,"timeout":5 199 | ,"depends_on":"ECHO_JSON" 200 | } 201 | ################################################################################ 202 | # ECHO tests, TEXT 203 | ################################################################################ 204 | # This echo host 205 | service ECHO_STRING={ 206 | "url":"/echo_string" 207 | ,"errors":"text" 208 | ,"echo":true 209 | ,"echo_time":1 210 | ,"echo_max_fail":2 211 | ,"echo_min_ok":3 212 | ,"echo_conv":"text" 213 | ,"echo_data":"This is echo string!" 214 | } 215 | 216 | service DEP_STRING={ 217 | "url":"/dep_stringhte" 218 | ,"errors":"http" 219 | ,"timeout":5 220 | ,"depends_on":"ECHO_STRING" 221 | } 222 | ################################################################################ 223 | # ECHO tests, RAW 224 | ################################################################################ 225 | # This echo host 226 | service ECHO_RAW={ 227 | "url":"/echo_raw" 228 | ,"errors":"text" 229 | ,"echo":true 230 | ,"echo_time":1 231 | ,"echo_max_fail":2 232 | ,"echo_min_ok":3 233 | ,"echo_conv":"raw" 234 | ,"echo_data":"AQIDBAUGBwgJEBESExQV" 235 | } 236 | 237 | service DEP_RAW={ 238 | "url":"/dep_rawhte" 239 | ,"errors":"http" 240 | ,"timeout":5 241 | ,"depends_on":"ECHO_RAW" 242 | } 243 | 244 | 245 | 246 | ################################################################################ 247 | # VIEW tests, json2view errors 248 | ################################################################################ 249 | 250 | service VIEWERR_OK={ 251 | "url":"/viewerr/ok" 252 | ,"errors":"json2view" 253 | ,"errfmt_view_msg":"rspmessage" 254 | ,"errfmt_view_code":"rspcode" 255 | ,"timeout":5 256 | } 257 | 258 | service VIEWERR_FAIL={ 259 | "url":"/viewerr/fail" 260 | ,"errors":"json2view" 261 | ,"errfmt_view_msg":"rspmessage" 262 | ,"errfmt_view_code":"rspcode" 263 | ,"parseonerror":true 264 | ,"timeout":5 265 | } 266 | 267 | service VIEWERR_TOUT={ 268 | "url":"/viewerr/tout" 269 | ,"errors":"json2view" 270 | ,"errfmt_view_msg":"rspmessage" 271 | ,"errfmt_view_code":"rspcode" 272 | ,"timeout":1 273 | } 274 | 275 | service VIEWHTTP_OK={ 276 | "url":"/viewhttp/ok" 277 | ,"errors":"http" 278 | ,"timeout":5 279 | } 280 | 281 | service VIEWHTTP_FAIL={ 282 | "url":"/viewhttp/fail" 283 | ,"errors":"http" 284 | ,"parseonerror":true 285 | ,"timeout":5 286 | } 287 | 288 | 289 | ################################################################################ 290 | # ECHO tests, JSON2VIEW 291 | ################################################################################ 292 | # This echo host 293 | service ECHO_JSON2VIEW={ 294 | "url":"/echo_json2view" 295 | ,"errors":"json2view" 296 | ,"echo":true 297 | ,"echo_time":1 298 | ,"echo_max_fail":2 299 | ,"echo_min_ok":3 300 | ,"echo_conv":"json2view" 301 | ,"errfmt_view_msg":"rspmessage" 302 | ,"errfmt_view_code":"rspcode" 303 | #This is JSON2VIEW JSON format: 304 | ,"echo_data":"{\"REQUEST1\":{\"tshort1\": 5,\"tlong1\": 77777,\"tstring1\": [\"\",\"INCOMING TEST\"]}}" 305 | } 306 | 307 | # This depends on echo host ECHO_JSON2VIEW 308 | # once it is up, the service DEP_JSON2VIEW should be advertised 309 | service DEP_JSON2VIEW={ 310 | "url":"/viewerr/ok" 311 | ,"errors":"json2view" 312 | , "errfmt_view_msg":"rspmessage" 313 | , "errfmt_view_code":"rspcode" 314 | ,"timeout":5 315 | ,"depends_on":"ECHO_JSON2UBF" 316 | } 317 | 318 | # 319 | # Moved down for second pass config read test 320 | # 321 | defaults={"urlbase":"https://localhost:8080" 322 | ,"errors":"http" 323 | ,"noreqfilersp": true 324 | ,"sslinsecure": true 325 | } 326 | 327 | [@restout/bigmsg] 328 | # Enduro/X debug string setup 329 | debug = tp=4 ndrx=4 iflags=detailed file= threaded=y 330 | gencore=1 331 | workers=5 332 | scan_time=7 333 | 334 | defaults={"urlbase":"http://localhost:8181" 335 | ,"errors":"http" 336 | ,"noreqfilersp": true 337 | } 338 | 339 | # Big messages (1M over the rest) 340 | service BIGMSG_REST={ 341 | "url":"/bigmsg" 342 | ,"errors":"json2ubf" 343 | ,"timeout":5 344 | } 345 | 346 | -------------------------------------------------------------------------------- /go/src/restincl/transactions.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Transaction API and context handling 3 | * 4 | * @file transactions.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | "encoding/json" 37 | "fmt" 38 | "net/http" 39 | "ubftab" 40 | 41 | atmi "github.com/endurox-dev/endurox-go" 42 | ) 43 | 44 | const ( 45 | TX_REQ_HDR = "endurox-tptranid-req" 46 | TX_RSP_HDR = "endurox-tptranid-rsp" 47 | 48 | OP_TPBEGIN = "tpbegin" 49 | OP_TPCOMMIT = "tpcommit" 50 | OP_TPABORT = "tpabort" 51 | ) 52 | 53 | /** 54 | * Transaction API request 55 | */ 56 | type TxReqData struct { 57 | Operation string `json:"operation"` 58 | Timeout uint64 `json:"timeout"` 59 | Flags int64 `json:"flags"` 60 | Tptranid string `json:"tptranid"` 61 | } 62 | 63 | /** 64 | * Transaction API response 65 | */ 66 | type TxRspData struct { 67 | Operation string `json:"operation,omitempty"` 68 | ErrorCode int `json:"error_code"` 69 | ErrorMessage string `json:"error_message"` 70 | Tptranid string `json:"tptranid,omitempty"` 71 | } 72 | 73 | /** 74 | * Transaction handler entry. 75 | * Assumes that buffers are encoded in "ext" mode 76 | * TODO: Needs to think about http status codes. Maybe in case of failure, we could 77 | * give basic indication to caller, that something failed. 78 | * 79 | * @param ac ATMI Context 80 | * @param buf ATMI buffer to call 81 | * @param svc service mapping to call 82 | * @param req request object 83 | * @param w response object 84 | * @param rctx request context 85 | * @param flags call flags 86 | */ 87 | func txHandler(ac *atmi.ATMICtx, buf atmi.TypedBuffer, svc *ServiceMap, req *http.Request, 88 | w http.ResponseWriter, rctx *RequestContext, flags int64) (ret atmi.ATMIError) { 89 | 90 | var reqData TxReqData 91 | var rspData TxRspData 92 | var err atmi.ATMIError 93 | bufu, ok := buf.(*atmi.TypedUBF) 94 | 95 | if !ok { 96 | ac.TpLogError("ERROR: txHandler - got non UBF buffer") 97 | return atmi.NewCustomATMIError(atmi.TPESYSTEM, "Invalid buffer") 98 | } 99 | 100 | body, errU := bufu.BGetByteArr(ubftab.EX_IF_REQDATA, 0) 101 | if nil != errU { 102 | 103 | ac.TpLogError("ERROR: txHandler - failed to get EX_IF_REQDATA: %s", 104 | errU.Error()) 105 | 106 | return atmi.NewCustomATMIError(atmi.TPESYSTEM, 107 | fmt.Sprintf("Failed to get ubftab.EX_IF_REQDATA: %s", errU.Error())) 108 | } 109 | 110 | //If we have valid buffer, we can start to generate 111 | //Normal json responses 112 | defer func() { 113 | 114 | http_status := http.StatusOK 115 | 116 | if nil != ret { 117 | rspData.ErrorCode = ret.Code() 118 | rspData.ErrorMessage = ret.Message() 119 | } else { 120 | rspData.ErrorCode = 0 121 | rspData.ErrorMessage = "Succeed" 122 | } 123 | 124 | //Return http response codes correspodingly & marshal the response 125 | 126 | if nil != ret && (ret.Code() == atmi.TPEINVAL || ret.Code() == atmi.TPEPROTO) { 127 | 128 | http_status = http.StatusBadRequest 129 | 130 | } else if nil != ret && ret.Code() > 0 { 131 | 132 | //in this case it is 500 133 | http_status = http.StatusInternalServerError 134 | } 135 | 136 | //Load the response body... 137 | 138 | rspBody, err := json.Marshal(&rspData) 139 | 140 | if nil != err { 141 | ac.TpLogError("Failed to prepare response: %s", err.Error()) 142 | http_status = http.StatusInternalServerError 143 | } else { 144 | 145 | err := bufu.BChg(ubftab.EX_IF_RSPDATA, 0, rspBody) 146 | 147 | if err != nil { 148 | ac.TpLogError("Failed to set response body: %s", err.Error()) 149 | http_status = http.StatusInternalServerError 150 | } 151 | } 152 | 153 | //Setup the response code finally 154 | 155 | if err := bufu.BChg(ubftab.EX_NETRCODE, 0, http_status); nil != err { 156 | ac.TpLogError("Failed to set EX_NETRCODE to %d: %s", http_status, err.Error()) 157 | } 158 | 159 | }() 160 | 161 | //Parse the request... 162 | //Invalid request we 163 | errJ := json.Unmarshal(body, &reqData) 164 | 165 | if nil != errJ { 166 | return atmi.NewCustomATMIError(atmi.TPEINVAL, 167 | fmt.Sprintf("Failed to parse JSON request: %s", errJ.Error())) 168 | } 169 | 170 | rspData.Operation = reqData.Operation 171 | rspData.Tptranid = reqData.Tptranid 172 | 173 | //Check do we recognize the function 174 | ac.TpLogInfo("txHandler: operation: [%s], timeout: %d, flags: %d tptranid: [%s]", 175 | reqData.Operation, reqData.Timeout, reqData.Flags, reqData.Tptranid) 176 | 177 | if reqData.Operation == OP_TPCOMMIT || reqData.Operation == OP_TPABORT { 178 | //Resume transaction 179 | err = ac.TpResumeString(reqData.Tptranid, 0) 180 | 181 | if nil != err { 182 | ac.TpLogError("%s: failed to resume transaction: %s", 183 | reqData.Operation, err.Error()) 184 | 185 | return err 186 | } 187 | } 188 | 189 | switch reqData.Operation { 190 | 191 | case OP_TPBEGIN: 192 | 193 | err = ac.TpBegin(reqData.Timeout, reqData.Flags) 194 | 195 | if nil != err { 196 | ac.TpLogError("Failed to begin transaction: %s", err.Error()) 197 | return err 198 | } 199 | 200 | //Suspend transactions & get TID 201 | tid, err := ac.TpSuspendString(0) 202 | 203 | if nil != err { 204 | ac.TpLogError("tpbegin: Failed to suspend transaction: %s", err.Error()) 205 | return err 206 | } 207 | 208 | rspData.Tptranid = tid 209 | 210 | ac.TpLogInfo("Started transaction: [%s]", rspData.Tptranid) 211 | 212 | case OP_TPCOMMIT: 213 | err = ac.TpCommit(0) 214 | 215 | if nil != err { 216 | ac.TpLogError("Failed to commit transaction: %s", err.Error()) 217 | //In any case, context now becomes disasociated from tran 218 | return err 219 | } 220 | 221 | case OP_TPABORT: 222 | 223 | err = ac.TpAbort(0) 224 | 225 | if nil != err { 226 | ac.TpLogError("Failed to abort transaction: %s", err.Error()) 227 | //In any case, context now becomes disasociated from tran 228 | return err 229 | } 230 | 231 | default: 232 | return atmi.NewCustomATMIError(atmi.TPEINVAL, 233 | fmt.Sprintf("Unsupported operation: [%s]", reqData.Operation)) 234 | 235 | } 236 | 237 | return nil 238 | 239 | } 240 | 241 | /** 242 | * Transaction service call, in case if transaction headers are present 243 | * otherwise just normal call 244 | * @param ac ATMI Context 245 | * @param buf ATMI buffer to call 246 | * @param svc service mapping to call 247 | * @param req request object 248 | * @param w response object 249 | * @param rctx request context 250 | * @param flags call flags 251 | */ 252 | func txCall(ac *atmi.ATMICtx, buf atmi.TypedBuffer, svc *ServiceMap, req *http.Request, 253 | w http.ResponseWriter, rctx *RequestContext, flags int64) atmi.ATMIError { 254 | 255 | var err atmi.ATMIError 256 | 257 | tidreq := req.Header.Get(TX_REQ_HDR) 258 | 259 | if tidreq != "" { 260 | 261 | var resum_flags int64 262 | 263 | if svc.TxNoOptim { 264 | resum_flags |= atmi.TPTXNOOPTIM 265 | } 266 | 267 | err = ac.TpResumeString(tidreq, resum_flags) 268 | 269 | if nil != err { 270 | ac.TpLogError("Failed to resume transaction [%s] for svc call [%s]", 271 | tidreq, svc.Svc) 272 | ac.UserLog("Failed to resume transaction [%s] for svc call [%s]", 273 | tidreq, svc.Svc) 274 | return err 275 | } 276 | 277 | ac.TpLogDebug("Resumed global transaction [%s]", tidreq) 278 | } 279 | 280 | if svc.NoAbort { 281 | flags |= atmi.TPNOABORT 282 | } 283 | 284 | _, err = ac.TpCall(svc.Svc, buf, flags|atmi.TPTRANSUSPEND) 285 | 286 | if ac.TpGetLev() > 0 { 287 | 288 | tidrsp, err_susp := ac.TpSuspendString(0) 289 | 290 | if nil != err_susp { 291 | ac.TpLogError("Failed to suspend transaction for %s call: %s", svc.Svc, 292 | err_susp.Message()) 293 | ac.UserLog("Failed to suspend transaction for %s call: %s", svc.Svc, 294 | err_susp.Message()) 295 | //Ignore and continue... (do not return tran header) 296 | } else { 297 | ac.TpLogDebug("Transaction suspended [%s]", tidrsp) 298 | w.Header().Set(TX_RSP_HDR, tidrsp) 299 | } 300 | } 301 | 302 | return err 303 | } 304 | 305 | /* vim: set ts=4 sw=4 et smartindent: */ 306 | -------------------------------------------------------------------------------- /go/src/tcpgatesv/netin.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Network -> Enduro/X 3 | * 4 | * @file netin.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | u "ubftab" 37 | 38 | atmi "github.com/endurox-dev/endurox-go" 39 | ) 40 | 41 | //Allocate UBF buffer for holding the full 42 | //Hmm buf we have a problem here with error, as the interface appears to be the 43 | //same for UBF and ATMI, and also error codes to collide. But for now it is not 44 | //important. 45 | //@param con Connection object 46 | //@param corr Correlator 47 | //@param data Data received from network 48 | //@param isRsp true if request is response, else it is assumed as request 49 | //@return UBF buffer if no error, ATMI Error if problem occurred. 50 | func AllocReplyDataBuffer(ac *atmi.ATMICtx, con *ExCon, corr string, data []byte, isRsp bool) (*atmi.TypedUBF, atmi.ATMIError) { 51 | 52 | buf, err := ac.NewUBF(int64(len(data) + 1024)) 53 | if nil != err { 54 | ac.TpLogError("Failed to allocate buffer: [%s] - dropping incoming message", 55 | err.Error()) 56 | return nil, err 57 | } 58 | 59 | if err = buf.BChg(u.EX_NETGATEWAY, 0, MGateway); err != nil { 60 | ac.TpLogError("Failed to set EX_NETGATEWAY %d: %s", err.Code(), err.Message()) 61 | return nil, err 62 | } 63 | 64 | if err = buf.BChg(u.EX_NETCONNID, 0, con.id_comp); err != nil { 65 | ac.TpLogError("Failed to set EX_NETCONNID %d: %s", err.Code(), err.Message()) 66 | return nil, err 67 | } 68 | 69 | if err = buf.BChg(u.EX_NETDATA, 0, data); err != nil { 70 | ac.TpLogError("Failed to set EX_NETDATA %d: %s", err.Code(), err.Message()) 71 | return nil, err 72 | } 73 | 74 | if "" != corr { 75 | if buf.BChg(u.EX_NETCORR, 0, corr); err != nil { 76 | ac.TpLogError("Failed to set EX_NETCORR %d: %s", err.Code(), err.Message()) 77 | return nil, err 78 | } 79 | } 80 | 81 | //Setup IP/port our/their and role 82 | if err = buf.BChg(u.EX_NETOURIP, 0, con.ourip); err != nil { 83 | ac.TpLogError("Failed to set EX_NETOURIP %d: %s", err.Code(), err.Message()) 84 | return nil, err 85 | } 86 | 87 | if err = buf.BChg(u.EX_NETOURPORT, 0, con.outport); err != nil { 88 | ac.TpLogError("Failed to set EX_NETOURPORT %d: %s", err.Code(), err.Message()) 89 | return nil, err 90 | } 91 | 92 | //Setup IP/port our/their and role 93 | if err = buf.BChg(u.EX_NETTHEIRIP, 0, con.theirip); err != nil { 94 | ac.TpLogError("Failed to set EX_NETTHEIRIP %d: %s", err.Code(), err.Message()) 95 | return nil, err 96 | } 97 | 98 | if err = buf.BChg(u.EX_NETTHEIRPORT, 0, con.theirport); err != nil { 99 | ac.TpLogError("Failed to set EX_NETTHEIRPORT %d: %s", err.Code(), err.Message()) 100 | return nil, err 101 | } 102 | 103 | if err = buf.BChg(u.EX_NETCONMODE, 0, con.conmode); err != nil { 104 | ac.TpLogError("Failed to set EX_NETCONMODE %d: %s", err.Code(), err.Message()) 105 | return nil, err 106 | } 107 | 108 | if isRsp { 109 | buf.BChg(u.EX_NERROR_CODE, 0, 0) 110 | buf.BChg(u.EX_NERROR_MSG, 0, "SUCCEED") 111 | } 112 | 113 | return buf, nil 114 | } 115 | 116 | //We have recieved new call from Network 117 | //So shall wait for new ATMI context & send the message in 118 | //This should be run on go routine. 119 | //@param data Data received from Network 120 | //@param bool set to false if do not need to continue (i.e. close conn) 121 | func NetDispatchCall(pool *XATMIPool, nr int, con *ExCon, 122 | preAllocUBF *atmi.TypedUBF, corr string, data []byte) { 123 | 124 | buf := preAllocUBF 125 | ac := pool.ctxs[nr] 126 | 127 | //Return to the caller 128 | defer func() { 129 | ac.TpLogInfo("About to put back XATMI-in object %d", nr) 130 | //put batch in channel 131 | pool.freechan <- nr 132 | }() 133 | 134 | var errA atmi.ATMIError 135 | //Setup UBF buffer, load the fields 136 | if nil == buf { 137 | buf, errA = AllocReplyDataBuffer(ac, con, corr, data, false) 138 | 139 | if errA != nil { 140 | ac.TpLogError("failed to create the net->ex UBF buffer: %s", 141 | errA.Message()) 142 | return 143 | } 144 | } else { 145 | //Set the current context of the buffer 146 | buf.GetBuf().TpSetCtxt(ac) 147 | } 148 | 149 | //OK we are here, lets call the service 150 | //If we work on non req_reply mode, then just async call 151 | 152 | buf.TpLogPrintUBF(atmi.LOG_DEBUG, "Incoming message") 153 | 154 | //Full async mode 155 | // Feature #204 - allow in full async mode sync invopcation of incomings... 156 | if (RR_PERS_ASYNC_INCL_CORR == MReqReply || 157 | RR_PERS_CONN_EX2NET == MReqReply) && !MIncomingSvcSync { 158 | ac.TpLogInfo("Calling in async mode (fully async or conn_ex2net mode)") 159 | _, errA := ac.TpACall(MIncomingSvc, buf, atmi.TPNOREPLY) 160 | 161 | if nil != errA { 162 | ac.TpLogError("Failed to acall [%s]: %s", 163 | MIncomingSvc, errA.Message()) 164 | } 165 | } else { 166 | ac.TpLogInfo("Req-reply mode enabled and this is incoming call, " + 167 | "do call the service in sync mode") 168 | 169 | _, errA := ac.TpCall(MIncomingSvc, buf, atmi.TPNOTIME) 170 | 171 | if errA != nil { 172 | ac.TpLogError("Failed to call %s service: %d: %s", 173 | MIncomingSvc, errA.Code(), errA.Message()) 174 | //Nothing to reply back 175 | } else { 176 | //Read the data block and reply back 177 | var b DataBlock 178 | b.data, errA = buf.BGetByteArr(u.EX_NETDATA, 0) 179 | if nil != errA { 180 | ac.TpLogError("Protocol error: failed to get "+ 181 | "EX_NETDATA: %s", errA) 182 | //Shutdonw the sync incoming connection only 183 | //If needed (i.e. if it one connection per request) 184 | con.shutdown <- true 185 | 186 | } else { 187 | ac.TpLogInfo("Got message from EX, sending to net len: %d", 188 | len(b.data)) 189 | //Maybe send to channel for reply 190 | //And then shutdown (if needed, will by done by con it self) 191 | //How about locking, connection is already locked!!!! 192 | 193 | //Really, the incoming thread already holds the lock! 194 | //ac.TpLogDebug("No lock mode") 195 | //b.nolock = true 196 | con.outgoing <- &b 197 | } 198 | } 199 | } 200 | } 201 | 202 | //Dispatch connection answer 203 | 204 | //@param call Call data block (what caller thread actually made) 205 | //@param data Data block received from network 206 | //@param bool ptr for finish off parameter 207 | func NetDispatchConAnswer(ac *atmi.ATMICtx, con *ExCon, block *DataBlock, data []byte, doContinue *bool) { 208 | 209 | //Setup UBF buffer, load the fields 210 | buf, err := AllocReplyDataBuffer(ac, con, "", data, true) 211 | 212 | if err != nil { 213 | ac.TpLogError("failed to create the net->ex UBF buffer: %s", 214 | err.Message()) 215 | return 216 | } 217 | 218 | //Network answer on connection 219 | block.atmi_chan <- buf 220 | 221 | //We should shutdown the connection if this is request/reply mode 222 | //with out persistent connections 223 | if MReqReply == RR_NONPERS_EX2NET { 224 | 225 | ac.TpLogWarn("Non peristent connection mode, got answer from network" + 226 | " - requesting connection shutdown") 227 | *doContinue = false 228 | } 229 | } 230 | 231 | //Dispatch connection answer 232 | //@param call Call data block (what caller thread actually made) 233 | //@param data Data block received from network 234 | //@param bool ptr for finish off parameter 235 | func NetDispatchCorAnswer(ac *atmi.ATMICtx, con *ExCon, block *DataBlock, 236 | buf *atmi.TypedUBF, doContinue *bool) { 237 | ac.TpLogInfo("Doing reply to correlated ex->net call") 238 | block.atmi_chan <- buf //Send the data to caller 239 | } 240 | 241 | //Get correlator id from incoming message. The correlator is set in UBF buffer 242 | //@param ac ATMI Context 243 | //@param buf ATMI buffer 244 | //@return ATMI error if fail, or nil if all ok 245 | func NetGetCorID(ac *atmi.ATMICtx, buf *atmi.TypedUBF) (string, atmi.ATMIError) { 246 | 247 | _, err := ac.TpCall(MCorrSvc, buf, 0) 248 | 249 | if nil != err { 250 | ac.TpLogError("Failed to call [%s] service: %s", 251 | MCorrSvc, err.Message()) 252 | return "", err 253 | } 254 | 255 | ret, _ := buf.BGetString(u.EX_NETCORR, 0) 256 | ac.TpLogInfo("Got correlation from service: [%s]", ret) 257 | 258 | return ret, nil 259 | } 260 | 261 | /* vim: set ts=4 sw=4 et smartindent: */ 262 | -------------------------------------------------------------------------------- /pkg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## 2 | ## @brief Connectivity packaging scripts 3 | ## 4 | ## @file CMakeLists.txt 5 | ## 6 | ## ----------------------------------------------------------------------------- 7 | ## Enduro/X Middleware Platform for Distributed Transaction Processing 8 | ## Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | ## Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | ## This software is released under one of the following licenses: 11 | ## AGPL or Mavimax's license for commercial use. 12 | ## ----------------------------------------------------------------------------- 13 | ## AGPL license: 14 | ## 15 | ## This program is free software; you can redistribute it and/or modify it under 16 | ## the terms of the GNU Affero General Public License, version 3 as published 17 | ## by the Free Software Foundation; 18 | ## 19 | ## This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | ## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | ## PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | ## for more details. 23 | ## 24 | ## You should have received a copy of the GNU Affero General Public License along 25 | ## with this program; if not, write to the Free Software Foundation, Inc., 26 | ## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | ## 28 | ## ----------------------------------------------------------------------------- 29 | ## A commercial use license is available from Mavimax, Ltd 30 | ## contact@mavimax.com 31 | ## ----------------------------------------------------------------------------- 32 | ## 33 | 34 | cmake_minimum_required (VERSION 3.1) 35 | project (ENDUROX-CONNECT) 36 | set(VERSION "8.0.8") 37 | set(PROJ_NAME "Enduro/X Connectivity Module") 38 | set(RELEASE "1") 39 | 40 | set(CMAKE_MODULE_PATH $ENV{CMAKE_MODULE_PATH} ${CMAKE_MODULE_PATH} "/usr/share/endurox/cmake") 41 | include(ex_osver) 42 | 43 | ################################################################################ 44 | # Process any required includes 45 | ################################################################################ 46 | ex_osver_include() 47 | ################################################################################ 48 | 49 | 50 | ################################################################################ 51 | # Check versions if defined, export build env 52 | ################################################################################ 53 | 54 | if(DEFINED ENV{NDRX_BLD_VERSION}) 55 | IF(NOT $ENV{NDRX_BLD_VERSION} MATCHES ${VERSION}) 56 | message( FATAL_ERROR "Invalid versions: ENV: [$ENV{NDRX_BLD_VERSION}] Code: [${VERSION}]" ) 57 | endif() 58 | endif() 59 | 60 | if(DEFINED ENV{NDRX_BLD_RELEASE}) 61 | set(RELEASE $ENV{NDRX_BLD_RELEASE}) 62 | endif() 63 | 64 | message("CMake RELEASE = ${RELEASE}") 65 | 66 | SET (NDRX_BLD_PRODUCT $ENV{NDRX_BLD_PRODUCT}) 67 | SET (NDRX_BLD_SYSTEM $ENV{NDRX_BLD_SYSTEM}) 68 | SET (NDRX_BLD_CONFIG $ENV{NDRX_BLD_CONFIG}) 69 | SET (NDRX_BLD_VERSION $ENV{NDRX_BLD_VERSION}) 70 | SET (NDRX_BLD_RELEASE $ENV{NDRX_BLD_RELEASE}) 71 | SET (NDRX_BLD_TAG $ENV{NDRX_BLD_TAG}) 72 | SET (NDRX_BLD_BRANCH $ENV{NDRX_BLD_BRANCH}) 73 | SET (NDRX_BLD_COMMIT $ENV{NDRX_BLD_COMMIT}) 74 | SET (NDRX_BLD_FLAGS $ENV{NDRX_BLD_FLAGS}) 75 | 76 | 77 | ################################################################################ 78 | # OS Configuration 79 | ################################################################################ 80 | 81 | find_program(A2X_EXECUTABLE NAMES a2x) 82 | 83 | 84 | EXEC_PROGRAM(uname ARGS -a OUTPUT_VARIABLE _TMP_CMAKE_OS_NAME) 85 | string(REGEX MATCH "^[a-zA-Z0-9-]*" _TMP_CMAKE_OS_NAME_EXTR ${_TMP_CMAKE_OS_NAME}) 86 | string(TOUPPER ${_TMP_CMAKE_OS_NAME_EXTR} CMAKE_OS_NAME) 87 | 88 | message("CMake CMAKE_OS_NAME = ${CMAKE_OS_NAME}") 89 | message("CMake CMAKE_C_COMPILER_ID = ${CMAKE_C_COMPILER_ID}") 90 | message("CMake CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}") 91 | 92 | if( "${CMAKE_OS_NAME}" STREQUAL "LINUX" ) 93 | set(EX_OS_LINUX "1") 94 | elseif("${CMAKE_OS_NAME}" STREQUAL "AIX") 95 | set(EX_OS_AIX "1") 96 | set ( CMAKE_C_FLAGS "-D_SEM_SEMUN_UNDEFINED -D_MSGQSUPPORT -D_THREAD_SAFE -pthread -maix64 -Wl,-brtl -Wl,-G ${CMAKE_C_FLAGS}") 97 | set ( CMAKE_CXX_FLAGS "-D_SEM_SEMUN_UNDEFINED -D_MSGQSUPPORT -D_THREAD_SAFE -pthread -maix64 -Wl,-brtl -Wl,-G ${CMAKE_CXX_FLAGS}") 98 | elseif("${CMAKE_OS_NAME}" STREQUAL "HP-UX") 99 | set(EX_OS_HPUX "1") 100 | elseif("${CMAKE_OS_NAME}" STREQUAL "SUNOS") 101 | set(EX_OS_SUNOS "1") 102 | elseif("${CMAKE_OS_NAME}" STREQUAL "FREEBSD") 103 | set(EX_OS_FREEBSD "1") 104 | elseif("${CMAKE_OS_NAME}" STREQUAL "CYGWIN") 105 | set(EX_OS_CYGWIN "1") 106 | elseif("${CMAKE_OS_NAME}" STREQUAL "DARWIN") 107 | set(EX_OS_DARWIN "1") 108 | # Unkonwn OS: 109 | else() 110 | message( FATAL_ERROR "Unsupported OS" ) 111 | endif() 112 | 113 | 114 | if(${CMAKE_OS_NAME} STREQUAL "DARWIN") 115 | set(LIB_SUFFIX "") 116 | elseif ("${LIB64}" STREQUAL "TRUE") 117 | set(LIB_SUFFX 64) 118 | else() 119 | set(LIB_SUFFIX "") 120 | endif() 121 | 122 | set(INSTALL_LIB_DIR lib${LIB_SUFFIX} CACHE PATH "Installation directory for libraries") 123 | mark_as_advanced(INSTALL_LIB_DIR) 124 | MESSAGE( STATUS "INSTALL_LIB_DIR: " ${INSTALL_LIB_DIR} ) 125 | ################################################################################ 126 | # Files to install 127 | ################################################################################ 128 | 129 | install (FILES 130 | ../go/src/tcpgatesv/tcpgatesv 131 | ../go/src/restincl/restincl 132 | ../go/src/restoutsv/restoutsv 133 | PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ 134 | DESTINATION bin) 135 | 136 | # check that a2x actually works, on aix there is a2x but it is not asciidoc 137 | 138 | execute_process(COMMAND a2x "--version" RESULT_VARIABLE RET) 139 | if(A2X_EXECUTABLE) 140 | 141 | if( NOT ${RET} MATCHES "0") 142 | message("a2x does not work - disabling doc...") 143 | unset(A2X_EXECUTABLE) 144 | elseif() 145 | # Install manpages (if any 146 | install (FILES 147 | ../doc/manpage/restincl.8 148 | ../doc/manpage/restousv.8 149 | ../doc/manpage/tcpgatesv.8 150 | DESTINATION share/man/man8) 151 | 152 | install (FILES 153 | ../doc/manpage/tcpgatesv.html 154 | ../doc/manpage/restincl.html 155 | ../doc/manpage/restoutsv.html 156 | DESTINATION share/endurox-connect/doc/html/manpage) 157 | 158 | install (FILES 159 | ../doc/manpage/docbook-xsl.css 160 | DESTINATION share/endurox-connect/doc/html/manpage 161 | OPTIONAL) 162 | 163 | install (FILES 164 | ../doc/restinout_user_guide.html 165 | ../doc/tcpgatesv_user_guide.html 166 | ../doc/nonpers_sync_ex_to_net.png 167 | ../doc/nonpers_sync_net_to_ex.png 168 | ../doc/pers_async_ex_to_net_wo_corr.png 169 | ../doc/pers_async_net_to_ex_w_corr.png 170 | ../doc/pers_async_net_to_ex_wo_corr.png 171 | ../doc/pers_sync_ex_to_net_connid.png 172 | ../doc/pers_sync_net_to_ex.png 173 | ../doc/restinout_tutor_1.png 174 | DESTINATION share/endurox-connect/doc/html/guides) 175 | 176 | install (FILES 177 | ../doc/docbook-xsl.css 178 | DESTINATION share/endurox-connect/doc/html/guides 179 | OPTIONAL) 180 | endif() 181 | endif() 182 | 183 | ################################################################################ 184 | # Packages 185 | ################################################################################ 186 | ex_osver() 187 | ex_cpuarch() 188 | 189 | MESSAGE( "CPack:Debug: CMAKE_SYSTEM_NAME = " ${CMAKE_SYSTEM_NAME} ) 190 | MESSAGE( "CPack:Debug: CMAKE_SYSTEM_PROCESSOR = " ${CMAKE_SYSTEM_PROCESSOR} ) 191 | set(CPACK_MONOLITHIC_INSTALL 1) 192 | 193 | find_program(RPMPROG "rpmbuild") 194 | find_program(APTPROG "dpkg") 195 | 196 | # avoid file /usr/share/man from install of endurox-3.5.1-1.x86_64 conflicts with file from package filesystem-3.2-21.el7.x86_64 197 | # problems... 198 | set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/share/man 199 | /usr/share/man/man3 200 | /usr/share/man/man5 201 | /usr/share/man/man8 202 | /usr/share/java 203 | /usr/lib64/pkgconfig 204 | /usr/lib/pkgconfig) 205 | message("Excl: ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION}") 206 | 207 | set(CPACK_GENERATOR "TGZ") 208 | if(RPMPROG) 209 | message("Outputting RPM") 210 | set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM") 211 | endif() 212 | 213 | if(APTPROG) 214 | message("Outputting DEB") 215 | set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB") 216 | endif() 217 | 218 | INCLUDE (${CMAKE_ROOT}/Modules/CheckTypeSize.cmake) 219 | CHECK_TYPE_SIZE("void*" EX_SIZEOF_VOIDPTR) 220 | MATH (EXPR EX_PLATFORM_BITS "${EX_SIZEOF_VOIDPTR} * 8") 221 | 222 | message("Generator: ${CPACK_GENERATOR}") 223 | 224 | set(CPACK_PACKAGE_CONTACT "contact@mavimax.com") 225 | set(CPACK_PACKAGE_VERSION ${VERSION}) 226 | set(CPACK_PACKAGE_VENDOR "Mavimax Ltd") 227 | #set(CPACK_DEBIAN_PACKAGE_DEPENDS "endurox") 228 | #set(CPACK_RPM_PACKAGE_REQUIRES "endurox") 229 | string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LO) 230 | message("CPack:Debug: PROJECT NAME = ${PROJECT_NAME_LO}") 231 | set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME_LO}-${VERSION}-${RELEASE}.${LSB_RELEASE_OUTPUT_OS}${LSB_RELEASE_OUTPUT_VER}.${EX_CPU_ARCH}) 232 | string(TOLOWER ${CPACK_PACKAGE_FILE_NAME} CPACK_PACKAGE_FILE_NAME) 233 | message("CPack:Debug: CPACK_PACKAGE_FILE_NAME = ${CPACK_PACKAGE_FILE_NAME}") 234 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Enduro/X Connectivity Module") 235 | set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION}) 236 | set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION}) 237 | set(CPACK_RPM_PACKAGE_AUTOREQ "0") 238 | #set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/Debian/postinst") 239 | 240 | include(CPack) 241 | ################################################################################ 242 | 243 | 244 | # vim: set ts=4 sw=4 et smartindent: 245 | -------------------------------------------------------------------------------- /go/src/tcpgatesv/periodic.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief This module contains periodic callback processing 3 | * 4 | * @file periodic.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | "exutil" 37 | 38 | atmi "github.com/endurox-dev/endurox-go" 39 | ) 40 | 41 | //Zero sending periodic stopwatch 42 | var MStatusRefreshStopWatch exutil.StopWatch 43 | var MInIdleCheckStopWatch exutil.StopWatch 44 | 45 | //Send zero 46 | func RunZero(ac *atmi.ATMICtx, con *ExCon) { 47 | 48 | var block DataBlock 49 | 50 | if MFramingOffset > 0 { 51 | //Go by default set to 0 52 | block.data = make([]byte, MFramingLen) 53 | } 54 | 55 | p_block := &block 56 | ac.TpLogInfo("Sending zero length message to id:%d conn_id: %d ", 57 | con.id, con.id_comp) 58 | 59 | select { 60 | case con.outgoing <- p_block: 61 | default: 62 | ac.TpLogDebug("No zero msg -> channel full") 63 | } 64 | 65 | } 66 | 67 | //Check activity over open conns 68 | //So that if we have not received anyting 69 | func RunCheckInIdleChk(ac *atmi.ATMICtx) { 70 | 71 | //Lock all connections 72 | MConnMutex.Lock() 73 | for _, v := range MConnectionsComp { 74 | 75 | if v.is_open { 76 | 77 | spent := v.inIdle.GetDetlaSec() 78 | if spent > MInIdleMax { 79 | ac.TpLogWarn("RESET: Connect %d/%d not received any data in %d sec "+ 80 | "(already spent: %d sec) - resetting conn", 81 | v.id, v.id_comp, MInIdleMax, spent) 82 | //Close connection 83 | v.shutdown <- true 84 | } 85 | 86 | } else { 87 | ac.TpLogInfo("conn %d/%d is not yet open - not sending zero msg", 88 | v.id, v.id_comp) 89 | } 90 | } 91 | 92 | MConnMutex.Unlock() 93 | } 94 | 95 | //Send zero length messages over the channels 96 | func RunStatusRefresh(ac *atmi.ATMICtx) { 97 | 98 | //Lock all connections 99 | MConnMutex.Lock() 100 | var i int64 101 | 102 | for i = 1; i <= MMaxConnections; i++ { 103 | 104 | if nil != MConnectionsSimple[i] && MConnectionsSimple[i].is_open { 105 | ac.TpLogInfo("REFRESH: Notify connection %d UP", i) 106 | 107 | NotifyStatus(ac, i, MConnectionsSimple[i].id_comp, FLAG_CON_ESTABLISHED, 108 | MConnectionsSimple[i]) 109 | } else { 110 | ac.TpLogInfo("REFRESH: Notify connection %d DOWN", i) 111 | NotifyStatus(ac, i, atmi.FAIL, FLAG_CON_DISCON, nil) 112 | } 113 | } 114 | 115 | MConnMutex.Unlock() 116 | 117 | } 118 | 119 | //Check the outgoint connections 120 | func CheckDial(ac *atmi.ATMICtx) { 121 | 122 | //var openConns int64 = MMaxConnections - int64(len(MConnections)) 123 | var i int64 124 | 125 | ac.TpLogInfo("CheckDial: Active connection, checking outgoing connections...") 126 | 127 | for i = GetOpenConnectionCount(); i < MMaxConnections; i++ { 128 | 129 | //Spawn new connection threads 130 | var con ExCon 131 | 132 | SetupConnection(&con) 133 | 134 | //1. Prepare connection block 135 | MConnMutex.Lock() 136 | con.id, con.id_stamp, con.id_comp = GetNewConnectionId(ac) 137 | 138 | if con.id == FAIL { 139 | ac.TpLogError("Failed to get connection id - max reached?") 140 | MConnMutex.Unlock() 141 | break 142 | } 143 | 144 | //2. Add to hash, -- why not 2017/09/29 - we get the same connection ids... 145 | //when they are not connect but new ids are generated? 146 | /* 147 | mvitolin 2017/01/25 do it when connection is established in GoDial*/ 148 | 149 | MConnectionsSimple[con.id] = &con 150 | MConnectionsComp[con.id_comp] = &con 151 | 152 | MConnMutex.Unlock() 153 | 154 | //3. and spawn the routine... 155 | go GoDial(&con, nil) 156 | } 157 | 158 | } 159 | 160 | //Test is call block timed out 161 | //@param v Call block 162 | //@return true - timed out, false - call not timed out 163 | func IsBlockTimeout(ac *atmi.ATMICtx, v *DataBlock) bool { 164 | 165 | cur := exutil.GetEpochMillis() 166 | sum := v.tstamp_sent + MReqReplyTimeout 167 | ac.TpLogDebug("Testing tout: tstamp_sent=%d, "+ 168 | "MReqReplyTimeout=%d, sum=%d, current=%d, delta=%d", 169 | v.tstamp_sent, MReqReplyTimeout, 170 | sum, cur, 171 | (cur - v.tstamp_sent)) 172 | 173 | if sum < cur { 174 | ac.TpLogWarn("Call timed out!") 175 | return true 176 | } 177 | 178 | return false 179 | } 180 | 181 | //Check the connection timeouts 182 | //if needed generate timeout-response 183 | //and repond to service. Remove from waiter list 184 | //if timed out 185 | //@param ac ATMI Context 186 | func CheckTimeouts(ac *atmi.ATMICtx) atmi.ATMIError { 187 | 188 | //Lock the channels 189 | //The message shall not appear in both list correlated & by connection 190 | MConWaiterMutex.Lock() 191 | ac.TpLogDebug("Checking sync connection lists for timeouts") 192 | for k, v := range MConWaiter { 193 | 194 | if MReqReply == RR_PERS_CONN_EX2NET || MReqReply == RR_PERS_CONN_NET2EX || 195 | MReqReply == RR_NONPERS_EX2NET || MReqReply == RR_NONPERS_NET2EX { 196 | 197 | if IsBlockTimeout(ac, v) { 198 | ac.TpLogWarn("Call expired!") 199 | buf, err := GenErrorUBF(ac, 0, atmi.NETOUT, 200 | "Timed out waiting for answer...") 201 | 202 | if nil == err { 203 | //Remove from list 204 | delete(MConWaiter, k) 205 | ac.TpLogInfo("Sending reply back to ATMI") 206 | v.atmi_chan <- buf 207 | ac.TpLogInfo("Sending reply back to ATMI, done") 208 | 209 | //Will kill a connection 210 | //Because the other end will might sent reply 211 | //later and that will confuse next caller. 212 | ac.TpLogInfo("Killing connection") 213 | ac.TpLogDebug("v=%p", v) 214 | ac.TpLogDebug("v.con=%p", v.con) 215 | 216 | v.con.shutdown <- true 217 | ac.TpLogInfo("Killing connection, done") 218 | 219 | } else { 220 | MConWaiterMutex.Unlock() 221 | return err 222 | } 223 | } 224 | } 225 | } 226 | MConWaiterMutex.Unlock() 227 | 228 | MCorrWaiterMutex.Lock() 229 | ac.TpLogDebug("Checking async correlation connection lists for timeout") 230 | for k, v := range MCorrWaiter { 231 | 232 | if v.corr != "" || MReqReply == RR_NONPERS_EX2NET || 233 | MReqReply == RR_PERS_CONN_EX2NET { 234 | 235 | if IsBlockTimeout(ac, v) { 236 | buf, err := GenErrorUBF(ac, 0, atmi.NETOUT, 237 | "Timed out waiting for answer...") 238 | 239 | if nil == err { 240 | //Remove from list 241 | delete(MCorrWaiter, k) 242 | ac.TpLogInfo("Sending reply back to ATMI") 243 | v.atmi_chan <- buf 244 | ac.TpLogInfo("Sending reply back to ATMI, done") 245 | 246 | //Kill the connection, if non persistent 247 | if MReqReply == RR_NONPERS_EX2NET || 248 | MReqReply == RR_PERS_CONN_EX2NET { 249 | ac.TpLogInfo("Killing connection") 250 | ac.TpLogDebug("v=%p", v) 251 | ac.TpLogDebug("v.con=%p", v.con) 252 | v.con.shutdown <- true 253 | ac.TpLogInfo("Killing connection, done") 254 | } 255 | 256 | } else { 257 | MCorrWaiterMutex.Unlock() 258 | return err 259 | } 260 | } 261 | } 262 | } 263 | MCorrWaiterMutex.Unlock() 264 | 265 | return nil 266 | 267 | } 268 | 269 | //Periodic callback function 270 | //Hmm do we have some context here? 271 | //We will spawn connections here.. 272 | func Periodic(ac *atmi.ATMICtx) int { 273 | 274 | ret := atmi.SUCCEED 275 | //if we are active, check that we have enought connections 276 | if MType == CON_TYPE_ACTIVE && (MReqReply == RR_PERS_ASYNC_INCL_CORR || 277 | MReqReply == RR_PERS_CONN_EX2NET) { 278 | CheckDial(ac) 279 | } 280 | 281 | if err := CheckTimeouts(ac); nil != err { 282 | 283 | ac.TpLogError("Failed check timeouts: %s - Aborting...", 284 | err.Message()) 285 | return atmi.FAIL 286 | 287 | } 288 | 289 | if MStatusRefresh > 0 && MStatusRefreshStopWatch.GetDetlaSec() > int64(MStatusRefresh) { 290 | ac.TpLogInfo("Time for status refresh messages to be sent...") 291 | 292 | RunStatusRefresh(ac) 293 | MStatusRefreshStopWatch.Reset() 294 | 295 | } 296 | 297 | //Check the idle time incoming activitiy, if no messages received in given 298 | //time frame then connection is reset 299 | if MInIdleCheck > 0 && MInIdleCheckStopWatch.GetDetlaSec() > MInIdleCheck { 300 | ac.TpLogInfo("Time for idle connection checks with no incomming traffic") 301 | 302 | RunCheckInIdleChk(ac) 303 | MInIdleCheckStopWatch.Reset() 304 | 305 | } 306 | 307 | //TODO: Check for any outstanding network calls... 308 | //Send the timeout message of tout got. 309 | //Close the connection if req/reply.. 310 | 311 | if MShutdown == RUN_SHUTDOWN_FAIL { 312 | //Hmm does not cause shutdown!!! 313 | ac.TpLogWarn("Fail state shutdown requested! - Aborting...") 314 | ret = atmi.FAIL 315 | } 316 | 317 | return ret 318 | } 319 | 320 | /* vim: set ts=4 sw=4 et smartindent: */ 321 | -------------------------------------------------------------------------------- /tests/02_tcpgatesv/runtime/conf/ndrxconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 12 | 5 13 | 14 | 17 | 6 18 | 19 | 22 | 1 23 | 24 | 27 | 1 28 | 29 | 32 | 5 33 | 34 | 37 | 38 | 42 | 20 43 | 44 | 45 | 50 | Y 51 | 52 | 53 | 54 | 55 | 1 56 | 2 57 | 58 | 61 | 1 62 | 63 | 67 | 2 68 | 69 | 72 | 1 73 | 74 | 79 | 40 80 | 81 | 85 | 1 86 | 87 | 91 | 1 92 | 93 | 96 | Y 97 | 98 | 3,2,9 99 | 100 | 101 | 102 | 1 103 | 1 104 | 1 105 | -e ${NDRX_APPHOME}/log/cconfsrv.log -r 106 | 107 | 108 | 2 109 | 2 110 | 20 111 | -e ${NDRX_APPHOME}/log/tpevsrv.log -r 112 | 113 | 114 | 3 115 | 3 116 | 40 117 | RM1TMQ 118 | -e ${NDRX_APPHOME}/log/tmsrv-rm1.log -r -- -t1 -l${NDRX_APPHOME}/tmlogs/rm1 119 | 120 | 121 | 1 122 | 1 123 | 60 124 | RM1TMQ 125 | -e ${NDRX_APPHOME}/log/tmqueue-rm1.log -r -- -s1 126 | 127 | 128 | 1 129 | 1 130 | 150 131 | -e ${NDRX_APPHOME}/log/tpbridge_2.log -r 132 | -f -n2 -r -i 172.0.0.1 -p 21003 -tA -z30 133 | 134 | 135 | 1 136 | 1 137 | 500 138 | -e ${NDRX_APPHOME}/log/testsv.log -r 139 | 140 | 141 | pers/async/active 142 | 1 143 | 1 144 | 200 145 | -e ${NDRX_APPHOME}/log/tcpgatesv-async-active.log -r 146 | 147 | 148 | pers/async/passive 149 | 1 150 | 1 151 | 210 152 | -e ${NDRX_APPHOME}/log/tcpgatesv-async-passive.log -r 153 | 154 | 155 | pers/asyncsync/active 156 | 1 157 | 1 158 | 215 159 | -e ${NDRX_APPHOME}/log/tcpgatesv-asyncsync-active.log -r 160 | 161 | 162 | pers/asyncsync/passive 163 | 1 164 | 1 165 | 216 166 | -e ${NDRX_APPHOME}/log/tcpgatesv-asyncsync-passive.log -r 167 | 168 | 169 | pers/sync/active 170 | 1 171 | 1 172 | 220 173 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-active.log -r 174 | 175 | 176 | pers/sync/passive 177 | 1 178 | 1 179 | 230 180 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-passive.log -r 181 | 182 | 183 | nonpers/active 184 | 1 185 | 1 186 | 240 187 | -e ${NDRX_APPHOME}/log/tcpgatesv-nonpers-active.log -r 188 | 189 | 190 | nonpers/pasive 191 | 1 192 | 1 193 | 250 194 | -e ${NDRX_APPHOME}/log/tcpgatesv-nonpers-passive.log -r 195 | 196 | 197 | pers/async/active/idlerst 198 | 1 199 | 1 200 | 260 201 | -e ${NDRX_APPHOME}/log/tcpgatesv-async-active-idlerst.log -r 202 | 203 | 204 | pers/async/passive/idlerst 205 | 1 206 | 1 207 | 270 208 | -e ${NDRX_APPHOME}/log/tcpgatesv-async-passive-idlerst.log -r 209 | 210 | 211 | pers/async/active/idlerstact 212 | 1 213 | 1 214 | 280 215 | -e ${NDRX_APPHOME}/log/tcpgatesv-async-active-idlerstact.log -r 216 | 217 | 218 | pers/async/passive/idlerstact 219 | 1 220 | 1 221 | 290 222 | -e ${NDRX_APPHOME}/log/tcpgatesv-async-passive-idlerstact.log -r 223 | 224 | 225 | 226 | pers/sync_offset_incl/active 227 | 1 228 | 1 229 | 300 230 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-offset_incl-active.log -r 231 | 232 | 233 | pers/sync_offset_incl/passive 234 | 1 235 | 1 236 | 310 237 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-offset_incl-passive.log -r 238 | 239 | 240 | pers/sync_offset/active 241 | 1 242 | 1 243 | 320 244 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-offset-active.log -r 245 | 246 | 247 | pers/sync_offset/passive 248 | 1 249 | 1 250 | 330 251 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-offset-passive.log -r 252 | 253 | 254 | 255 | 256 | pers/sync_offset_incl_P/active 257 | 1 258 | 1 259 | 331 260 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-offset_incl_P-active.log -r 261 | 262 | 263 | pers/sync_offset_incl_P/passive 264 | 1 265 | 1 266 | 332 267 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-offset_incl_P-passive.log -r 268 | 269 | 270 | pers/sync_offset_p/active 271 | 1 272 | 1 273 | 333 274 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-offset_p-active.log -r 275 | 276 | 277 | pers/sync_offset_p/passive 278 | 1 279 | 1 280 | 334 281 | -e ${NDRX_APPHOME}/log/tcpgatesv-pers-sync-offset_p-passive.log -r 282 | 283 | 284 | 285 | 286 | pers/sequence/active 287 | 1 288 | 1 289 | 340 290 | -e ${NDRX_APPHOME}/log/tcpgatesv-sequence-active.log -r 291 | 292 | 293 | pers/sequence/passive 294 | 1 295 | 1 296 | 350 297 | -e ${NDRX_APPHOME}/log/tcpgatesv-sequence-passive.log -r 298 | 299 | 300 | 301 | pers/tls/active 302 | 1 303 | 1 304 | 400 305 | -e ${NDRX_APPHOME}/log/tcpgatesv-tls-active.log -r 306 | 307 | 308 | pers/tls/passive 309 | 1 310 | 1 311 | 410 312 | -e ${NDRX_APPHOME}/log/tcpgatesv-tls-passive.log -r 313 | 314 | 315 | 316 | 1 317 | 1 318 | 9999 319 | -e ${NDRX_APPHOME}/log/cpmsrv.log -r -- -k3 -i1 320 | 321 | 322 | 323 | 326 | 327 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | -------------------------------------------------------------------------------- /tests/03_restout/src/testcl/testcl.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "os" 8 | "strconv" 9 | u "ubftab" 10 | 11 | atmi "github.com/endurox-dev/endurox-go" 12 | ) 13 | 14 | /* 15 | #include 16 | */ 17 | import "C" 18 | 19 | const ( 20 | ProgSection = "testcl" 21 | ) 22 | 23 | var MSomeConfigFlag string = "" 24 | var MSomeOtherConfigFlag int = 0 25 | var MErrorCode int = atmi.TPMINVAL 26 | 27 | type TestJSONMsg struct { 28 | StringField string `json:"StringField"` 29 | StringField2 string `json:"StringField2"` 30 | NumField int `json:"NumField"` 31 | NumField2 int `json:"NumField2"` 32 | BoolField bool `json:"BoolField"` 33 | BoolField2 bool `json:"BoolField2"` 34 | } 35 | 36 | //Test big message over the rest interface 37 | func BigMsg(ac *atmi.ATMICtx, cmd string, svc string, times string) error { 38 | 39 | nrTimes, _ := strconv.Atoi(times) 40 | 41 | for i := 0; i < nrTimes; i++ { 42 | buf, err := ac.NewUBF(1024*1024 + 1024) 43 | 44 | if err != nil { 45 | return errors.New(err.Error()) 46 | } 47 | 48 | testdata := make([]byte, 1024*1024) 49 | 50 | for i := 0; i < len(testdata); i++ { 51 | testdata[i] = byte((i + 1) % 255) 52 | } 53 | 54 | if err := buf.BChg(u.T_CARRAY_FLD, 0, testdata); nil != err { 55 | fmt.Printf("! ATMI Error %d:[%s]\n", err.Code(), err.Message()) 56 | return errors.New(fmt.Sprintf("! ATMI Error %d:[%s]\n", 57 | err.Code(), err.Message())) 58 | } 59 | 60 | //Call the server 61 | if _, err := ac.TpCall(svc, buf, 0); nil != err { 62 | MErrorCode = err.Code() 63 | return errors.New(err.Error()) 64 | } 65 | 66 | testdata, err = buf.BGetByteArr(u.T_CARRAY_FLD, 0) 67 | 68 | if nil != err { 69 | fmt.Printf("! Failed to get rsp: ATMI Error %d:[%s]\n", 70 | err.Code(), err.Message()) 71 | return errors.New(fmt.Sprintf("! Failed to get rsp: ATMI Error %d:[%s]\n", 72 | err.Code(), err.Message())) 73 | } 74 | 75 | for i := 0; i < len(testdata); i++ { 76 | if testdata[i] != byte((i+2)%255) { 77 | 78 | ac.TpLogError("TESTERROR: Error at index %d expected %d got: %d", 79 | i, (i+2)%255, testdata[i]) 80 | 81 | return errors.New(fmt.Sprintf("TESTERROR: Error at index %d expected %d got: %d", 82 | i, (i+2)%255, testdata[i])) 83 | } 84 | } 85 | } 86 | 87 | return nil 88 | 89 | } 90 | 91 | //Do the service call with UBF buffer 92 | func UBFCall(ac *atmi.ATMICtx, cmd string, svc string, times string) error { 93 | 94 | nrTimes, _ := strconv.Atoi(times) 95 | 96 | for i := 0; i < nrTimes; i++ { 97 | 98 | buf, err := ac.NewUBF(1024) 99 | 100 | if err != nil { 101 | return errors.New(err.Error()) 102 | } 103 | 104 | //Set some field for call 105 | buf.BChg(u.T_CHAR_FLD, 0, "A") 106 | buf.BChg(u.T_SHORT_FLD, 0, "123") 107 | buf.BChg(u.T_LONG_FLD, 0, i) 108 | buf.BChg(u.T_FLOAT_FLD, 0, "1.33") 109 | buf.BChg(u.T_DOUBLE_FLD, 0, "4444.3333") 110 | buf.BChg(u.T_STRING_FLD, 0, "HELLO") 111 | buf.BChg(u.T_CARRAY_FLD, 0, "WORLD") 112 | 113 | //Call the server 114 | if _, err := ac.TpCall(svc, buf, 0); nil != err { 115 | MErrorCode = err.Code() 116 | return errors.New(err.Error()) 117 | } 118 | 119 | //Test the response... 120 | stmt := fmt.Sprintf("T_SHORT_2_FLD==123 "+ 121 | "&& T_LONG_2_FLD==%d"+ 122 | "&& T_CHAR_2_FLD=='A'"+ 123 | "&& T_FLOAT_2_FLD==1.33"+ 124 | "&& T_DOUBLE_2_FLD==4444.3333"+ 125 | "&& T_STRING_2_FLD=='HELLO'"+ 126 | "&& T_CARRAY_2_FLD=='WORLD'", i) 127 | 128 | if res, err := buf.BQBoolEv(stmt); !res || nil != err { 129 | if nil != err { 130 | return errors.New(fmt.Sprintf("juerrors: Expression "+ 131 | "failed: %s", err.Error())) 132 | } else { 133 | return errors.New("juerrors: Expression is FALSE!: %s") 134 | } 135 | } 136 | } 137 | 138 | return nil 139 | } 140 | 141 | //Call the service with string buffer 142 | func STRINGCall(ac *atmi.ATMICtx, cmd string, svc string, times string) error { 143 | 144 | nrTimes, _ := strconv.Atoi(times) 145 | 146 | for i := 0; i < nrTimes; i++ { 147 | 148 | buf, err := ac.NewString("Hi there!") 149 | 150 | if err != nil { 151 | return errors.New(err.Error()) 152 | } 153 | 154 | //Call the server 155 | if _, err := ac.TpCall(svc, buf, 0); nil != err { 156 | MErrorCode = err.Code() 157 | return errors.New(err.Error()) 158 | } 159 | 160 | //Test the response... 161 | s := buf.GetString() 162 | exp := "Hello from EnduroX" 163 | 164 | if s != exp { 165 | ac.TpLogError("Expected: [%s] got [%s]", exp, s) 166 | return errors.New(fmt.Sprintf("Expected: [%s] got [%s]", 167 | exp, s)) 168 | } 169 | 170 | } 171 | 172 | return nil 173 | } 174 | 175 | //Call the sever with JSON buffer 176 | func JSONCall(ac *atmi.ATMICtx, cmd string, svc string, times string) error { 177 | 178 | nrTimes, _ := strconv.Atoi(times) 179 | 180 | call := "{\"StringField\":\"Hello\", \"NumField\":12345, \"BoolField\":true}" 181 | 182 | for i := 0; i < nrTimes; i++ { 183 | 184 | var msg TestJSONMsg 185 | buf, err := ac.NewJSON([]byte(call)) 186 | 187 | if err != nil { 188 | return errors.New(err.Error()) 189 | } 190 | 191 | //Call the server 192 | if _, err := ac.TpCall(svc, buf, 0); nil != err { 193 | MErrorCode = err.Code() 194 | return errors.New(err.Error()) 195 | } 196 | 197 | jerr := json.Unmarshal(buf.GetJSON(), &msg) 198 | if jerr != nil { 199 | return fmt.Errorf("Unmarshal: %s", jerr.Error()) 200 | } 201 | 202 | //Test the response... 203 | if svc == "JSONJE_OK" || svc == "JSONJE_OKNS" { 204 | //Check the normal rsp... 205 | 206 | if msg.StringField2 != "Hello" { 207 | return fmt.Errorf("StringField2 expted [Hello],"+ 208 | " got [%s]", msg.StringField2) 209 | } 210 | 211 | if !msg.BoolField2 { 212 | return errors.New("BoolField2 = true") 213 | } 214 | 215 | if msg.NumField2 != 12345 { 216 | 217 | return fmt.Errorf("NumField2 expected [12345],"+ 218 | " got [%d]", msg.NumField) 219 | } 220 | } 221 | } 222 | 223 | return nil 224 | } 225 | 226 | func CmpArrays(a []byte, b []byte) bool { 227 | if len(a) != len(b) { 228 | return false 229 | } 230 | for i, v := range a { 231 | if v != b[i] { 232 | return false 233 | } 234 | } 235 | return true 236 | } 237 | 238 | //Carray/RAW/BINARY tests... 239 | //Call the sever with JSON buffer 240 | func CARRAYCall(ac *atmi.ATMICtx, cmd string, svc string, times string) error { 241 | 242 | nrTimes, _ := strconv.Atoi(times) 243 | 244 | for i := 0; i < nrTimes; i++ { 245 | 246 | buf, err := ac.NewCarray([]byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}) 247 | 248 | if err != nil { 249 | return errors.New(err.Error()) 250 | } 251 | 252 | //Call the server 253 | if _, err := ac.TpCall(svc, buf, 0); nil != err { 254 | MErrorCode = err.Code() 255 | return errors.New(err.Error()) 256 | } 257 | //Test the response... 258 | if !CmpArrays(buf.GetBytes(), []byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}) { 259 | return fmt.Errorf("Carray fail: expected [[]byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}],"+ 260 | " got [%x]", buf.GetBytes()) 261 | } 262 | } 263 | 264 | return nil 265 | } 266 | 267 | //Call the view with REQUEST1 268 | func VIEWCallREQUEST1(ac *atmi.ATMICtx, cmd string, svc string, times string) error { 269 | 270 | nrTimes, _ := strconv.Atoi(times) 271 | 272 | for i := 0; i < nrTimes; i++ { 273 | 274 | buf, err := ac.NewVIEW("REQUEST1", 0) 275 | 276 | if err != nil { 277 | return errors.New(err.Error()) 278 | } 279 | 280 | //Set some values in buffer... 281 | ac.TpAssertEqualPanic(buf.BVChg("tshort1", 0, 5), nil, "Failed to set tshort1") 282 | ac.TpAssertEqualPanic(buf.BVChg("tlong1", 0, 77777), nil, "Failed to set tlong1") 283 | ac.TpAssertEqualPanic(buf.BVChg("tstring1", 1, "INCOMING TEST"), nil, "Failed to set tstring1") 284 | 285 | //Call the server 286 | if _, err := ac.TpCall(svc, buf, 0); nil != err { 287 | MErrorCode = err.Code() 288 | //In this case return error directly... 289 | if cmd == "view_request1_tout" { 290 | return errors.New(err.Error()) 291 | } 292 | } 293 | 294 | //The data still must be parsed in! 295 | 296 | //Test the response... 297 | tstring1, errU := buf.BVGetString("tstring1", 0, 0) 298 | ac.TpAssertEqualPanic(errU, nil, "tstring1 must be present") 299 | ac.TpLogInfo("Got string: [%s]", tstring1) 300 | ac.TpAssertEqualPanic(tstring1, "HELLO RESPONSE", "tstring1 must be set "+ 301 | "to \"HELLO RESPONSE\"") 302 | 303 | tstring1, errU = buf.BVGetString("tstring1", 1, 0) 304 | ac.TpAssertEqualPanic(errU, nil, "tstring1[1] must be present") 305 | ac.TpAssertEqualPanic(tstring1, "INCOMING TEST", "tstring1[1] must be set"+ 306 | " to \"HELLO TESTCL\"") 307 | 308 | tlong1, errU := buf.BVGetInt64("tlong1", 0, 0) 309 | ac.TpAssertEqualPanic(errU, nil, "tlong1[0] must be present") 310 | ac.TpAssertEqualPanic(tlong1, 11111, "tlong1 must be 11111") 311 | } 312 | 313 | if 0 != MErrorCode { 314 | return errors.New("VIEWCallREQUEST1 failed") 315 | } else { 316 | return nil 317 | } 318 | 319 | } 320 | 321 | //Run the listener 322 | func apprun(ac *atmi.ATMICtx) error { 323 | 324 | //Do some work here 325 | 326 | if len(os.Args) != 4 { 327 | return errors.New(fmt.Sprintf("usage: %s ", 328 | os.Args[0])) 329 | } 330 | 331 | cmd := os.Args[1] 332 | svc := os.Args[2] 333 | times := os.Args[3] 334 | 335 | ac.TpLogInfo("Got command: [%s], service: [%s], times: [%s]", cmd, svc, times) 336 | 337 | //These are projection on 01_restin/runtime/conf/restin.ini cases 338 | switch cmd { 339 | case "ubfcall": 340 | return UBFCall(ac, cmd, svc, times) 341 | case "stringcall": 342 | return STRINGCall(ac, cmd, svc, times) 343 | case "jsoncall": 344 | return JSONCall(ac, cmd, svc, times) 345 | case "carraycall": 346 | return CARRAYCall(ac, cmd, svc, times) 347 | case "view_request1", "view_request1_tout": 348 | 349 | return VIEWCallREQUEST1(ac, cmd, svc, times) 350 | case "bigmsg": 351 | return BigMsg(ac, cmd, svc, times) 352 | default: 353 | return errors.New(fmt.Sprintf("Invalid test case: [%s]", cmd)) 354 | } 355 | 356 | } 357 | 358 | //Init function 359 | //@param ac ATMI context 360 | //@return error (if erro) or nil 361 | func appinit(ac *atmi.ATMICtx) error { 362 | 363 | if err := ac.TpInit(); err != nil { 364 | return errors.New(err.Error()) 365 | } 366 | 367 | return nil 368 | } 369 | 370 | //Un-init & Terminate the application 371 | //@param ac ATMI Context 372 | //@param restCode Return code. atmi.FAIL (-1) or atmi.SUCCEED(0) 373 | func unInit(ac *atmi.ATMICtx, retCode int) { 374 | 375 | ac.TpTerm() 376 | ac.FreeATMICtx() 377 | os.Exit(retCode) 378 | } 379 | 380 | //Cliet process main entry 381 | func main() { 382 | 383 | ac, errA := atmi.NewATMICtx() 384 | 385 | if nil != errA { 386 | fmt.Fprintf(os.Stderr, "Failed to allocate cotnext %d:%s!\n", 387 | errA.Code(), errA.Message()) 388 | os.Exit(atmi.FAIL) 389 | } 390 | 391 | if err := appinit(ac); nil != err { 392 | ac.TpLogError("Failed to init: %s", err) 393 | os.Exit(atmi.FAIL) 394 | } 395 | 396 | ac.TpLogWarn("Init complete, processing...") 397 | 398 | if err := apprun(ac); nil != err { 399 | ac.TpLogError("Got error: [%s]", err.Error()) 400 | if 0 == MErrorCode { 401 | MErrorCode = atmi.TPESYSTEM 402 | } 403 | unInit(ac, MErrorCode) 404 | } 405 | 406 | unInit(ac, atmi.SUCCEED) 407 | } 408 | -------------------------------------------------------------------------------- /go/src/tcpgatesv/atmiout.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Enduro/X -> World (OUT) Request handling... 3 | * 4 | * @file atmiout.go 5 | */ 6 | /* ----------------------------------------------------------------------------- 7 | * Enduro/X Middleware Platform for Distributed Transaction Processing 8 | * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved. 9 | * Copyright (C) 2017-2018, Mavimax, Ltd. All Rights Reserved. 10 | * This software is released under one of the following licenses: 11 | * AGPL or Mavimax's license for commercial use. 12 | * ----------------------------------------------------------------------------- 13 | * AGPL license: 14 | * 15 | * This program is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU Affero General Public License, version 3 as published 17 | * by the Free Software Foundation; 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY 20 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21 | * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3 22 | * for more details. 23 | * 24 | * You should have received a copy of the GNU Affero General Public License along 25 | * with this program; if not, write to the Free Software Foundation, Inc., 26 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | * ----------------------------------------------------------------------------- 29 | * A commercial use license is available from Mavimax, Ltd 30 | * contact@mavimax.com 31 | * ----------------------------------------------------------------------------- 32 | */ 33 | package main 34 | 35 | import ( 36 | "exutil" 37 | u "ubftab" 38 | 39 | atmi "github.com/endurox-dev/endurox-go" 40 | ) 41 | 42 | //Generate error that connection is not found 43 | //@param buf UBF buffer 44 | //@param id_comp Compiled/composite connection id (can be simple too) 45 | //@param code Error code 46 | //@param messages Customer error message 47 | func GenResponse(ac *atmi.ATMICtx, buf *atmi.TypedUBF, id_comp int64, code int, message string) { 48 | 49 | sz, _ := buf.BSizeof() 50 | ac.TpLogDebug("Allocating: %d", sz) 51 | ac.BInit(buf, sz) 52 | 53 | if id_comp > 0 { 54 | buf.BChg(u.EX_NETCONNID, 0, id_comp) 55 | } 56 | 57 | buf.BChg(u.EX_NERROR_CODE, 0, code) 58 | buf.BChg(u.EX_NERROR_MSG, 0, message) 59 | } 60 | 61 | //Generate error that connection is not found 62 | //@param buf UBF buffer 63 | //@param id_comp Compiled/composite connection id (can be simple too) 64 | //@param code Error code 65 | //@param messages Customer error message 66 | //@return , ATMI Error code ir failure 67 | func GenErrorUBF(ac *atmi.ATMICtx, id_comp int64, code int, message string) (*atmi.TypedUBF, atmi.ATMIError) { 68 | 69 | buf, errA := ac.NewUBF(1024) 70 | 71 | if nil != errA { 72 | ac.TpLogError("Failed to allocate UBF buffer: %s", errA.Message()) 73 | return nil, errA 74 | } 75 | 76 | if id_comp > 0 { 77 | buf.BChg(u.EX_NETCONNID, 0, id_comp) 78 | } 79 | 80 | buf.BChg(u.EX_NERROR_CODE, 0, code) 81 | buf.BChg(u.EX_NERROR_MSG, 0, message) 82 | 83 | return buf, nil 84 | 85 | } 86 | 87 | //Dispatcht the XATMI call (in own go routine) 88 | //@param pool XATMI Pool 89 | //@param nr XATMI client number 90 | //@param ctxData Context data for request 91 | //@param buf ATMI buffer with request data 92 | //@param[in] releaseChan should we release channel here? 93 | func XATMIDispatchCall(pool *XATMIPool, nr int, ctxData *atmi.TPSRVCTXDATA, 94 | buf *atmi.TypedUBF, cd int, releaseChan bool) { 95 | 96 | ret := SUCCEED 97 | ac := pool.ctxs[nr] 98 | var connid int64 = 0 99 | var corr string = "" 100 | 101 | defer func() { 102 | 103 | if SUCCEED == ret { 104 | buf.TpLogPrintUBF(atmi.LOG_DEBUG, "Reply with SUCCEED") 105 | ac.TpReturn(atmi.TPSUCCESS, 0, buf, 0) 106 | } else { 107 | buf.TpLogPrintUBF(atmi.LOG_DEBUG, "Reply with FAIL") 108 | ac.TpReturn(atmi.TPFAIL, 0, buf, 0) 109 | } 110 | 111 | //Put back the channel 112 | //!!!! MUST Be last, otherwise while tpreturn completes 113 | //Other thread can take this object, and that makes race condition + 114 | //Corrpuption !!!! 115 | if releaseChan { 116 | pool.freechan <- nr 117 | } 118 | }() 119 | 120 | ac.TpLogInfo("About to restore context data in goroutine...") 121 | ac.TpSrvSetCtxData(ctxData, 0) 122 | ac.TpSrvFreeCtxData(ctxData) //missing bit... 123 | 124 | //Change the buffer owning context 125 | buf.GetBuf().TpSetCtxt(ac) 126 | 127 | //OK so our context have a call, now do something with it 128 | 129 | connid, _ = buf.BGetInt64(u.EX_NETCONNID, 0) 130 | corr, _ = buf.BGetString(u.EX_NETCORR, 0) 131 | 132 | if RR_PERS_ASYNC_INCL_CORR == MReqReply || RR_PERS_CONN_EX2NET == MReqReply { 133 | if GetOpenConnectionCount() > 0 { 134 | //Get the connection to send message to 135 | /* If connection id specified, then get that one.. */ 136 | var con *ExCon 137 | var block DataBlock 138 | var errA atmi.ATMIError 139 | 140 | SetupDataBlock(&block) 141 | block.data, errA = buf.BGetByteArr(u.EX_NETDATA, 0) 142 | 143 | if nil != errA { 144 | ac.TpLogError("Missing EX_NETDATA: %s!", errA.Message()) 145 | //Reply with failure 146 | 147 | GenResponse(ac, buf, atmi.NEMANDATORY, 0, 148 | "Mandatory field EX_NETDATA missing!") 149 | ret = FAIL 150 | return 151 | 152 | } 153 | ac.TpLogInfo("Waiting for connection...") 154 | if connid == 0 { 155 | con = GetOpenConnection(ac) 156 | } else { 157 | con = GetConnectionByID(ac, connid) 158 | } 159 | 160 | if nil == con { 161 | GenResponse(ac, buf, 0, atmi.NENOCONN, 162 | "No open connections available") 163 | ret = FAIL 164 | return 165 | } 166 | 167 | block.corr = corr 168 | block.atmi_out_conn_id = connid 169 | block.tstamp_sent = exutil.GetEpochMillis() 170 | block.con = con 171 | 172 | //Register in tables (if needed by config) 173 | haveMCorrWaiter := false 174 | if MReqReply == RR_PERS_ASYNC_INCL_CORR { 175 | //Only in asyn mode 176 | //In process can be only in one waiting list 177 | if corr != "" { 178 | ac.TpLogInfo("Adding request to corr table, by "+ 179 | "correlator: [%s]", corr) 180 | MCorrWaiterMutex.Lock() 181 | MCorrWaiter[corr] = &block 182 | MCorrWaiterMutex.Unlock() 183 | haveMCorrWaiter = true 184 | } 185 | } 186 | 187 | //If we work on sync way, only one data exchange over 188 | //The single channel, then lets add to id waiter list 189 | haveMConWaiter := false 190 | if MReqReply == RR_PERS_CONN_EX2NET { 191 | ac.TpLogInfo("Adding request to conn table, by "+ 192 | "comp_id: [%d]", con.id_comp) 193 | MConWaiterMutex.Lock() 194 | //WARNING! If we have multiple senders! We loose pervious in-progress calls 195 | //Probably needs to introduce some conditionals to waiton particular 196 | //connection. 197 | //Bug #533 198 | //to overcome this issue, may use seqout=1, this will send away 199 | //with single sender. 200 | MConWaiter[con.id_comp] = &block 201 | MConWaiterMutex.Unlock() 202 | haveMConWaiter = true 203 | } 204 | 205 | ac.TpLogWarn("About to send data...") 206 | con.outgoing <- &block 207 | 208 | //If we are in correl or sync mode we need to wait data 209 | //block back... 210 | 211 | if corr != "" || MReqReply == RR_PERS_CONN_EX2NET { 212 | ac.TpLogWarn("Waiting for reply: correl [%s] "+ 213 | "req_reply %d", corr, MReqReply) 214 | //Override the reply buffer 215 | //No more checks... as tout should be already generated. 216 | //So it looks like GO does not track 217 | //pointer in the channel... 218 | 219 | buf = <-block.atmi_chan 220 | 221 | //Change the context of the buf back to ours... 222 | buf.Buf.TpSetCtxt(ac) 223 | 224 | //Remove waiter from lists... 225 | ac.TpLogInfo("Got reply back") 226 | 227 | if haveMCorrWaiter { 228 | ac.TpLogInfo("Removing request from corr table, by "+ 229 | "correlator: [%s]", corr) 230 | MCorrWaiterMutex.Lock() 231 | delete(MCorrWaiter, corr) 232 | MCorrWaiterMutex.Unlock() 233 | } 234 | 235 | if haveMConWaiter { 236 | ac.TpLogInfo("Request from conn table, by "+ 237 | "comp_id: [%d]", con.id_comp) 238 | MConWaiterMutex.Lock() 239 | delete(MConWaiter, con.id_comp) 240 | MConWaiterMutex.Unlock() 241 | } 242 | } else { 243 | //Just approve the call (and remove data 244 | //so that we do not generate extra IPC traffic 245 | buf.BDel(u.EX_NETDATA, 0) 246 | GenResponse(ac, buf, con.id_comp, 0, "SUCCEED") 247 | } 248 | } else { 249 | //Reply - no connection 250 | GenResponse(ac, buf, 0, atmi.NENOCONN, 251 | "No open connections available") 252 | ret = FAIL 253 | return 254 | } 255 | } else if RR_NONPERS_EX2NET == MReqReply { 256 | ac.TpLogInfo("Non persistent mode, one connection per message. " + 257 | "Try to connect") 258 | 259 | //So we are about to open channel, get the connection id 260 | //Add connection to compiled connection list as normal 261 | //get the connection and send stuff away. The connection Handler 262 | //should know already that conn must be closed by req_reply 263 | 264 | var con ExCon 265 | var block DataBlock 266 | var errA atmi.ATMIError 267 | 268 | SetupDataBlock(&block) 269 | block.data, errA = buf.BGetByteArr(u.EX_NETDATA, 0) 270 | 271 | if nil != errA { 272 | ac.TpLogError("Missing EX_NETDATA: %s!", errA.Message()) 273 | //Reply with failure 274 | 275 | GenResponse(ac, buf, 0, atmi.NEMANDATORY, 276 | "Mandatory field EX_NETDATA missing!") 277 | ret = FAIL 278 | return 279 | 280 | } 281 | 282 | SetupConnection(&con) 283 | block.corr = corr 284 | block.atmi_out_conn_id = connid 285 | block.tstamp_sent = exutil.GetEpochMillis() 286 | 287 | //1. Prepare connection block 288 | MConnMutex.Lock() 289 | con.id, con.id_stamp, con.id_comp = GetNewConnectionId(ac) 290 | 291 | if con.id == FAIL { 292 | MConnMutex.Unlock() 293 | ac.TpLogError("Failed to get connection id - max reached?") 294 | ret = FAIL 295 | GenResponse(ac, buf, 0, atmi.NELIMIT, 296 | "Max connections reached!") 297 | return 298 | } 299 | 300 | //2. Add to hash 301 | 302 | MConnectionsSimple[con.id] = &con 303 | MConnectionsComp[con.id_comp] = &con 304 | MConnMutex.Unlock() 305 | 306 | block.con = &con 307 | 308 | //3. and spawn the routine... 309 | //Connection did not succeed. 310 | ac.TpLogInfo("About to Dial...") 311 | go GoDial(&con, &block) 312 | 313 | //4. Register conn in list 314 | ac.TpLogInfo("Register the call") 315 | MConWaiterMutex.Lock() 316 | MConWaiter[con.id_comp] = &block 317 | MConWaiterMutex.Unlock() 318 | 319 | //5. Now try to send stuff out? 320 | ac.TpLogInfo("Sending block out...") 321 | con.outgoing <- &block 322 | 323 | //6. Wait for reply 324 | ac.TpLogInfo("Waiting for reply...") 325 | buf = <-block.atmi_chan 326 | 327 | //Change the context of the buf back to ours... 328 | buf.Buf.TpSetCtxt(ac) 329 | 330 | ac.TpLogInfo("Got reply back") 331 | } else { 332 | ac.TpLogError("Unsupported operation - assuming no connection") 333 | //Reply - no connection 334 | buf.BDel(u.EX_NETDATA, 0) 335 | GenResponse(ac, buf, 0, atmi.NENOCONN, 336 | "No open connections available") 337 | ret = FAIL 338 | return 339 | } 340 | } 341 | 342 | //TODO: Allow to broadcast message over all open connections 343 | /* vim: set ts=4 sw=4 et smartindent: */ 344 | --------------------------------------------------------------------------------