Compare commits
No commits in common. "rudi_s" and "main" have entirely different histories.
|
@ -1,25 +0,0 @@
|
||||||
on: [push]
|
|
||||||
jobs:
|
|
||||||
build-doc:
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: git.tkolb.de/amateurfunk/hamnet70/asciidoctor:1.6
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: cd doc && make
|
|
||||||
- uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: documentation
|
|
||||||
path: doc/out/
|
|
||||||
deploy-doc:
|
|
||||||
needs: build-doc
|
|
||||||
runs-on: docker
|
|
||||||
if: github.ref == 'refs/heads/main'
|
|
||||||
container:
|
|
||||||
image: git.tkolb.de/amateurfunk/hamnet70/asciidoctor:1.6
|
|
||||||
steps:
|
|
||||||
- run: mkdir ~/.ssh && echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_ed25519 && chmod 0600 ~/.ssh/id_ed25519 && echo "${{ secrets.SSH_KNOWN_HOST }}" > ~/.ssh/known_hosts
|
|
||||||
- uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: documentation
|
|
||||||
- run: 'rsync -e "ssh -p 2342" -r . deployment@tkolb.de:'
|
|
|
@ -1,10 +0,0 @@
|
||||||
on: [push]
|
|
||||||
jobs:
|
|
||||||
build-hamnet70:
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: git.tkolb.de/amateurfunk/hamnet70/impl_buildenv:1.1
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: cd impl && cp src/config.h.template src/config.h && sed -i 's/undefined/"TESTCALL"/' src/config.h
|
|
||||||
- run: cd impl && ./make.sh
|
|
|
@ -1,16 +0,0 @@
|
||||||
FROM debian:stable
|
|
||||||
|
|
||||||
# for basic Forgejo + AsciiDoctor support
|
|
||||||
RUN apt update && apt install -y --no-install-recommends nodejs git ruby-rubygems make ca-certificates && apt clean
|
|
||||||
|
|
||||||
RUN gem install asciidoctor asciidoctor-diagram
|
|
||||||
|
|
||||||
# tools for diagram generation
|
|
||||||
RUN apt install -y --no-install-recommends mscgen && apt clean
|
|
||||||
|
|
||||||
# tools for automatic deployment
|
|
||||||
RUN apt install -y --no-install-recommends rsync openssh-client && apt clean
|
|
||||||
|
|
||||||
# run as unprivileged user in the container
|
|
||||||
RUN useradd -m ciuser
|
|
||||||
USER ciuser
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "usage: $0 <tag-version>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker build -t git.tkolb.de/amateurfunk/hamnet70/asciidoctor:$1 .
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "usage: $0 <tag-version>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker run -v $(realpath ../../../doc):/doc -it git.tkolb.de/amateurfunk/hamnet70/asciidoctor:$1
|
|
|
@ -1,10 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "usage: $0 <tag-version>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker login
|
|
||||||
docker push git.tkolb.de/amateurfunk/hamnet70/asciidoctor:$1
|
|
||||||
docker logout
|
|
|
@ -1,11 +0,0 @@
|
||||||
FROM debian:stable
|
|
||||||
|
|
||||||
# for Forgejo Actions
|
|
||||||
RUN apt update && apt install -y --no-install-recommends nodejs git ca-certificates && apt clean
|
|
||||||
|
|
||||||
# Hamnet70 build dependencies
|
|
||||||
RUN apt install -y --no-install-recommends cmake make gcc libc-dev libliquid-dev libhackrf-dev libfec-dev libfftw3-dev && apt clean
|
|
||||||
|
|
||||||
# run as unprivileged user in the container
|
|
||||||
RUN useradd -m ciuser
|
|
||||||
USER ciuser
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "usage: $0 <tag-version>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker build -t git.tkolb.de/amateurfunk/hamnet70/impl_buildenv:$1 .
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "usage: $0 <tag-version>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker run -v $(realpath ../../../impl):/impl -it git.tkolb.de/amateurfunk/hamnet70/impl_buildenv:$1
|
|
|
@ -1,10 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "usage: $0 <tag-version>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker login
|
|
||||||
docker push git.tkolb.de/amateurfunk/hamnet70/impl_buildenv:$1
|
|
||||||
docker logout
|
|
|
@ -3,9 +3,6 @@ OUT_DIR=out
|
||||||
$(OUT_DIR)/hamnet70.html: hamnet70.adoc
|
$(OUT_DIR)/hamnet70.html: hamnet70.adoc
|
||||||
mkdir -p $(OUT_DIR)
|
mkdir -p $(OUT_DIR)
|
||||||
asciidoctor -D $(OUT_DIR) -r asciidoctor-diagram $<
|
asciidoctor -D $(OUT_DIR) -r asciidoctor-diagram $<
|
||||||
@# Use local files to prevent privacy issues
|
|
||||||
cp -a ext/* $(OUT_DIR)
|
|
||||||
sed -i 's!src="[^"]*mathjax/[^/]*/!src="mathjax-2.7.9/!' $@
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/Arrows.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{infix:{"\u219A":c.RELACCENT,"\u219B":c.RELACCENT,"\u219C":c.WIDEREL,"\u219D":c.WIDEREL,"\u219E":c.WIDEREL,"\u219F":c.WIDEREL,"\u21A0":c.WIDEREL,"\u21A1":c.RELSTRETCH,"\u21A2":c.WIDEREL,"\u21A3":c.WIDEREL,"\u21A4":c.WIDEREL,"\u21A5":c.RELSTRETCH,"\u21A7":c.RELSTRETCH,"\u21A8":c.RELSTRETCH,"\u21AB":c.WIDEREL,"\u21AC":c.WIDEREL,"\u21AD":c.WIDEREL,"\u21AE":c.RELACCENT,"\u21AF":c.RELSTRETCH,"\u21B0":c.RELSTRETCH,"\u21B1":c.RELSTRETCH,"\u21B2":c.RELSTRETCH,"\u21B3":c.RELSTRETCH,"\u21B4":c.RELSTRETCH,"\u21B5":c.RELSTRETCH,"\u21B6":c.RELACCENT,"\u21B7":c.RELACCENT,"\u21B8":c.REL,"\u21B9":c.WIDEREL,"\u21BA":c.REL,"\u21BB":c.REL,"\u21BE":c.RELSTRETCH,"\u21BF":c.RELSTRETCH,"\u21C2":c.RELSTRETCH,"\u21C3":c.RELSTRETCH,"\u21C4":c.WIDEREL,"\u21C5":c.RELSTRETCH,"\u21C6":c.WIDEREL,"\u21C7":c.WIDEREL,"\u21C8":c.RELSTRETCH,"\u21C9":c.WIDEREL,"\u21CA":c.RELSTRETCH,"\u21CB":c.WIDEREL,"\u21CD":c.RELACCENT,"\u21CE":c.RELACCENT,"\u21CF":c.RELACCENT,"\u21D6":c.RELSTRETCH,"\u21D7":c.RELSTRETCH,"\u21D8":c.RELSTRETCH,"\u21D9":c.RELSTRETCH,"\u21DA":c.WIDEREL,"\u21DB":c.WIDEREL,"\u21DC":c.WIDEREL,"\u21DD":c.WIDEREL,"\u21DE":c.REL,"\u21DF":c.REL,"\u21E0":c.WIDEREL,"\u21E1":c.RELSTRETCH,"\u21E2":c.WIDEREL,"\u21E3":c.RELSTRETCH,"\u21E4":c.WIDEREL,"\u21E5":c.WIDEREL,"\u21E6":c.WIDEREL,"\u21E7":c.RELSTRETCH,"\u21E8":c.WIDEREL,"\u21E9":c.RELSTRETCH,"\u21EA":c.RELSTRETCH,"\u21EB":c.RELSTRETCH,"\u21EC":c.RELSTRETCH,"\u21ED":c.RELSTRETCH,"\u21EE":c.RELSTRETCH,"\u21EF":c.RELSTRETCH,"\u21F0":c.WIDEREL,"\u21F1":c.REL,"\u21F2":c.REL,"\u21F3":c.RELSTRETCH,"\u21F4":c.RELACCENT,"\u21F5":c.RELSTRETCH,"\u21F6":c.WIDEREL,"\u21F7":c.RELACCENT,"\u21F8":c.RELACCENT,"\u21F9":c.RELACCENT,"\u21FA":c.RELACCENT,"\u21FB":c.RELACCENT,"\u21FC":c.RELACCENT,"\u21FD":c.WIDEREL,"\u21FE":c.WIDEREL,"\u21FF":c.WIDEREL}}});MathJax.Ajax.loadComplete(a.optableDir+"/Arrows.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/BasicLatin.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{prefix:{"||":[0,0,b.BIN,{fence:true,stretchy:true,symmetric:true}],"|||":[0,0,b.ORD,{fence:true,stretchy:true,symmetric:true}]},postfix:{"!!":[1,0,b.BIN],"'":c.ACCENT,"++":[0,0,b.BIN],"--":[0,0,b.BIN],"..":[0,0,b.BIN],"...":c.ORD,"||":[0,0,b.BIN,{fence:true,stretchy:true,symmetric:true}],"|||":[0,0,b.ORD,{fence:true,stretchy:true,symmetric:true}]},infix:{"!=":c.BIN4,"&&":c.BIN4,"**":[1,1,b.BIN],"*=":c.BIN4,"+=":c.BIN4,"-=":c.BIN4,"->":c.BIN5,"//":[1,1,b.BIN],"/=":c.BIN4,":=":c.BIN4,"<=":c.BIN5,"<>":[1,1,b.BIN],"==":c.BIN4,">=":c.BIN5,"@":c.ORD11,"||":[2,2,b.BIN,{fence:true,stretchy:true,symmetric:true}],"|||":[2,2,b.ORD,{fence:true,stretchy:true,symmetric:true}]}}});MathJax.Ajax.loadComplete(a.optableDir+"/BasicLatin.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/CombDiacritMarks.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{postfix:{"\u0311":c.ACCENT}}});MathJax.Ajax.loadComplete(a.optableDir+"/CombDiacritMarks.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/CombDiactForSymbols.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{postfix:{"\u20DB":c.ACCENT,"\u20DC":c.ACCENT}}});MathJax.Ajax.loadComplete(a.optableDir+"/CombDiactForSymbols.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/Dingbats.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{prefix:{"\u2772":c.OPEN},postfix:{"\u2773":c.CLOSE}}});MathJax.Ajax.loadComplete(a.optableDir+"/Dingbats.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/GeneralPunctuation.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{prefix:{"\u2016":[0,0,b.ORD,{fence:true,stretchy:true}],"\u2018":[0,0,b.OPEN,{fence:true}],"\u201C":[0,0,b.OPEN,{fence:true}]},postfix:{"\u2016":[0,0,b.ORD,{fence:true,stretchy:true}],"\u2019":[0,0,b.CLOSE,{fence:true}],"\u201D":[0,0,b.CLOSE,{fence:true}]}}});MathJax.Ajax.loadComplete(a.optableDir+"/GeneralPunctuation.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/GeometricShapes.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{infix:{"\u25A0":c.BIN3,"\u25A1":c.BIN3,"\u25AA":c.BIN3,"\u25AB":c.BIN3,"\u25AD":c.BIN3,"\u25AE":c.BIN3,"\u25AF":c.BIN3,"\u25B0":c.BIN3,"\u25B1":c.BIN3,"\u25B2":c.BIN4,"\u25B4":c.BIN4,"\u25B6":c.BIN4,"\u25B7":c.BIN4,"\u25B8":c.BIN4,"\u25BC":c.BIN4,"\u25BE":c.BIN4,"\u25C0":c.BIN4,"\u25C1":c.BIN4,"\u25C2":c.BIN4,"\u25C4":c.BIN4,"\u25C5":c.BIN4,"\u25C6":c.BIN4,"\u25C7":c.BIN4,"\u25C8":c.BIN4,"\u25C9":c.BIN4,"\u25CC":c.BIN4,"\u25CD":c.BIN4,"\u25CE":c.BIN4,"\u25CF":c.BIN4,"\u25D6":c.BIN4,"\u25D7":c.BIN4,"\u25E6":c.BIN4}}});MathJax.Ajax.loadComplete(a.optableDir+"/GeometricShapes.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/GreekAndCoptic.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{infix:{"\u03F6":c.REL}}});MathJax.Ajax.loadComplete(a.optableDir+"/GreekAndCoptic.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/Latin1Supplement.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{postfix:{"\u00B0":c.ORD,"\u00B4":c.ACCENT,"\u00B8":c.ACCENT}}});MathJax.Ajax.loadComplete(a.optableDir+"/Latin1Supplement.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/LetterlikeSymbols.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{prefix:{"\u2145":c.ORD21,"\u2146":[2,0,b.ORD]}}});MathJax.Ajax.loadComplete(a.optableDir+"/LetterlikeSymbols.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/MathOperators.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{prefix:{"\u2204":c.ORD21,"\u221B":c.ORD11,"\u221C":c.ORD11,"\u2221":c.ORD,"\u2222":c.ORD,"\u222C":c.INTEGRAL,"\u222D":c.INTEGRAL,"\u222F":c.INTEGRAL,"\u2230":c.INTEGRAL,"\u2231":c.INTEGRAL,"\u2232":c.INTEGRAL,"\u2233":c.INTEGRAL},infix:{"\u2201":[1,2,b.ORD],"\u2206":c.BIN3,"\u220A":c.REL,"\u220C":c.REL,"\u220D":c.REL,"\u220E":c.BIN3,"\u2214":c.BIN4,"\u221F":c.REL,"\u2224":c.REL,"\u2226":c.REL,"\u2234":c.REL,"\u2235":c.REL,"\u2236":c.REL,"\u2237":c.REL,"\u2238":c.BIN4,"\u2239":c.REL,"\u223A":c.BIN4,"\u223B":c.REL,"\u223D":c.REL,"\u223D\u0331":c.BIN3,"\u223E":c.REL,"\u223F":c.BIN3,"\u2241":c.REL,"\u2242":c.REL,"\u2242\u0338":c.REL,"\u2244":c.REL,"\u2246":c.REL,"\u2247":c.REL,"\u2249":c.REL,"\u224A":c.REL,"\u224B":c.REL,"\u224C":c.REL,"\u224E":c.REL,"\u224E\u0338":c.REL,"\u224F":c.REL,"\u224F\u0338":c.REL,"\u2251":c.REL,"\u2252":c.REL,"\u2253":c.REL,"\u2254":c.REL,"\u2255":c.REL,"\u2256":c.REL,"\u2257":c.REL,"\u2258":c.REL,"\u2259":c.REL,"\u225A":c.REL,"\u225C":c.REL,"\u225D":c.REL,"\u225E":c.REL,"\u225F":c.REL,"\u2262":c.REL,"\u2263":c.REL,"\u2266":c.REL,"\u2266\u0338":c.REL,"\u2267":c.REL,"\u2268":c.REL,"\u2269":c.REL,"\u226A\u0338":c.REL,"\u226B\u0338":c.REL,"\u226C":c.REL,"\u226D":c.REL,"\u226E":c.REL,"\u226F":c.REL,"\u2270":c.REL,"\u2271":c.REL,"\u2272":c.REL,"\u2273":c.REL,"\u2274":c.REL,"\u2275":c.REL,"\u2276":c.REL,"\u2277":c.REL,"\u2278":c.REL,"\u2279":c.REL,"\u227C":c.REL,"\u227D":c.REL,"\u227E":c.REL,"\u227F":c.REL,"\u227F\u0338":c.REL,"\u2280":c.REL,"\u2281":c.REL,"\u2282\u20D2":c.REL,"\u2283\u20D2":c.REL,"\u2284":c.REL,"\u2285":c.REL,"\u2288":c.REL,"\u2289":c.REL,"\u228A":c.REL,"\u228B":c.REL,"\u228C":c.BIN4,"\u228D":c.BIN4,"\u228F":c.REL,"\u228F\u0338":c.REL,"\u2290":c.REL,"\u2290\u0338":c.REL,"\u229A":c.BIN4,"\u229B":c.BIN4,"\u229C":c.BIN4,"\u229D":c.BIN4,"\u229E":c.BIN4,"\u229F":c.BIN4,"\u22A0":c.BIN4,"\u22A1":c.BIN4,"\u22A6":c.REL,"\u22A7":c.REL,"\u22A9":c.REL,"\u22AA":c.REL,"\u22AB":c.REL,"\u22AC":c.REL,"\u22AD":c.REL,"\u22AE":c.REL,"\u22AF":c.REL,"\u22B0":c.REL,"\u22B1":c.REL,"\u22B2":c.REL,"\u22B3":c.REL,"\u22B4":c.REL,"\u22B5":c.REL,"\u22B6":c.REL,"\u22B7":c.REL,"\u22B8":c.REL,"\u22B9":c.REL,"\u22BA":c.BIN4,"\u22BB":c.BIN4,"\u22BC":c.BIN4,"\u22BD":c.BIN4,"\u22BE":c.BIN3,"\u22BF":c.BIN3,"\u22C7":c.BIN4,"\u22C9":c.BIN4,"\u22CA":c.BIN4,"\u22CB":c.BIN4,"\u22CC":c.BIN4,"\u22CD":c.REL,"\u22CE":c.BIN4,"\u22CF":c.BIN4,"\u22D0":c.REL,"\u22D1":c.REL,"\u22D2":c.BIN4,"\u22D3":c.BIN4,"\u22D4":c.REL,"\u22D5":c.REL,"\u22D6":c.REL,"\u22D7":c.REL,"\u22D8":c.REL,"\u22D9":c.REL,"\u22DA":c.REL,"\u22DB":c.REL,"\u22DC":c.REL,"\u22DD":c.REL,"\u22DE":c.REL,"\u22DF":c.REL,"\u22E0":c.REL,"\u22E1":c.REL,"\u22E2":c.REL,"\u22E3":c.REL,"\u22E4":c.REL,"\u22E5":c.REL,"\u22E6":c.REL,"\u22E7":c.REL,"\u22E8":c.REL,"\u22E9":c.REL,"\u22EA":c.REL,"\u22EB":c.REL,"\u22EC":c.REL,"\u22ED":c.REL,"\u22F0":c.REL,"\u22F2":c.REL,"\u22F3":c.REL,"\u22F4":c.REL,"\u22F5":c.REL,"\u22F6":c.REL,"\u22F7":c.REL,"\u22F8":c.REL,"\u22F9":c.REL,"\u22FA":c.REL,"\u22FB":c.REL,"\u22FC":c.REL,"\u22FD":c.REL,"\u22FE":c.REL,"\u22FF":c.REL}}});MathJax.Ajax.loadComplete(a.optableDir+"/MathOperators.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/MiscMathSymbolsA.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{prefix:{"\u27E6":c.OPEN,"\u27EA":c.OPEN,"\u27EC":c.OPEN},postfix:{"\u27E7":c.CLOSE,"\u27EB":c.CLOSE,"\u27ED":c.CLOSE}}});MathJax.Ajax.loadComplete(a.optableDir+"/MiscMathSymbolsA.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/MiscMathSymbolsB.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{prefix:{"\u2980":[0,0,b.ORD,{fence:true,stretchy:true}],"\u2983":c.OPEN,"\u2985":c.OPEN,"\u2987":c.OPEN,"\u2989":c.OPEN,"\u298B":c.OPEN,"\u298D":c.OPEN,"\u298F":c.OPEN,"\u2991":c.OPEN,"\u2993":c.OPEN,"\u2995":c.OPEN,"\u2997":c.OPEN,"\u29FC":c.OPEN},postfix:{"\u2980":[0,0,b.ORD,{fence:true,stretchy:true}],"\u2984":c.CLOSE,"\u2986":c.CLOSE,"\u2988":c.CLOSE,"\u298A":c.CLOSE,"\u298C":c.CLOSE,"\u298E":c.CLOSE,"\u2990":c.CLOSE,"\u2992":c.CLOSE,"\u2994":c.CLOSE,"\u2996":c.CLOSE,"\u2998":c.CLOSE,"\u29FD":c.CLOSE},infix:{"\u2981":c.BIN3,"\u2982":c.BIN3,"\u2999":c.BIN3,"\u299A":c.BIN3,"\u299B":c.BIN3,"\u299C":c.BIN3,"\u299D":c.BIN3,"\u299E":c.BIN3,"\u299F":c.BIN3,"\u29A0":c.BIN3,"\u29A1":c.BIN3,"\u29A2":c.BIN3,"\u29A3":c.BIN3,"\u29A4":c.BIN3,"\u29A5":c.BIN3,"\u29A6":c.BIN3,"\u29A7":c.BIN3,"\u29A8":c.BIN3,"\u29A9":c.BIN3,"\u29AA":c.BIN3,"\u29AB":c.BIN3,"\u29AC":c.BIN3,"\u29AD":c.BIN3,"\u29AE":c.BIN3,"\u29AF":c.BIN3,"\u29B0":c.BIN3,"\u29B1":c.BIN3,"\u29B2":c.BIN3,"\u29B3":c.BIN3,"\u29B4":c.BIN3,"\u29B5":c.BIN3,"\u29B6":c.BIN4,"\u29B7":c.BIN4,"\u29B8":c.BIN4,"\u29B9":c.BIN4,"\u29BA":c.BIN4,"\u29BB":c.BIN4,"\u29BC":c.BIN4,"\u29BD":c.BIN4,"\u29BE":c.BIN4,"\u29BF":c.BIN4,"\u29C0":c.REL,"\u29C1":c.REL,"\u29C2":c.BIN3,"\u29C3":c.BIN3,"\u29C4":c.BIN4,"\u29C5":c.BIN4,"\u29C6":c.BIN4,"\u29C7":c.BIN4,"\u29C8":c.BIN4,"\u29C9":c.BIN3,"\u29CA":c.BIN3,"\u29CB":c.BIN3,"\u29CC":c.BIN3,"\u29CD":c.BIN3,"\u29CE":c.REL,"\u29CF":c.REL,"\u29CF\u0338":c.REL,"\u29D0":c.REL,"\u29D0\u0338":c.REL,"\u29D1":c.REL,"\u29D2":c.REL,"\u29D3":c.REL,"\u29D4":c.REL,"\u29D5":c.REL,"\u29D6":c.BIN4,"\u29D7":c.BIN4,"\u29D8":c.BIN3,"\u29D9":c.BIN3,"\u29DB":c.BIN3,"\u29DC":c.BIN3,"\u29DD":c.BIN3,"\u29DE":c.REL,"\u29DF":c.BIN3,"\u29E0":c.BIN3,"\u29E1":c.REL,"\u29E2":c.BIN4,"\u29E3":c.REL,"\u29E4":c.REL,"\u29E5":c.REL,"\u29E6":c.REL,"\u29E7":c.BIN3,"\u29E8":c.BIN3,"\u29E9":c.BIN3,"\u29EA":c.BIN3,"\u29EB":c.BIN3,"\u29EC":c.BIN3,"\u29ED":c.BIN3,"\u29EE":c.BIN3,"\u29EF":c.BIN3,"\u29F0":c.BIN3,"\u29F1":c.BIN3,"\u29F2":c.BIN3,"\u29F3":c.BIN3,"\u29F4":c.REL,"\u29F5":c.BIN4,"\u29F6":c.BIN4,"\u29F7":c.BIN4,"\u29F8":c.BIN3,"\u29F9":c.BIN3,"\u29FA":c.BIN3,"\u29FB":c.BIN3,"\u29FE":c.BIN4,"\u29FF":c.BIN4}}});MathJax.Ajax.loadComplete(a.optableDir+"/MiscMathSymbolsB.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/MiscSymbolsAndArrows.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{infix:{"\u2B45":c.RELSTRETCH,"\u2B46":c.RELSTRETCH}}});MathJax.Ajax.loadComplete(a.optableDir+"/MiscSymbolsAndArrows.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/MiscTechnical.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{postfix:{"\u23B4":c.WIDEACCENT,"\u23B5":c.WIDEACCENT,"\u23DC":c.WIDEACCENT,"\u23DD":c.WIDEACCENT,"\u23E0":c.WIDEACCENT,"\u23E1":c.WIDEACCENT}}});MathJax.Ajax.loadComplete(a.optableDir+"/MiscTechnical.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/SpacingModLetters.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{postfix:{"\u02CD":c.WIDEACCENT,"\u02DA":c.ACCENT,"\u02DD":c.ACCENT,"\u02F7":c.WIDEACCENT}}});MathJax.Ajax.loadComplete(a.optableDir+"/SpacingModLetters.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/SuppMathOperators.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{prefix:{"\u2A03":c.OP,"\u2A05":c.OP,"\u2A07":c.OP,"\u2A08":c.OP,"\u2A09":c.OP,"\u2A0A":c.OP,"\u2A0B":c.INTEGRAL2,"\u2A0C":c.INTEGRAL,"\u2A0D":c.INTEGRAL2,"\u2A0E":c.INTEGRAL2,"\u2A0F":c.INTEGRAL2,"\u2A10":c.OP,"\u2A11":c.OP,"\u2A12":c.OP,"\u2A13":c.OP,"\u2A14":c.OP,"\u2A15":c.INTEGRAL2,"\u2A16":c.INTEGRAL2,"\u2A17":c.INTEGRAL2,"\u2A18":c.INTEGRAL2,"\u2A19":c.INTEGRAL2,"\u2A1A":c.INTEGRAL2,"\u2A1B":c.INTEGRAL2,"\u2A1C":c.INTEGRAL2,"\u2AFC":c.OP,"\u2AFF":c.OP},infix:{"\u2A1D":c.BIN3,"\u2A1E":c.BIN3,"\u2A1F":c.BIN3,"\u2A20":c.BIN3,"\u2A21":c.BIN3,"\u2A22":c.BIN4,"\u2A23":c.BIN4,"\u2A24":c.BIN4,"\u2A25":c.BIN4,"\u2A26":c.BIN4,"\u2A27":c.BIN4,"\u2A28":c.BIN4,"\u2A29":c.BIN4,"\u2A2A":c.BIN4,"\u2A2B":c.BIN4,"\u2A2C":c.BIN4,"\u2A2D":c.BIN4,"\u2A2E":c.BIN4,"\u2A30":c.BIN4,"\u2A31":c.BIN4,"\u2A32":c.BIN4,"\u2A33":c.BIN4,"\u2A34":c.BIN4,"\u2A35":c.BIN4,"\u2A36":c.BIN4,"\u2A37":c.BIN4,"\u2A38":c.BIN4,"\u2A39":c.BIN4,"\u2A3A":c.BIN4,"\u2A3B":c.BIN4,"\u2A3C":c.BIN4,"\u2A3D":c.BIN4,"\u2A3E":c.BIN4,"\u2A40":c.BIN4,"\u2A41":c.BIN4,"\u2A42":c.BIN4,"\u2A43":c.BIN4,"\u2A44":c.BIN4,"\u2A45":c.BIN4,"\u2A46":c.BIN4,"\u2A47":c.BIN4,"\u2A48":c.BIN4,"\u2A49":c.BIN4,"\u2A4A":c.BIN4,"\u2A4B":c.BIN4,"\u2A4C":c.BIN4,"\u2A4D":c.BIN4,"\u2A4E":c.BIN4,"\u2A4F":c.BIN4,"\u2A50":c.BIN4,"\u2A51":c.BIN4,"\u2A52":c.BIN4,"\u2A53":c.BIN4,"\u2A54":c.BIN4,"\u2A55":c.BIN4,"\u2A56":c.BIN4,"\u2A57":c.BIN4,"\u2A58":c.BIN4,"\u2A59":c.REL,"\u2A5A":c.BIN4,"\u2A5B":c.BIN4,"\u2A5C":c.BIN4,"\u2A5D":c.BIN4,"\u2A5E":c.BIN4,"\u2A5F":c.BIN4,"\u2A60":c.BIN4,"\u2A61":c.BIN4,"\u2A62":c.BIN4,"\u2A63":c.BIN4,"\u2A64":c.BIN4,"\u2A65":c.BIN4,"\u2A66":c.REL,"\u2A67":c.REL,"\u2A68":c.REL,"\u2A69":c.REL,"\u2A6A":c.REL,"\u2A6B":c.REL,"\u2A6C":c.REL,"\u2A6D":c.REL,"\u2A6E":c.REL,"\u2A6F":c.REL,"\u2A70":c.REL,"\u2A71":c.BIN4,"\u2A72":c.BIN4,"\u2A73":c.REL,"\u2A74":c.REL,"\u2A75":c.REL,"\u2A76":c.REL,"\u2A77":c.REL,"\u2A78":c.REL,"\u2A79":c.REL,"\u2A7A":c.REL,"\u2A7B":c.REL,"\u2A7C":c.REL,"\u2A7D":c.REL,"\u2A7D\u0338":c.REL,"\u2A7E":c.REL,"\u2A7E\u0338":c.REL,"\u2A7F":c.REL,"\u2A80":c.REL,"\u2A81":c.REL,"\u2A82":c.REL,"\u2A83":c.REL,"\u2A84":c.REL,"\u2A85":c.REL,"\u2A86":c.REL,"\u2A87":c.REL,"\u2A88":c.REL,"\u2A89":c.REL,"\u2A8A":c.REL,"\u2A8B":c.REL,"\u2A8C":c.REL,"\u2A8D":c.REL,"\u2A8E":c.REL,"\u2A8F":c.REL,"\u2A90":c.REL,"\u2A91":c.REL,"\u2A92":c.REL,"\u2A93":c.REL,"\u2A94":c.REL,"\u2A95":c.REL,"\u2A96":c.REL,"\u2A97":c.REL,"\u2A98":c.REL,"\u2A99":c.REL,"\u2A9A":c.REL,"\u2A9B":c.REL,"\u2A9C":c.REL,"\u2A9D":c.REL,"\u2A9E":c.REL,"\u2A9F":c.REL,"\u2AA0":c.REL,"\u2AA1":c.REL,"\u2AA1\u0338":c.REL,"\u2AA2":c.REL,"\u2AA2\u0338":c.REL,"\u2AA3":c.REL,"\u2AA4":c.REL,"\u2AA5":c.REL,"\u2AA6":c.REL,"\u2AA7":c.REL,"\u2AA8":c.REL,"\u2AA9":c.REL,"\u2AAA":c.REL,"\u2AAB":c.REL,"\u2AAC":c.REL,"\u2AAD":c.REL,"\u2AAE":c.REL,"\u2AAF\u0338":c.REL,"\u2AB0\u0338":c.REL,"\u2AB1":c.REL,"\u2AB2":c.REL,"\u2AB3":c.REL,"\u2AB4":c.REL,"\u2AB5":c.REL,"\u2AB6":c.REL,"\u2AB7":c.REL,"\u2AB8":c.REL,"\u2AB9":c.REL,"\u2ABA":c.REL,"\u2ABB":c.REL,"\u2ABC":c.REL,"\u2ABD":c.REL,"\u2ABE":c.REL,"\u2ABF":c.REL,"\u2AC0":c.REL,"\u2AC1":c.REL,"\u2AC2":c.REL,"\u2AC3":c.REL,"\u2AC4":c.REL,"\u2AC5":c.REL,"\u2AC6":c.REL,"\u2AC7":c.REL,"\u2AC8":c.REL,"\u2AC9":c.REL,"\u2ACA":c.REL,"\u2ACB":c.REL,"\u2ACC":c.REL,"\u2ACD":c.REL,"\u2ACE":c.REL,"\u2ACF":c.REL,"\u2AD0":c.REL,"\u2AD1":c.REL,"\u2AD2":c.REL,"\u2AD3":c.REL,"\u2AD4":c.REL,"\u2AD5":c.REL,"\u2AD6":c.REL,"\u2AD7":c.REL,"\u2AD8":c.REL,"\u2AD9":c.REL,"\u2ADA":c.REL,"\u2ADB":c.REL,"\u2ADC":c.REL,"\u2ADD":c.REL,"\u2ADE":c.REL,"\u2ADF":c.REL,"\u2AE0":c.REL,"\u2AE1":c.REL,"\u2AE2":c.REL,"\u2AE3":c.REL,"\u2AE4":c.REL,"\u2AE5":c.REL,"\u2AE6":c.REL,"\u2AE7":c.REL,"\u2AE8":c.REL,"\u2AE9":c.REL,"\u2AEA":c.REL,"\u2AEB":c.REL,"\u2AEC":c.REL,"\u2AED":c.REL,"\u2AEE":c.REL,"\u2AEF":c.REL,"\u2AF0":c.REL,"\u2AF1":c.REL,"\u2AF2":c.REL,"\u2AF3":c.REL,"\u2AF4":c.BIN4,"\u2AF5":c.BIN4,"\u2AF6":c.BIN4,"\u2AF7":c.REL,"\u2AF8":c.REL,"\u2AF9":c.REL,"\u2AFA":c.REL,"\u2AFB":c.BIN4,"\u2AFD":c.BIN4,"\u2AFE":c.BIN3}}});MathJax.Ajax.loadComplete(a.optableDir+"/SuppMathOperators.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/SupplementalArrowsA.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{infix:{"\u27F0":c.RELSTRETCH,"\u27F1":c.RELSTRETCH,"\u27FB":c.WIDEREL,"\u27FD":c.WIDEREL,"\u27FE":c.WIDEREL,"\u27FF":c.WIDEREL}}});MathJax.Ajax.loadComplete(a.optableDir+"/SupplementalArrowsA.js")})(MathJax.ElementJax.mml);
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*
|
|
||||||
* /MathJax-v2/jax/element/mml/optable/SupplementalArrowsB.js
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009-2018 The MathJax Consortium
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function(a){var c=a.mo.OPTYPES;var b=a.TEXCLASS;MathJax.Hub.Insert(a.mo.prototype,{OPTABLE:{infix:{"\u2900":c.RELACCENT,"\u2901":c.RELACCENT,"\u2902":c.RELACCENT,"\u2903":c.RELACCENT,"\u2904":c.RELACCENT,"\u2905":c.RELACCENT,"\u2906":c.RELACCENT,"\u2907":c.RELACCENT,"\u2908":c.REL,"\u2909":c.REL,"\u290A":c.RELSTRETCH,"\u290B":c.RELSTRETCH,"\u290C":c.WIDEREL,"\u290D":c.WIDEREL,"\u290E":c.WIDEREL,"\u290F":c.WIDEREL,"\u2910":c.WIDEREL,"\u2911":c.RELACCENT,"\u2912":c.RELSTRETCH,"\u2913":c.RELSTRETCH,"\u2914":c.RELACCENT,"\u2915":c.RELACCENT,"\u2916":c.RELACCENT,"\u2917":c.RELACCENT,"\u2918":c.RELACCENT,"\u2919":c.RELACCENT,"\u291A":c.RELACCENT,"\u291B":c.RELACCENT,"\u291C":c.RELACCENT,"\u291D":c.RELACCENT,"\u291E":c.RELACCENT,"\u291F":c.RELACCENT,"\u2920":c.RELACCENT,"\u2921":c.RELSTRETCH,"\u2922":c.RELSTRETCH,"\u2923":c.REL,"\u2924":c.REL,"\u2925":c.REL,"\u2926":c.REL,"\u2927":c.REL,"\u2928":c.REL,"\u2929":c.REL,"\u292A":c.REL,"\u292B":c.REL,"\u292C":c.REL,"\u292D":c.REL,"\u292E":c.REL,"\u292F":c.REL,"\u2930":c.REL,"\u2931":c.REL,"\u2932":c.REL,"\u2933":c.RELACCENT,"\u2934":c.REL,"\u2935":c.REL,"\u2936":c.REL,"\u2937":c.REL,"\u2938":c.REL,"\u2939":c.REL,"\u293A":c.RELACCENT,"\u293B":c.RELACCENT,"\u293C":c.RELACCENT,"\u293D":c.RELACCENT,"\u293E":c.REL,"\u293F":c.REL,"\u2940":c.REL,"\u2941":c.REL,"\u2942":c.RELACCENT,"\u2943":c.RELACCENT,"\u2944":c.RELACCENT,"\u2945":c.RELACCENT,"\u2946":c.RELACCENT,"\u2947":c.RELACCENT,"\u2948":c.RELACCENT,"\u2949":c.REL,"\u294A":c.RELACCENT,"\u294B":c.RELACCENT,"\u294C":c.REL,"\u294D":c.REL,"\u294E":c.WIDEREL,"\u294F":c.RELSTRETCH,"\u2950":c.WIDEREL,"\u2951":c.RELSTRETCH,"\u2952":c.WIDEREL,"\u2953":c.WIDEREL,"\u2954":c.RELSTRETCH,"\u2955":c.RELSTRETCH,"\u2956":c.RELSTRETCH,"\u2957":c.RELSTRETCH,"\u2958":c.RELSTRETCH,"\u2959":c.RELSTRETCH,"\u295A":c.WIDEREL,"\u295B":c.WIDEREL,"\u295C":c.RELSTRETCH,"\u295D":c.RELSTRETCH,"\u295E":c.WIDEREL,"\u295F":c.WIDEREL,"\u2960":c.RELSTRETCH,"\u2961":c.RELSTRETCH,"\u2962":c.RELACCENT,"\u2963":c.REL,"\u2964":c.RELACCENT,"\u2965":c.REL,"\u2966":c.RELACCENT,"\u2967":c.RELACCENT,"\u2968":c.RELACCENT,"\u2969":c.RELACCENT,"\u296A":c.RELACCENT,"\u296B":c.RELACCENT,"\u296C":c.RELACCENT,"\u296D":c.RELACCENT,"\u296E":c.RELSTRETCH,"\u296F":c.RELSTRETCH,"\u2970":c.RELACCENT,"\u2971":c.RELACCENT,"\u2972":c.RELACCENT,"\u2973":c.RELACCENT,"\u2974":c.RELACCENT,"\u2975":c.RELACCENT,"\u2976":c.RELACCENT,"\u2977":c.RELACCENT,"\u2978":c.RELACCENT,"\u2979":c.RELACCENT,"\u297A":c.RELACCENT,"\u297B":c.RELACCENT,"\u297C":c.RELACCENT,"\u297D":c.RELACCENT,"\u297E":c.REL,"\u297F":c.REL}}});MathJax.Ajax.loadComplete(a.optableDir+"/SupplementalArrowsB.js")})(MathJax.ElementJax.mml);
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,7 +3,6 @@ Thomas Kolb DL5TKL
|
||||||
0.1, 2024-04-25
|
0.1, 2024-04-25
|
||||||
:toc:
|
:toc:
|
||||||
:stem:
|
:stem:
|
||||||
:webfonts!:
|
|
||||||
|
|
||||||
// SPDX-License-Identifier: CC-BY-SA-4.0
|
// SPDX-License-Identifier: CC-BY-SA-4.0
|
||||||
// List of contributors is at the end of the document.
|
// List of contributors is at the end of the document.
|
||||||
|
@ -268,109 +267,108 @@ To be defined:
|
||||||
|
|
||||||
==== Connection Establishment
|
==== Connection Establishment
|
||||||
|
|
||||||
[msc,format=svg,svg-type=interactive, scale=1.4]
|
[mermaid,format=svg,svg-type=interactive]
|
||||||
.Connection establishment
|
.Connection establishment
|
||||||
....
|
....
|
||||||
msc {
|
sequenceDiagram
|
||||||
digi [label="Digipeater"],
|
participant digi as Digipeater
|
||||||
client [label="Client"];
|
participant client as Client
|
||||||
|
|
||||||
digi -> client [label="Beacon (Broadcast)"];
|
digi -->> client: Beacon (Broadcast)
|
||||||
digi -> client [label="Beacon (Broadcast)"];
|
digi -->> client: Beacon (Broadcast)
|
||||||
|
digi -->> client: Beacon (Broadcast)
|
||||||
|
|
||||||
client box client [label="Decides to connect"];
|
Note over client: Decides to connect
|
||||||
...;
|
|
||||||
|
|
||||||
digi -> client [label="Beacon (Broadcast)"];
|
client ->> digi: Connection Request
|
||||||
digi <- client [label="Connection Request"];
|
|
||||||
|
|
||||||
--- [label="Alternative 1: Connection is accepted"];
|
alt Connection accepted
|
||||||
digi -> client [label="Connection Parameters"];
|
digi ->> client: Connection Parameters
|
||||||
digi <- client [label="Connection Acknowledgement"];
|
client ->> digi: Connection Acknowledgement
|
||||||
digi box client [label="Connection established"];
|
Note over digi,client: Connection established
|
||||||
|
else Connection rejected
|
||||||
--- [label="Alternative 2: Connection is rejected"];
|
digi ->> client: Connection Refusal
|
||||||
digi -> client [label="Connection Refusal"];
|
end
|
||||||
}
|
|
||||||
....
|
....
|
||||||
|
|
||||||
==== Communication during a Connection
|
==== Communication during a Connection
|
||||||
|
|
||||||
[msc,format=svg,svg-type=interactive, scale=1.4]
|
[mermaid,format=svg,svg-type=interactive]
|
||||||
.In-connection communication
|
.In-connection communication
|
||||||
....
|
....
|
||||||
msc {
|
sequenceDiagram
|
||||||
digi [label="Digipeater"],
|
participant digi as Digipeater
|
||||||
client [label="Client"];
|
participant client as Client
|
||||||
|
|
||||||
--- [label="Connection established"];
|
Note over digi,client: Connection established
|
||||||
digi => client [label="Up to 14 packets without Transmission Request"];
|
|
||||||
digi -> client [label="Packet with Transmission Request"];
|
|
||||||
|
|
||||||
digi box digi [label="Start timeout timer"];
|
loop For up to 14 packets
|
||||||
|
digi ->> client: Packet without Transmission Request
|
||||||
|
end
|
||||||
|
|
||||||
--- [label="Alternative 1: Normal reply"];
|
digi ->> client: Packet with Transmission Request
|
||||||
|
|
||||||
digi <= client [label="Up to 14 packets without Transmission Request"];
|
Note over digi: Start timeout timer
|
||||||
digi <- client [label="Packet with Transmission Request"];
|
|
||||||
|
|
||||||
--- [label="Alternative 2: Partial reply"];
|
alt Normal reply
|
||||||
|
loop For up to 14 packets
|
||||||
|
client ->> digi: Packet without Transmission Request
|
||||||
|
end
|
||||||
|
|
||||||
digi <= client [label="Up to 14 packets without Transmission Request"];
|
client ->> digi: Packet with Transmission Request
|
||||||
digi x- client [label="Packet with Transmission Request"];
|
else Partial reply
|
||||||
...;
|
loop For up to 14 packets
|
||||||
digi rbox digi [label="Timeout expired"];
|
client ->> digi: Packet without Transmission Request
|
||||||
|
end
|
||||||
|
|
||||||
--- [label="Alternative 3: No reply"];
|
client --x digi: Packet with Transmission Request (lost)
|
||||||
|
|
||||||
digi x- client [label="Packets from client"];
|
Note over digi: Timeout expired
|
||||||
...;
|
else No reply
|
||||||
digi rbox digi [label="Timeout expired"];
|
Note over digi: Timeout expired
|
||||||
|
end
|
||||||
|
|
||||||
--- [label="Finally"];
|
Note over digi: Query next client
|
||||||
|
|
||||||
digi box digi [label="Query next client"];
|
|
||||||
}
|
|
||||||
....
|
....
|
||||||
|
|
||||||
==== Connection Shutdown
|
==== Connection Shutdown
|
||||||
|
|
||||||
===== Client-initiated
|
===== Client-initiated
|
||||||
|
|
||||||
[msc,format=svg,svg-type=interactive, scale=1.4]
|
[mermaid,format=svg,svg-type=interactive]
|
||||||
.Client-initiated shutdown
|
.Client-initiated shutdown
|
||||||
....
|
....
|
||||||
msc {
|
sequenceDiagram
|
||||||
digi [label="Digipeater"],
|
participant digi as Digipeater
|
||||||
client [label="Client"];
|
participant client as Client
|
||||||
|
|
||||||
--- [label="Connection established"];
|
Note over digi,client: Connection established
|
||||||
client box client [label="Decides to disconnect"];
|
|
||||||
...;
|
|
||||||
digi -> client [label="Transmission request"];
|
|
||||||
digi <- client [label="Disconnect"];
|
|
||||||
|
|
||||||
--- [label="Connection closed"];
|
Note over client: Decides to disconnect
|
||||||
}
|
|
||||||
|
digi ->> client: Transmission Request
|
||||||
|
client ->> digi: Disconnect
|
||||||
|
|
||||||
|
Note over digi,client: Connection closed
|
||||||
....
|
....
|
||||||
|
|
||||||
===== Digipeater-initiated
|
===== Digipeater-initiated
|
||||||
|
|
||||||
[msc,format=svg,svg-type=interactive, scale=1.4]
|
[mermaid,format=svg,svg-type=interactive]
|
||||||
.Digipeater-initiated shutdown
|
.Digipeater-initiated shutdown
|
||||||
....
|
....
|
||||||
msc {
|
sequenceDiagram
|
||||||
digi [label="Digipeater"],
|
participant digi as Digipeater
|
||||||
client [label="Client"];
|
participant client as Client
|
||||||
|
|
||||||
--- [label="Connection established"];
|
Note over digi,client: Connection established
|
||||||
digi box digi [label="Decides to disconnect Client"];
|
|
||||||
|
|
||||||
digi -> client [label="Disconnect request"];
|
Note over digi: Decides to disconnect client
|
||||||
digi <- client [label="Disconnect"];
|
|
||||||
|
|
||||||
--- [label="Connection closed"];
|
digi ->> client: Disconnect Request
|
||||||
}
|
client ->> digi: Disconnect
|
||||||
|
|
||||||
|
Note over digi,client: Connection closed
|
||||||
....
|
....
|
||||||
|
|
||||||
== Higher Layer Protocols
|
== Higher Layer Protocols
|
||||||
|
|
|
@ -53,8 +53,6 @@ set(sources
|
||||||
src/layer2/layer2_rx.h
|
src/layer2/layer2_rx.h
|
||||||
src/layer2/ham64.c
|
src/layer2/ham64.c
|
||||||
src/layer2/ham64.h
|
src/layer2/ham64.h
|
||||||
src/layer2/connection.c
|
|
||||||
src/layer2/connection.h
|
|
||||||
src/sdr/sdr.c
|
src/sdr/sdr.c
|
||||||
src/sdr/sdr.h
|
src/sdr/sdr.h
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
# Hamnet70 Implementation
|
|
||||||
|
|
||||||
This directory contains an implementation of the Hamnet70 protocol.
|
|
||||||
|
|
||||||
Before you can compile and use this code, some additional steps are necessary:
|
|
||||||
|
|
||||||
1. Copy `src/config.h.template` to `src/config.h` and set the following variables:
|
|
||||||
- `MY_CALL`: the station call sign (i.e. your amateur radio call sign).
|
|
||||||
This will be encoded into the address fields of outgoing packets.
|
|
||||||
2. Install dependencies:
|
|
||||||
- _libliquid_ compiled with _libfec_ support
|
|
||||||
- _libfec_
|
|
||||||
- _fftw3_
|
|
||||||
- _libhackrf_
|
|
||||||
|
|
||||||
After everything is prepared, compile the code using `./make.sh`.
|
|
||||||
Parameters to this script are forwarded to `make` so you can speed things up a little with `./make.sh -j4` (on a CPU with 4 threads).
|
|
||||||
|
|
||||||
When compiled, you have two options for running Hamnet70:
|
|
||||||
|
|
||||||
1. In digipeater (base station) mode: `build/hamnet70 -c`. This will broadcast beacons and wait for clients to connect.
|
|
||||||
2. In client mode: `build/hamnet70`. This will wait for a beacon to arrive and connect to it.
|
|
|
@ -9,10 +9,6 @@
|
||||||
|
|
||||||
#include <liquid/liquid.h>
|
#include <liquid/liquid.h>
|
||||||
|
|
||||||
/*** LAYER 2 CONFIG ***/
|
|
||||||
|
|
||||||
#define MY_CALL undefined // define MY_CALL to your call sign as a C string, e.g. "DL5TKL"
|
|
||||||
|
|
||||||
/*** TIMING CONFIG ***/
|
/*** TIMING CONFIG ***/
|
||||||
|
|
||||||
#define TX_SWITCH_BACKOFF_PREAMBLE_MS 42 // only relevant if packet cannot be decoded (maximum packet duration)
|
#define TX_SWITCH_BACKOFF_PREAMBLE_MS 42 // only relevant if packet cannot be decoded (maximum packet duration)
|
|
@ -1,375 +0,0 @@
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "connection.h"
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "layer2/ham64.h"
|
|
||||||
#include "results.h"
|
|
||||||
|
|
||||||
#define SEQ_NR_MASK 0xF
|
|
||||||
|
|
||||||
result_t connection_init(connection_ctx_t *ctx, const ham64_t *my_addr, const ham64_t *peer_addr)
|
|
||||||
{
|
|
||||||
ctx->last_acked_seq = 0;
|
|
||||||
ctx->next_expected_seq = 0;
|
|
||||||
|
|
||||||
packet_queue_init(&ctx->packet_queue);
|
|
||||||
ctx->next_packet_index = 0;
|
|
||||||
ctx->next_seq_nr = 0;
|
|
||||||
|
|
||||||
ctx->my_addr = *my_addr;
|
|
||||||
ctx->peer_addr = *peer_addr;
|
|
||||||
|
|
||||||
ctx->conn_state = CONN_STATE_INITIALIZED;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void connection_destroy(connection_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
if(ctx->conn_state == CONN_STATE_UNINITIALIZED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->conn_state = CONN_STATE_UNINITIALIZED;
|
|
||||||
packet_queue_destroy(&ctx->packet_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
result_t connection_handle_packet(connection_ctx_t *ctx, const uint8_t *buf, size_t buf_len)
|
|
||||||
{
|
|
||||||
// check the connection state
|
|
||||||
switch(ctx->conn_state) {
|
|
||||||
case CONN_STATE_UNINITIALIZED:
|
|
||||||
case CONN_STATE_INITIALIZED:
|
|
||||||
case CONN_STATE_CLOSED:
|
|
||||||
LOG(LVL_ERR, "Trying to pass packet to connection in state %u", ctx->conn_state);
|
|
||||||
return ERR_INVALID_STATE;
|
|
||||||
|
|
||||||
case CONN_STATE_CONNECTING:
|
|
||||||
case CONN_STATE_ESTABLISHED:
|
|
||||||
// in these states, packets can be handled
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the CRC
|
|
||||||
size_t packet_size = buf_len - crc_sizeof_key(PAYLOAD_CRC_SCHEME);
|
|
||||||
|
|
||||||
if(!crc_check_key(PAYLOAD_CRC_SCHEME, (unsigned char*)buf, packet_size)) {
|
|
||||||
LOG(LVL_ERR, "payload CRC check failed!");
|
|
||||||
return ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode the header
|
|
||||||
layer2_packet_header_t header;
|
|
||||||
|
|
||||||
if(!layer2_decode_packet_header(buf, buf_len, &header)) {
|
|
||||||
LOG(LVL_ERR, "Header could not be decoded!");
|
|
||||||
return ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the packet really should be handled by us
|
|
||||||
if(!ham64_is_equal(&header.src_addr, &ctx->peer_addr)) {
|
|
||||||
char fmt_src_addr[HAM64_FMT_MAX_LEN];
|
|
||||||
char fmt_peer_addr[HAM64_FMT_MAX_LEN];
|
|
||||||
|
|
||||||
ham64_format(&header.src_addr, fmt_src_addr);
|
|
||||||
ham64_format(&ctx->peer_addr, fmt_peer_addr);
|
|
||||||
|
|
||||||
LOG(LVL_ERR, "Packet has the wrong source address: got %s, expected %s",
|
|
||||||
fmt_src_addr, fmt_peer_addr);
|
|
||||||
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!ham64_is_equal(&header.dst_addr, &ctx->my_addr)) {
|
|
||||||
char fmt_dst_addr[HAM64_FMT_MAX_LEN];
|
|
||||||
char fmt_my_addr[HAM64_FMT_MAX_LEN];
|
|
||||||
|
|
||||||
ham64_format(&header.dst_addr, fmt_dst_addr);
|
|
||||||
ham64_format(&ctx->my_addr, fmt_my_addr);
|
|
||||||
|
|
||||||
LOG(LVL_ERR, "Packet has the wrong destination address: got %s, expected %s",
|
|
||||||
fmt_dst_addr, fmt_my_addr);
|
|
||||||
|
|
||||||
return ERR_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(LVL_DEBUG, "Handling %s packet with rx_seq_nr %u, tx_seq_nr %u.",
|
|
||||||
layer2_msg_type_to_string(header.msg_type), header.rx_seq_nr, header.tx_seq_nr);
|
|
||||||
|
|
||||||
ctx->last_acked_seq = header.rx_seq_nr;
|
|
||||||
|
|
||||||
|
|
||||||
switch(header.msg_type) {
|
|
||||||
case L2_MSG_TYPE_EMPTY:
|
|
||||||
LOG(LVL_DEBUG, "Empty packet: accepted ACK for %u.", ctx->last_acked_seq);
|
|
||||||
return OK; // do not ACK and call back
|
|
||||||
|
|
||||||
case L2_MSG_TYPE_CONN_MGMT:
|
|
||||||
case L2_MSG_TYPE_CONNECTIONLESS:
|
|
||||||
LOG(LVL_WARN, "Message type %s is not implemented yet.", layer2_msg_type_to_string(header.msg_type));
|
|
||||||
return OK;
|
|
||||||
|
|
||||||
case L2_MSG_TYPE_DATA:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
LOG(LVL_ERR, "Invalid message type %d.", header.msg_type);
|
|
||||||
return ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ctx->next_expected_seq != header.tx_seq_nr) {
|
|
||||||
LOG(LVL_ERR, "Expected sequence number %u, received %u.", ctx->next_expected_seq, header.tx_seq_nr);
|
|
||||||
return ERR_SEQUENCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->next_expected_seq++;
|
|
||||||
ctx->next_expected_seq &= 0xF;
|
|
||||||
|
|
||||||
LOG(LVL_INFO, "Received ACK for seq_nr %u in packet seq_nr %u.", header.rx_seq_nr, header.tx_seq_nr);
|
|
||||||
|
|
||||||
// handle the acknowledgement internally
|
|
||||||
connection_handle_ack(ctx, header.rx_seq_nr);
|
|
||||||
|
|
||||||
size_t header_size = layer2_get_encoded_header_size(&header);
|
|
||||||
|
|
||||||
// extract the payload and forward it to the tun device
|
|
||||||
const uint8_t *payload = buf + header_size;
|
|
||||||
size_t payload_len = packet_size - header_size;
|
|
||||||
|
|
||||||
ctx->data_cb(ctx, payload, payload_len);
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t connection_get_next_expected_seq(const connection_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
return ctx->next_expected_seq;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t connection_get_last_acked_seq(const connection_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
return ctx->last_acked_seq;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
result_t connection_enqueue_packet(connection_ctx_t *ctx, uint8_t *buf, size_t buf_len)
|
|
||||||
{
|
|
||||||
// check the connection state
|
|
||||||
switch(ctx->conn_state) {
|
|
||||||
case CONN_STATE_UNINITIALIZED:
|
|
||||||
case CONN_STATE_INITIALIZED:
|
|
||||||
case CONN_STATE_CLOSED:
|
|
||||||
case CONN_STATE_CONNECTING:
|
|
||||||
LOG(LVL_ERR, "Trying to enqueue packet in inactive state %u", ctx->conn_state);
|
|
||||||
return ERR_INVALID_STATE;
|
|
||||||
|
|
||||||
case CONN_STATE_ESTABLISHED:
|
|
||||||
// in these states, packets can be handled
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
layer2_packet_header_t header;
|
|
||||||
|
|
||||||
if(packet_queue_get_free_space(&ctx->packet_queue) == 0) {
|
|
||||||
return ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
header.dst_addr = ctx->peer_addr;
|
|
||||||
header.src_addr = ctx->my_addr;
|
|
||||||
header.msg_type = L2_MSG_TYPE_DATA;
|
|
||||||
header.rx_seq_nr = 0; // will be filled in layer2_tx_encode_next_packet()
|
|
||||||
header.tx_request = 0;
|
|
||||||
header.tx_seq_nr = ctx->next_seq_nr;
|
|
||||||
|
|
||||||
// create a persistent copy of the packet data.
|
|
||||||
// TODO: possibly this copy operation can be removed by passing a malloc'd buffer in.
|
|
||||||
uint8_t *packetbuf = malloc(buf_len);
|
|
||||||
if(!packetbuf) {
|
|
||||||
LOG(LVL_ERR, "malloc failed.");
|
|
||||||
return ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(packetbuf, buf, buf_len);
|
|
||||||
|
|
||||||
packet_queue_add(&ctx->packet_queue, &header, packetbuf, buf_len);
|
|
||||||
|
|
||||||
LOG(LVL_INFO, "Added packet tx_seq %u to queue -> %zu entries",
|
|
||||||
header.tx_seq_nr, packet_queue_get_used_space(&ctx->packet_queue));
|
|
||||||
|
|
||||||
ctx->next_seq_nr++;
|
|
||||||
ctx->next_seq_nr &= SEQ_NR_MASK;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
result_t connection_add_empty_packet(connection_ctx_t *ctx, bool tx_request)
|
|
||||||
{
|
|
||||||
// check the connection state
|
|
||||||
switch(ctx->conn_state) {
|
|
||||||
case CONN_STATE_UNINITIALIZED:
|
|
||||||
case CONN_STATE_INITIALIZED:
|
|
||||||
case CONN_STATE_CLOSED:
|
|
||||||
case CONN_STATE_CONNECTING:
|
|
||||||
LOG(LVL_ERR, "Trying to add empty packet in inactive state %u", ctx->conn_state);
|
|
||||||
return ERR_INVALID_STATE;
|
|
||||||
|
|
||||||
case CONN_STATE_ESTABLISHED:
|
|
||||||
// in these states, packets can be handled
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
layer2_packet_header_t header;
|
|
||||||
|
|
||||||
header.dst_addr.addr[0] = 0xFFFF;
|
|
||||||
header.dst_addr.length = 1;
|
|
||||||
header.src_addr.addr[0] = 0x0001;
|
|
||||||
header.src_addr.length = 1;
|
|
||||||
header.msg_type = L2_MSG_TYPE_EMPTY;
|
|
||||||
header.rx_seq_nr = 0; // will be filled in layer2_tx_encode_next_packet()
|
|
||||||
header.tx_seq_nr = 0; // not used in empty packets
|
|
||||||
header.tx_request = tx_request;
|
|
||||||
|
|
||||||
if (!packet_queue_add(&ctx->packet_queue, &header, NULL, 0)) {
|
|
||||||
return ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t connection_encode_next_packet(connection_ctx_t *ctx, uint8_t ack_seq_nr, uint8_t *buf, size_t buf_len)
|
|
||||||
{
|
|
||||||
// check the connection state
|
|
||||||
switch(ctx->conn_state) {
|
|
||||||
case CONN_STATE_UNINITIALIZED:
|
|
||||||
case CONN_STATE_INITIALIZED:
|
|
||||||
case CONN_STATE_CLOSED:
|
|
||||||
LOG(LVL_ERR, "Trying to encode packet in inactive state %u", ctx->conn_state);
|
|
||||||
return ERR_INVALID_STATE;
|
|
||||||
|
|
||||||
case CONN_STATE_CONNECTING:
|
|
||||||
case CONN_STATE_ESTABLISHED:
|
|
||||||
// in these states, packets may be present for transmission
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const packet_queue_entry_t *entry = packet_queue_get(&ctx->packet_queue, ctx->next_packet_index);
|
|
||||||
|
|
||||||
if(!entry) {
|
|
||||||
// no more entries
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int crc_size = crc_sizeof_key(PAYLOAD_CRC_SCHEME);
|
|
||||||
|
|
||||||
assert(buf_len >= LAYER2_PACKET_HEADER_ENCODED_SIZE_MAX + crc_size + entry->data_len);
|
|
||||||
|
|
||||||
layer2_packet_header_t header = entry->header;
|
|
||||||
header.rx_seq_nr = ack_seq_nr;
|
|
||||||
|
|
||||||
// encode the header
|
|
||||||
LOG(LVL_DEBUG, "Encoding packet with rx_seq_nr %u, tx_seq_nr %u.", header.rx_seq_nr, header.tx_seq_nr);
|
|
||||||
|
|
||||||
size_t packet_size = layer2_encode_packet_header(&header, buf);
|
|
||||||
|
|
||||||
// add the payload data
|
|
||||||
if(entry->data) {
|
|
||||||
memcpy(buf + packet_size, entry->data, entry->data_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_size += entry->data_len;
|
|
||||||
|
|
||||||
// calculate CRC of everything and append it to the packet
|
|
||||||
crc_append_key(PAYLOAD_CRC_SCHEME, buf, packet_size);
|
|
||||||
|
|
||||||
packet_size += crc_size;
|
|
||||||
|
|
||||||
ctx->next_packet_index++;
|
|
||||||
|
|
||||||
return packet_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void connection_restart_tx(connection_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
ctx->next_packet_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void connection_tx_clean_empty_packet(connection_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
assert(ctx->conn_state != CONN_STATE_UNINITIALIZED);
|
|
||||||
|
|
||||||
const packet_queue_entry_t *entry = packet_queue_get(&ctx->packet_queue, 0);
|
|
||||||
if(entry && entry->header.msg_type == L2_MSG_TYPE_EMPTY) {
|
|
||||||
packet_queue_delete(&ctx->packet_queue, 1);
|
|
||||||
|
|
||||||
if(ctx->next_packet_index > 0) {
|
|
||||||
ctx->next_packet_index--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void connection_handle_ack(connection_ctx_t *ctx, uint8_t acked_seq)
|
|
||||||
{
|
|
||||||
// check the connection state
|
|
||||||
switch(ctx->conn_state) {
|
|
||||||
case CONN_STATE_UNINITIALIZED:
|
|
||||||
case CONN_STATE_INITIALIZED:
|
|
||||||
case CONN_STATE_CLOSED:
|
|
||||||
case CONN_STATE_CONNECTING:
|
|
||||||
LOG(LVL_ERR, "Trying to call connection_handle_ack() in inactive state %u", ctx->conn_state);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case CONN_STATE_ESTABLISHED:
|
|
||||||
// in these states, packets may be present for transmission
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->next_packet_index = 0;
|
|
||||||
|
|
||||||
size_t packets_to_remove = 0;
|
|
||||||
size_t packets_available = packet_queue_get_used_space(&ctx->packet_queue);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < packets_available; i++) {
|
|
||||||
const packet_queue_entry_t *entry = packet_queue_get(&ctx->packet_queue, i);
|
|
||||||
|
|
||||||
if(entry->header.tx_seq_nr == acked_seq) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
packets_to_remove++;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_queue_delete(&ctx->packet_queue, packets_to_remove);
|
|
||||||
|
|
||||||
packets_available = packet_queue_get_used_space(&ctx->packet_queue);
|
|
||||||
|
|
||||||
LOG(LVL_DEBUG, "handling ack for seq_nr %u, removing %zu packets, %zu packets remaining.", acked_seq, packets_to_remove, packets_available);
|
|
||||||
|
|
||||||
if(packets_available == 0) {
|
|
||||||
// no packets left in queue, but an acknowledgement must be
|
|
||||||
// transmitted. Add an empty packet to do that.
|
|
||||||
result_t res = connection_add_empty_packet(ctx, false);
|
|
||||||
if (res != OK) {
|
|
||||||
LOG(LVL_WARN, "Failed to add empty packet: %d.", res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool connection_can_transmit(const connection_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
assert(ctx->conn_state != CONN_STATE_UNINITIALIZED);
|
|
||||||
|
|
||||||
return (packet_queue_get_used_space(&ctx->packet_queue) != 0)
|
|
||||||
&& (packet_queue_get(&ctx->packet_queue, ctx->next_packet_index) != NULL);
|
|
||||||
}
|
|
|
@ -1,126 +0,0 @@
|
||||||
/*
|
|
||||||
* This file contains functions to handle a single layer 2 connection.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*
|
|
||||||
* Copyright (C) 2024 Thomas Kolb
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CONNECTION_H
|
|
||||||
#define CONNECTION_H
|
|
||||||
|
|
||||||
#include <results.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "packet_queue.h"
|
|
||||||
|
|
||||||
struct connection_ctx_s;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CONN_STATE_UNINITIALIZED, //!< Uninitialized. Cannot be used in any way
|
|
||||||
CONN_STATE_INITIALIZED, //!< Initialized, no packets processed yet
|
|
||||||
CONN_STATE_CONNECTING, //!< Connection request sent, no two-way communication yet
|
|
||||||
CONN_STATE_ESTABLISHED, //!< Connection is established
|
|
||||||
CONN_STATE_CLOSED //!< Connection has been closed (gracefully or by timeout)
|
|
||||||
} connection_state_t;
|
|
||||||
|
|
||||||
/*!\brief Type for a callback function that is called when a data packet was received. */
|
|
||||||
typedef void (*connection_data_callback_t)(struct connection_ctx_s *conn, const uint8_t *data, size_t len);
|
|
||||||
|
|
||||||
typedef struct connection_ctx_s {
|
|
||||||
connection_state_t conn_state; //!< State of the connection.
|
|
||||||
|
|
||||||
connection_data_callback_t data_cb; //!< Callback function for received data packets.
|
|
||||||
|
|
||||||
ham64_t my_addr; //!< The local link layer address.
|
|
||||||
ham64_t peer_addr; //!< The link layer address of the peer.
|
|
||||||
|
|
||||||
uint8_t last_acked_seq; //!< Next sequence number expected by the peer (from last Ack).
|
|
||||||
uint8_t next_expected_seq; //!< Next sequence number expected by us.
|
|
||||||
|
|
||||||
packet_queue_t packet_queue; //!< Transmission packet queue.
|
|
||||||
|
|
||||||
size_t next_packet_index; //!< Index in the packet queue of the next packet to transmit.
|
|
||||||
uint8_t next_seq_nr; //!< Sequence number to tag the next transmitted packet with.
|
|
||||||
} connection_ctx_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*!\brief Initialize the layer 2 connection context.
|
|
||||||
*
|
|
||||||
* \param ctx The connection context to initialize.
|
|
||||||
* \param my_addr The local link layer address.
|
|
||||||
* \param peer_addr The remote link layer address.
|
|
||||||
* \returns OK if everything worked or a fitting error code.
|
|
||||||
*/
|
|
||||||
result_t connection_init(connection_ctx_t *ctx, const ham64_t *my_addr, const ham64_t *peer_addr);
|
|
||||||
|
|
||||||
/*!\brief Destroy the given layer 2 connection context.
|
|
||||||
*/
|
|
||||||
void connection_destroy(connection_ctx_t *ctx);
|
|
||||||
|
|
||||||
/*!\brief Handle a received packet.
|
|
||||||
*
|
|
||||||
* \param ctx The receiver context.
|
|
||||||
* \param buf Where to write the encoded packet data.
|
|
||||||
* \param buf_len Space available in the buffer.
|
|
||||||
* \returns A result code from the packet handling procedure.
|
|
||||||
*/
|
|
||||||
result_t connection_handle_packet(connection_ctx_t *ctx, const uint8_t *buf, size_t buf_len);
|
|
||||||
|
|
||||||
/*!\brief Return the sequence number expected next by our side.
|
|
||||||
*/
|
|
||||||
uint8_t connection_get_next_expected_seq(const connection_ctx_t *ctx);
|
|
||||||
|
|
||||||
/*!\brief Return the sequence number expected next by the other side.
|
|
||||||
*/
|
|
||||||
uint8_t connection_get_last_acked_seq(const connection_ctx_t *ctx);
|
|
||||||
|
|
||||||
/*!\brief Enqueue a packet for transmission.
|
|
||||||
* \param ctx The connection context.
|
|
||||||
*/
|
|
||||||
result_t connection_enqueue_packet(connection_ctx_t *ctx, uint8_t *buf, size_t buf_len);
|
|
||||||
|
|
||||||
/*!\brief Add an empty packet to ensure an acknowledgement is sent.
|
|
||||||
* \param ctx The connection context.
|
|
||||||
* \param tx_request Value of the TX Request field in the packet.
|
|
||||||
*/
|
|
||||||
result_t connection_add_empty_packet(connection_ctx_t *ctx, bool tx_request);
|
|
||||||
|
|
||||||
/*!\brief Encode the next packet for transmission.
|
|
||||||
*
|
|
||||||
* \note
|
|
||||||
* If no more packets are available, this function returns zero. In that case,
|
|
||||||
* either \ref connection_restart() or \ref connection_handle_ack() must be
|
|
||||||
* called to handle retransmits correctly.
|
|
||||||
*
|
|
||||||
* \param ctx The connection context.
|
|
||||||
* \param ack_seq_nr The received sequence number to send as an acknowledgement.
|
|
||||||
* \param buf Where to write the encoded packet data.
|
|
||||||
* \param buf_len Space available in the buffer.
|
|
||||||
* \returns The number of bytes written to buf or zero if no packet was available.
|
|
||||||
*/
|
|
||||||
size_t connection_encode_next_packet(connection_ctx_t *ctx, uint8_t ack_seq_nr, uint8_t *buf, size_t buf_len);
|
|
||||||
|
|
||||||
/*!\brief Restart the transmission from the beginning of the packet queue.
|
|
||||||
*/
|
|
||||||
void connection_restart_tx(connection_ctx_t *ctx);
|
|
||||||
|
|
||||||
/*!\brief Remove the first packet from the queue if it is an empty packet.
|
|
||||||
*/
|
|
||||||
void connection_tx_clean_empty_packet(connection_ctx_t *ctx);
|
|
||||||
|
|
||||||
/*!\brief Handle acknowledgements.
|
|
||||||
* \details
|
|
||||||
* Removes all packets before the given sequence number from the queue.
|
|
||||||
*
|
|
||||||
* \param ctx The connection context.
|
|
||||||
* \param acked_seq The acknowledged (= next expected) sequence number.
|
|
||||||
* \param do_ack Whether an empty packet shall be generated if the queue is empty.
|
|
||||||
*/
|
|
||||||
void connection_handle_ack(connection_ctx_t *ctx, uint8_t acked_seq);
|
|
||||||
|
|
||||||
/*!\brief Check if there are packets queued for transmission.
|
|
||||||
*/
|
|
||||||
bool connection_can_transmit(const connection_ctx_t *ctx);
|
|
||||||
|
|
||||||
#endif // CONNECTION_H
|
|
|
@ -187,19 +187,3 @@ void ham64_format(const ham64_t *ham64, char *out)
|
||||||
|
|
||||||
out[5*ham64->length - 1] = '\0';
|
out[5*ham64->length - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ham64_is_equal(const ham64_t *a, const ham64_t *b)
|
|
||||||
{
|
|
||||||
if(a->length != b->length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(uint8_t i = 0; i < a->length; i++) {
|
|
||||||
if(a->addr[i] != b->addr[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
// buffer size required for the string representation of a maximum-length HAM64
|
// buffer size required for the string representation of a maximum-length HAM64
|
||||||
// address, including terminating zero.
|
// address, including terminating zero.
|
||||||
|
@ -63,11 +62,4 @@ const char *ham64_addr_type_to_string(ham64_addr_type_t addr_type);
|
||||||
*/
|
*/
|
||||||
void ham64_format(const ham64_t *ham64, char *out);
|
void ham64_format(const ham64_t *ham64, char *out);
|
||||||
|
|
||||||
/*!\brief Check if two ham64 addresses are equal.
|
|
||||||
* \param a Pointer to the first address.
|
|
||||||
* \param b Pointer to the second address.
|
|
||||||
* \returns True if a and b are equal, false otherwise.
|
|
||||||
*/
|
|
||||||
bool ham64_is_equal(const ham64_t *a, const ham64_t *b);
|
|
||||||
|
|
||||||
#endif // HAM64_H
|
#endif // HAM64_H
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
|
@ -11,17 +11,16 @@
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OK,
|
OK,
|
||||||
ERR_INVALID_STATE, // module or context is in an invalid state
|
ERR_INVALID_STATE,
|
||||||
ERR_INVALID_PARAM, // invalid / nonsense parameters given
|
ERR_INVALID_PARAM, // invalid / nonsense parameters given
|
||||||
ERR_INVALID_ADDRESS, // invalid address received or given
|
ERR_NO_MEM, // not enough memory or allocation error
|
||||||
ERR_NO_MEM, // not enough memory or allocation error
|
ERR_SIZE, // a given size is invalid
|
||||||
ERR_SIZE, // a given size is invalid
|
ERR_LIQUID, // an error occurred in the LiquidDSP library.
|
||||||
ERR_LIQUID, // an error occurred in the LiquidDSP library.
|
ERR_SYSCALL, // a syscall failed. Use errno to determine the cause.
|
||||||
ERR_SYSCALL, // a syscall failed. Use errno to determine the cause.
|
ERR_SOAPY, // an error occurred in the SoapySDR library.
|
||||||
ERR_SOAPY, // an error occurred in the SoapySDR library.
|
ERR_SDR, // an error occurred in the SDR interface.
|
||||||
ERR_SDR, // an error occurred in the SDR interface.
|
ERR_INTEGRITY, // an integrity check failed (e.g. CRC of received packet is wrong)
|
||||||
ERR_INTEGRITY, // an integrity check failed (e.g. CRC of received packet is wrong)
|
ERR_SEQUENCE, // an unexpected packet was received
|
||||||
ERR_SEQUENCE, // an unexpected packet was received
|
|
||||||
} result_t;
|
} result_t;
|
||||||
|
|
||||||
#ifdef DEBUG_LIQUID
|
#ifdef DEBUG_LIQUID
|
||||||
|
|
Loading…
Reference in a new issue