chore: import local project into Gitea
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
# See: https://github.com/codespell-project/codespell#using-a-config-file
|
||||
[codespell]
|
||||
# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here:
|
||||
ignore-words-list = ,
|
||||
check-filenames =
|
||||
check-hidden =
|
||||
skip = ./.git,./src,./examples,./Packages_Patches,./LibraryPatches
|
||||
76
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
76
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Describe the bug
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
### Steps to Reproduce
|
||||
|
||||
Steps to reproduce the behavior. Including the [MRE](https://stackoverflow.com/help/minimal-reproducible-example) sketches
|
||||
|
||||
### Expected behavior
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
### Actual behavior
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
### Debug and AT-command log (if applicable)
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
### Screenshots
|
||||
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
---
|
||||
|
||||
### Information
|
||||
|
||||
Please ensure to specify the following:
|
||||
|
||||
* Arduino IDE version (e.g. 1.8.19) or Platform.io version
|
||||
* `RP2040` Core Version (e.g. RP2040 core v2.7.1)
|
||||
* `RP2040` Board type (e.g. RASPBERRY_PI_PICO_W)
|
||||
* Contextual information (e.g. what you were trying to achieve)
|
||||
* Simplest possible steps to reproduce
|
||||
* Anything that might be relevant in your opinion, such as:
|
||||
* Operating system (Windows, Ubuntu, etc.) and the output of `uname -a`
|
||||
* Network configuration
|
||||
|
||||
|
||||
Please be educated, civilized and constructive as you've always been. Disrespective posts against [GitHub Code of Conduct](https://docs.github.com/en/site-policy/github-terms/github-event-code-of-conduct) will be ignored and deleted.
|
||||
|
||||
---
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
Arduino IDE version: 1.8.19
|
||||
RP2040 core v2.7.1
|
||||
RASPBERRY_PI_PICO_W Module
|
||||
OS: Ubuntu 20.04 LTS
|
||||
Linux xy-Inspiron-3593 5.15.0-58-generic #64~20.04.1-Ubuntu SMP Fri Jan 6 16:42:31 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
|
||||
|
||||
Context:
|
||||
I encountered a crash while using this library
|
||||
|
||||
Steps to reproduce:
|
||||
1. ...
|
||||
2. ...
|
||||
3. ...
|
||||
4. ...
|
||||
```
|
||||
|
||||
### Additional context
|
||||
|
||||
Add any other context about the problem here.
|
||||
|
||||
23
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
23
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Is your feature request related to a problem? Please describe.
|
||||
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
### Describe the solution you'd like
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
### Describe alternatives you've considered
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
### Additional context
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
53
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/workflows/build-arduino.yml
vendored
Normal file
53
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/workflows/build-arduino.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
|
||||
name: Build (Arduino)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
arduino-rpi:
|
||||
name: Arduino RPI
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
board:
|
||||
- rpipicow
|
||||
- rpipico2w
|
||||
|
||||
steps:
|
||||
- name: Install arduino-cli
|
||||
run: curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=/usr/local/bin sh
|
||||
|
||||
- name: Update core index
|
||||
run: arduino-cli core update-index --additional-urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
- name: Install core
|
||||
run: arduino-cli core install --additional-urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json rp2040:rp2040
|
||||
|
||||
- name: Install ArduinoJson
|
||||
run: arduino-cli lib install ArduinoJson
|
||||
|
||||
- name: Install RPAsyncTCP
|
||||
run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/ayushsharma82/RPAsyncTCP#v1.3.0
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build Examples
|
||||
run: |
|
||||
for i in `ls examples`; do
|
||||
echo "============================================================="
|
||||
echo "Building examples/$i..."
|
||||
echo "============================================================="
|
||||
arduino-cli compile --library . --warnings none -b rp2040:rp2040:${{ matrix.board }} "examples/$i/$i.ino"
|
||||
done
|
||||
57
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/workflows/build-pio.yml
vendored
Normal file
57
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/workflows/build-pio.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
|
||||
name: Build (pioarduino)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
- release/*
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
platformio-rpi:
|
||||
name: PIO RPI
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
board:
|
||||
- rpipicow
|
||||
- rpipico2w
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache PlatformIO
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ runner.os }}-pio
|
||||
path: |
|
||||
~/.cache/pip
|
||||
~/.platformio
|
||||
|
||||
- name: Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Install PIO
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade platformio
|
||||
|
||||
- name: Build Examples
|
||||
run: |
|
||||
for i in `ls examples`; do
|
||||
echo "============================================================="
|
||||
echo "Building examples/$i..."
|
||||
echo "============================================================="
|
||||
PLATFORMIO_SRC_DIR=examples/$i PIO_BOARD=${{ matrix.board }} pio run -e ci-raspberrypi
|
||||
done
|
||||
16
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/workflows/report-size-deltas.yml
vendored
Normal file
16
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/workflows/report-size-deltas.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: Report Size Deltas
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '*/5 * * * *'
|
||||
|
||||
jobs:
|
||||
report:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Comment size deltas reports to PRs
|
||||
uses: arduino/report-size-deltas@v1
|
||||
with:
|
||||
# The name of the workflow artifact created by the "Compile Examples" workflow
|
||||
sketches-reports-source: sketches-reports
|
||||
20
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/workflows/stale.yml
vendored
Normal file
20
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: 'Close stale issues and PR'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 6 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
|
||||
stale-pr-message: 'This PR is marked as stale because it has been open 45 days with no activity. You can remove stale label or comment if this PR is still valid.'
|
||||
close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.'
|
||||
exempt-issue-labels: bug,triage,feature_request
|
||||
exempt-pr-labels: wip,feature_request
|
||||
exempt-all-assignees: true
|
||||
days-before-stale: 30
|
||||
days-before-close: 7
|
||||
days-before-pr-close: -1
|
||||
35
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.gitignore
vendored
Normal file
35
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.gitignore
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
.DS_Store
|
||||
.vscode
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
1
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.piopm
Normal file
1
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/.piopm
Normal file
@@ -0,0 +1 @@
|
||||
{"type": "library", "name": "RPAsyncTCP", "version": "1.3.2", "spec": {"owner": "ayushsharma82", "id": 18425, "name": "RPAsyncTCP", "requirements": null, "uri": null}}
|
||||
@@ -0,0 +1,60 @@
|
||||
## Contributing to RPAsyncTCP
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
Please report bugs in [RPAsyncTCP Issues](https://github.com/ayushsharma82/RPAsyncTCP/issues) if you find them.
|
||||
|
||||
However, before reporting a bug please check through the following:
|
||||
|
||||
* [Existing Open Issues](https://github.com/ayushsharma82/RPAsyncTCP/issues) - someone might have already encountered this.
|
||||
|
||||
If you don't find anything, please [open a new issue](https://github.com/ayushsharma82/RPAsyncTCP/issues/new).
|
||||
|
||||
---
|
||||
|
||||
### How to submit a bug report
|
||||
|
||||
Please ensure to specify the following:
|
||||
|
||||
* Arduino IDE version (e.g. 1.8.19) or Platform.io version
|
||||
* `RP2040` Core Version (e.g. RP2040 core v2.7.1)
|
||||
* `RP2040` Board type (e.g. RASPBERRY_PI_PICO_W)
|
||||
* Contextual information (e.g. what you were trying to achieve)
|
||||
* Simplest possible steps to reproduce
|
||||
* Anything that might be relevant in your opinion, such as:
|
||||
* Operating system (Windows, Ubuntu, etc.) and the output of `uname -a`
|
||||
* Network configuration
|
||||
|
||||
|
||||
Please be educated, civilized and constructive as you've always been. Disrespective posts against [GitHub Code of Conduct](https://docs.github.com/en/site-policy/github-terms/github-event-code-of-conduct) will be ignored and deleted.
|
||||
|
||||
---
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
Arduino IDE version: 1.8.19
|
||||
RP2040 core v2.7.1
|
||||
RASPBERRY_PI_PICO_W Module
|
||||
OS: Ubuntu 20.04 LTS
|
||||
Linux xy-Inspiron-3593 5.15.0-58-generic #64~20.04.1-Ubuntu SMP Fri Jan 6 16:42:31 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
|
||||
|
||||
Context:
|
||||
I encountered a crash while using this library
|
||||
|
||||
Steps to reproduce:
|
||||
1. ...
|
||||
2. ...
|
||||
3. ...
|
||||
4. ...
|
||||
```
|
||||
|
||||
### Sending Feature Requests
|
||||
|
||||
Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful.
|
||||
|
||||
There are usually some outstanding feature requests in the [existing issues list](https://github.com/ayushsharma82/RPAsyncTCP/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), feel free to add comments to them.
|
||||
|
||||
### Sending Pull Requests
|
||||
|
||||
Pull Requests with changes and fixes are also welcome!
|
||||
165
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/LICENSE
Normal file
165
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/LICENSE
Normal file
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
105
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/README.md
Normal file
105
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/README.md
Normal file
@@ -0,0 +1,105 @@
|
||||

|
||||

|
||||
|
||||
[](https://github.com/ayushsharma82/RPAsyncTCP/releases)
|
||||
[](http://github.com/ayushsharma82/RPAsyncTCP/issues)
|
||||
[](https://www.ardu-badge.com/RPAsyncTCP)
|
||||
|
||||
|
||||
> [!TIP]
|
||||
> This library is a fork of **AsyncTCP_RP2040W** and is a drop-in replacement for it. If you were previously using `AsyncTCP_RP2040W`, you will need to update your `include` directives to `#include <RPAsyncTCP.h>`.
|
||||
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [What is RPAsyncTCP?](#what-is-rpasynctcp)
|
||||
- [Features](#i-features)
|
||||
- [Supported Boards](#ii-supported-boards)
|
||||
- [Installation](#installation)
|
||||
- [Using Arduino Library Manager](#i-using-arduino-library-manager)
|
||||
- [Using PlatformIO](#ii-using-platformio)
|
||||
- [Manual Installation](#iii-manual-installation)
|
||||
- [Examples](#examples)
|
||||
- [Debugging](#debugging)
|
||||
- [License](#license)
|
||||
- [Authors & Maintainers](#authors--maintainers)
|
||||
|
||||
<br/>
|
||||
|
||||
## What is RPAsyncTCP?
|
||||
|
||||
RPAsyncTCP brings the **asynchronous** networking power of ESPAsyncTCP to **RP2040+W and RP2350+W MCUs**, serving as the foundation for libraries like `ESPAsyncWebServer` which allows for advanced routing and better performance compared to syncronous `WebServer` library.
|
||||
|
||||
### I. Features
|
||||
|
||||
- Handles multiple connections simultaneously
|
||||
- Callbacks are triggered when requests are ready
|
||||
- Faster response handling and improved efficiency
|
||||
- Support for WebSockets, EventSource (Server-Sent Events), and URL Rewriting
|
||||
- Static file serving with cache and indexing support
|
||||
- Simple template processing
|
||||
|
||||
### II. Supported Boards
|
||||
|
||||
RPAsyncTCP supports [earlephilhower/arduino-pico](https://github.com/earlephilhower/arduino-pico) Arduino Board.
|
||||
|
||||
- **RP2040** + CYW43439 WiFi (Example: RaspberryPi Pico W)
|
||||
- **RP2350** + CYW43439 WiFi (Example: RaspberryPi Pico 2W)
|
||||
|
||||
<br/>
|
||||
|
||||
## Installation
|
||||
|
||||
### I. Using Arduino Library Manager
|
||||
|
||||
Search for **RPAsyncTCP** in the Arduino Library Manager and install the latest version.
|
||||
|
||||
|
||||
### II. Using PlatformIO
|
||||
|
||||
Search for **RPAsyncTCP** in the PlatformIO Library Manager and install in your project.
|
||||
|
||||
|
||||
### III. Manual Installation
|
||||
|
||||
If you would like to install manually, you can follow these steps:
|
||||
|
||||
1. Download the latest release from [GitHub](https://github.com/ayushsharma82/RPAsyncTCP)
|
||||
2. For Arduino IDE: Extract and place the folder in `~/Arduino/libraries/`
|
||||
3. For PlatformIO, you can place the folder in your `libs` folder of your project.
|
||||
|
||||
<br/>
|
||||
|
||||
## Examples
|
||||
|
||||
Check out the example projects:
|
||||
|
||||
- [Client](https://github.com/ayushsharma82/RPAsyncTCP/tree/main/examples/Client/Client.ino)
|
||||
- [Server](https://github.com/ayushsharma82/RPAsyncTCP/tree/main/examples/Server/Server.ino)
|
||||
|
||||
<br/>
|
||||
|
||||
## Debugging
|
||||
|
||||
Debugging is enabled by default on Serial. You can adjust the log level by modifying `_RPAsyncTCP_LOGLEVEL_` in the library files:
|
||||
|
||||
```cpp
|
||||
// 0: DISABLED: no logging
|
||||
// 1: ERROR: errors
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
```
|
||||
|
||||
<br/>
|
||||
|
||||
## License
|
||||
|
||||
This library is licensed under the [LGPL-3.0 License](LICENSE).
|
||||
|
||||
<br/>
|
||||
|
||||
## Authors & Maintainers
|
||||
|
||||
Thanks to [Khoi Hoang](https://github.com/khoih-prog) for the original fork to add support for RP2040+W. You can support him for his original work [here](https://www.buymeacoffee.com/khoihprog6).
|
||||
|
||||
- **Previous Authors:** Hristo Gochkov (2016), Khoi Hoang (2022)
|
||||
- **Current Maintainer:** Ayush Sharma (2025)
|
||||
@@ -0,0 +1,42 @@
|
||||
# RPAsyncTCP Library
|
||||
|
||||
[](https://www.ardu-badge.com/RPAsyncTCP)
|
||||
[](https://github.com/ayushsharma82/RPAsyncTCP/releases)
|
||||
[](#Contributing)
|
||||
[](http://github.com/ayushsharma82/RPAsyncTCP/issues)
|
||||
|
||||
|
||||
<a href="https://www.buymeacoffee.com/khoihprog6" title="Donate to my libraries using BuyMeACoffee"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Donate to my libraries using BuyMeACoffee" style="height: 50px !important;width: 181px !important;" ></a>
|
||||
<a href="https://www.buymeacoffee.com/khoihprog6" title="Donate to my libraries using BuyMeACoffee"><img src="https://img.shields.io/badge/buy%20me%20a%20coffee-donate-orange.svg?logo=buy-me-a-coffee&logoColor=FFDD00" style="height: 20px !important;width: 200px !important;" ></a>
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Changelog](#changelog)
|
||||
* [Releases v1.2.0](#Releases-v120)
|
||||
* [Releases v1.1.0](#Releases-v110)
|
||||
* [Initial Releases v1.0.0](#Initial-Releases-v100)
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
### Releases v1.2.0
|
||||
|
||||
1. Add complex auto-reconnect `AsyncTCP_Client` and `AsyncTCP_Server` examples
|
||||
2. Improve `README.md` so that links can be used in other sites, such as `PIO`
|
||||
|
||||
### Releases v1.1.0
|
||||
|
||||
1. Fix issue with slow browsers or network
|
||||
2. Remove hard-code if possible
|
||||
3. Improve debug messages by adding functions to display `error/state messages` instead of `cryptic error/state number`
|
||||
4. Clean up
|
||||
|
||||
|
||||
### Initial Releases v1.0.0
|
||||
|
||||
1. Initial coding to support **RASPBERRY_PI_PICO_W with CYW43439 WiFi**, using [**arduino-pico core v2.4.0+**](https://github.com/earlephilhower/arduino-pico)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
@@ -0,0 +1,130 @@
|
||||
#include <RPAsyncTCP.h>
|
||||
|
||||
// Network Configuration
|
||||
const char* SSID = "your_ssid";
|
||||
const char* PASSWORD = "12345678";
|
||||
const IPAddress SERVER_IP(192, 168, 2, 128);
|
||||
const uint16_t TCP_PORT = 5698;
|
||||
|
||||
// Timing Configuration
|
||||
const unsigned long RECONNECT_CHECK_INTERVAL = 1000; // 1 second
|
||||
const unsigned long HEARTBEAT_INTERVAL = 10000; // 10 seconds
|
||||
|
||||
// Client Configuration
|
||||
AsyncClient* tcpClient = nullptr;
|
||||
bool isConnected = false;
|
||||
const uint8_t REPLY_BUFFER_SIZE = 64;
|
||||
|
||||
// Status Tracking
|
||||
unsigned long lastHeartbeat = 0;
|
||||
unsigned long lastReconnectAttempt = 0;
|
||||
|
||||
void printNetworkStatus() {
|
||||
Serial.print("Connected to: ");
|
||||
Serial.println(WiFi.SSID());
|
||||
Serial.print("Local IP: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
bool sendHeartbeat(AsyncClient* client) {
|
||||
if (!client || !client->canSend()) {
|
||||
Serial.println("Cannot send heartbeat");
|
||||
return false;
|
||||
}
|
||||
|
||||
char message[REPLY_BUFFER_SIZE];
|
||||
snprintf(message, sizeof(message), "Client heartbeat from %s", WiFi.localIP().toString().c_str());
|
||||
|
||||
size_t added = client->add(message, strlen(message));
|
||||
if (added == 0) {
|
||||
Serial.println("Failed to add heartbeat to buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!client->send()) {
|
||||
Serial.println("Failed to send heartbeat");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void handleServerData(void* arg, AsyncClient* client, void* data, size_t len) {
|
||||
Serial.printf("\nReceived %d bytes from %s\n", len, client->remoteIP().toString().c_str());
|
||||
Serial.write(static_cast<uint8_t*>(data), len);
|
||||
|
||||
// Immediate reply to server
|
||||
char ackMsg[] = "ACK";
|
||||
client->add(ackMsg, strlen(ackMsg));
|
||||
client->send();
|
||||
}
|
||||
|
||||
void handleConnect(void* arg, AsyncClient* client) {
|
||||
Serial.printf("Connected to server %s:%d\n", SERVER_IP.toString().c_str(), TCP_PORT);
|
||||
isConnected = true;
|
||||
sendHeartbeat(client); // Send initial heartbeat
|
||||
}
|
||||
|
||||
void handleDisconnect(void* arg, AsyncClient* client) {
|
||||
Serial.println("Disconnected from server");
|
||||
isConnected = false;
|
||||
}
|
||||
|
||||
bool connectToServer() {
|
||||
if (tcpClient) {
|
||||
delete tcpClient;
|
||||
tcpClient = nullptr;
|
||||
}
|
||||
|
||||
tcpClient = new AsyncClient();
|
||||
if (!tcpClient) {
|
||||
Serial.println("Failed to create TCP client");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup event handlers
|
||||
tcpClient->onData(handleServerData);
|
||||
tcpClient->onConnect(handleConnect);
|
||||
tcpClient->onDisconnect(handleDisconnect);
|
||||
|
||||
return tcpClient->connect(SERVER_IP, TCP_PORT);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial && millis() < 5000); // Wait for serial port
|
||||
|
||||
if (WiFi.status() == WL_NO_MODULE) {
|
||||
Serial.println("WiFi module not found!");
|
||||
while (true); // Halt if no WiFi
|
||||
}
|
||||
|
||||
Serial.print("Connecting to: ");
|
||||
Serial.println(SSID);
|
||||
|
||||
while (WiFi.begin(SSID, PASSWORD) != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
printNetworkStatus();
|
||||
connectToServer();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// Heartbeat logic: Send every HEARTBEAT_INTERVAL
|
||||
if (isConnected && (currentTime - lastHeartbeat >= HEARTBEAT_INTERVAL)) {
|
||||
if (sendHeartbeat(tcpClient)) {
|
||||
lastHeartbeat = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Reconnection logic
|
||||
if (!isConnected && (currentTime - lastReconnectAttempt >= RECONNECT_CHECK_INTERVAL)) {
|
||||
Serial.println("Attempting to reconnect...");
|
||||
connectToServer();
|
||||
lastReconnectAttempt = currentTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
#include <RPAsyncTCP.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
// Network Configuration
|
||||
const char* SSID = "your_ssid";
|
||||
const char* PASSWORD = "12345678";
|
||||
const uint16_t TCP_PORT = 5698;
|
||||
|
||||
// Server Configuration
|
||||
AsyncServer* tcpServer = nullptr;
|
||||
std::vector<AsyncClient*> connectedClients;
|
||||
IPAddress serverIP;
|
||||
|
||||
// Server Response Configuration
|
||||
const uint16_t RESPONSE_BUFFER_SIZE = 128;
|
||||
|
||||
void printNetworkStatus() {
|
||||
if (serverIP == INADDR_NONE) return; // Ensure IP is valid
|
||||
Serial.print("Connected to: ");
|
||||
Serial.println(WiFi.SSID());
|
||||
serverIP = WiFi.localIP();
|
||||
Serial.print("Server IP: ");
|
||||
Serial.println(serverIP);
|
||||
}
|
||||
|
||||
void handleClientDisconnect(AsyncClient* client) {
|
||||
Serial.printf("Client %s disconnected\n", client->remoteIP().toString().c_str());
|
||||
|
||||
// Remove and delete client
|
||||
connectedClients.erase(std::remove(connectedClients.begin(), connectedClients.end(), client), connectedClients.end());
|
||||
delete client;
|
||||
}
|
||||
|
||||
void sendWelcomeMessage(AsyncClient* client) {
|
||||
if (!client->canSend() || client->space() < RESPONSE_BUFFER_SIZE) return;
|
||||
|
||||
char response[RESPONSE_BUFFER_SIZE];
|
||||
snprintf(response, sizeof(response), "Connected to RPAsyncTCP Server @ %s", serverIP.toString().c_str());
|
||||
|
||||
size_t len = strlen(response);
|
||||
size_t added = client->add(response, len, ASYNC_WRITE_FLAG_COPY);
|
||||
if (added != len) {
|
||||
Serial.println("Failed to add all data to buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!client->send()) {
|
||||
Serial.println("Failed to send data");
|
||||
}
|
||||
}
|
||||
|
||||
// Client Event Handlers
|
||||
void handleClientData(void* arg, AsyncClient* client, void* data, size_t length) {
|
||||
Serial.printf("\nReceived %zu bytes from %s\n", length, client->remoteIP().toString().c_str());
|
||||
Serial.write(static_cast<uint8_t*>(data), length);
|
||||
|
||||
sendWelcomeMessage(client);
|
||||
}
|
||||
|
||||
void handleClientError(void* arg, AsyncClient* client, err_t error) {
|
||||
Serial.printf("Client %s error: %s\n", client->remoteIP().toString().c_str(), client->errorToString(error));
|
||||
handleClientDisconnect(client);
|
||||
}
|
||||
|
||||
void handleClientTimeout(void* arg, AsyncClient* client, uint32_t time) {
|
||||
Serial.printf("Client %s timeout after %ums\n",
|
||||
client->remoteIP().toString().c_str(), time);
|
||||
handleClientDisconnect(client);
|
||||
}
|
||||
|
||||
// Server Event Handler
|
||||
void handleNewConnection(void* arg, AsyncClient* client) {
|
||||
Serial.printf("New client connected: %s\n", client->remoteIP().toString().c_str());
|
||||
|
||||
// Setup client callbacks
|
||||
client->onData(handleClientData, nullptr);
|
||||
client->onError(handleClientError, nullptr);
|
||||
client->onDisconnect([](void*, AsyncClient* c) { handleClientDisconnect(c); }, nullptr);
|
||||
client->onTimeout(handleClientTimeout, nullptr);
|
||||
|
||||
connectedClients.push_back(client);
|
||||
sendWelcomeMessage(client);
|
||||
}
|
||||
|
||||
void initializeWiFi() {
|
||||
if (WiFi.status() == WL_NO_MODULE) {
|
||||
Serial.println("WiFi module not found!");
|
||||
while(true);
|
||||
}
|
||||
|
||||
Serial.print("Connecting to: ");
|
||||
Serial.println(SSID);
|
||||
|
||||
while (WiFi.begin(SSID, PASSWORD) != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial && millis() < 5000);
|
||||
|
||||
initializeWiFi();
|
||||
printNetworkStatus();
|
||||
|
||||
tcpServer = new AsyncServer(TCP_PORT);
|
||||
tcpServer->onClient(handleNewConnection, tcpServer);
|
||||
tcpServer->begin();
|
||||
|
||||
Serial.printf("Server running at %s:%d\n", serverIP.toString().c_str(), TCP_PORT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(1); // Yield to background tasks
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "RPAsyncTCP",
|
||||
"version": "1.3.2",
|
||||
"keywords": "http, communication, async, websocket, webserver, async-webserver, async-tcp, async-udp, async-websocket, async-http, ssl, tls, rp2040, rp2350, rp2350w, rp2040w, raspberry-pi-pico-w, cyw43439, wifi",
|
||||
"description": "Asynchronous TCP Library for RP2040+W, RP2350+W (arduino-pico core)",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Hristo Gochkov",
|
||||
"url": "https://github.com/me-no-dev"
|
||||
},
|
||||
{
|
||||
"name": "Khoi Hoang",
|
||||
"url": "https://github.com/khoih-prog",
|
||||
"email": "khoih.prog@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Ayush Sharma",
|
||||
"url": "https://github.com/ayushsharma82",
|
||||
"email": "asrocks5@gmail.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ayushsharma82/RPAsyncTCP"
|
||||
},
|
||||
"homepage": "https://github.com/ayushsharma82/RPAsyncTCP",
|
||||
"export": {
|
||||
"exclude": ["linux", "extras", "tests"]
|
||||
},
|
||||
"license": "LGPL-3.0",
|
||||
"frameworks": "*",
|
||||
"platforms": "raspberrypi",
|
||||
"examples": "examples/*/*/*.ino",
|
||||
"headers": "RPAsyncTCP.h"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
name=RPAsyncTCP
|
||||
version=1.3.2
|
||||
author=Hristo Gochkov,Khoi Hoang,Ayush Sharma
|
||||
maintainer=Ayush Sharma <asrocks5@gmail.com>
|
||||
sentence=Asynchronous TCP Library for RP2040+W, RP2350+W (arduino-pico core)
|
||||
paragraph=Asynchronous TCP Library for RP2040+W, RP2350+W (arduino-pico core), intended to be used with ESPAsyncWebServer library.
|
||||
category=Communication
|
||||
url=https://github.com/ayushsharma82/RPAsyncTCP
|
||||
architectures=rp2040,rp2350
|
||||
repository=https://github.com/ayushsharma82/RPAsyncTCP
|
||||
license=LGPL-3.0
|
||||
includes=RPAsyncTCP.h
|
||||
@@ -0,0 +1,59 @@
|
||||
[platformio]
|
||||
default_envs = rp2040, rp2350
|
||||
lib_dir = .
|
||||
; src_dir = examples/Client
|
||||
src_dir = examples/Server
|
||||
|
||||
[env:rp2040]
|
||||
framework = arduino
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = rpipicow
|
||||
board_build.core = earlephilhower
|
||||
build_flags =
|
||||
-Og
|
||||
-Wall -Wextra
|
||||
-Wno-unused-parameter
|
||||
; -D CONFIG_ARDUHAL_LOG_COLORS
|
||||
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
|
||||
monitor_speed = 115200
|
||||
monitor_filters = log2file
|
||||
lib_compat_mode = strict
|
||||
lib_ldf_mode = chain
|
||||
lib_deps =
|
||||
ayushsharma82/RPAsyncTCP@^1.3.1
|
||||
lib_ignore =
|
||||
lwIP_ESPHost
|
||||
|
||||
[env:rp2350]
|
||||
framework = arduino
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = rpipico2w
|
||||
board_build.core = earlephilhower
|
||||
build_flags =
|
||||
-Og
|
||||
-Wall -Wextra
|
||||
-Wno-unused-parameter
|
||||
; -D CONFIG_ARDUHAL_LOG_COLORS
|
||||
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
|
||||
monitor_speed = 115200
|
||||
monitor_filters = log2file
|
||||
lib_compat_mode = strict
|
||||
lib_ldf_mode = chain
|
||||
lib_deps =
|
||||
ayushsharma82/RPAsyncTCP@^1.3.1
|
||||
lib_ignore =
|
||||
lwIP_ESPHost
|
||||
|
||||
; CI
|
||||
|
||||
[env:ci-raspberrypi]
|
||||
framework = arduino
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = ${sysenv.PIO_BOARD}
|
||||
board_build.core = earlephilhower
|
||||
lib_deps =
|
||||
ayushsharma82/RPAsyncTCP@^1.3.1
|
||||
lib_ignore =
|
||||
lwIP_ESPHost
|
||||
build_flags = ${env.build_flags}
|
||||
-Wno-missing-field-initializers
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
Asynchronous TCP library for Espressif MCUs
|
||||
|
||||
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(_RPAsyncTCP_LOGLEVEL_)
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
#include "AsyncPrinter.h"
|
||||
#include "debug.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter::AsyncPrinter()
|
||||
: _client(NULL)
|
||||
, _data_cb(NULL)
|
||||
, _data_arg(NULL)
|
||||
, _close_cb(NULL)
|
||||
, _close_arg(NULL)
|
||||
, _tx_buffer(NULL)
|
||||
, _tx_buffer_size(TCP_MSS)
|
||||
, next(NULL)
|
||||
{}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter::AsyncPrinter(AsyncClient *client, size_t txBufLen)
|
||||
: _client(client)
|
||||
, _data_cb(NULL)
|
||||
, _data_arg(NULL)
|
||||
, _close_cb(NULL)
|
||||
, _close_arg(NULL)
|
||||
, _tx_buffer(NULL)
|
||||
, _tx_buffer_size(txBufLen)
|
||||
, next(NULL)
|
||||
{
|
||||
_attachCallbacks();
|
||||
_tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
|
||||
|
||||
if (_tx_buffer == NULL)
|
||||
{
|
||||
panic(); //What should we do?
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter::~AsyncPrinter()
|
||||
{
|
||||
_on_close();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::onData(ApDataHandler cb, void *arg)
|
||||
{
|
||||
_data_cb = cb;
|
||||
_data_arg = arg;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::onClose(ApCloseHandler cb, void *arg)
|
||||
{
|
||||
_close_cb = cb;
|
||||
_close_arg = arg;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int AsyncPrinter::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (_client != NULL && connected())
|
||||
return 0;
|
||||
|
||||
_client = new (std::nothrow) AsyncClient();
|
||||
|
||||
if (_client == NULL)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
_client->onConnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((AsyncPrinter*)(obj))->_onConnect(c);
|
||||
}, this);
|
||||
|
||||
if (_client->connect(ip, port))
|
||||
{
|
||||
while (_client && _client->state() < 4)
|
||||
delay(1);
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int AsyncPrinter::connect(const char *host, uint16_t port)
|
||||
{
|
||||
if (_client != NULL && connected())
|
||||
return 0;
|
||||
|
||||
_client = new (std::nothrow) AsyncClient();
|
||||
|
||||
if (_client == NULL)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
_client->onConnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((AsyncPrinter*)(obj))->_onConnect(c);
|
||||
}, this);
|
||||
|
||||
if (_client->connect(host, port))
|
||||
{
|
||||
while (_client && _client->state() < 4)
|
||||
delay(1);
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::_onConnect(AsyncClient *c)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
_tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
|
||||
|
||||
if (_tx_buffer)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
_attachCallbacks();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter::operator bool()
|
||||
{
|
||||
return connected();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter & AsyncPrinter::operator=(const AsyncPrinter &other)
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client->close(true);
|
||||
_client = NULL;
|
||||
}
|
||||
|
||||
_tx_buffer_size = other._tx_buffer_size;
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
_tx_buffer = new (std::nothrow) cbuf(other._tx_buffer_size);
|
||||
|
||||
if (_tx_buffer == NULL)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
_client = other._client;
|
||||
_attachCallbacks();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncPrinter::write(uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncPrinter::write(const uint8_t *data, size_t len)
|
||||
{
|
||||
if (_tx_buffer == NULL || !connected())
|
||||
return 0;
|
||||
|
||||
size_t toWrite = 0;
|
||||
size_t toSend = len;
|
||||
|
||||
while (_tx_buffer->room() < toSend)
|
||||
{
|
||||
toWrite = _tx_buffer->room();
|
||||
_tx_buffer->write((const char*)data, toWrite);
|
||||
|
||||
while (connected() && !_client->canSend())
|
||||
delay(0);
|
||||
|
||||
if (!connected())
|
||||
return 0; // or len - toSend;
|
||||
|
||||
_sendBuffer();
|
||||
toSend -= toWrite;
|
||||
}
|
||||
|
||||
_tx_buffer->write((const char*)(data + (len - toSend)), toSend);
|
||||
|
||||
while (connected() && !_client->canSend())
|
||||
delay(0);
|
||||
|
||||
if (!connected())
|
||||
return 0; // or len - toSend;
|
||||
|
||||
_sendBuffer();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool AsyncPrinter::connected()
|
||||
{
|
||||
return (_client != NULL && _client->connected());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::close()
|
||||
{
|
||||
if (_client != NULL)
|
||||
_client->close(true);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncPrinter::_sendBuffer()
|
||||
{
|
||||
size_t available = _tx_buffer->available();
|
||||
|
||||
if (!connected() || !_client->canSend() || available == 0)
|
||||
return 0;
|
||||
|
||||
size_t sendable = _client->space();
|
||||
|
||||
if (sendable < available)
|
||||
available = sendable;
|
||||
|
||||
char *out = new (std::nothrow) char[available];
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
panic(); // Connection should be aborted instead
|
||||
}
|
||||
|
||||
_tx_buffer->read(out, available);
|
||||
size_t sent = _client->write(out, available);
|
||||
delete out;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::_onData(void *data, size_t len)
|
||||
{
|
||||
if (_data_cb)
|
||||
_data_cb(_data_arg, this, (uint8_t*)data, len);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::_on_close()
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client = NULL;
|
||||
}
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
if (_close_cb)
|
||||
_close_cb(_close_arg, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::_attachCallbacks()
|
||||
{
|
||||
_client->onPoll([](void *obj, AsyncClient * c)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
((AsyncPrinter*)(obj))->_sendBuffer();
|
||||
}, this);
|
||||
|
||||
_client->onAck([](void *obj, AsyncClient * c, size_t len, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
RPAsyncTCP_UNUSED(len);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
|
||||
((AsyncPrinter*)(obj))->_sendBuffer();
|
||||
}, this);
|
||||
|
||||
_client->onDisconnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((AsyncPrinter*)(obj))->_on_close(); delete c;
|
||||
}, this);
|
||||
|
||||
_client->onData([](void *obj, AsyncClient * c, void *data, size_t len)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
((AsyncPrinter*)(obj))->_onData(data, len);
|
||||
}, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Asynchronous TCP library for Espressif MCUs
|
||||
|
||||
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ASYNCPRINTER_H_
|
||||
#define ASYNCPRINTER_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "RPAsyncTCP.h"
|
||||
#include "cbuf.h"
|
||||
|
||||
class AsyncPrinter;
|
||||
|
||||
typedef std::function<void(void*, AsyncPrinter*, uint8_t*, size_t)> ApDataHandler;
|
||||
typedef std::function<void(void*, AsyncPrinter*)> ApCloseHandler;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
class AsyncPrinter: public Print
|
||||
{
|
||||
private:
|
||||
AsyncClient *_client;
|
||||
ApDataHandler _data_cb;
|
||||
void *_data_arg;
|
||||
ApCloseHandler _close_cb;
|
||||
void *_close_arg;
|
||||
cbuf *_tx_buffer;
|
||||
size_t _tx_buffer_size;
|
||||
|
||||
void _onConnect(AsyncClient *c);
|
||||
|
||||
public:
|
||||
AsyncPrinter *next;
|
||||
|
||||
AsyncPrinter();
|
||||
AsyncPrinter(AsyncClient *client, size_t txBufLen = TCP_MSS);
|
||||
virtual ~AsyncPrinter();
|
||||
|
||||
int connect(IPAddress ip, uint16_t port);
|
||||
int connect(const char *host, uint16_t port);
|
||||
|
||||
void onData(ApDataHandler cb, void *arg);
|
||||
void onClose(ApCloseHandler cb, void *arg);
|
||||
|
||||
operator bool();
|
||||
AsyncPrinter & operator=(const AsyncPrinter &other);
|
||||
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *data, size_t len);
|
||||
|
||||
bool connected();
|
||||
void close();
|
||||
|
||||
size_t _sendBuffer();
|
||||
void _onData(void *data, size_t len);
|
||||
void _on_close();
|
||||
void _attachCallbacks();
|
||||
};
|
||||
|
||||
#endif /* ASYNCPRINTER_H_ */
|
||||
@@ -0,0 +1,127 @@
|
||||
#ifndef _DEBUG_PRINT_MACROS_H
|
||||
#define _DEBUG_PRINT_MACROS_H
|
||||
|
||||
// Some customizable print macros to suite the debug needs de jour.
|
||||
|
||||
// Debug macros
|
||||
// #include <pgmspace.h>
|
||||
// https://stackoverflow.com/questions/8487986/file-macro-shows-full-path
|
||||
// This value is resolved at compile time.
|
||||
#define _FILENAME_ strrchr("/" __FILE__, '/')
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_PORT) && !defined(DEBUG_TIME_STAMP_FMT)
|
||||
#define DEBUG_TIME_STAMP_FMT "%06u.%03u "
|
||||
|
||||
struct _DEBUG_TIME_STAMP
|
||||
{
|
||||
unsigned dec;
|
||||
unsigned whole;
|
||||
};
|
||||
|
||||
inline struct _DEBUG_TIME_STAMP debugTimeStamp()
|
||||
{
|
||||
struct _DEBUG_TIME_STAMP st;
|
||||
unsigned now = millis() % 1000000000;
|
||||
st.dec = now % 1000;
|
||||
st.whole = now / 1000;
|
||||
return st;
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_PORT) && !defined(DEBUG_GENERIC)
|
||||
#define DEBUG_GENERIC( module, format, ... ) \
|
||||
do { \
|
||||
struct _DEBUG_TIME_STAMP st = debugTimeStamp(); \
|
||||
DEBUG_ESP_PORT.printf( DEBUG_TIME_STAMP_FMT module " " format, st.whole, st.dec, ##__VA_ARGS__ ); \
|
||||
} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_PORT) && !defined(DEBUG_GENERIC_P)
|
||||
#define DEBUG_GENERIC_P( module, format, ... ) \
|
||||
do { \
|
||||
struct _DEBUG_TIME_STAMP st = debugTimeStamp(); \
|
||||
DEBUG_ESP_PORT.printf_P(PSTR( DEBUG_TIME_STAMP_FMT module " " format ), st.whole, st.dec, ##__VA_ARGS__ ); \
|
||||
} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_GENERIC) && !defined(ASSERT_GENERIC)
|
||||
#define ASSERT_GENERIC( a, module ) \
|
||||
do { \
|
||||
if ( !(a) ) { \
|
||||
DEBUG_GENERIC( module, "%s:%s:%u: ASSERT("#a") failed!\n", __FILE__, __func__, __LINE__); \
|
||||
DEBUG_ESP_PORT.flush(); \
|
||||
} \
|
||||
} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_GENERIC_P) && !defined(ASSERT_GENERIC_P)
|
||||
#define ASSERT_GENERIC_P( a, module ) \
|
||||
do { \
|
||||
if ( !(a) ) { \
|
||||
DEBUG_GENERIC_P( module, "%s:%s:%u: ASSERT("#a") failed!\n", __FILE__, __func__, __LINE__); \
|
||||
DEBUG_ESP_PORT.flush(); \
|
||||
} \
|
||||
} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DEBUG_GENERIC
|
||||
#define DEBUG_GENERIC(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DEBUG_GENERIC_P
|
||||
#define DEBUG_GENERIC_P(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ASSERT_GENERIC
|
||||
#define ASSERT_GENERIC(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ASSERT_GENERIC_P
|
||||
#define ASSERT_GENERIC_P(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DEBUG_ESP_PRINTF
|
||||
#define DEBUG_ESP_PRINTF( format, ...) DEBUG_GENERIC_P("[%s]", format, &_FILENAME_[1], ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_ASYNC_TCP) && !defined(ASYNC_TCP_DEBUG)
|
||||
#define ASYNC_TCP_DEBUG( format, ...) DEBUG_GENERIC_P("[ASYNC_TCP]", format, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ASYNC_TCP_ASSERT
|
||||
#define ASYNC_TCP_ASSERT( a ) ASSERT_GENERIC_P( (a), "[ASYNC_TCP]")
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_TCP_SSL) && !defined(TCP_SSL_DEBUG)
|
||||
#define TCP_SSL_DEBUG( format, ...) DEBUG_GENERIC_P("[TCP_SSL]", format, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#endif //_DEBUG_PRINT_MACROS_H
|
||||
2056
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/RPAsyncTCP.cpp
Normal file
2056
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/RPAsyncTCP.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,417 @@
|
||||
#ifndef RPAsyncTCP_H_
|
||||
#define RPAsyncTCP_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
#undef ASYNC_TCP_SSL_ENABLED
|
||||
#define ASYNC_TCP_SSL_ENABLED false
|
||||
|
||||
#warning ASYNC_TCP_SSL_ENABLED is not ready yet. Disable it
|
||||
#endif
|
||||
|
||||
#define DEBUG_ESP_ASYNC_TCP true
|
||||
#include "RPAsyncTCP_Debug.h"
|
||||
|
||||
#include <async_config.h>
|
||||
#include "IPAddress.h"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/pbuf.h"
|
||||
};
|
||||
|
||||
#ifndef RPAsyncTCP_UNUSED
|
||||
#define RPAsyncTCP_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
class AsyncClient;
|
||||
class AsyncServer;
|
||||
class ACErrorTracker;
|
||||
|
||||
#define ASYNC_MAX_ACK_TIME 5000
|
||||
#define ASYNC_WRITE_FLAG_COPY 0x01 //to allocate new buffer to hold the data while sending
|
||||
#define ASYNC_WRITE_FLAG_MORE 0x02 //not send PSH flag. More data to be sent before the application should react.
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
struct tcp_pcb;
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
struct SSL_;
|
||||
typedef struct SSL_ SSL;
|
||||
struct SSL_CTX_;
|
||||
typedef struct SSL_CTX_ SSL_CTX;
|
||||
#endif
|
||||
|
||||
typedef std::function<void(void*, AsyncClient*)> AcConnectHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, size_t len, uint32_t time)> AcAckHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, err_t error)> AcErrorHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, void *data, size_t len)> AcDataHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, struct pbuf *pb)> AcPacketHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, uint32_t time)> AcTimeoutHandler;
|
||||
typedef std::function<void(void*, size_t event)> AsNotifyHandler;
|
||||
|
||||
enum error_events
|
||||
{
|
||||
EE_OK = 0,
|
||||
EE_ABORTED, // Callback or foreground aborted connections
|
||||
EE_ERROR_CB, // Stack initiated aborts via error Callbacks.
|
||||
EE_CONNECTED_CB,
|
||||
EE_RECV_CB,
|
||||
EE_ACCEPT_CB,
|
||||
EE_MAX
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
// DEBUG_MORE is for gathering more information on which CBs close events are
|
||||
// occuring and count.
|
||||
// #define DEBUG_MORE 1
|
||||
class ACErrorTracker
|
||||
{
|
||||
private:
|
||||
AsyncClient *_client;
|
||||
err_t _close_error;
|
||||
int _errored;
|
||||
|
||||
#if DEBUG_ESP_ASYNC_TCP
|
||||
size_t _connectionId;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
AsNotifyHandler _error_event_cb;
|
||||
void* _error_event_cb_arg;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend class AsyncClient;
|
||||
friend class AsyncServer;
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
void onErrorEvent(AsNotifyHandler cb, void *arg);
|
||||
#endif
|
||||
|
||||
#if DEBUG_ESP_ASYNC_TCP
|
||||
void setConnectionId(size_t id)
|
||||
{
|
||||
_connectionId = id;
|
||||
}
|
||||
|
||||
size_t getConnectionId()
|
||||
{
|
||||
return _connectionId;
|
||||
}
|
||||
#endif
|
||||
|
||||
void setCloseError(err_t e);
|
||||
void setErrored(size_t errorEvent);
|
||||
err_t getCallbackCloseError();
|
||||
|
||||
void clearClient()
|
||||
{
|
||||
if (_client) _client = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
err_t getCloseError() const
|
||||
{
|
||||
return _close_error;
|
||||
}
|
||||
|
||||
bool hasClient() const
|
||||
{
|
||||
return (_client != NULL);
|
||||
}
|
||||
|
||||
ACErrorTracker(AsyncClient *c);
|
||||
~ACErrorTracker() {}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
class AsyncClient
|
||||
{
|
||||
protected:
|
||||
friend class AsyncTCPbuffer;
|
||||
friend class AsyncServer;
|
||||
tcp_pcb* _pcb;
|
||||
AcConnectHandler _connect_cb;
|
||||
void* _connect_cb_arg;
|
||||
AcConnectHandler _discard_cb;
|
||||
void* _discard_cb_arg;
|
||||
AcAckHandler _sent_cb;
|
||||
void* _sent_cb_arg;
|
||||
AcErrorHandler _error_cb;
|
||||
void* _error_cb_arg;
|
||||
AcDataHandler _recv_cb;
|
||||
void* _recv_cb_arg;
|
||||
AcPacketHandler _pb_cb;
|
||||
void* _pb_cb_arg;
|
||||
AcTimeoutHandler _timeout_cb;
|
||||
void* _timeout_cb_arg;
|
||||
AcConnectHandler _poll_cb;
|
||||
void* _poll_cb_arg;
|
||||
bool _pcb_busy;
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
bool _pcb_secure;
|
||||
bool _handshake_done;
|
||||
#endif
|
||||
|
||||
uint32_t _pcb_sent_at;
|
||||
bool _close_pcb;
|
||||
bool _ack_pcb;
|
||||
uint32_t _tx_unacked_len;
|
||||
uint32_t _tx_acked_len;
|
||||
uint32_t _tx_unsent_len;
|
||||
uint32_t _rx_ack_len;
|
||||
uint32_t _rx_last_packet;
|
||||
uint32_t _rx_since_timeout;
|
||||
uint32_t _ack_timeout;
|
||||
uint16_t _connect_port;
|
||||
u8_t _recv_pbuf_flags;
|
||||
std::shared_ptr<ACErrorTracker> _errorTracker;
|
||||
|
||||
void _close();
|
||||
void _connected(std::shared_ptr<ACErrorTracker>& closeAbort, void* pcb, err_t err);
|
||||
void _error(err_t err);
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
void _ssl_error(int8_t err);
|
||||
#endif
|
||||
|
||||
void _poll(std::shared_ptr<ACErrorTracker>& closeAbort, tcp_pcb* pcb);
|
||||
void _sent(std::shared_ptr<ACErrorTracker>& closeAbort, tcp_pcb* pcb, uint16_t len);
|
||||
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
void _dns_found(struct ip_addr *ipaddr);
|
||||
#else
|
||||
void _dns_found(ip_addr_t *p);
|
||||
#endif
|
||||
|
||||
static err_t _s_poll(void *arg, struct tcp_pcb *tpcb);
|
||||
static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err);
|
||||
static void _s_error(void *arg, err_t err);
|
||||
static err_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
|
||||
static err_t _s_connected(void* arg, void* tpcb, err_t err);
|
||||
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
|
||||
#else
|
||||
static void _s_dns_found(const char *name, ip_addr_t *p, void *arg);
|
||||
#endif
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
static void _s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len);
|
||||
static void _s_handshake(void *arg, struct tcp_pcb *tcp, SSL *ssl);
|
||||
static void _s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err);
|
||||
#endif
|
||||
|
||||
std::shared_ptr<ACErrorTracker> getACErrorTracker() const
|
||||
{
|
||||
return _errorTracker;
|
||||
};
|
||||
|
||||
void setCloseError(err_t e) const
|
||||
{
|
||||
_errorTracker->setCloseError(e);
|
||||
}
|
||||
|
||||
public:
|
||||
AsyncClient* prev;
|
||||
AsyncClient* next;
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
AsyncClient(tcp_pcb* pcb = 0, SSL_CTX * ssl_ctx = NULL);
|
||||
#else
|
||||
AsyncClient(tcp_pcb* pcb = 0);
|
||||
#endif
|
||||
|
||||
~AsyncClient();
|
||||
|
||||
AsyncClient & operator=(const AsyncClient &other);
|
||||
AsyncClient & operator+=(const AsyncClient &other);
|
||||
|
||||
bool operator==(const AsyncClient &other) const;
|
||||
|
||||
bool operator!=(const AsyncClient &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
bool connect(IPAddress ip, uint16_t port, bool secure = false);
|
||||
bool connect(const char* host, uint16_t port, bool secure = false);
|
||||
#else
|
||||
bool connect(IPAddress ip, uint16_t port);
|
||||
bool connect(const char* host, uint16_t port);
|
||||
#endif
|
||||
|
||||
void close(bool now = false);
|
||||
void stop();
|
||||
void abort();
|
||||
bool free();
|
||||
|
||||
bool canSend() const;//ack is not pending
|
||||
size_t space() const;
|
||||
size_t add(const char* data, size_t size, uint8_t apiflags = 0); //add for sending
|
||||
bool send();//send all data added with the method above
|
||||
size_t ack(size_t len); //ack data that you have not acked using the method below
|
||||
|
||||
void ackLater()
|
||||
{
|
||||
_ack_pcb = false; //will not ack the current packet. Call from onData
|
||||
}
|
||||
|
||||
bool isRecvPush()
|
||||
{
|
||||
return !!(_recv_pbuf_flags & PBUF_FLAG_PUSH);
|
||||
}
|
||||
|
||||
#if DEBUG_ESP_ASYNC_TCP
|
||||
size_t getConnectionId() const
|
||||
{
|
||||
return _errorTracker->getConnectionId();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
SSL *getSSL();
|
||||
#endif
|
||||
|
||||
size_t write(const char* data);
|
||||
size_t write(const char* data, size_t size, uint8_t apiflags = 0); //only when canSend() == true
|
||||
|
||||
uint8_t state() const;
|
||||
bool connecting() const;
|
||||
bool connected() const;
|
||||
bool disconnecting() const;
|
||||
bool disconnected() const;
|
||||
bool freeable() const;//disconnected or disconnecting
|
||||
|
||||
uint16_t getMss() const;
|
||||
uint32_t getRxTimeout() const;
|
||||
void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds
|
||||
uint32_t getAckTimeout() const;
|
||||
void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds
|
||||
void setNoDelay(bool nodelay);
|
||||
bool getNoDelay() const;
|
||||
uint32_t getRemoteAddress() const;
|
||||
uint16_t getRemotePort() const;
|
||||
uint32_t getLocalAddress() const;
|
||||
uint16_t getLocalPort() const;
|
||||
|
||||
IPAddress remoteIP() const;
|
||||
uint16_t remotePort() const;
|
||||
IPAddress localIP() const;
|
||||
uint16_t localPort() const;
|
||||
|
||||
void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect
|
||||
void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected
|
||||
void onAck(AcAckHandler cb, void* arg = 0); //ack received
|
||||
void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error
|
||||
void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used)
|
||||
void onPacket(AcPacketHandler cb, void* arg = 0); //data received
|
||||
void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout
|
||||
void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected
|
||||
void ackPacket(struct pbuf * pb);
|
||||
|
||||
const char * errorToString(err_t error) const;
|
||||
const char * stateToString() const;
|
||||
|
||||
void _recv(std::shared_ptr<ACErrorTracker>& closeAbort, tcp_pcb* pcb, pbuf* pb, err_t err);
|
||||
|
||||
err_t getCloseError() const
|
||||
{
|
||||
return _errorTracker->getCloseError();
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
typedef std::function<int(void* arg, const char *filename, uint8_t **buf)> AcSSlFileHandler;
|
||||
struct pending_pcb;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
class AsyncServer
|
||||
{
|
||||
protected:
|
||||
uint16_t _port;
|
||||
IPAddress _addr;
|
||||
bool _noDelay;
|
||||
tcp_pcb* _pcb;
|
||||
AcConnectHandler _connect_cb;
|
||||
void* _connect_cb_arg;
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
struct pending_pcb * _pending;
|
||||
SSL_CTX * _ssl_ctx;
|
||||
AcSSlFileHandler _file_cb;
|
||||
void* _file_cb_arg;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
int _event_count[EE_MAX];
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
AsyncServer(IPAddress addr, uint16_t port);
|
||||
AsyncServer(uint16_t port);
|
||||
~AsyncServer();
|
||||
void onClient(AcConnectHandler cb, void* arg);
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
void onSslFileRequest(AcSSlFileHandler cb, void* arg);
|
||||
void beginSecure(const char *cert, const char *private_key_file, const char *password);
|
||||
#endif
|
||||
|
||||
void begin();
|
||||
void end();
|
||||
void setNoDelay(bool nodelay);
|
||||
bool getNoDelay() const;
|
||||
uint8_t status() const;
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
int getEventCount(size_t ee) const
|
||||
{
|
||||
return _event_count[ee];
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
err_t _accept(tcp_pcb* newpcb, err_t err);
|
||||
static err_t _s_accept(void *arg, tcp_pcb* newpcb, err_t err);
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
int incEventCount(size_t ee)
|
||||
{
|
||||
return ++_event_count[ee];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
int _cert(const char *filename, uint8_t **buf);
|
||||
err_t _poll(tcp_pcb* pcb);
|
||||
err_t _recv(tcp_pcb *pcb, struct pbuf *pb, err_t err);
|
||||
static int _s_cert(void *arg, const char *filename, uint8_t **buf);
|
||||
static err_t _s_poll(void *arg, struct tcp_pcb *tpcb);
|
||||
static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err);
|
||||
#endif
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
#endif /* RPAsyncTCP_H_ */
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef RPAsyncTCP_DEBUG_H
|
||||
#define RPAsyncTCP_DEBUG_H
|
||||
|
||||
#ifdef RPAsyncTCP_DEBUG_PORT
|
||||
#define DBG_PORT_ATCP RPAsyncTCP_DEBUG_PORT
|
||||
#else
|
||||
#define DBG_PORT_ATCP Serial
|
||||
#endif
|
||||
|
||||
// Change _RPAsyncTCP_LOGLEVEL_ to set tracing and logging verbosity
|
||||
// 0: DISABLED: no logging
|
||||
// 1: ERROR: errors
|
||||
// 2: WARN: errors and warnings
|
||||
// 3: INFO: errors, warnings and informational (default)
|
||||
// 4: DEBUG: errors, warnings, informational and debug
|
||||
|
||||
#ifndef _RPAsyncTCP_LOGLEVEL_
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_PRINT_MARK ATCP_PRINT("[ATCP] ")
|
||||
#define ATCP_PRINT_SP DBG_PORT_ATCP.print(" ")
|
||||
|
||||
#define ATCP_PRINT DBG_PORT_ATCP.print
|
||||
#define ATCP_PRINTLN DBG_PORT_ATCP.println
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_LOGERROR(x) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT_MARK; ATCP_PRINTLN(x); }
|
||||
#define ATCP_LOGERROR0(x) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT(x); }
|
||||
#define ATCP_LOGERROR1(x,y) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINTLN(y); }
|
||||
#define ATCP_LOGERROR2(x,y,z) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINTLN(z); }
|
||||
#define ATCP_LOGERROR3(x,y,z,w) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINT(z); ATCP_PRINT_SP; ATCP_PRINTLN(w); }
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_LOGWARN(x) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT_MARK; ATCP_PRINTLN(x); }
|
||||
#define ATCP_LOGWARN0(x) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT(x); }
|
||||
#define ATCP_LOGWARN1(x,y) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINTLN(y); }
|
||||
#define ATCP_LOGWARN2(x,y,z) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINTLN(z); }
|
||||
#define ATCP_LOGWARN3(x,y,z,w) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINT(z); ATCP_PRINT_SP; ATCP_PRINTLN(w); }
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_LOGINFO(x) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT_MARK; ATCP_PRINTLN(x); }
|
||||
#define ATCP_LOGINFO0(x) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT(x); }
|
||||
#define ATCP_LOGINFO1(x,y) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINTLN(y); }
|
||||
#define ATCP_LOGINFO2(x,y,z) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINTLN(z); }
|
||||
#define ATCP_LOGINFO3(x,y,z,w) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINT(z); ATCP_PRINT_SP; ATCP_PRINTLN(w); }
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_LOGDEBUG(x) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT_MARK; ATCP_PRINTLN(x); }
|
||||
#define ATCP_LOGDEBUG0(x) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT(x); }
|
||||
#define ATCP_LOGDEBUG1(x,y) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINTLN(y); }
|
||||
#define ATCP_LOGDEBUG2(x,y,z) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINTLN(z); }
|
||||
#define ATCP_LOGDEBUG3(x,y,z,w) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINT(z); ATCP_PRINT_SP; ATCP_PRINTLN(w); }
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#endif //RPAsyncTCP_DEBUG_H
|
||||
@@ -0,0 +1,721 @@
|
||||
#include <Arduino.h>
|
||||
#include "debug.h"
|
||||
|
||||
#if !defined(_RPAsyncTCP_LOGLEVEL_)
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
#include "RPAsyncTCP_buffer.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncTCPbuffer::AsyncTCPbuffer(AsyncClient* client)
|
||||
{
|
||||
if (client == NULL)
|
||||
{
|
||||
ATCP_LOGDEBUG("client is null!!!");
|
||||
panic();
|
||||
}
|
||||
|
||||
_client = client;
|
||||
_TXbufferWrite = new (std::nothrow) cbuf(TCP_MSS);
|
||||
_TXbufferRead = _TXbufferWrite;
|
||||
_RXbuffer = new (std::nothrow) cbuf(100);
|
||||
_RXmode = ATB_RX_MODE_FREE;
|
||||
_rxSize = 0;
|
||||
_rxTerminator = 0x00;
|
||||
_rxReadBytesPtr = NULL;
|
||||
_rxReadStringPtr = NULL;
|
||||
_cbDisconnect = NULL;
|
||||
|
||||
_cbRX = NULL;
|
||||
_cbDone = NULL;
|
||||
_attachCallbacks();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncTCPbuffer::~AsyncTCPbuffer()
|
||||
{
|
||||
if (_client)
|
||||
{
|
||||
_client->close();
|
||||
}
|
||||
|
||||
if (_RXbuffer)
|
||||
{
|
||||
delete _RXbuffer;
|
||||
_RXbuffer = NULL;
|
||||
}
|
||||
|
||||
if (_TXbufferWrite)
|
||||
{
|
||||
// will be deleted in _TXbufferRead chain
|
||||
_TXbufferWrite = NULL;
|
||||
}
|
||||
|
||||
if (_TXbufferRead)
|
||||
{
|
||||
cbuf * next = _TXbufferRead->next;
|
||||
delete _TXbufferRead;
|
||||
|
||||
while (next != NULL)
|
||||
{
|
||||
_TXbufferRead = next;
|
||||
next = _TXbufferRead->next;
|
||||
delete _TXbufferRead;
|
||||
}
|
||||
|
||||
_TXbufferRead = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::write(String & data)
|
||||
{
|
||||
return write(data.c_str(), data.length());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::write(uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::write(const char* data)
|
||||
{
|
||||
return write((const uint8_t *) data, strlen(data));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::write(const char *data, size_t len)
|
||||
{
|
||||
return write((const uint8_t *) data, len);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
write data in to buffer and try to send the data
|
||||
@param data
|
||||
@param len
|
||||
@return
|
||||
*/
|
||||
size_t AsyncTCPbuffer::write(const uint8_t *data, size_t len)
|
||||
{
|
||||
if (_TXbufferWrite == NULL || _client == NULL || !_client->connected() || data == NULL || len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t bytesLeft = len;
|
||||
|
||||
while (bytesLeft)
|
||||
{
|
||||
size_t w = _TXbufferWrite->write((const char*) data, bytesLeft);
|
||||
bytesLeft -= w;
|
||||
data += w;
|
||||
|
||||
_sendBuffer();
|
||||
|
||||
// add new buffer since we have more data
|
||||
if (_TXbufferWrite->full() && bytesLeft > 0)
|
||||
{
|
||||
/*
|
||||
// to less ram!!!
|
||||
if(ESP.getFreeHeap() < 4096) {
|
||||
ATCP_LOGDEBUG("run out of Heap can not send all Data!");
|
||||
return (len - bytesLeft);
|
||||
}
|
||||
*/
|
||||
cbuf * next = new (std::nothrow) cbuf(TCP_MSS);
|
||||
|
||||
if (next == NULL)
|
||||
{
|
||||
ATCP_LOGDEBUG("run out of Heap!");
|
||||
panic();
|
||||
}
|
||||
else
|
||||
{
|
||||
ATCP_LOGDEBUG("new cbuf");
|
||||
}
|
||||
|
||||
// add new buffer to chain (current cbuf)
|
||||
_TXbufferWrite->next = next;
|
||||
|
||||
// move ptr for next data
|
||||
_TXbufferWrite = next;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
wait until all data has send out
|
||||
*/
|
||||
void AsyncTCPbuffer::flush()
|
||||
{
|
||||
while (!_TXbufferWrite->empty())
|
||||
{
|
||||
while (connected() && !_client->canSend())
|
||||
{
|
||||
delay(0);
|
||||
}
|
||||
|
||||
if (!connected())
|
||||
return;
|
||||
_sendBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::noCallback()
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::readStringUntil(char terminator, String * str, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
if (_client == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG1("readStringUntil terminator:", terminator);
|
||||
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone = done;
|
||||
_rxReadStringPtr = str;
|
||||
_rxTerminator = terminator;
|
||||
_rxSize = 0;
|
||||
_RXmode = ATB_RX_MODE_TERMINATOR_STRING;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
void AsyncTCPbuffer::readBytesUntil(char terminator, char *buffer, size_t length, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone = done;
|
||||
_rxReadBytesPtr = (uint8_t *) buffer;
|
||||
_rxTerminator = terminator;
|
||||
_rxSize = length;
|
||||
_RXmode = ATB_RX_MODE_TERMINATOR;
|
||||
_handleRxBuffer(NULL, 0);
|
||||
}
|
||||
|
||||
void AsyncTCPbuffer::readBytesUntil(char terminator, uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
readBytesUntil(terminator, (char *) buffer, length, done);
|
||||
}
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::readBytes(char *buffer, size_t length, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
if (_client == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG1("readBytes length:", length);
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone = done;
|
||||
_rxReadBytesPtr = (uint8_t *) buffer;
|
||||
_rxSize = length;
|
||||
_RXmode = ATB_RX_MODE_READ_BYTES;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::readBytes(uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
readBytes((char *) buffer, length, done);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::onData(AsyncTCPbufferDataCb cb)
|
||||
{
|
||||
if (_client == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG("onData");
|
||||
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone = NULL;
|
||||
_cbRX = cb;
|
||||
_RXmode = ATB_RX_MODE_FREE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::onDisconnect(AsyncTCPbufferDisconnectCb cb)
|
||||
{
|
||||
_cbDisconnect = cb;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
IPAddress AsyncTCPbuffer::remoteIP()
|
||||
{
|
||||
if (!_client)
|
||||
{
|
||||
return IPAddress(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return _client->remoteIP();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
uint16_t AsyncTCPbuffer::remotePort()
|
||||
{
|
||||
if (!_client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _client->remotePort();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool AsyncTCPbuffer::connected()
|
||||
{
|
||||
if (!_client)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _client->connected();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::stop()
|
||||
{
|
||||
|
||||
if (!_client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_client->stop();
|
||||
_client = NULL;
|
||||
|
||||
if (_cbDone)
|
||||
{
|
||||
switch (_RXmode)
|
||||
{
|
||||
case ATB_RX_MODE_READ_BYTES:
|
||||
case ATB_RX_MODE_TERMINATOR:
|
||||
case ATB_RX_MODE_TERMINATOR_STRING:
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone(false, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::close()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
attachCallbacks to AsyncClient class
|
||||
*/
|
||||
void AsyncTCPbuffer::_attachCallbacks()
|
||||
{
|
||||
if (!_client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG("attachCallbacks");
|
||||
|
||||
_client->onPoll([](void *obj, AsyncClient * c)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
AsyncTCPbuffer* b = ((AsyncTCPbuffer*)(obj));
|
||||
|
||||
if ((b->_TXbufferRead != NULL) && !b->_TXbufferRead->empty())
|
||||
{
|
||||
b->_sendBuffer();
|
||||
}
|
||||
|
||||
// if(!b->_RXbuffer->empty()) {
|
||||
// b->_handleRxBuffer(NULL, 0);
|
||||
// }
|
||||
}, this);
|
||||
|
||||
_client->onAck([](void *obj, AsyncClient * c, size_t len, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
RPAsyncTCP_UNUSED(len);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
ATCP_LOGDEBUG("onAck");
|
||||
((AsyncTCPbuffer*)(obj))->_sendBuffer();
|
||||
}, this);
|
||||
|
||||
_client->onDisconnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
ATCP_LOGDEBUG("onDisconnect");
|
||||
AsyncTCPbuffer* b = ((AsyncTCPbuffer*)(obj));
|
||||
b->_client = NULL;
|
||||
bool del = true;
|
||||
|
||||
if (b->_cbDisconnect)
|
||||
{
|
||||
del = b->_cbDisconnect(b);
|
||||
}
|
||||
|
||||
delete c;
|
||||
|
||||
if (del)
|
||||
{
|
||||
delete b;
|
||||
}
|
||||
}, this);
|
||||
|
||||
_client->onData([](void *obj, AsyncClient * c, void *buf, size_t len)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
AsyncTCPbuffer* b = ((AsyncTCPbuffer*)(obj));
|
||||
b->_rxData((uint8_t *)buf, len);
|
||||
}, this);
|
||||
|
||||
_client->onTimeout([](void *obj, AsyncClient * c, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(obj);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
|
||||
ATCP_LOGDEBUG("onTimeout");
|
||||
|
||||
c->close();
|
||||
}, this);
|
||||
|
||||
ATCP_LOGDEBUG("attachCallbacks Done.");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
send TX buffer if possible
|
||||
*/
|
||||
void AsyncTCPbuffer::_sendBuffer()
|
||||
{
|
||||
//ATCP_LOGDEBUG("_sendBuffer...");
|
||||
size_t available = _TXbufferRead->available();
|
||||
|
||||
if (available == 0 || _client == NULL || !_client->connected() || !_client->canSend())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (connected() && (_client->space() > 0) && (_TXbufferRead->available() > 0) && _client->canSend())
|
||||
{
|
||||
available = _TXbufferRead->available();
|
||||
|
||||
if (available > _client->space())
|
||||
{
|
||||
available = _client->space();
|
||||
}
|
||||
|
||||
char *out = new (std::nothrow) char[available];
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
ATCP_LOGDEBUG("to less heap, try later.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// read data from buffer
|
||||
_TXbufferRead->peek(out, available);
|
||||
|
||||
// send data
|
||||
size_t send = _client->write((const char*) out, available);
|
||||
|
||||
if (send != available)
|
||||
{
|
||||
ATCP_LOGDEBUG3("_sendBuffer write failed send:", send, ", available:", available);
|
||||
|
||||
if (!connected())
|
||||
{
|
||||
ATCP_LOGDEBUG("incomplete transfer, connection lost.");
|
||||
}
|
||||
}
|
||||
|
||||
// remove really send data from buffer
|
||||
_TXbufferRead->remove(send);
|
||||
|
||||
// if buffer is empty and there is a other buffer in chain delete the empty one
|
||||
if (_TXbufferRead->available() == 0 && _TXbufferRead->next != NULL)
|
||||
{
|
||||
cbuf * old = _TXbufferRead;
|
||||
_TXbufferRead = _TXbufferRead->next;
|
||||
delete old;
|
||||
|
||||
ATCP_LOGDEBUG("delete cbuf");
|
||||
}
|
||||
|
||||
delete[] out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
called on incoming data
|
||||
@param buf
|
||||
@param len
|
||||
*/
|
||||
void AsyncTCPbuffer::_rxData(uint8_t *buf, size_t len)
|
||||
{
|
||||
if (!_client || !_client->connected())
|
||||
{
|
||||
ATCP_LOGDEBUG("not connected!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_RXbuffer)
|
||||
{
|
||||
ATCP_LOGDEBUG("_rxData no _RXbuffer!");
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG3("_rxData len:", len, ", RXmode:", _RXmode);
|
||||
|
||||
size_t handled = 0;
|
||||
|
||||
if (_RXmode != ATB_RX_MODE_NONE)
|
||||
{
|
||||
handled = _handleRxBuffer((uint8_t *) buf, len);
|
||||
buf += handled;
|
||||
len -= handled;
|
||||
|
||||
// handle as much as possible before using the buffer
|
||||
if (_RXbuffer->empty())
|
||||
{
|
||||
while (_RXmode != ATB_RX_MODE_NONE && handled != 0 && len > 0)
|
||||
{
|
||||
handled = _handleRxBuffer(buf, len);
|
||||
buf += handled;
|
||||
len -= handled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
|
||||
if (_RXbuffer->room() < len)
|
||||
{
|
||||
// to less space
|
||||
ATCP_LOGDEBUG("_rxData buffer full try resize");
|
||||
_RXbuffer->resizeAdd((len + _RXbuffer->room()));
|
||||
|
||||
if (_RXbuffer->room() < len)
|
||||
{
|
||||
ATCP_LOGDEBUG1("_rxData buffer to full can only handle:", _RXbuffer->room());
|
||||
}
|
||||
}
|
||||
|
||||
_RXbuffer->write((const char *) (buf), len);
|
||||
}
|
||||
|
||||
if (!_RXbuffer->empty() && _RXmode != ATB_RX_MODE_NONE)
|
||||
{
|
||||
// handle as much as possible data in buffer
|
||||
handled = _handleRxBuffer(NULL, 0);
|
||||
|
||||
while (_RXmode != ATB_RX_MODE_NONE && handled != 0)
|
||||
{
|
||||
handled = _handleRxBuffer(NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// clean up ram
|
||||
if (_RXbuffer->empty() && _RXbuffer->room() != 100)
|
||||
{
|
||||
_RXbuffer->resize(100);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::_handleRxBuffer(uint8_t *buf, size_t len)
|
||||
{
|
||||
if (!_client || !_client->connected() || _RXbuffer == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG3("_handleRxBuffer len:", len, ", RXmode:", _RXmode);
|
||||
|
||||
size_t BufferAvailable = _RXbuffer->available();
|
||||
size_t r = 0;
|
||||
|
||||
if (_RXmode == ATB_RX_MODE_NONE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (_RXmode == ATB_RX_MODE_FREE)
|
||||
{
|
||||
if (_cbRX == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BufferAvailable > 0)
|
||||
{
|
||||
uint8_t * b = new (std::nothrow) uint8_t[BufferAvailable];
|
||||
|
||||
if (b == NULL)
|
||||
{
|
||||
panic(); //TODO: What action should this be ?
|
||||
}
|
||||
|
||||
_RXbuffer->peek((char *) b, BufferAvailable);
|
||||
r = _cbRX(b, BufferAvailable);
|
||||
_RXbuffer->remove(r);
|
||||
}
|
||||
|
||||
if (r == BufferAvailable && buf && (len > 0))
|
||||
{
|
||||
return _cbRX(buf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
else if (_RXmode == ATB_RX_MODE_READ_BYTES)
|
||||
{
|
||||
if (_rxReadBytesPtr == NULL || _cbDone == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t newReadCount = 0;
|
||||
|
||||
if (BufferAvailable)
|
||||
{
|
||||
r = _RXbuffer->read((char *) _rxReadBytesPtr, _rxSize);
|
||||
_rxSize -= r;
|
||||
_rxReadBytesPtr += r;
|
||||
}
|
||||
|
||||
if (_RXbuffer->empty() && (len > 0) && buf)
|
||||
{
|
||||
r = len;
|
||||
|
||||
if (r > _rxSize)
|
||||
{
|
||||
r = _rxSize;
|
||||
}
|
||||
|
||||
memcpy(_rxReadBytesPtr, buf, r);
|
||||
_rxReadBytesPtr += r;
|
||||
_rxSize -= r;
|
||||
newReadCount += r;
|
||||
}
|
||||
|
||||
if (_rxSize == 0)
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone(true, NULL);
|
||||
}
|
||||
|
||||
// add left over bytes to Buffer
|
||||
return newReadCount;
|
||||
|
||||
}
|
||||
else if (_RXmode == ATB_RX_MODE_TERMINATOR)
|
||||
{
|
||||
// TODO implement read terminator non string
|
||||
|
||||
}
|
||||
else if (_RXmode == ATB_RX_MODE_TERMINATOR_STRING)
|
||||
{
|
||||
if (_rxReadStringPtr == NULL || _cbDone == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// handle Buffer
|
||||
if (BufferAvailable > 0)
|
||||
{
|
||||
while (!_RXbuffer->empty())
|
||||
{
|
||||
char c = _RXbuffer->read();
|
||||
|
||||
if (c == _rxTerminator || c == 0x00)
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone(true, _rxReadStringPtr);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*_rxReadStringPtr) += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_RXbuffer->empty() && (len > 0) && buf)
|
||||
{
|
||||
size_t newReadCount = 0;
|
||||
|
||||
while (newReadCount < len)
|
||||
{
|
||||
char c = (char) * buf;
|
||||
buf++;
|
||||
newReadCount++;
|
||||
|
||||
if (c == _rxTerminator || c == 0x00)
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone(true, _rxReadStringPtr);
|
||||
return newReadCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*_rxReadStringPtr) += c;
|
||||
}
|
||||
}
|
||||
|
||||
return newReadCount;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#ifndef RPAsyncTCP_BUFFER_H_
|
||||
#define RPAsyncTCP_BUFFER_H_
|
||||
|
||||
#ifndef DEBUG_ASYNC_TCP
|
||||
#define DEBUG_ASYNC_TCP(...)
|
||||
#endif
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <cbuf.h>
|
||||
|
||||
#include "RPAsyncTCP.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATB_RX_MODE_NONE,
|
||||
ATB_RX_MODE_FREE,
|
||||
ATB_RX_MODE_READ_BYTES,
|
||||
ATB_RX_MODE_TERMINATOR,
|
||||
ATB_RX_MODE_TERMINATOR_STRING
|
||||
} atbRxMode_t;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
class AsyncTCPbuffer: public Print
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef std::function<size_t(uint8_t * payload, size_t length)> AsyncTCPbufferDataCb;
|
||||
typedef std::function<void(bool ok, void * ret)> AsyncTCPbufferDoneCb;
|
||||
typedef std::function<bool(AsyncTCPbuffer * obj)> AsyncTCPbufferDisconnectCb;
|
||||
|
||||
AsyncTCPbuffer(AsyncClient* c);
|
||||
virtual ~AsyncTCPbuffer();
|
||||
|
||||
size_t write(String & data);
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const char* data);
|
||||
size_t write(const char *data, size_t len);
|
||||
size_t write(const uint8_t *data, size_t len);
|
||||
|
||||
void flush();
|
||||
|
||||
void noCallback();
|
||||
|
||||
void readStringUntil(char terminator, String * str, AsyncTCPbufferDoneCb done);
|
||||
|
||||
// TODO implement read terminator non string
|
||||
//void readBytesUntil(char terminator, char *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||
//void readBytesUntil(char terminator, uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||
|
||||
void readBytes(char *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||
void readBytes(uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||
|
||||
// TODO implement
|
||||
// void setTimeout(size_t timeout);
|
||||
|
||||
void onData(AsyncTCPbufferDataCb cb);
|
||||
void onDisconnect(AsyncTCPbufferDisconnectCb cb);
|
||||
|
||||
IPAddress remoteIP();
|
||||
uint16_t remotePort();
|
||||
IPAddress localIP();
|
||||
uint16_t localPort();
|
||||
|
||||
bool connected();
|
||||
|
||||
void stop();
|
||||
void close();
|
||||
|
||||
protected:
|
||||
AsyncClient* _client;
|
||||
cbuf * _TXbufferRead;
|
||||
cbuf * _TXbufferWrite;
|
||||
cbuf * _RXbuffer;
|
||||
atbRxMode_t _RXmode;
|
||||
size_t _rxSize;
|
||||
char _rxTerminator;
|
||||
uint8_t * _rxReadBytesPtr;
|
||||
String * _rxReadStringPtr;
|
||||
|
||||
AsyncTCPbufferDataCb _cbRX;
|
||||
AsyncTCPbufferDoneCb _cbDone;
|
||||
AsyncTCPbufferDisconnectCb _cbDisconnect;
|
||||
|
||||
void _attachCallbacks();
|
||||
void _sendBuffer();
|
||||
void _on_close();
|
||||
void _rxData(uint8_t *buf, size_t len);
|
||||
size_t _handleRxBuffer(uint8_t *buf, size_t len);
|
||||
};
|
||||
|
||||
#endif /* RPAsyncTCP_BUFFER_H_ */
|
||||
@@ -0,0 +1,615 @@
|
||||
#if !defined(_RPAsyncTCP_LOGLEVEL_)
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "SyncClient.h"
|
||||
#include "RPAsyncTCP.h"
|
||||
#include "cbuf.h"
|
||||
|
||||
#define DEBUG_ESP_SYNC_CLIENT
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_SYNC_CLIENT) && !defined(SYNC_CLIENT_DEBUG)
|
||||
#define SYNC_CLIENT_DEBUG( format, ...) DEBUG_GENERIC_P("[SYNC_CLIENT]", format, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SYNC_CLIENT_DEBUG
|
||||
#define SYNC_CLIENT_DEBUG(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
Without LWIP_NETIF_TX_SINGLE_PBUF, all tcp_writes default to "no copy".
|
||||
Referenced data must be preserved and free-ed from the specified tcp_sent()
|
||||
callback. Alternative, tcp_writes need to use the TCP_WRITE_FLAG_COPY
|
||||
attribute.
|
||||
*/
|
||||
static_assert(LWIP_NETIF_TX_SINGLE_PBUF, "Required, tcp_write() must always copy.");
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SyncClient::SyncClient(size_t txBufLen)
|
||||
: _client(NULL)
|
||||
, _tx_buffer(NULL)
|
||||
, _tx_buffer_size(txBufLen)
|
||||
, _rx_buffer(NULL)
|
||||
, _ref(NULL)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SyncClient::SyncClient(AsyncClient *client, size_t txBufLen)
|
||||
: _client(client)
|
||||
, _tx_buffer(new (std::nothrow) cbuf(txBufLen))
|
||||
, _tx_buffer_size(txBufLen)
|
||||
, _rx_buffer(NULL)
|
||||
, _ref(NULL)
|
||||
{
|
||||
if (ref() > 0 && _client != NULL)
|
||||
_attachCallbacks();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SyncClient::~SyncClient()
|
||||
{
|
||||
if (0 == unref())
|
||||
_release();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_release()
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client->onData(NULL, NULL);
|
||||
_client->onAck(NULL, NULL);
|
||||
_client->onPoll(NULL, NULL);
|
||||
_client->abort();
|
||||
_client = NULL;
|
||||
}
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
while (_rx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _rx_buffer;
|
||||
_rx_buffer = _rx_buffer->next;
|
||||
delete b;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::ref()
|
||||
{
|
||||
if (_ref == NULL)
|
||||
{
|
||||
_ref = new (std::nothrow) int;
|
||||
|
||||
if (_ref != NULL)
|
||||
*_ref = 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (++*_ref);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::unref()
|
||||
{
|
||||
int count = -1;
|
||||
|
||||
if (_ref != NULL)
|
||||
{
|
||||
count = --*_ref;
|
||||
|
||||
if (0 == count)
|
||||
{
|
||||
delete _ref;
|
||||
_ref = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
int SyncClient::_connect(const IPAddress& ip, uint16_t port, bool secure)
|
||||
#else
|
||||
int SyncClient::_connect(const IPAddress& ip, uint16_t port)
|
||||
#endif
|
||||
{
|
||||
if (connected())
|
||||
return 0;
|
||||
|
||||
if (_client != NULL)
|
||||
delete _client;
|
||||
|
||||
_client = new (std::nothrow) AsyncClient();
|
||||
|
||||
if (_client == NULL)
|
||||
return 0;
|
||||
|
||||
_client->onConnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((SyncClient*)(obj))->_onConnect(c);
|
||||
}, this);
|
||||
|
||||
_attachCallbacks_Disconnect();
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
if (_client->connect(ip, port, secure))
|
||||
#else
|
||||
if (_client->connect(ip, port))
|
||||
#endif
|
||||
{
|
||||
while (_client != NULL && !_client->connected() && !_client->disconnecting())
|
||||
delay(1);
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
int SyncClient::connect(const char *host, uint16_t port, bool secure)
|
||||
#else
|
||||
int SyncClient::connect(const char *host, uint16_t port)
|
||||
#endif
|
||||
{
|
||||
if (connected())
|
||||
return 0;
|
||||
|
||||
if (_client != NULL)
|
||||
delete _client;
|
||||
|
||||
_client = new (std::nothrow) AsyncClient();
|
||||
|
||||
if (_client == NULL)
|
||||
return 0;
|
||||
|
||||
_client->onConnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((SyncClient*)(obj))->_onConnect(c);
|
||||
}, this);
|
||||
|
||||
_attachCallbacks_Disconnect();
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
if (_client->connect(host, port, secure))
|
||||
#else
|
||||
if (_client->connect(host, port))
|
||||
#endif
|
||||
{
|
||||
while (_client != NULL && !_client->connected() && !_client->disconnecting())
|
||||
delay(1);
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
//#define SYNCCLIENT_NEW_OPERATOR_EQUAL
|
||||
#ifdef SYNCCLIENT_NEW_OPERATOR_EQUAL
|
||||
|
||||
/*
|
||||
New behavior for operator=
|
||||
|
||||
Allow for the object to be placed on a queue and transfered to a new container
|
||||
with buffers still in tact. Avoiding receive data drops. Transfers rx and tx
|
||||
buffers. Supports return by value.
|
||||
|
||||
Note, this is optional, the old behavior is the default.
|
||||
|
||||
*/
|
||||
SyncClient & SyncClient::operator=(const SyncClient &other)
|
||||
{
|
||||
int *rhsref = other._ref;
|
||||
++*rhsref; // Just in case the left and right side are the same object with different containers
|
||||
|
||||
if (0 == unref())
|
||||
_release();
|
||||
|
||||
_ref = other._ref;
|
||||
ref();
|
||||
--*rhsref;
|
||||
|
||||
// Why do I not test _tx_buffer for != NULL and free?
|
||||
// I allow for the lh target container, to be a copy of an active
|
||||
// connection. Thus we are just reusing the container.
|
||||
// The above unref() handles releaseing the previous client of the container.
|
||||
_tx_buffer_size = other._tx_buffer_size;
|
||||
_tx_buffer = other._tx_buffer;
|
||||
_client = other._client;
|
||||
|
||||
if (_client != NULL && _tx_buffer == NULL)
|
||||
_tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
|
||||
|
||||
_rx_buffer = other._rx_buffer;
|
||||
|
||||
if (_client)
|
||||
_attachCallbacks();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#else // ! SYNCCLIENT_NEW_OPERATOR_EQUAL
|
||||
|
||||
// This is the origianl logic with null checks
|
||||
SyncClient & SyncClient::operator=(const SyncClient &other)
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client->abort();
|
||||
_client->free();
|
||||
_client = NULL;
|
||||
}
|
||||
_tx_buffer_size = other._tx_buffer_size;
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
while (_rx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _rx_buffer;
|
||||
_rx_buffer = b->next;
|
||||
delete b;
|
||||
}
|
||||
|
||||
if (other._client != NULL)
|
||||
_tx_buffer = new (std::nothrow) cbuf(other._tx_buffer_size);
|
||||
|
||||
_client = other._client;
|
||||
|
||||
if (_client)
|
||||
_attachCallbacks();
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::setTimeout(uint32_t seconds)
|
||||
{
|
||||
if (_client != NULL)
|
||||
_client->setRxTimeout(seconds);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t SyncClient::status()
|
||||
{
|
||||
if (_client == NULL)
|
||||
return 0;
|
||||
|
||||
return _client->state();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t SyncClient::connected()
|
||||
{
|
||||
return (_client != NULL && _client->connected());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool SyncClient::stop(unsigned int maxWaitMs)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(maxWaitMs);
|
||||
|
||||
if (_client != NULL)
|
||||
_client->close(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t SyncClient::_sendBuffer()
|
||||
{
|
||||
if (_client == NULL || _tx_buffer == NULL)
|
||||
return 0;
|
||||
|
||||
size_t available = _tx_buffer->available();
|
||||
|
||||
if ( !connected() || !_client->canSend() || (available == 0) )
|
||||
return 0;
|
||||
|
||||
size_t sendable = _client->space();
|
||||
|
||||
if (sendable < available)
|
||||
available = sendable;
|
||||
|
||||
char *out = new (std::nothrow) char[available];
|
||||
|
||||
if (out == NULL)
|
||||
return 0;
|
||||
|
||||
_tx_buffer->read(out, available);
|
||||
size_t sent = _client->write(out, available);
|
||||
delete[] out;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_onData(void *data, size_t len)
|
||||
{
|
||||
_client->ackLater();
|
||||
cbuf *b = new (std::nothrow) cbuf(len + 1);
|
||||
|
||||
if (b != NULL)
|
||||
{
|
||||
b->write((const char *)data, len);
|
||||
|
||||
if (_rx_buffer == NULL)
|
||||
_rx_buffer = b;
|
||||
else
|
||||
{
|
||||
cbuf *p = _rx_buffer;
|
||||
while (p->next != NULL)
|
||||
p = p->next;
|
||||
p->next = b;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We ran out of memory. This fail causes lost receive data.
|
||||
// The connection should be closed in a manner that conveys something
|
||||
// bad/abnormal has happened to the connection. Hence, we abort the
|
||||
// connection to avoid possible data corruption.
|
||||
// Note, callbacks maybe called.
|
||||
_client->abort();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_onDisconnect()
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client = NULL;
|
||||
}
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_onConnect(AsyncClient *c)
|
||||
{
|
||||
_client = c;
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
_tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
|
||||
_attachCallbacks_AfterConnected();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_attachCallbacks()
|
||||
{
|
||||
_attachCallbacks_Disconnect();
|
||||
_attachCallbacks_AfterConnected();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_attachCallbacks_AfterConnected()
|
||||
{
|
||||
_client->onAck([](void *obj, AsyncClient * c, size_t len, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
RPAsyncTCP_UNUSED(len);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
((SyncClient*)(obj))->_sendBuffer();
|
||||
}, this);
|
||||
|
||||
_client->onData([](void *obj, AsyncClient * c, void *data, size_t len)
|
||||
{ RPAsyncTCP_UNUSED(c);
|
||||
((SyncClient*)(obj))->_onData(data, len);
|
||||
}, this);
|
||||
|
||||
_client->onTimeout([](void *obj, AsyncClient * c, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(obj);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
c->close();
|
||||
}, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_attachCallbacks_Disconnect()
|
||||
{
|
||||
_client->onDisconnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((SyncClient*)(obj))->_onDisconnect();
|
||||
delete c;
|
||||
}, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t SyncClient::write(uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t SyncClient::write(const uint8_t *data, size_t len)
|
||||
{
|
||||
if (_tx_buffer == NULL || !connected())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t toWrite = 0;
|
||||
size_t toSend = len;
|
||||
|
||||
while (_tx_buffer->room() < toSend)
|
||||
{
|
||||
toWrite = _tx_buffer->room();
|
||||
_tx_buffer->write((const char*)data, toWrite);
|
||||
|
||||
while (connected() && !_client->canSend())
|
||||
delay(0);
|
||||
|
||||
if (!connected())
|
||||
return 0;
|
||||
|
||||
_sendBuffer();
|
||||
toSend -= toWrite;
|
||||
}
|
||||
|
||||
_tx_buffer->write((const char*)(data + (len - toSend)), toSend);
|
||||
|
||||
if (connected() && _client->canSend())
|
||||
_sendBuffer();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::available()
|
||||
{
|
||||
if (_rx_buffer == NULL)
|
||||
return 0;
|
||||
|
||||
size_t a = 0;
|
||||
cbuf *b = _rx_buffer;
|
||||
|
||||
while (b != NULL)
|
||||
{
|
||||
a += b->available();
|
||||
b = b->next;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::peek()
|
||||
{
|
||||
if (_rx_buffer == NULL)
|
||||
return -1;
|
||||
|
||||
return _rx_buffer->peek();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::read(uint8_t *data, size_t len)
|
||||
{
|
||||
if (_rx_buffer == NULL)
|
||||
return -1;
|
||||
|
||||
size_t readSoFar = 0;
|
||||
|
||||
while (_rx_buffer != NULL && (len - readSoFar) >= _rx_buffer->available())
|
||||
{
|
||||
cbuf *b = _rx_buffer;
|
||||
_rx_buffer = _rx_buffer->next;
|
||||
size_t toRead = b->available();
|
||||
readSoFar += b->read((char*)(data + readSoFar), toRead);
|
||||
|
||||
if (connected())
|
||||
{
|
||||
_client->ack(b->size() - 1);
|
||||
}
|
||||
|
||||
delete b;
|
||||
}
|
||||
|
||||
if (_rx_buffer != NULL && readSoFar < len)
|
||||
{
|
||||
readSoFar += _rx_buffer->read((char*)(data + readSoFar), (len - readSoFar));
|
||||
}
|
||||
|
||||
return readSoFar;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::read()
|
||||
{
|
||||
uint8_t res = 0;
|
||||
|
||||
if (read(&res, 1) != 1)
|
||||
return -1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool SyncClient::flush(unsigned int maxWaitMs)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(maxWaitMs);
|
||||
|
||||
if (_tx_buffer == NULL || !connected())
|
||||
return false;
|
||||
|
||||
if (_tx_buffer->available())
|
||||
{
|
||||
while (connected() && !_client->canSend())
|
||||
delay(0);
|
||||
|
||||
if (_client == NULL || _tx_buffer == NULL)
|
||||
return false;
|
||||
|
||||
_sendBuffer();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,125 @@
|
||||
#ifndef SYNCCLIENT_H_
|
||||
#define SYNCCLIENT_H_
|
||||
|
||||
#define LWIP_NETIF_TX_SINGLE_PBUF 1
|
||||
|
||||
#include "Client.h"
|
||||
// Needed for Arduino core releases prior to 2.5.0, because of changes
|
||||
// made to accommodate Arduino core 2.5.0
|
||||
// CONST was 1st defined in Core 2.5.0 in IPAddress.h
|
||||
#ifndef CONST
|
||||
#define CONST
|
||||
#endif
|
||||
|
||||
#include <async_config.h>
|
||||
|
||||
class cbuf;
|
||||
class AsyncClient;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
class SyncClient: public Client
|
||||
{
|
||||
private:
|
||||
AsyncClient *_client;
|
||||
cbuf *_tx_buffer;
|
||||
size_t _tx_buffer_size;
|
||||
cbuf *_rx_buffer;
|
||||
int *_ref;
|
||||
|
||||
size_t _sendBuffer();
|
||||
void _onData(void *data, size_t len);
|
||||
void _onConnect(AsyncClient *c);
|
||||
void _onDisconnect();
|
||||
void _attachCallbacks();
|
||||
void _attachCallbacks_Disconnect();
|
||||
void _attachCallbacks_AfterConnected();
|
||||
void _release();
|
||||
|
||||
public:
|
||||
SyncClient(size_t txBufLen = TCP_MSS);
|
||||
SyncClient(AsyncClient *client, size_t txBufLen = TCP_MSS);
|
||||
virtual ~SyncClient();
|
||||
|
||||
int ref();
|
||||
int unref();
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return connected();
|
||||
}
|
||||
|
||||
SyncClient & operator=(const SyncClient &other);
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
int _connect(const IPAddress& ip, uint16_t port, bool secure);
|
||||
|
||||
int connect(CONST IPAddress& ip, uint16_t port, bool secure)
|
||||
{
|
||||
return _connect(ip, port, secure);
|
||||
}
|
||||
|
||||
int connect(IPAddress ip, uint16_t port, bool secure)
|
||||
{
|
||||
return _connect(reinterpret_cast<const IPAddress&>(ip), port, secure);
|
||||
}
|
||||
|
||||
int connect(const char *host, uint16_t port, bool secure);
|
||||
|
||||
int connect(CONST IPAddress& ip, uint16_t port)
|
||||
{
|
||||
return _connect(ip, port, false);
|
||||
}
|
||||
|
||||
int connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
return _connect(reinterpret_cast<const IPAddress&>(ip), port, false);
|
||||
}
|
||||
|
||||
int connect(const char *host, uint16_t port)
|
||||
{
|
||||
return connect(host, port, false);
|
||||
}
|
||||
#else
|
||||
int _connect(const IPAddress& ip, uint16_t port);
|
||||
|
||||
int connect(CONST IPAddress& ip, uint16_t port)
|
||||
{
|
||||
return _connect(ip, port);
|
||||
}
|
||||
|
||||
int connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
return _connect(reinterpret_cast<const IPAddress&>(ip), port);
|
||||
}
|
||||
|
||||
int connect(const char *host, uint16_t port);
|
||||
#endif
|
||||
void setTimeout(uint32_t seconds);
|
||||
|
||||
uint8_t status();
|
||||
uint8_t connected();
|
||||
|
||||
bool stop(unsigned int maxWaitMs);
|
||||
bool flush(unsigned int maxWaitMs);
|
||||
|
||||
void stop()
|
||||
{
|
||||
(void)stop(0);
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
(void)flush(0);
|
||||
}
|
||||
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *data, size_t len);
|
||||
|
||||
int available();
|
||||
int peek();
|
||||
int read();
|
||||
int read(uint8_t *data, size_t len);
|
||||
};
|
||||
|
||||
#endif /* SYNCCLIENT_H_ */
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef _RP2040W_ASYNC_CONFIG_H_
|
||||
#define _RP2040W_ASYNC_CONFIG_H_
|
||||
|
||||
#ifndef TCP_MSS
|
||||
// May have been definded as a -DTCP_MSS option on the compile line or not.
|
||||
// Arduino core 2.3.0 or earlier does not do the -DTCP_MSS option.
|
||||
// Later versions may set this option with info from board.txt.
|
||||
// However, Core 2.4.0 and up board.txt does not define TCP_MSS for lwIP v1.4
|
||||
#define TCP_MSS MBED_CONF_LWIP_TCP_MSS //(1460)
|
||||
#endif
|
||||
|
||||
#endif // _RP2040W_ASYNC_CONFIG_H_
|
||||
109
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/c_types.h
Normal file
109
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/c_types.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _C_TYPES_H_
|
||||
#define _C_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
typedef signed char sint8_t;
|
||||
typedef signed short sint16_t;
|
||||
typedef signed long sint32_t;
|
||||
typedef signed long long sint64_t;
|
||||
typedef unsigned long long u_int64_t;
|
||||
typedef float real32_t;
|
||||
typedef double real64_t;
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned char u8;
|
||||
typedef signed char sint8;
|
||||
typedef signed char int8;
|
||||
typedef signed char s8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned short u16;
|
||||
typedef signed short sint16;
|
||||
typedef signed short s16;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned int u32;
|
||||
typedef signed int sint32;
|
||||
typedef signed int s32;
|
||||
typedef int int32;
|
||||
typedef signed long long sint64;
|
||||
typedef unsigned long long uint64;
|
||||
typedef unsigned long long u64;
|
||||
typedef float real32;
|
||||
typedef double real64;
|
||||
|
||||
#define __le16 u16
|
||||
|
||||
#define LOCAL static
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif /* NULL */
|
||||
|
||||
/* probably should not put STATUS here */
|
||||
typedef enum
|
||||
{
|
||||
OK = 0,
|
||||
FAIL,
|
||||
PENDING,
|
||||
BUSY,
|
||||
CANCEL,
|
||||
} STATUS;
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
|
||||
#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b))
|
||||
#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b))
|
||||
|
||||
#define DMEM_ATTR __attribute__((section(".bss")))
|
||||
#define SHMEM_ATTR
|
||||
|
||||
#ifdef ICACHE_FLASH
|
||||
#define __ICACHE_STRINGIZE_NX(A) #A
|
||||
#define __ICACHE_STRINGIZE(A) __ICACHE_STRINGIZE_NX(A)
|
||||
#define ICACHE_FLASH_ATTR __attribute__((section("\".irom0.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||
#define ICACHE_RAM_ATTR __attribute__((section("\".iram.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||
#else
|
||||
#define ICACHE_FLASH_ATTR
|
||||
#define ICACHE_RAM_ATTR
|
||||
#endif /* ICACHE_FLASH */
|
||||
|
||||
// counterpart https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp8266-compat.h
|
||||
#define IRAM_ATTR ICACHE_RAM_ATTR
|
||||
|
||||
#define STORE_ATTR __attribute__((aligned(4)))
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define BOOL bool
|
||||
#define TRUE true
|
||||
#define FALSE false
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
#endif /* _C_TYPES_H_ */
|
||||
221
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/cbuf.cpp
Normal file
221
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/cbuf.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
cbuf.cpp - Circular buffer implementation
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "cbuf.h"
|
||||
#include "c_types.h"
|
||||
|
||||
cbuf::cbuf(size_t size) :
|
||||
next(NULL), _size(size), _buf(new char[size]), _bufend(_buf + size), _begin(_buf), _end(_begin)
|
||||
{
|
||||
}
|
||||
|
||||
cbuf::~cbuf()
|
||||
{
|
||||
delete[] _buf;
|
||||
}
|
||||
|
||||
size_t cbuf::resizeAdd(size_t addSize)
|
||||
{
|
||||
return resize(_size + addSize);
|
||||
}
|
||||
|
||||
size_t cbuf::resize(size_t newSize)
|
||||
{
|
||||
size_t bytes_available = available();
|
||||
|
||||
// not lose any data
|
||||
// if data can be lost use remove or flush before resize
|
||||
if ((newSize <= bytes_available) || (newSize == _size))
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
char *newbuf = new char[newSize];
|
||||
char *oldbuf = _buf;
|
||||
|
||||
if (!newbuf)
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
if (_buf)
|
||||
{
|
||||
read(newbuf, bytes_available);
|
||||
memset((newbuf + bytes_available), 0x00, (newSize - bytes_available));
|
||||
}
|
||||
|
||||
_begin = newbuf;
|
||||
_end = newbuf + bytes_available;
|
||||
_bufend = newbuf + newSize;
|
||||
_size = newSize;
|
||||
|
||||
_buf = newbuf;
|
||||
delete[] oldbuf;
|
||||
|
||||
return _size;
|
||||
}
|
||||
|
||||
size_t ICACHE_RAM_ATTR cbuf::available() const
|
||||
{
|
||||
if (_end >= _begin)
|
||||
{
|
||||
return _end - _begin;
|
||||
}
|
||||
|
||||
return _size - (_begin - _end);
|
||||
}
|
||||
|
||||
size_t cbuf::size()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
size_t cbuf::room() const
|
||||
{
|
||||
if (_end >= _begin)
|
||||
{
|
||||
return _size - (_end - _begin) - 1;
|
||||
}
|
||||
|
||||
return _begin - _end - 1;
|
||||
}
|
||||
|
||||
int cbuf::peek()
|
||||
{
|
||||
if (empty())
|
||||
return -1;
|
||||
|
||||
return static_cast<int>(*_begin);
|
||||
}
|
||||
|
||||
size_t cbuf::peek(char *dst, size_t size)
|
||||
{
|
||||
size_t bytes_available = available();
|
||||
size_t size_to_read = (size < bytes_available) ? size : bytes_available;
|
||||
size_t size_read = size_to_read;
|
||||
char * begin = _begin;
|
||||
|
||||
if (_end < _begin && size_to_read > (size_t) (_bufend - _begin))
|
||||
{
|
||||
size_t top_size = _bufend - _begin;
|
||||
memcpy(dst, _begin, top_size);
|
||||
begin = _buf;
|
||||
size_to_read -= top_size;
|
||||
dst += top_size;
|
||||
}
|
||||
|
||||
memcpy(dst, begin, size_to_read);
|
||||
|
||||
return size_read;
|
||||
}
|
||||
|
||||
int ICACHE_RAM_ATTR cbuf::read()
|
||||
{
|
||||
if (empty())
|
||||
return -1;
|
||||
|
||||
char result = *_begin;
|
||||
_begin = wrap_if_bufend(_begin + 1);
|
||||
|
||||
return static_cast<int>(result);
|
||||
}
|
||||
|
||||
size_t cbuf::read(char* dst, size_t size)
|
||||
{
|
||||
size_t bytes_available = available();
|
||||
size_t size_to_read = (size < bytes_available) ? size : bytes_available;
|
||||
size_t size_read = size_to_read;
|
||||
|
||||
if (_end < _begin && size_to_read > (size_t) (_bufend - _begin))
|
||||
{
|
||||
size_t top_size = _bufend - _begin;
|
||||
memcpy(dst, _begin, top_size);
|
||||
_begin = _buf;
|
||||
size_to_read -= top_size;
|
||||
dst += top_size;
|
||||
}
|
||||
|
||||
memcpy(dst, _begin, size_to_read);
|
||||
_begin = wrap_if_bufend(_begin + size_to_read);
|
||||
|
||||
return size_read;
|
||||
}
|
||||
|
||||
size_t ICACHE_RAM_ATTR cbuf::write(char c)
|
||||
{
|
||||
if (full())
|
||||
return 0;
|
||||
|
||||
*_end = c;
|
||||
_end = wrap_if_bufend(_end + 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t cbuf::write(const char* src, size_t size)
|
||||
{
|
||||
size_t bytes_available = room();
|
||||
size_t size_to_write = (size < bytes_available) ? size : bytes_available;
|
||||
size_t size_written = size_to_write;
|
||||
|
||||
if (_end >= _begin && size_to_write > (size_t) (_bufend - _end))
|
||||
{
|
||||
size_t top_size = _bufend - _end;
|
||||
memcpy(_end, src, top_size);
|
||||
_end = _buf;
|
||||
size_to_write -= top_size;
|
||||
src += top_size;
|
||||
}
|
||||
|
||||
memcpy(_end, src, size_to_write);
|
||||
_end = wrap_if_bufend(_end + size_to_write);
|
||||
|
||||
return size_written;
|
||||
}
|
||||
|
||||
void cbuf::flush()
|
||||
{
|
||||
_begin = _buf;
|
||||
_end = _buf;
|
||||
}
|
||||
|
||||
size_t cbuf::remove(size_t size)
|
||||
{
|
||||
size_t bytes_available = available();
|
||||
|
||||
if (size >= bytes_available)
|
||||
{
|
||||
flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t size_to_remove = (size < bytes_available) ? size : bytes_available;
|
||||
|
||||
if (_end < _begin && size_to_remove > (size_t) (_bufend - _begin))
|
||||
{
|
||||
size_t top_size = _bufend - _begin;
|
||||
_begin = _buf;
|
||||
size_to_remove -= top_size;
|
||||
}
|
||||
|
||||
_begin = wrap_if_bufend(_begin + size_to_remove);
|
||||
|
||||
return available();
|
||||
}
|
||||
78
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/cbuf.h
Normal file
78
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/cbuf.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
cbuf.h - Circular buffer implementation
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __cbuf_h
|
||||
#define __cbuf_h
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
class cbuf
|
||||
{
|
||||
public:
|
||||
cbuf(size_t size);
|
||||
~cbuf();
|
||||
|
||||
size_t resizeAdd(size_t addSize);
|
||||
size_t resize(size_t newSize);
|
||||
size_t available() const;
|
||||
size_t size();
|
||||
|
||||
size_t room() const;
|
||||
|
||||
inline bool empty() const
|
||||
{
|
||||
return _begin == _end;
|
||||
}
|
||||
|
||||
inline bool full() const
|
||||
{
|
||||
return wrap_if_bufend(_end + 1) == _begin;
|
||||
}
|
||||
|
||||
int peek();
|
||||
size_t peek(char *dst, size_t size);
|
||||
|
||||
int read();
|
||||
size_t read(char* dst, size_t size);
|
||||
|
||||
size_t write(char c);
|
||||
size_t write(const char* src, size_t size);
|
||||
|
||||
void flush();
|
||||
size_t remove(size_t size);
|
||||
|
||||
cbuf *next;
|
||||
|
||||
private:
|
||||
inline char* wrap_if_bufend(char* ptr) const
|
||||
{
|
||||
return (ptr == _bufend) ? _buf : ptr;
|
||||
}
|
||||
|
||||
size_t _size;
|
||||
char* _buf;
|
||||
const char* _bufend;
|
||||
char* _begin;
|
||||
char* _end;
|
||||
};
|
||||
|
||||
#endif//__cbuf_h
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
void panic()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef DEBUG_H_
|
||||
#define DEBUG_H_
|
||||
|
||||
void panic();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,802 @@
|
||||
#if !defined(_RPAsyncTCP_LOGLEVEL_)
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
#include <async_config.h>
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <tcp_axtls.h>
|
||||
|
||||
uint8_t * default_private_key = NULL;
|
||||
uint16_t default_private_key_len = 0;
|
||||
|
||||
uint8_t * default_certificate = NULL;
|
||||
uint16_t default_certificate_len = 0;
|
||||
|
||||
static uint8_t _tcp_ssl_has_client = 0;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SSL_CTX * tcp_ssl_new_server_ctx(const char *cert, const char *private_key_file, const char *password)
|
||||
{
|
||||
uint32_t options = SSL_CONNECT_IN_PARTS;
|
||||
SSL_CTX *ssl_ctx;
|
||||
|
||||
if (private_key_file)
|
||||
{
|
||||
options |= SSL_NO_DEFAULT_KEY;
|
||||
}
|
||||
|
||||
if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_SVR_SESS)) == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: failed to allocate context\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (private_key_file)
|
||||
{
|
||||
int obj_type = SSL_OBJ_RSA_KEY;
|
||||
|
||||
if (strstr(private_key_file, ".p8"))
|
||||
obj_type = SSL_OBJ_PKCS8;
|
||||
else if (strstr(private_key_file, ".p12"))
|
||||
obj_type = SSL_OBJ_PKCS12;
|
||||
|
||||
if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password))
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: load private key '%s' failed\n", private_key_file);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cert)
|
||||
{
|
||||
if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert, NULL))
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: load certificate '%s' failed\n", cert);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ssl_ctx;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
struct tcp_ssl_pcb
|
||||
{
|
||||
struct tcp_pcb *tcp;
|
||||
int fd;
|
||||
SSL_CTX* ssl_ctx;
|
||||
SSL *ssl;
|
||||
uint8_t type;
|
||||
int handshake;
|
||||
void * arg;
|
||||
tcp_ssl_data_cb_t on_data;
|
||||
tcp_ssl_handshake_cb_t on_handshake;
|
||||
tcp_ssl_error_cb_t on_error;
|
||||
int last_wr;
|
||||
struct pbuf *tcp_pbuf;
|
||||
int pbuf_offset;
|
||||
struct tcp_ssl_pcb * next;
|
||||
};
|
||||
|
||||
typedef struct tcp_ssl_pcb tcp_ssl_t;
|
||||
|
||||
static tcp_ssl_t * tcp_ssl_array = NULL;
|
||||
static int tcp_ssl_next_fd = 0;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t tcp_ssl_has_client()
|
||||
{
|
||||
return _tcp_ssl_has_client;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
tcp_ssl_t * tcp_ssl_new(struct tcp_pcb *tcp)
|
||||
{
|
||||
|
||||
if (tcp_ssl_next_fd < 0)
|
||||
{
|
||||
tcp_ssl_next_fd = 0;//overflow
|
||||
}
|
||||
|
||||
tcp_ssl_t * new_item = (tcp_ssl_t*)malloc(sizeof(tcp_ssl_t));
|
||||
|
||||
if (!new_item)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new: failed to allocate tcp_ssl\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_item->tcp = tcp;
|
||||
new_item->handshake = SSL_NOT_OK;
|
||||
new_item->arg = NULL;
|
||||
new_item->on_data = NULL;
|
||||
new_item->on_handshake = NULL;
|
||||
new_item->on_error = NULL;
|
||||
new_item->tcp_pbuf = NULL;
|
||||
new_item->pbuf_offset = 0;
|
||||
new_item->next = NULL;
|
||||
new_item->ssl_ctx = NULL;
|
||||
new_item->ssl = NULL;
|
||||
new_item->type = TCP_SSL_TYPE_CLIENT;
|
||||
new_item->fd = tcp_ssl_next_fd++;
|
||||
|
||||
if (tcp_ssl_array == NULL)
|
||||
{
|
||||
tcp_ssl_array = new_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_array;
|
||||
|
||||
while (item->next != NULL)
|
||||
item = item->next;
|
||||
|
||||
item->next = new_item;
|
||||
}
|
||||
|
||||
TCP_SSL_DEBUG("tcp_ssl_new: %d\n", new_item->fd);
|
||||
|
||||
return new_item;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
tcp_ssl_t* tcp_ssl_get(struct tcp_pcb *tcp)
|
||||
{
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tcp_ssl_t * item = tcp_ssl_array;
|
||||
|
||||
while (item && item->tcp != tcp)
|
||||
{
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_new_client(struct tcp_pcb *tcp)
|
||||
{
|
||||
SSL_CTX* ssl_ctx;
|
||||
tcp_ssl_t * tcp_ssl;
|
||||
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tcp_ssl_get(tcp) != NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_client: tcp_ssl already exists\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssl_ctx = ssl_ctx_new(SSL_CONNECT_IN_PARTS | SSL_SERVER_VERIFY_LATER, 1);
|
||||
|
||||
if (ssl_ctx == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_client: failed to allocate ssl context\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl = tcp_ssl_new(tcp);
|
||||
|
||||
if (tcp_ssl == NULL)
|
||||
{
|
||||
ssl_ctx_free(ssl_ctx);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl->ssl_ctx = ssl_ctx;
|
||||
|
||||
tcp_ssl->ssl = ssl_client_new(ssl_ctx, tcp_ssl->fd, NULL, 0, NULL);
|
||||
|
||||
if (tcp_ssl->ssl == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_client: failed to allocate ssl\n");
|
||||
tcp_ssl_free(tcp);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return tcp_ssl->fd;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_new_server(struct tcp_pcb *tcp, SSL_CTX* ssl_ctx)
|
||||
{
|
||||
tcp_ssl_t * tcp_ssl;
|
||||
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssl_ctx == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tcp_ssl_get(tcp) != NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server: tcp_ssl already exists\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl = tcp_ssl_new(tcp);
|
||||
|
||||
if (tcp_ssl == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl->type = TCP_SSL_TYPE_SERVER;
|
||||
tcp_ssl->ssl_ctx = ssl_ctx;
|
||||
|
||||
_tcp_ssl_has_client = 1;
|
||||
tcp_ssl->ssl = ssl_server_new(ssl_ctx, tcp_ssl->fd);
|
||||
|
||||
if (tcp_ssl->ssl == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server: failed to allocate ssl\n");
|
||||
tcp_ssl_free(tcp);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return tcp_ssl->fd;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_free(struct tcp_pcb *tcp)
|
||||
{
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl_t * item = tcp_ssl_array;
|
||||
|
||||
if (item->tcp == tcp)
|
||||
{
|
||||
tcp_ssl_array = tcp_ssl_array->next;
|
||||
|
||||
if (item->tcp_pbuf != NULL)
|
||||
{
|
||||
pbuf_free(item->tcp_pbuf);
|
||||
}
|
||||
|
||||
TCP_SSL_DEBUG("tcp_ssl_free: %d\n", item->fd);
|
||||
|
||||
if (item->ssl)
|
||||
ssl_free(item->ssl);
|
||||
|
||||
if (item->type == TCP_SSL_TYPE_CLIENT && item->ssl_ctx)
|
||||
ssl_ctx_free(item->ssl_ctx);
|
||||
|
||||
if (item->type == TCP_SSL_TYPE_SERVER)
|
||||
_tcp_ssl_has_client = 0;
|
||||
|
||||
free(item);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (item->next && item->next->tcp != tcp)
|
||||
item = item->next;
|
||||
|
||||
if (item->next == NULL)
|
||||
{
|
||||
return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;//item not found
|
||||
}
|
||||
|
||||
tcp_ssl_t * i = item->next;
|
||||
item->next = i->next;
|
||||
|
||||
if (i->tcp_pbuf != NULL)
|
||||
{
|
||||
pbuf_free(i->tcp_pbuf);
|
||||
}
|
||||
|
||||
TCP_SSL_DEBUG("tcp_ssl_free: %d\n", i->fd);
|
||||
|
||||
if (i->ssl)
|
||||
ssl_free(i->ssl);
|
||||
|
||||
if (i->type == TCP_SSL_TYPE_CLIENT && i->ssl_ctx)
|
||||
ssl_ctx_free(i->ssl_ctx);
|
||||
|
||||
if (i->type == TCP_SSL_TYPE_SERVER)
|
||||
_tcp_ssl_has_client = 0;
|
||||
|
||||
free(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef AXTLS_2_0_0_SNDBUF
|
||||
|
||||
int tcp_ssl_sndbuf(struct tcp_pcb *tcp)
|
||||
{
|
||||
int expected;
|
||||
int available;
|
||||
int result = -1;
|
||||
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||
|
||||
if (!tcp_ssl)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_ssl is NULL\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
available = tcp_sndbuf(tcp);
|
||||
|
||||
if (!available)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_sndbuf is zero\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = available;
|
||||
|
||||
while ((expected = ssl_calculate_write_length(tcp_ssl->ssl, result)) > available)
|
||||
{
|
||||
result -= (expected - available) + 4;
|
||||
}
|
||||
|
||||
if (expected > 0)
|
||||
{
|
||||
//TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_sndbuf is %d from %d\n", result, available);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // AXTLS_2_0_0_SNDBUF
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len)
|
||||
{
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||
|
||||
if (!tcp_ssl)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_write: tcp_ssl is NULL\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
tcp_ssl->last_wr = 0;
|
||||
|
||||
#ifdef AXTLS_2_0_0_SNDBUF
|
||||
int expected_len = ssl_calculate_write_length(tcp_ssl->ssl, len);
|
||||
int available_len = tcp_sndbuf(tcp);
|
||||
|
||||
if (expected_len < 0 || expected_len > available_len)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_write: data will not fit! %u < %d(%u)\r\n", available_len, expected_len, len);
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif // AXTLS_2_0_0_SNDBUF
|
||||
|
||||
int rc = ssl_write(tcp_ssl->ssl, data, len);
|
||||
|
||||
//TCP_SSL_DEBUG("tcp_ssl_write: %u -> %d (%d)\r\n", len, tcp_ssl->last_wr, rc);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
if (rc != SSL_CLOSE_NOTIFY)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_write error: %d\r\n", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
return tcp_ssl->last_wr;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
Reads data from the SSL over TCP stream. Returns decrypted data.
|
||||
@param tcp_pcb *tcp - pointer to the raw tcp object
|
||||
@param pbuf *p - pointer to the buffer with the TCP packet data
|
||||
|
||||
@return int
|
||||
0 - when everything is fine but there are no symbols to process yet
|
||||
< 0 - when there is an error
|
||||
> 0 - the length of the clear text characters that were read
|
||||
*/
|
||||
int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p)
|
||||
{
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl_t* fd_data = NULL;
|
||||
|
||||
int read_bytes = 0;
|
||||
int total_bytes = 0;
|
||||
uint8_t *read_buf;
|
||||
|
||||
fd_data = tcp_ssl_get(tcp);
|
||||
|
||||
if (fd_data == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_read: tcp_ssl is NULL\n");
|
||||
return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;
|
||||
}
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_read:p == NULL\n");
|
||||
return ERR_TCP_SSL_INVALID_DATA;
|
||||
}
|
||||
|
||||
//TCP_SSL_DEBUG("READY TO READ SOME DATA\n");
|
||||
|
||||
fd_data->tcp_pbuf = p;
|
||||
fd_data->pbuf_offset = 0;
|
||||
|
||||
do
|
||||
{
|
||||
read_bytes = ssl_read(fd_data->ssl, &read_buf);
|
||||
//TCP_SSL_DEBUG("tcp_ssl_ssl_read: %d\n", read_bytes);
|
||||
|
||||
if (read_bytes < SSL_OK)
|
||||
{
|
||||
if (read_bytes != SSL_CLOSE_NOTIFY)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes);
|
||||
}
|
||||
|
||||
total_bytes = read_bytes;
|
||||
break;
|
||||
}
|
||||
else if (read_bytes > 0)
|
||||
{
|
||||
if (fd_data->on_data)
|
||||
{
|
||||
fd_data->on_data(fd_data->arg, tcp, read_buf, read_bytes);
|
||||
}
|
||||
|
||||
total_bytes += read_bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fd_data->handshake != SSL_OK)
|
||||
{
|
||||
fd_data->handshake = ssl_handshake_status(fd_data->ssl);
|
||||
|
||||
if (fd_data->handshake == SSL_OK)
|
||||
{
|
||||
//TCP_SSL_DEBUG("tcp_ssl_read: handshake OK\n");
|
||||
if (fd_data->on_handshake)
|
||||
fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data->ssl);
|
||||
}
|
||||
else if (fd_data->handshake != SSL_NOT_OK)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_read: handshake error: %d\n", fd_data->handshake);
|
||||
|
||||
if (fd_data->on_error)
|
||||
fd_data->on_error(fd_data->arg, fd_data->tcp, fd_data->handshake);
|
||||
|
||||
return fd_data->handshake;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (p->tot_len - fd_data->pbuf_offset > 0);
|
||||
|
||||
tcp_recved(tcp, p->tot_len);
|
||||
fd_data->tcp_pbuf = NULL;
|
||||
pbuf_free(p);
|
||||
|
||||
return total_bytes;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SSL * tcp_ssl_get_ssl(struct tcp_pcb *tcp)
|
||||
{
|
||||
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||
|
||||
if (tcp_ssl)
|
||||
{
|
||||
return tcp_ssl->ssl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool tcp_ssl_has(struct tcp_pcb *tcp)
|
||||
{
|
||||
return tcp_ssl_get(tcp) != NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_is_server(struct tcp_pcb *tcp)
|
||||
{
|
||||
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||
|
||||
if (tcp_ssl)
|
||||
{
|
||||
return tcp_ssl->type;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->arg = arg;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_data(struct tcp_pcb *tcp, tcp_ssl_data_cb_t arg)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->on_data = arg;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_handshake(struct tcp_pcb *tcp, tcp_ssl_handshake_cb_t arg)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->on_handshake = arg;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->on_error = arg;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
static tcp_ssl_file_cb_t _tcp_ssl_file_cb = NULL;
|
||||
static void * _tcp_ssl_file_arg = NULL;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_file(tcp_ssl_file_cb_t cb, void * arg)
|
||||
{
|
||||
_tcp_ssl_file_cb = cb;
|
||||
_tcp_ssl_file_arg = arg;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int ax_get_file(const char *filename, uint8_t **buf)
|
||||
{
|
||||
//TCP_SSL_DEBUG("ax_get_file: %s\n", filename);
|
||||
if (_tcp_ssl_file_cb)
|
||||
{
|
||||
return _tcp_ssl_file_cb(_tcp_ssl_file_arg, filename, buf);
|
||||
}
|
||||
|
||||
*buf = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
tcp_ssl_t* tcp_ssl_get_by_fd(int fd)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_array;
|
||||
|
||||
while (item && item->fd != fd)
|
||||
{
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The LWIP tcp raw version of the SOCKET_WRITE(A, B, C)
|
||||
*/
|
||||
int ax_port_write(int fd, uint8_t *data, uint16_t len)
|
||||
{
|
||||
tcp_ssl_t *fd_data = NULL;
|
||||
int tcp_len = 0;
|
||||
err_t err = ERR_OK;
|
||||
|
||||
//TCP_SSL_DEBUG("ax_port_write: %d, %d\n", fd, len);
|
||||
|
||||
fd_data = tcp_ssl_get_by_fd(fd);
|
||||
|
||||
if (fd_data == NULL)
|
||||
{
|
||||
//TCP_SSL_DEBUG("ax_port_write: tcp_ssl[%d] is NULL\n", fd);
|
||||
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
if (data == NULL || len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tcp_sndbuf(fd_data->tcp) < len)
|
||||
{
|
||||
tcp_len = tcp_sndbuf(fd_data->tcp);
|
||||
|
||||
if (tcp_len == 0)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_write: tcp_sndbuf is zero: %d\n", len);
|
||||
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tcp_len = len;
|
||||
}
|
||||
|
||||
if (tcp_len > 2 * fd_data->tcp->mss)
|
||||
{
|
||||
tcp_len = 2 * fd_data->tcp->mss;
|
||||
}
|
||||
|
||||
err = tcp_write(fd_data->tcp, data, tcp_len, TCP_WRITE_FLAG_COPY);
|
||||
|
||||
if (err < ERR_OK)
|
||||
{
|
||||
if (err == ERR_MEM)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_write: No memory %d (%d)\n", tcp_len, len);
|
||||
return err;
|
||||
}
|
||||
|
||||
TCP_SSL_DEBUG("ax_port_write: tcp_write error: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
else if (err == ERR_OK)
|
||||
{
|
||||
//TCP_SSL_DEBUG("ax_port_write: tcp_output: %d / %d\n", tcp_len, len);
|
||||
err = tcp_output(fd_data->tcp);
|
||||
|
||||
if (err != ERR_OK)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_write: tcp_output err: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
fd_data->last_wr += tcp_len;
|
||||
|
||||
return tcp_len;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The LWIP tcp raw version of the SOCKET_READ(A, B, C)
|
||||
*/
|
||||
int ax_port_read(int fd, uint8_t *data, int len)
|
||||
{
|
||||
tcp_ssl_t *fd_data = NULL;
|
||||
uint8_t *read_buf = NULL;
|
||||
uint8_t *pread_buf = NULL;
|
||||
u16_t recv_len = 0;
|
||||
|
||||
//TCP_SSL_DEBUG("ax_port_read: %d, %d\n", fd, len);
|
||||
|
||||
fd_data = tcp_ssl_get_by_fd(fd);
|
||||
|
||||
if (fd_data == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_read: tcp_ssl[%d] is NULL\n", fd);
|
||||
|
||||
return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;
|
||||
}
|
||||
|
||||
if (fd_data->tcp_pbuf == NULL || fd_data->tcp_pbuf->tot_len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_buf = (uint8_t*) calloc(fd_data->tcp_pbuf->len + 1, sizeof(uint8_t));
|
||||
pread_buf = read_buf;
|
||||
|
||||
if (pread_buf != NULL)
|
||||
{
|
||||
recv_len = pbuf_copy_partial(fd_data->tcp_pbuf, read_buf, len, fd_data->pbuf_offset);
|
||||
fd_data->pbuf_offset += recv_len;
|
||||
}
|
||||
|
||||
if (recv_len != 0)
|
||||
{
|
||||
memcpy(data, read_buf, recv_len);
|
||||
}
|
||||
|
||||
if (len < recv_len)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_read: got %d bytes more than expected\n", recv_len - len);
|
||||
}
|
||||
|
||||
free(pread_buf);
|
||||
pread_buf = NULL;
|
||||
|
||||
return recv_len;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void ax_wdt_feed() {}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#endif // ASYNC_TCP_SSL_ENABLED
|
||||
@@ -0,0 +1,73 @@
|
||||
#ifndef LWIPR_COMPAT_H
|
||||
#define LWIPR_COMPAT_H
|
||||
|
||||
#include <async_config.h>
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
|
||||
#include "lwipopts.h"
|
||||
/*
|
||||
All those functions will run only if LWIP tcp raw mode is used
|
||||
*/
|
||||
#if LWIP_RAW==1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "include/ssl.h"
|
||||
|
||||
#define ERR_TCP_SSL_INVALID_SSL -101
|
||||
#define ERR_TCP_SSL_INVALID_TCP -102
|
||||
#define ERR_TCP_SSL_INVALID_CLIENTFD -103
|
||||
#define ERR_TCP_SSL_INVALID_CLIENTFD_DATA -104
|
||||
#define ERR_TCP_SSL_INVALID_DATA -105
|
||||
|
||||
#define TCP_SSL_TYPE_CLIENT 0
|
||||
#define TCP_SSL_TYPE_SERVER 1
|
||||
|
||||
#define tcp_ssl_ssl_write(A, B, C) tcp_ssl_write(A, B, C)
|
||||
#define tcp_ssl_ssl_read(A, B) tcp_ssl_read(A, B)
|
||||
|
||||
typedef void (* tcp_ssl_data_cb_t)(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len);
|
||||
typedef void (* tcp_ssl_handshake_cb_t)(void *arg, struct tcp_pcb *tcp, SSL *ssl);
|
||||
typedef void (* tcp_ssl_error_cb_t)(void *arg, struct tcp_pcb *tcp, int8_t error);
|
||||
typedef int (* tcp_ssl_file_cb_t)(void *arg, const char *filename, uint8_t **buf);
|
||||
|
||||
uint8_t tcp_ssl_has_client();
|
||||
|
||||
int tcp_ssl_new_client(struct tcp_pcb *tcp);
|
||||
|
||||
SSL_CTX * tcp_ssl_new_server_ctx(const char *cert, const char *private_key_file, const char *password);
|
||||
int tcp_ssl_new_server(struct tcp_pcb *tcp, SSL_CTX* ssl_ctx);
|
||||
int tcp_ssl_is_server(struct tcp_pcb *tcp);
|
||||
|
||||
int tcp_ssl_free(struct tcp_pcb *tcp);
|
||||
int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p);
|
||||
|
||||
#ifdef AXTLS_2_0_0_SNDBUF
|
||||
int tcp_ssl_sndbuf(struct tcp_pcb *tcp);
|
||||
#endif
|
||||
|
||||
int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len);
|
||||
|
||||
void tcp_ssl_file(tcp_ssl_file_cb_t cb, void * arg);
|
||||
|
||||
void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg);
|
||||
void tcp_ssl_data(struct tcp_pcb *tcp, tcp_ssl_data_cb_t arg);
|
||||
void tcp_ssl_handshake(struct tcp_pcb *tcp, tcp_ssl_handshake_cb_t arg);
|
||||
void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg);
|
||||
|
||||
SSL * tcp_ssl_get_ssl(struct tcp_pcb *tcp);
|
||||
bool tcp_ssl_has(struct tcp_pcb *tcp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_RAW==1 */
|
||||
|
||||
#endif /* ASYNC_TCP_SSL_ENABLED */
|
||||
|
||||
#endif /* LWIPR_COMPAT_H */
|
||||
@@ -0,0 +1,70 @@
|
||||
# Code formatting rules for Arduino libraries, modified from for KH libraries:
|
||||
#
|
||||
# https://github.com/arduino/Arduino/blob/master/build/shared/examples_formatter.conf
|
||||
#
|
||||
|
||||
# astyle --style=allman -s2 -t2 -C -S -xW -Y -M120 -f -p -xg -H -xb -c --xC120 -xL *.h *.cpp *.ino
|
||||
|
||||
--mode=c
|
||||
--lineend=linux
|
||||
--style=allman
|
||||
|
||||
# -r or -R
|
||||
#--recursive
|
||||
|
||||
# -c => Converts tabs into spaces
|
||||
convert-tabs
|
||||
|
||||
# -s2 => 2 spaces indentation
|
||||
--indent=spaces=2
|
||||
|
||||
# -t2 => tab =2 spaces
|
||||
#--indent=tab=2
|
||||
|
||||
# -C
|
||||
--indent-classes
|
||||
|
||||
# -S
|
||||
--indent-switches
|
||||
|
||||
# -xW
|
||||
--indent-preproc-block
|
||||
|
||||
# -Y => indent classes, switches (and cases), comments starting at column 1
|
||||
--indent-col1-comments
|
||||
|
||||
# -M120 => maximum of 120 spaces to indent a continuation line
|
||||
--max-continuation-indent=120
|
||||
|
||||
# -xC120 => max‑code‑length will break a line if the code exceeds # characters
|
||||
--max-code-length=120
|
||||
|
||||
# -f =>
|
||||
--break-blocks
|
||||
|
||||
# -p => put a space around operators
|
||||
--pad-oper
|
||||
|
||||
# -xg => Insert space padding after commas
|
||||
--pad-comma
|
||||
|
||||
# -H => put a space after if/for/while
|
||||
pad-header
|
||||
|
||||
# -xb => Break one line headers (e.g. if/for/while)
|
||||
--break-one-line-headers
|
||||
|
||||
# -c => Converts tabs into spaces
|
||||
#--convert-tabs
|
||||
|
||||
# if you like one-liners, keep them
|
||||
#keep-one-line-statements
|
||||
|
||||
# -xV
|
||||
--attach-closing-while
|
||||
|
||||
#unpad-paren
|
||||
|
||||
# -xp
|
||||
remove-comment-prefix
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
for dir in . ; do
|
||||
find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.ino" \) -exec astyle --suffix=none --options=./utils/astyle_library.conf \{\} \;
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user