diff --git a/interface/package.json b/interface/package.json
index 6f5a18cc6..b3adefc58 100644
--- a/interface/package.json
+++ b/interface/package.json
@@ -30,7 +30,7 @@
"@mui/material": "^5.15.19",
"@table-library/react-table-library": "4.1.7",
"@types/lodash-es": "^4.17.12",
- "@types/node": "^20.14.1",
+ "@types/node": "^20.14.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-router-dom": "^5.3.3",
@@ -50,7 +50,7 @@
"typescript": "^5.4.5"
},
"devDependencies": {
- "@babel/core": "^7.24.6",
+ "@babel/core": "^7.24.7",
"@eslint/js": "^9.4.0",
"@preact/compat": "^17.1.2",
"@preact/preset-vite": "^2.8.2",
@@ -60,11 +60,11 @@
"eslint": "^9.4.0",
"eslint-config-prettier": "^9.1.0",
"preact": "^10.22.0",
- "prettier": "^3.3.0",
+ "prettier": "^3.3.1",
"rollup-plugin-visualizer": "^5.12.0",
- "terser": "^5.31.0",
+ "terser": "^5.31.1",
"typescript-eslint": "^7.12.0",
- "vite": "^5.2.12",
+ "vite": "^5.2.13",
"vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^4.3.2"
},
diff --git a/interface/src/framework/system/SystemStatus.tsx b/interface/src/framework/system/SystemStatus.tsx
index 4b616fac4..73f5db67d 100644
--- a/interface/src/framework/system/SystemStatus.tsx
+++ b/interface/src/framework/system/SystemStatus.tsx
@@ -10,8 +10,10 @@ import MemoryIcon from '@mui/icons-material/Memory';
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
import RefreshIcon from '@mui/icons-material/Refresh';
+import RouterIcon from '@mui/icons-material/Router';
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
import TimerIcon from '@mui/icons-material/Timer';
+import WifiIcon from '@mui/icons-material/Wifi';
import {
Avatar,
Box,
@@ -38,7 +40,7 @@ import ListMenuItem from 'components/layout/ListMenuItem';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
import { busConnectionStatus } from 'project/types';
-import { NTPSyncStatus } from 'types';
+import { NTPSyncStatus, NetworkConnectionStatus } from 'types';
import RestartMonitor from './RestartMonitor';
@@ -151,6 +153,46 @@ const SystemStatus: FC = () => {
}
};
+ const networkStatusHighlight = () => {
+ switch (data.network_status) {
+ case NetworkConnectionStatus.WIFI_STATUS_IDLE:
+ case NetworkConnectionStatus.WIFI_STATUS_DISCONNECTED:
+ case NetworkConnectionStatus.WIFI_STATUS_NO_SHIELD:
+ return theme.palette.info.main;
+ case NetworkConnectionStatus.WIFI_STATUS_CONNECTED:
+ case NetworkConnectionStatus.ETHERNET_STATUS_CONNECTED:
+ return theme.palette.success.main;
+ case NetworkConnectionStatus.WIFI_STATUS_CONNECT_FAILED:
+ case NetworkConnectionStatus.WIFI_STATUS_CONNECTION_LOST:
+ return theme.palette.error.main;
+ default:
+ return theme.palette.warning.main;
+ }
+ };
+
+ const networkStatus = () => {
+ switch (data.network_status) {
+ case NetworkConnectionStatus.WIFI_STATUS_NO_SHIELD:
+ return LL.INACTIVE(1);
+ case NetworkConnectionStatus.WIFI_STATUS_IDLE:
+ return LL.IDLE();
+ case NetworkConnectionStatus.WIFI_STATUS_NO_SSID_AVAIL:
+ return 'No SSID Available';
+ case NetworkConnectionStatus.WIFI_STATUS_CONNECTED:
+ return LL.CONNECTED(0) + ' (WiFi, ' + data.wifi_rssi + ' dBm)';
+ case NetworkConnectionStatus.ETHERNET_STATUS_CONNECTED:
+ return LL.CONNECTED(0) + ' (Ethernet)';
+ case NetworkConnectionStatus.WIFI_STATUS_CONNECT_FAILED:
+ return LL.CONNECTED(1) + ' ' + LL.FAILED(0);
+ case NetworkConnectionStatus.WIFI_STATUS_CONNECTION_LOST:
+ return LL.CONNECTED(1) + ' ' + LL.LOST();
+ case NetworkConnectionStatus.WIFI_STATUS_DISCONNECTED:
+ return LL.DISCONNECTED();
+ default:
+ return LL.UNKNOWN();
+ }
+ };
+
const activeHighlight = (value: boolean) =>
value ? theme.palette.success.main : theme.palette.info.main;
@@ -296,7 +338,7 @@ const SystemStatus: FC = () => {
}
variant="outlined"
- color="primary"
+ color="error"
onClick={() => setConfirmRestart(true)}
>
{LL.RESTART()}
@@ -355,6 +397,20 @@ const SystemStatus: FC = () => {
/>
+
+
+
{
const { LL } = useI18nContext();
const [numChanges, setNumChanges] = useState(0);
+ const [licenseChanges, setLicenseChanges] = useState(0);
const blocker = useBlocker(numChanges !== 0);
+ const [selectedModuleItem, setSelectedModuleItem] = useState();
+ const [dialogOpen, setDialogOpen] = useState(false);
+ const [restarting, setRestarting] = useState(false);
+ const [restartNeeded, setRestartNeeded] = useState(false);
+
const {
data: modules,
send: fetchModules,
@@ -44,6 +56,17 @@ const Modules: FC = () => {
initialData: []
});
+ const { send: restartCommand } = useRequest(SystemApi.restart(), {
+ immediate: false
+ });
+
+ const restart = async () => {
+ await restartCommand().catch((error: Error) => {
+ toast.error(error.message);
+ });
+ setRestarting(true);
+ };
+
const { send: writeModules } = useRequest(
(data: Modules) => EMSESP.writeModules(data),
{
@@ -53,7 +76,7 @@ const Modules: FC = () => {
const modules_theme = useTheme({
Table: `
- --data-table-library_grid-template-columns: 48px 180px 120px 100px repeat(1, minmax(160px, 1fr));
+ --data-table-library_grid-template-columns: 48px 180px 120px 100px repeat(1, minmax(160px, 1fr)) 180px;
`,
BaseRow: `
font-size: 14px;
@@ -93,6 +116,20 @@ const Modules: FC = () => {
`
});
+ const onDialogClose = () => {
+ setDialogOpen(false);
+ };
+
+ const onDialogSave = (updatedItem: ModuleItem) => {
+ setDialogOpen(false);
+ updateModuleItem(updatedItem);
+ };
+
+ const editModuleItem = useCallback((mi: ModuleItem) => {
+ setSelectedModuleItem(mi);
+ setDialogOpen(true);
+ }, []);
+
const onCancel = async () => {
await fetchModules().then(() => {
setNumChanges(0);
@@ -100,16 +137,20 @@ const Modules: FC = () => {
};
function hasModulesChanged(mi: ModuleItem) {
- return mi.enabled !== mi.o_enabled;
+ return mi.enabled !== mi.o_enabled || mi.license !== mi.o_license;
}
- const selectModule = (updatedItem: ModuleItem) => {
- updatedItem.enabled = !updatedItem.enabled;
+ function hasModuleLicenseChanged(mi: ModuleItem) {
+ return mi.license !== mi.o_license;
+ }
+
+ const updateModuleItem = (updatedItem: ModuleItem) => {
updateState('modules', (data: ModuleItem[]) => {
const new_data = data.map((mi) =>
mi.id === updatedItem.id ? { ...mi, ...updatedItem } : mi
);
setNumChanges(new_data.filter((mi) => hasModulesChanged(mi)).length);
+ setLicenseChanges(new_data.filter((mi) => hasModuleLicenseChanged(mi)).length);
return new_data;
});
};
@@ -117,12 +158,13 @@ const Modules: FC = () => {
const saveModules = async () => {
await writeModules({
modules: modules.map((condensed_mi) => ({
- name: condensed_mi.name,
- enabled: condensed_mi.enabled
+ key: condensed_mi.key,
+ enabled: condensed_mi.enabled,
+ license: condensed_mi.license
}))
})
.then(() => {
- toast.success('Modules saved');
+ toast.success(LL.MODULES_UPDATED());
})
.catch((error: Error) => {
toast.error(error.message);
@@ -130,104 +172,134 @@ const Modules: FC = () => {
.finally(() => {
setNumChanges(0);
});
+ setRestartNeeded(licenseChanges > 0);
};
- const renderModules = () => {
+ const renderContent = () => {
if (!modules) {
return ;
}
- useLayoutTitle('Modules');
+ useLayoutTitle(LL.MODULES());
if (modules.length === 0) {
return (
- No modules detected
+ {LL.MODULES_NONE()}
);
}
+ const colorStatus = (status: number) => {
+ if (status === 1) {
+ return Pending Activation
;
+ }
+ return Activated
;
+ };
+
return (
-
- {(tableList: ModuleItem[]) => (
- <>
-
-
-
- {LL.NAME(0)}
- Author
- {LL.VERSION()}
- {LL.STATUS_OF('')}
-
-
-
- {tableList.map((mi: ModuleItem) => (
- selectModule(mi)}>
- |
- {mi.enabled ? (
-
- ) : (
-
- )}
- |
- {mi.name} |
- {mi.author} |
- {mi.version} |
- {mi.status} |
-
- ))}
-
- >
+ <>
+
+ {LL.MODULES_DESCRIPTION()}
+
+
+ {(tableList: ModuleItem[]) => (
+ <>
+
+
+
+ {LL.NAME(0)}
+ Author
+ {LL.VERSION()}
+ Message
+ {LL.STATUS_OF('')}
+
+
+
+ {tableList.map((mi: ModuleItem) => (
+ editModuleItem(mi)}>
+ |
+ {mi.enabled ? (
+
+ ) : (
+
+ )}
+ |
+ {mi.name} |
+ {mi.author} |
+ {mi.version} |
+ {mi.message} |
+ {colorStatus(mi.status)} |
+
+ ))}
+
+ >
+ )}
+
+
+ {restartNeeded ? (
+
+ }
+ variant="contained"
+ color="error"
+ onClick={restart}
+ >
+ {LL.RESTART()}
+
+
+ ) : (
+
+
+ {numChanges !== 0 && (
+
+ }
+ variant="outlined"
+ onClick={onCancel}
+ color="secondary"
+ >
+ {LL.CANCEL()}
+
+ }
+ variant="contained"
+ color="info"
+ onClick={saveModules}
+ >
+ {LL.APPLY_CHANGES(numChanges)}
+
+
+ )}
+
+
)}
-
+ >
);
};
return (
{blocker ? : null}
-
-
- Activate or de-activate EMS-ESP library modules by selecting (**
- experimental **)
-
-
- {renderModules()}
-
-
-
- {numChanges !== 0 && (
-
- }
- variant="outlined"
- onClick={onCancel}
- color="secondary"
- >
- {LL.CANCEL()}
-
- }
- variant="contained"
- color="info"
- onClick={saveModules}
- >
- {LL.APPLY_CHANGES(numChanges)}
-
-
- )}
-
-
+ {restarting ? : renderContent()}
+ {selectedModuleItem && (
+
+ )}
);
};
diff --git a/interface/src/project/ModulesDialog.tsx b/interface/src/project/ModulesDialog.tsx
new file mode 100644
index 000000000..f3293ab7a
--- /dev/null
+++ b/interface/src/project/ModulesDialog.tsx
@@ -0,0 +1,108 @@
+import { useEffect, useState } from 'react';
+
+import CancelIcon from '@mui/icons-material/Cancel';
+import DoneIcon from '@mui/icons-material/Done';
+import {
+ Box,
+ Button,
+ Checkbox,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Grid,
+ TextField
+} from '@mui/material';
+
+import { dialogStyle } from 'CustomTheme';
+import { BlockFormControlLabel } from 'components';
+import { useI18nContext } from 'i18n/i18n-react';
+import { updateValue } from 'utils';
+
+import type { ModuleItem } from './types';
+
+interface ModulesDialogProps {
+ open: boolean;
+ onClose: () => void;
+ onSave: (mi: ModuleItem) => void;
+ selectedItem: ModuleItem;
+}
+
+const ModulesDialog = ({
+ open,
+ onClose,
+ onSave,
+ selectedItem
+}: ModulesDialogProps) => {
+ const { LL } = useI18nContext();
+ const [editItem, setEditItem] = useState(selectedItem);
+
+ const updateFormValue = updateValue(setEditItem);
+
+ useEffect(() => {
+ if (open) {
+ setEditItem(selectedItem);
+ }
+ }, [open, selectedItem]);
+
+ const close = () => {
+ onClose();
+ };
+
+ const save = () => {
+ onSave(editItem);
+ };
+
+ return (
+
+ );
+};
+
+export default ModulesDialog;
diff --git a/interface/src/project/api.ts b/interface/src/project/api.ts
index 9a778c839..ae3336361 100644
--- a/interface/src/project/api.ts
+++ b/interface/src/project/api.ts
@@ -113,7 +113,8 @@ export const readModules = () =>
transformData(data) {
return (data as Modules).modules.map((mi: ModuleItem) => ({
...mi,
- o_enabled: mi.enabled
+ o_enabled: mi.enabled,
+ o_license: mi.license
}));
}
});
diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts
index e864e5ba8..c2a28423b 100644
--- a/interface/src/project/types.ts
+++ b/interface/src/project/types.ts
@@ -310,12 +310,16 @@ export interface Schedule {
export interface ModuleItem {
id: number; // unique index
+ key: string;
name: string;
author: string;
version: string;
- status: string;
+ status: number;
+ message: string;
enabled: boolean;
+ license: string;
o_enabled?: boolean;
+ o_license?: string;
}
export interface Modules {
diff --git a/interface/src/types/system.ts b/interface/src/types/system.ts
index de1616e0b..beb30e6a9 100644
--- a/interface/src/types/system.ts
+++ b/interface/src/types/system.ts
@@ -1,5 +1,7 @@
import type { busConnectionStatus } from 'project/types';
+import type { NetworkConnectionStatus } from './network';
+
export interface ESPSystemStatus {
emsesp_version: string;
esp_platform: string;
@@ -37,6 +39,8 @@ export interface SystemStatus {
ntp_status: number;
mqtt_status: boolean;
ap_status: boolean;
+ network_status: NetworkConnectionStatus;
+ wifi_rssi: number;
}
export enum LogLevel {
diff --git a/interface/yarn.lock b/interface/yarn.lock
index efbd3cad2..829ef28bd 100644
--- a/interface/yarn.lock
+++ b/interface/yarn.lock
@@ -39,13 +39,13 @@ __metadata:
languageName: node
linkType: hard
-"@babel/code-frame@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/code-frame@npm:7.24.6"
+"@babel/code-frame@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/code-frame@npm:7.24.7"
dependencies:
- "@babel/highlight": "npm:^7.24.6"
+ "@babel/highlight": "npm:^7.24.7"
picocolors: "npm:^1.0.0"
- checksum: 10c0/c93c6d1763530f415218c31d07359364397f19b70026abdff766164c21ed352a931cf07f3102c5fb9e04792de319e332d68bcb1f7debef601a02197f90f9ba24
+ checksum: 10c0/ab0af539473a9f5aeaac7047e377cb4f4edd255a81d84a76058595f8540784cc3fbe8acf73f1e073981104562490aabfb23008cd66dc677a456a4ed5390fdde6
languageName: node
linkType: hard
@@ -56,10 +56,10 @@ __metadata:
languageName: node
linkType: hard
-"@babel/compat-data@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/compat-data@npm:7.24.6"
- checksum: 10c0/f50abbd4008eb2a5d12139c578809cebbeaeb8e660fb12d546eb2e7c2108ae1836ab8339184a5f5ce0e95bf81bb91e18edce86b387c59db937b01693ec0bc774
+"@babel/compat-data@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/compat-data@npm:7.24.7"
+ checksum: 10c0/dcd93a5632b04536498fbe2be5af1057f635fd7f7090483d8e797878559037e5130b26862ceb359acbae93ed27e076d395ddb4663db6b28a665756ffd02d324f
languageName: node
linkType: hard
@@ -86,26 +86,26 @@ __metadata:
languageName: node
linkType: hard
-"@babel/core@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/core@npm:7.24.6"
+"@babel/core@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/core@npm:7.24.7"
dependencies:
"@ampproject/remapping": "npm:^2.2.0"
- "@babel/code-frame": "npm:^7.24.6"
- "@babel/generator": "npm:^7.24.6"
- "@babel/helper-compilation-targets": "npm:^7.24.6"
- "@babel/helper-module-transforms": "npm:^7.24.6"
- "@babel/helpers": "npm:^7.24.6"
- "@babel/parser": "npm:^7.24.6"
- "@babel/template": "npm:^7.24.6"
- "@babel/traverse": "npm:^7.24.6"
- "@babel/types": "npm:^7.24.6"
+ "@babel/code-frame": "npm:^7.24.7"
+ "@babel/generator": "npm:^7.24.7"
+ "@babel/helper-compilation-targets": "npm:^7.24.7"
+ "@babel/helper-module-transforms": "npm:^7.24.7"
+ "@babel/helpers": "npm:^7.24.7"
+ "@babel/parser": "npm:^7.24.7"
+ "@babel/template": "npm:^7.24.7"
+ "@babel/traverse": "npm:^7.24.7"
+ "@babel/types": "npm:^7.24.7"
convert-source-map: "npm:^2.0.0"
debug: "npm:^4.1.0"
gensync: "npm:^1.0.0-beta.2"
json5: "npm:^2.2.3"
semver: "npm:^6.3.1"
- checksum: 10c0/e0762a8daef7f417494d555929418cfacd6848c7fc3310ec00e6dd8cecac20b7f590e760bfc9365d2af07874a3f5599832f9c9ff7f1a9d126a168f77ba67945a
+ checksum: 10c0/4004ba454d3c20a46ea66264e06c15b82e9f6bdc35f88819907d24620da70dbf896abac1cb4cc4b6bb8642969e45f4d808497c9054a1388a386cf8c12e9b9e0d
languageName: node
linkType: hard
@@ -132,15 +132,15 @@ __metadata:
languageName: node
linkType: hard
-"@babel/generator@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/generator@npm:7.24.6"
+"@babel/generator@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/generator@npm:7.24.7"
dependencies:
- "@babel/types": "npm:^7.24.6"
+ "@babel/types": "npm:^7.24.7"
"@jridgewell/gen-mapping": "npm:^0.3.5"
"@jridgewell/trace-mapping": "npm:^0.3.25"
jsesc: "npm:^2.5.1"
- checksum: 10c0/8d71a17b386536582354afba53cc784396458a88cc9f05f0c6de0ec99475f6f539943b3566b2e733820c4928236952473831765e483c25d68cc007a6e604d782
+ checksum: 10c0/06b1f3350baf527a3309e50ffd7065f7aee04dd06e1e7db794ddfde7fe9d81f28df64edd587173f8f9295496a7ddb74b9a185d4bf4de7bb619e6d4ec45c8fd35
languageName: node
linkType: hard
@@ -166,16 +166,16 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-compilation-targets@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-compilation-targets@npm:7.24.6"
+"@babel/helper-compilation-targets@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-compilation-targets@npm:7.24.7"
dependencies:
- "@babel/compat-data": "npm:^7.24.6"
- "@babel/helper-validator-option": "npm:^7.24.6"
+ "@babel/compat-data": "npm:^7.24.7"
+ "@babel/helper-validator-option": "npm:^7.24.7"
browserslist: "npm:^4.22.2"
lru-cache: "npm:^5.1.1"
semver: "npm:^6.3.1"
- checksum: 10c0/4d41150086959f5f4d72d27bae29204192e943537ecb71df1711d1f5d8791358a44f3a5882ed3c8238ba0c874b0b55213af43767e14771765f13b8d15b262432
+ checksum: 10c0/1d580a9bcacefe65e6bf02ba1dafd7ab278269fef45b5e281d8354d95c53031e019890464e7f9351898c01502dd2e633184eb0bcda49ed2ecd538675ce310f51
languageName: node
linkType: hard
@@ -186,10 +186,12 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-environment-visitor@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-environment-visitor@npm:7.24.6"
- checksum: 10c0/fdcd18ac505ed71f40c05cc992b648a4495b0aa5310a774492a0f74d8dcf3579691102f516561a651d3de6c3a44fe64bfb3049d11c14c5857634ef1823ea409a
+"@babel/helper-environment-visitor@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-environment-visitor@npm:7.24.7"
+ dependencies:
+ "@babel/types": "npm:^7.24.7"
+ checksum: 10c0/36ece78882b5960e2d26abf13cf15ff5689bf7c325b10a2895a74a499e712de0d305f8d78bb382dd3c05cfba7e47ec98fe28aab5674243e0625cd38438dd0b2d
languageName: node
linkType: hard
@@ -203,13 +205,13 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-function-name@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-function-name@npm:7.24.6"
+"@babel/helper-function-name@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-function-name@npm:7.24.7"
dependencies:
- "@babel/template": "npm:^7.24.6"
- "@babel/types": "npm:^7.24.6"
- checksum: 10c0/5ba2f8db789b3f5a2b2239300a217aa212e303cd7bfad9c8b90563807f49215e8c679e8f8f177b6aaca2038038e29bc702b83839e1f7b4896d79c44a75cac97a
+ "@babel/template": "npm:^7.24.7"
+ "@babel/types": "npm:^7.24.7"
+ checksum: 10c0/e5e41e6cf86bd0f8bf272cbb6e7c5ee0f3e9660414174435a46653efba4f2479ce03ce04abff2aa2ef9359cf057c79c06cb7b134a565ad9c0e8a50dcdc3b43c4
languageName: node
linkType: hard
@@ -222,12 +224,12 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-hoist-variables@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-hoist-variables@npm:7.24.6"
+"@babel/helper-hoist-variables@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-hoist-variables@npm:7.24.7"
dependencies:
- "@babel/types": "npm:^7.24.6"
- checksum: 10c0/e10ec6b864aaa419ec4934f5fcb5d0cfcc9d0657584a1b6c3c42ada949d44ca6bffcdab433a90ada4396c747e551cca31ba0e565ea005ab3f50964e3817bf6cf
+ "@babel/types": "npm:^7.24.7"
+ checksum: 10c0/19ee37563bbd1219f9d98991ad0e9abef77803ee5945fd85aa7aa62a67c69efca9a801696a1b58dda27f211e878b3327789e6fd2a6f6c725ccefe36774b5ce95
languageName: node
linkType: hard
@@ -240,12 +242,13 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-module-imports@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-module-imports@npm:7.24.6"
+"@babel/helper-module-imports@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-module-imports@npm:7.24.7"
dependencies:
- "@babel/types": "npm:^7.24.6"
- checksum: 10c0/e0db3fbfcd963d138f0792ff626f940a576fcf212d02b8fe6478dccf3421bd1c2a76f8e69c7450c049985e7b63b30be309a24eeeb6ad7c2137a31b676a095a84
+ "@babel/traverse": "npm:^7.24.7"
+ "@babel/types": "npm:^7.24.7"
+ checksum: 10c0/97c57db6c3eeaea31564286e328a9fb52b0313c5cfcc7eee4bc226aebcf0418ea5b6fe78673c0e4a774512ec6c86e309d0f326e99d2b37bfc16a25a032498af0
languageName: node
linkType: hard
@@ -264,18 +267,18 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-module-transforms@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-module-transforms@npm:7.24.6"
+"@babel/helper-module-transforms@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-module-transforms@npm:7.24.7"
dependencies:
- "@babel/helper-environment-visitor": "npm:^7.24.6"
- "@babel/helper-module-imports": "npm:^7.24.6"
- "@babel/helper-simple-access": "npm:^7.24.6"
- "@babel/helper-split-export-declaration": "npm:^7.24.6"
- "@babel/helper-validator-identifier": "npm:^7.24.6"
+ "@babel/helper-environment-visitor": "npm:^7.24.7"
+ "@babel/helper-module-imports": "npm:^7.24.7"
+ "@babel/helper-simple-access": "npm:^7.24.7"
+ "@babel/helper-split-export-declaration": "npm:^7.24.7"
+ "@babel/helper-validator-identifier": "npm:^7.24.7"
peerDependencies:
"@babel/core": ^7.0.0
- checksum: 10c0/9e2e3d0ddb397b36b9e8c7d94e175a36be8cb888ef370cefef2cdfd53ae1f87d567b268bd90ed9a6c706485a8de3da19cac577657613e9cd17210b91cbdfb00b
+ checksum: 10c0/4f311755fcc3b4cbdb689386309cdb349cf0575a938f0b9ab5d678e1a81bbb265aa34ad93174838245f2ac7ff6d5ddbd0104638a75e4e961958ed514355687b6
languageName: node
linkType: hard
@@ -295,12 +298,13 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-simple-access@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-simple-access@npm:7.24.6"
+"@babel/helper-simple-access@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-simple-access@npm:7.24.7"
dependencies:
- "@babel/types": "npm:^7.24.6"
- checksum: 10c0/b17e404dd6c9787fc7d558aea5222471a77e29596705f0d10b4c2a58b9d71ff7eae915094204848cc1af99b771553caa69337a768b9abdd82b54a0050ba83eb9
+ "@babel/traverse": "npm:^7.24.7"
+ "@babel/types": "npm:^7.24.7"
+ checksum: 10c0/7230e419d59a85f93153415100a5faff23c133d7442c19e0cd070da1784d13cd29096ee6c5a5761065c44e8164f9f80e3a518c41a0256df39e38f7ad6744fed7
languageName: node
linkType: hard
@@ -313,12 +317,12 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-split-export-declaration@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-split-export-declaration@npm:7.24.6"
+"@babel/helper-split-export-declaration@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-split-export-declaration@npm:7.24.7"
dependencies:
- "@babel/types": "npm:^7.24.6"
- checksum: 10c0/53a5dd8691fdffc89cc7fcf5aed0ad1d8bc39796a5782a3d170dcbf249eb5c15cc8a290e8d09615711d18798ad04a7d0694ab5195d35fa651abbc1b9c885d6a8
+ "@babel/types": "npm:^7.24.7"
+ checksum: 10c0/0254577d7086bf09b01bbde98f731d4fcf4b7c3fa9634fdb87929801307c1f6202a1352e3faa5492450fa8da4420542d44de604daf540704ff349594a78184f6
languageName: node
linkType: hard
@@ -329,10 +333,10 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-string-parser@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-string-parser@npm:7.24.6"
- checksum: 10c0/95115bf676e92c4e99166395649108d97447e6cabef1fabaec8cdbc53a43f27b5df2268ff6534439d405bc1bd06685b163eb3b470455bd49f69159dada414145
+"@babel/helper-string-parser@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-string-parser@npm:7.24.7"
+ checksum: 10c0/47840c7004e735f3dc93939c77b099bb41a64bf3dda0cae62f60e6f74a5ff80b63e9b7cf77b5ec25a324516381fc994e1f62f922533236a8e3a6af57decb5e1e
languageName: node
linkType: hard
@@ -343,10 +347,10 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-validator-identifier@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-validator-identifier@npm:7.24.6"
- checksum: 10c0/d29d2e3fca66c31867a009014169b93f7bc21c8fc1dd7d0b9d85d7a4000670526ff2222d966febb75a6e12f9859a31d1e75b558984e28ecb69651314dd0a6fd1
+"@babel/helper-validator-identifier@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-validator-identifier@npm:7.24.7"
+ checksum: 10c0/87ad608694c9477814093ed5b5c080c2e06d44cb1924ae8320474a74415241223cc2a725eea2640dd783ff1e3390e5f95eede978bc540e870053152e58f1d651
languageName: node
linkType: hard
@@ -357,10 +361,10 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helper-validator-option@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helper-validator-option@npm:7.24.6"
- checksum: 10c0/787268dff5cf77f3b704454b96ab7b58aa4f43b2808247e51859a103a1c28a9c252100f830433f4b37a73f4a61ba745bbeef4cdccbab48c1e9adf037f4ca3491
+"@babel/helper-validator-option@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helper-validator-option@npm:7.24.7"
+ checksum: 10c0/21aea2b7bc5cc8ddfb828741d5c8116a84cbc35b4a3184ec53124f08e09746f1f67a6f9217850188995ca86059a7942e36d8965a6730784901def777b7e8a436
languageName: node
linkType: hard
@@ -375,13 +379,13 @@ __metadata:
languageName: node
linkType: hard
-"@babel/helpers@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/helpers@npm:7.24.6"
+"@babel/helpers@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/helpers@npm:7.24.7"
dependencies:
- "@babel/template": "npm:^7.24.6"
- "@babel/types": "npm:^7.24.6"
- checksum: 10c0/e5b5c0919fd6fa56ae11c15a72962d8de0ac19db524849554af28cf08ac32f9ae5aee49a43146eb150f54418cefb8e890fa2b2f33d029434dc7777dbcdfd5bac
+ "@babel/template": "npm:^7.24.7"
+ "@babel/types": "npm:^7.24.7"
+ checksum: 10c0/aa8e230f6668773e17e141dbcab63e935c514b4b0bf1fed04d2eaefda17df68e16b61a56573f7f1d4d1e605ce6cc162b5f7e9fdf159fde1fd9b77c920ae47d27
languageName: node
linkType: hard
@@ -397,15 +401,15 @@ __metadata:
languageName: node
linkType: hard
-"@babel/highlight@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/highlight@npm:7.24.6"
+"@babel/highlight@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/highlight@npm:7.24.7"
dependencies:
- "@babel/helper-validator-identifier": "npm:^7.24.6"
+ "@babel/helper-validator-identifier": "npm:^7.24.7"
chalk: "npm:^2.4.2"
js-tokens: "npm:^4.0.0"
picocolors: "npm:^1.0.0"
- checksum: 10c0/5bbc31695e5d44e97feb267f7aaf4c52908560d184ffeb2e2e57aae058d40125592931883889413e19def3326895ddb41ff45e090fa90b459d8c294b4ffc238c
+ checksum: 10c0/674334c571d2bb9d1c89bdd87566383f59231e16bcdcf5bb7835babdf03c9ae585ca0887a7b25bdf78f303984af028df52831c7989fecebb5101cc132da9393a
languageName: node
linkType: hard
@@ -418,12 +422,12 @@ __metadata:
languageName: node
linkType: hard
-"@babel/parser@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/parser@npm:7.24.6"
+"@babel/parser@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/parser@npm:7.24.7"
bin:
parser: ./bin/babel-parser.js
- checksum: 10c0/cbef70923078a20fe163b03f4a6482be65ed99d409a57f3091a23ce3a575ee75716c30e7ea9f40b692ac5660f34055f4cbeb66a354fad15a6cf1fca35c3496c5
+ checksum: 10c0/8b244756872185a1c6f14b979b3535e682ff08cb5a2a5fd97cc36c017c7ef431ba76439e95e419d43000c5b07720495b00cf29a7f0d9a483643d08802b58819b
languageName: node
linkType: hard
@@ -484,14 +488,14 @@ __metadata:
languageName: node
linkType: hard
-"@babel/template@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/template@npm:7.24.6"
+"@babel/template@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/template@npm:7.24.7"
dependencies:
- "@babel/code-frame": "npm:^7.24.6"
- "@babel/parser": "npm:^7.24.6"
- "@babel/types": "npm:^7.24.6"
- checksum: 10c0/a4d5805770de908b445f7cdcebfcb6eaa07b1ec9c7b78fd3f375a911b1522c249bddae6b96bc4aac24247cc603e3e6cffcf2fe50b4c929dfeb22de289b517525
+ "@babel/code-frame": "npm:^7.24.7"
+ "@babel/parser": "npm:^7.24.7"
+ "@babel/types": "npm:^7.24.7"
+ checksum: 10c0/95b0b3ee80fcef685b7f4426f5713a855ea2cd5ac4da829b213f8fb5afe48a2a14683c2ea04d446dbc7f711c33c5cd4a965ef34dcbe5bc387c9e966b67877ae3
languageName: node
linkType: hard
@@ -531,21 +535,21 @@ __metadata:
languageName: node
linkType: hard
-"@babel/traverse@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/traverse@npm:7.24.6"
+"@babel/traverse@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/traverse@npm:7.24.7"
dependencies:
- "@babel/code-frame": "npm:^7.24.6"
- "@babel/generator": "npm:^7.24.6"
- "@babel/helper-environment-visitor": "npm:^7.24.6"
- "@babel/helper-function-name": "npm:^7.24.6"
- "@babel/helper-hoist-variables": "npm:^7.24.6"
- "@babel/helper-split-export-declaration": "npm:^7.24.6"
- "@babel/parser": "npm:^7.24.6"
- "@babel/types": "npm:^7.24.6"
+ "@babel/code-frame": "npm:^7.24.7"
+ "@babel/generator": "npm:^7.24.7"
+ "@babel/helper-environment-visitor": "npm:^7.24.7"
+ "@babel/helper-function-name": "npm:^7.24.7"
+ "@babel/helper-hoist-variables": "npm:^7.24.7"
+ "@babel/helper-split-export-declaration": "npm:^7.24.7"
+ "@babel/parser": "npm:^7.24.7"
+ "@babel/types": "npm:^7.24.7"
debug: "npm:^4.3.1"
globals: "npm:^11.1.0"
- checksum: 10c0/39027d5fc7a241c6b71bb5872c2bdcec53743cd7ef3c151bbe6fd7cf874d15f4bc09e5d7e19e2f534b0eb2c115f5368553885fa4253aa1bc9441c6e5bf9efdaf
+ checksum: 10c0/a5135e589c3f1972b8877805f50a084a04865ccb1d68e5e1f3b94a8841b3485da4142e33413d8fd76bc0e6444531d3adf1f59f359c11ffac452b743d835068ab
languageName: node
linkType: hard
@@ -570,14 +574,14 @@ __metadata:
languageName: node
linkType: hard
-"@babel/types@npm:^7.24.6":
- version: 7.24.6
- resolution: "@babel/types@npm:7.24.6"
+"@babel/types@npm:^7.24.7":
+ version: 7.24.7
+ resolution: "@babel/types@npm:7.24.7"
dependencies:
- "@babel/helper-string-parser": "npm:^7.24.6"
- "@babel/helper-validator-identifier": "npm:^7.24.6"
+ "@babel/helper-string-parser": "npm:^7.24.7"
+ "@babel/helper-validator-identifier": "npm:^7.24.7"
to-fast-properties: "npm:^2.0.0"
- checksum: 10c0/1d94d92d97ef49030ad7f9e14cfccfeb70b1706dabcaa69037e659ec9d2c3178fb005d2088cce40d88dfc1306153d9157fe038a79ea2be92e5e6b99a59ef80cc
+ checksum: 10c0/d9ecbfc3eb2b05fb1e6eeea546836ac30d990f395ef3fe3f75ced777a222c3cfc4489492f72e0ce3d9a5a28860a1ce5f81e66b88cf5088909068b3ff4fab72c1
languageName: node
linkType: hard
@@ -1738,12 +1742,12 @@ __metadata:
languageName: node
linkType: hard
-"@types/node@npm:^20.14.1":
- version: 20.14.1
- resolution: "@types/node@npm:20.14.1"
+"@types/node@npm:^20.14.2":
+ version: 20.14.2
+ resolution: "@types/node@npm:20.14.2"
dependencies:
undici-types: "npm:~5.26.4"
- checksum: 10c0/12b7879047f50cc217bbea3add7c45e542070f6e9fb2092be97542152b7022512bcb2bf848d04f77e295c4c8699acd484e79a4a4dbe9bcfa4e89dd543d530611
+ checksum: 10c0/2d86e5f2227aaa42212e82ea0affe72799111b888ff900916376450b02b09b963ca888b20d9c332d8d2b833ed4781987867a38eaa2e4863fa8439071468b0a6f
languageName: node
linkType: hard
@@ -1962,7 +1966,7 @@ __metadata:
dependencies:
"@alova/adapter-xhr": "npm:^1.0.6"
"@alova/scene-react": "npm:^1.5.0"
- "@babel/core": "npm:^7.24.6"
+ "@babel/core": "npm:^7.24.7"
"@emotion/react": "npm:^11.11.4"
"@emotion/styled": "npm:^11.11.5"
"@eslint/js": "npm:^9.4.0"
@@ -1974,7 +1978,7 @@ __metadata:
"@trivago/prettier-plugin-sort-imports": "npm:^4.3.0"
"@types/babel__core": "npm:^7"
"@types/lodash-es": "npm:^4.17.12"
- "@types/node": "npm:^20.14.1"
+ "@types/node": "npm:^20.14.2"
"@types/react": "npm:^18.3.3"
"@types/react-dom": "npm:^18.3.0"
"@types/react-router-dom": "npm:^5.3.3"
@@ -1988,7 +1992,7 @@ __metadata:
lodash-es: "npm:^4.17.21"
mime-types: "npm:^2.1.35"
preact: "npm:^10.22.0"
- prettier: "npm:^3.3.0"
+ prettier: "npm:^3.3.1"
react: "npm:latest"
react-dom: "npm:latest"
react-dropzone: "npm:^14.2.3"
@@ -1996,11 +2000,11 @@ __metadata:
react-router-dom: "npm:^6.23.1"
react-toastify: "npm:^10.0.5"
rollup-plugin-visualizer: "npm:^5.12.0"
- terser: "npm:^5.31.0"
+ terser: "npm:^5.31.1"
typesafe-i18n: "npm:^5.26.2"
typescript: "npm:^5.4.5"
typescript-eslint: "npm:^7.12.0"
- vite: "npm:^5.2.12"
+ vite: "npm:^5.2.13"
vite-plugin-imagemin: "npm:^0.6.1"
vite-tsconfig-paths: "npm:^4.3.2"
languageName: unknown
@@ -5932,12 +5936,12 @@ __metadata:
languageName: node
linkType: hard
-"prettier@npm:^3.3.0":
- version: 3.3.0
- resolution: "prettier@npm:3.3.0"
+"prettier@npm:^3.3.1":
+ version: 3.3.1
+ resolution: "prettier@npm:3.3.1"
bin:
prettier: bin/prettier.cjs
- checksum: 10c0/d033c356320aa2e468bf29c931b094ac730d2f4defd5eb2989d8589313dec901d2fc866e3788f3d161e420b142ea4ec3dda535dbe0169ef4d0026397a68ba9cf
+ checksum: 10c0/c25a709c9f0be670dc6bcb190b622347e1dbeb6c3e7df8b0711724cb64d8647c60b839937a4df4df18e9cfb556c2b08ca9d24d9645eb5488a7fc032a2c4d5cb3
languageName: node
linkType: hard
@@ -6968,9 +6972,9 @@ __metadata:
languageName: node
linkType: hard
-"terser@npm:^5.31.0":
- version: 5.31.0
- resolution: "terser@npm:5.31.0"
+"terser@npm:^5.31.1":
+ version: 5.31.1
+ resolution: "terser@npm:5.31.1"
dependencies:
"@jridgewell/source-map": "npm:^0.3.3"
acorn: "npm:^8.8.2"
@@ -6978,7 +6982,7 @@ __metadata:
source-map-support: "npm:~0.5.20"
bin:
terser: bin/terser
- checksum: 10c0/cb127a579b03fb9dcee0d293ff24814deedcd430f447933b618e8593b7454f615b5c8493c68e86a4b0188769d5ea2af5251b5d507edb208114f7e8aebdc7c850
+ checksum: 10c0/4d49a58f64c11f3742e779a0a03aff69972ca5739decb361d909d22c8f3f7d8e2ec982a928d987d56737ad50229e8ab3f62d8ba993e4b5f360a53ed487d3c06c
languageName: node
linkType: hard
@@ -7318,9 +7322,9 @@ __metadata:
languageName: node
linkType: hard
-"vite@npm:^5.2.12":
- version: 5.2.12
- resolution: "vite@npm:5.2.12"
+"vite@npm:^5.2.13":
+ version: 5.2.13
+ resolution: "vite@npm:5.2.13"
dependencies:
esbuild: "npm:^0.20.1"
fsevents: "npm:~2.3.3"
@@ -7354,7 +7358,7 @@ __metadata:
optional: true
bin:
vite: bin/vite.js
- checksum: 10c0/f03fdfc320adea3397df3e327029fd875f8220779f679ab183a3a994e8788b4ce531fee28f830361fb274f3cf08ed9adb9429496ecefdc3faf535b38da7ea8b1
+ checksum: 10c0/f7a99da71884e69cc581dcfb43d73c8d56d73b9668d6980131603c544d6323c6003a20f376531dc0cfcf36bf5009bc465f89e6c5f8bd9d22868987aba4e4af1b
languageName: node
linkType: hard
diff --git a/lib/ESPAsyncWebServer/src/AsyncWebSocket.cpp b/lib/ESPAsyncWebServer/src/AsyncWebSocket.cpp
index 182ea0536..3bae20280 100644
--- a/lib/ESPAsyncWebServer/src/AsyncWebSocket.cpp
+++ b/lib/ESPAsyncWebServer/src/AsyncWebSocket.cpp
@@ -26,99 +26,105 @@
#include
#ifndef ESP8266
-#include "mbedtls/sha1.h"
+#if ESP_IDF_VERSION_MAJOR < 5
+#include "./port/SHA1Builder.h"
+#else
+#include
+#endif
+#include
#else
#include
#endif
#define MAX_PRINTF_LEN 64
-size_t webSocketSendFrameWindow(AsyncClient *client){
- if(!client->canSend())
- return 0;
- size_t space = client->space();
- if(space < 9)
- return 0;
- return space - 8;
+size_t webSocketSendFrameWindow(AsyncClient * client) {
+ if (!client->canSend())
+ return 0;
+ size_t space = client->space();
+ if (space < 9)
+ return 0;
+ return space - 8;
}
-size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool mask, uint8_t *data, size_t len){
- if(!client->canSend()) {
- // Serial.println("SF 1");
- return 0;
- }
- size_t space = client->space();
- if(space < 2) {
- // Serial.println("SF 2");
- return 0;
- }
- uint8_t mbuf[4] = {0,0,0,0};
- uint8_t headLen = 2;
- if(len && mask){
- headLen += 4;
- mbuf[0] = rand() % 0xFF;
- mbuf[1] = rand() % 0xFF;
- mbuf[2] = rand() % 0xFF;
- mbuf[3] = rand() % 0xFF;
- }
- if(len > 125)
- headLen += 2;
- if(space < headLen) {
- // Serial.println("SF 2");
- return 0;
- }
- space -= headLen;
+size_t webSocketSendFrame(AsyncClient * client, bool final, uint8_t opcode, bool mask, uint8_t * data, size_t len) {
+ if (!client->canSend()) {
+ // Serial.println("SF 1");
+ return 0;
+ }
+ size_t space = client->space();
+ if (space < 2) {
+ // Serial.println("SF 2");
+ return 0;
+ }
+ uint8_t mbuf[4] = {0, 0, 0, 0};
+ uint8_t headLen = 2;
+ if (len && mask) {
+ headLen += 4;
+ mbuf[0] = rand() % 0xFF;
+ mbuf[1] = rand() % 0xFF;
+ mbuf[2] = rand() % 0xFF;
+ mbuf[3] = rand() % 0xFF;
+ }
+ if (len > 125)
+ headLen += 2;
+ if (space < headLen) {
+ // Serial.println("SF 2");
+ return 0;
+ }
+ space -= headLen;
- if(len > space) len = space;
+ if (len > space)
+ len = space;
- uint8_t *buf = (uint8_t*)malloc(headLen);
- if(buf == NULL){
- //os_printf("could not malloc %u bytes for frame header\n", headLen);
- // Serial.println("SF 3");
- return 0;
- }
+ uint8_t * buf = (uint8_t *)malloc(headLen);
+ if (buf == NULL) {
+ //os_printf("could not malloc %u bytes for frame header\n", headLen);
+ // Serial.println("SF 3");
+ return 0;
+ }
- buf[0] = opcode & 0x0F;
- if(final)
- buf[0] |= 0x80;
- if(len < 126)
- buf[1] = len & 0x7F;
- else {
- buf[1] = 126;
- buf[2] = (uint8_t)((len >> 8) & 0xFF);
- buf[3] = (uint8_t)(len & 0xFF);
- }
- if(len && mask){
- buf[1] |= 0x80;
- memcpy(buf + (headLen - 4), mbuf, 4);
- }
- if(client->add((const char *)buf, headLen) != headLen){
- //os_printf("error adding %lu header bytes\n", headLen);
+ buf[0] = opcode & 0x0F;
+ if (final)
+ buf[0] |= 0x80;
+ if (len < 126)
+ buf[1] = len & 0x7F;
+ else {
+ buf[1] = 126;
+ buf[2] = (uint8_t)((len >> 8) & 0xFF);
+ buf[3] = (uint8_t)(len & 0xFF);
+ }
+ if (len && mask) {
+ buf[1] |= 0x80;
+ memcpy(buf + (headLen - 4), mbuf, 4);
+ }
+ if (client->add((const char *)buf, headLen) != headLen) {
+ //os_printf("error adding %lu header bytes\n", headLen);
+ free(buf);
+ // Serial.println("SF 4");
+ return 0;
+ }
free(buf);
- // Serial.println("SF 4");
- return 0;
- }
- free(buf);
- if(len){
- if(len && mask){
- size_t i;
- for(i=0;iadd((const char *)data, len) != len) {
+ //os_printf("error adding %lu data bytes\n", len);
+ // Serial.println("SF 5");
+ return 0;
+ }
}
- if(client->add((const char *)data, len) != len){
- //os_printf("error adding %lu data bytes\n", len);
- // Serial.println("SF 5");
- return 0;
+ if (!client->send()) {
+ //os_printf("error sending frame: %lu\n", headLen+len);
+ // Serial.println("SF 6");
+ return 0;
}
- }
- if(!client->send()){
- //os_printf("error sending frame: %lu\n", headLen+len);
- // Serial.println("SF 6");
- return 0;
- }
- // Serial.println("SF");
- return len;
+ // Serial.println("SF");
+ return len;
}
@@ -128,13 +134,11 @@ size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool
*/
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer()
- : _buffer(std::make_shared>(0))
-{
+ : _buffer(std::make_shared>(0)) {
}
-AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(uint8_t* data, size_t size)
- : _buffer(std::make_shared>(size))
-{
+AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(uint8_t * data, size_t size)
+ : _buffer(std::make_shared>(size)) {
if (_buffer->capacity() < size) {
_buffer.reset();
_buffer = std::make_shared>(0);
@@ -144,21 +148,18 @@ AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(uint8_t* data, size_t s
}
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(size_t size)
- : _buffer(std::make_shared>(size))
-{
+ : _buffer(std::make_shared>(size)) {
if (_buffer->capacity() < size) {
_buffer.reset();
_buffer = std::make_shared>(0);
}
}
-AsyncWebSocketMessageBuffer::~AsyncWebSocketMessageBuffer()
-{
+AsyncWebSocketMessageBuffer::~AsyncWebSocketMessageBuffer() {
_buffer.reset();
}
-bool AsyncWebSocketMessageBuffer::reserve(size_t size)
-{
+bool AsyncWebSocketMessageBuffer::reserve(size_t size) {
if (_buffer->capacity() >= size)
return true;
_buffer->reserve(size);
@@ -170,48 +171,50 @@ bool AsyncWebSocketMessageBuffer::reserve(size_t size)
*/
class AsyncWebSocketControl {
-private:
- uint8_t _opcode;
- uint8_t *_data;
- size_t _len;
- bool _mask;
- bool _finished;
+ private:
+ uint8_t _opcode;
+ uint8_t * _data;
+ size_t _len;
+ bool _mask;
+ bool _finished;
-public:
- AsyncWebSocketControl(uint8_t opcode, const uint8_t *data=NULL, size_t len=0, bool mask=false)
- :_opcode(opcode)
- ,_len(len)
- ,_mask(len && mask)
- ,_finished(false)
- {
+ public:
+ AsyncWebSocketControl(uint8_t opcode, const uint8_t * data = NULL, size_t len = 0, bool mask = false)
+ : _opcode(opcode)
+ , _len(len)
+ , _mask(len && mask)
+ , _finished(false) {
if (data == NULL)
_len = 0;
- if (_len)
- {
+ if (_len) {
if (_len > 125)
_len = 125;
- _data = (uint8_t*)malloc(_len);
+ _data = (uint8_t *)malloc(_len);
- if(_data == NULL)
+ if (_data == NULL)
_len = 0;
else
memcpy(_data, data, len);
- }
- else
+ } else
_data = NULL;
}
- virtual ~AsyncWebSocketControl()
- {
+ virtual ~AsyncWebSocketControl() {
if (_data != NULL)
free(_data);
}
- virtual bool finished() const { return _finished; }
- uint8_t opcode(){ return _opcode; }
- uint8_t len(){ return _len + 2; }
- size_t send(AsyncClient *client){
+ virtual bool finished() const {
+ return _finished;
+ }
+ uint8_t opcode() {
+ return _opcode;
+ }
+ uint8_t len() {
+ return _len + 2;
+ }
+ size_t send(AsyncClient * client) {
_finished = true;
return webSocketSendFrame(client, true, _opcode & 0x0F, _mask, _data, _len);
}
@@ -223,40 +226,34 @@ public:
*/
-AsyncWebSocketMessage::AsyncWebSocketMessage(std::shared_ptr> buffer, uint8_t opcode, bool mask) :
- _WSbuffer{buffer},
- _opcode(opcode & 0x07),
- _mask{mask},
- _status{_WSbuffer?WS_MSG_SENDING:WS_MSG_ERROR}
-{
-}
+AsyncWebSocketMessage::AsyncWebSocketMessage(std::shared_ptr> buffer, uint8_t opcode, bool mask)
+ : _WSbuffer{buffer}
+ , _opcode(opcode & 0x07)
+ , _mask{mask}
+ , _status{_WSbuffer ? WS_MSG_SENDING : WS_MSG_ERROR} {
+}
-void AsyncWebSocketMessage::ack(size_t len, uint32_t time)
-{
+void AsyncWebSocketMessage::ack(size_t len, uint32_t time) {
(void)time;
_acked += len;
- if (_sent >= _WSbuffer->size() && _acked >= _ack)
- {
+ if (_sent >= _WSbuffer->size() && _acked >= _ack) {
_status = WS_MSG_SENT;
}
//ets_printf("A: %u\n", len);
}
-size_t AsyncWebSocketMessage::send(AsyncClient *client)
-{
+size_t AsyncWebSocketMessage::send(AsyncClient * client) {
if (_status != WS_MSG_SENDING)
return 0;
- if (_acked < _ack){
+ if (_acked < _ack) {
return 0;
}
- if (_sent == _WSbuffer->size())
- {
- if(_acked == _ack)
+ if (_sent == _WSbuffer->size()) {
+ if (_acked == _ack)
_status = WS_MSG_SENT;
return 0;
}
- if (_sent > _WSbuffer->size())
- {
+ if (_sent > _WSbuffer->size()) {
_status = WS_MSG_ERROR;
//ets_printf("E: %u > %u\n", _sent, _WSbuffer->length());
return 0;
@@ -270,17 +267,17 @@ size_t AsyncWebSocketMessage::send(AsyncClient *client)
}
_sent += toSend;
- _ack += toSend + ((toSend < 126)?2:4) + (_mask * 4);
+ _ack += toSend + ((toSend < 126) ? 2 : 4) + (_mask * 4);
//ets_printf("W: %u %u\n", _sent - toSend, toSend);
- bool final = (_sent == _WSbuffer->size());
- uint8_t* dPtr = (uint8_t*)(_WSbuffer->data() + (_sent - toSend));
- uint8_t opCode = (toSend && _sent == toSend)?_opcode:(uint8_t)WS_CONTINUATION;
+ bool final = (_sent == _WSbuffer->size());
+ uint8_t * dPtr = (uint8_t *)(_WSbuffer->data() + (_sent - toSend));
+ uint8_t opCode = (toSend && _sent == toSend) ? _opcode : (uint8_t)WS_CONTINUATION;
size_t sent = webSocketSendFrame(client, final, opCode, _mask, dPtr, toSend);
- _status = WS_MSG_SENDING;
- if (toSend && sent != toSend){
+ _status = WS_MSG_SENDING;
+ if (toSend && sent != toSend) {
//ets_printf("E: %u != %u\n", toSend, sent);
_sent -= (toSend - sent);
_ack -= (toSend - sent);
@@ -293,33 +290,61 @@ size_t AsyncWebSocketMessage::send(AsyncClient *client)
/*
* Async WebSocket Client
*/
- const char * AWSC_PING_PAYLOAD = "ESPAsyncWebServer-PING";
- const size_t AWSC_PING_PAYLOAD_LEN = 22;
+const char * AWSC_PING_PAYLOAD = "ESPAsyncWebServer-PING";
+const size_t AWSC_PING_PAYLOAD_LEN = 22;
-AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server)
- : _tempObject(NULL)
-{
- _client = request->client();
- _server = server;
- _clientId = _server->_getNextId();
- _status = WS_CONNECTED;
- _pstate = 0;
+AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest * request, AsyncWebSocket * server)
+ : _tempObject(NULL) {
+ _client = request->client();
+ _server = server;
+ _clientId = _server->_getNextId();
+ _status = WS_CONNECTED;
+ _pstate = 0;
_lastMessageTime = millis();
_keepAlivePeriod = 0;
_client->setRxTimeout(0);
- _client->onError([](void *r, AsyncClient* c, int8_t error){ (void)c; ((AsyncWebSocketClient*)(r))->_onError(error); }, this);
- _client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onAck(len, time); }, this);
- _client->onDisconnect([](void *r, AsyncClient* c){ ((AsyncWebSocketClient*)(r))->_onDisconnect(); delete c; }, this);
- _client->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onTimeout(time); }, this);
- _client->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; ((AsyncWebSocketClient*)(r))->_onData(buf, len); }, this);
- _client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncWebSocketClient*)(r))->_onPoll(); }, this);
+ _client->onError(
+ [](void * r, AsyncClient * c, int8_t error) {
+ (void)c;
+ ((AsyncWebSocketClient *)(r))->_onError(error);
+ },
+ this);
+ _client->onAck(
+ [](void * r, AsyncClient * c, size_t len, uint32_t time) {
+ (void)c;
+ ((AsyncWebSocketClient *)(r))->_onAck(len, time);
+ },
+ this);
+ _client->onDisconnect(
+ [](void * r, AsyncClient * c) {
+ ((AsyncWebSocketClient *)(r))->_onDisconnect();
+ delete c;
+ },
+ this);
+ _client->onTimeout(
+ [](void * r, AsyncClient * c, uint32_t time) {
+ (void)c;
+ ((AsyncWebSocketClient *)(r))->_onTimeout(time);
+ },
+ this);
+ _client->onData(
+ [](void * r, AsyncClient * c, void * buf, size_t len) {
+ (void)c;
+ ((AsyncWebSocketClient *)(r))->_onData(buf, len);
+ },
+ this);
+ _client->onPoll(
+ [](void * r, AsyncClient * c) {
+ (void)c;
+ ((AsyncWebSocketClient *)(r))->_onPoll();
+ },
+ this);
_server->_handleEvent(this, WS_EVT_CONNECT, request, NULL, 0);
delete request;
- memset(&_pinfo,0,sizeof(_pinfo));
+ memset(&_pinfo, 0, sizeof(_pinfo));
}
-AsyncWebSocketClient::~AsyncWebSocketClient()
-{
+AsyncWebSocketClient::~AsyncWebSocketClient() {
{
AsyncWebLockGuard l(_lock);
@@ -329,33 +354,33 @@ AsyncWebSocketClient::~AsyncWebSocketClient()
_server->_handleEvent(this, WS_EVT_DISCONNECT, NULL, NULL, 0);
}
-void AsyncWebSocketClient::_clearQueue()
-{
+void AsyncWebSocketClient::_clearQueue() {
while (!_messageQueue.empty() && _messageQueue.front().finished())
- _messageQueue.pop_front();
+ _messageQueue.pop_front();
}
-void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){
+void AsyncWebSocketClient::_onAck(size_t len, uint32_t time) {
_lastMessageTime = millis();
AsyncWebLockGuard l(_lock);
if (!_controlQueue.empty()) {
- auto &head = _controlQueue.front();
- if (head.finished()){
+ auto & head = _controlQueue.front();
+ if (head.finished()) {
len -= head.len();
- if (_status == WS_DISCONNECTING && head.opcode() == WS_DISCONNECT){
+ if (_status == WS_DISCONNECTING && head.opcode() == WS_DISCONNECT) {
_controlQueue.pop_front();
_status = WS_DISCONNECTED;
l.unlock();
- if (_client) _client->close(true);
+ if (_client)
+ _client->close(true);
return;
}
_controlQueue.pop_front();
}
}
- if(len && !_messageQueue.empty()){
+ if (len && !_messageQueue.empty()) {
_messageQueue.front().ack(len, time);
}
@@ -364,26 +389,21 @@ void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){
_runQueue();
}
-void AsyncWebSocketClient::_onPoll()
-{
+void AsyncWebSocketClient::_onPoll() {
if (!_client)
return;
AsyncWebLockGuard l(_lock);
- if (_client->canSend() && (!_controlQueue.empty() || !_messageQueue.empty()))
- {
+ if (_client->canSend() && (!_controlQueue.empty() || !_messageQueue.empty())) {
l.unlock();
_runQueue();
- }
- else if (_keepAlivePeriod > 0 && (millis() - _lastMessageTime) >= _keepAlivePeriod && (_controlQueue.empty() && _messageQueue.empty()))
- {
+ } else if (_keepAlivePeriod > 0 && (millis() - _lastMessageTime) >= _keepAlivePeriod && (_controlQueue.empty() && _messageQueue.empty())) {
l.unlock();
ping((uint8_t *)AWSC_PING_PAYLOAD, AWSC_PING_PAYLOAD_LEN);
}
}
-void AsyncWebSocketClient::_runQueue()
-{
+void AsyncWebSocketClient::_runQueue() {
if (!_client)
return;
@@ -391,20 +411,17 @@ void AsyncWebSocketClient::_runQueue()
_clearQueue();
- if (!_controlQueue.empty() && (_messageQueue.empty() || _messageQueue.front().betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue.front().len() - 1))
- {
+ if (!_controlQueue.empty() && (_messageQueue.empty() || _messageQueue.front().betweenFrames())
+ && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue.front().len() - 1)) {
//l.unlock();
_controlQueue.front().send(_client);
- }
- else if (!_messageQueue.empty() && _messageQueue.front().betweenFrames() && webSocketSendFrameWindow(_client))
- {
+ } else if (!_messageQueue.empty() && _messageQueue.front().betweenFrames() && webSocketSendFrameWindow(_client)) {
//l.unlock();
_messageQueue.front().send(_client);
}
}
-bool AsyncWebSocketClient::queueIsFull() const
-{
+bool AsyncWebSocketClient::queueIsFull() const {
size_t size;
{
AsyncWebLockGuard l(_lock);
@@ -413,15 +430,13 @@ bool AsyncWebSocketClient::queueIsFull() const
return (size >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED);
}
-size_t AsyncWebSocketClient::queueLen() const
-{
+size_t AsyncWebSocketClient::queueLen() const {
AsyncWebLockGuard l(_lock);
return _messageQueue.size() + _controlQueue.size();
}
-bool AsyncWebSocketClient::canSend() const
-{
+bool AsyncWebSocketClient::canSend() const {
size_t size;
{
AsyncWebLockGuard l(_lock);
@@ -430,8 +445,7 @@ bool AsyncWebSocketClient::canSend() const
return size < WS_MAX_QUEUED_MESSAGES;
}
-void AsyncWebSocketClient::_queueControl(uint8_t opcode, const uint8_t *data, size_t len, bool mask)
-{
+void AsyncWebSocketClient::_queueControl(uint8_t opcode, const uint8_t * data, size_t len, bool mask) {
if (!_client)
return;
@@ -444,9 +458,8 @@ void AsyncWebSocketClient::_queueControl(uint8_t opcode, const uint8_t *data, si
_runQueue();
}
-void AsyncWebSocketClient::_queueMessage(std::shared_ptr> buffer, uint8_t opcode, bool mask)
-{
- if(_status != WS_CONNECTED)
+void AsyncWebSocketClient::_queueMessage(std::shared_ptr> buffer, uint8_t opcode, bool mask) {
+ if (_status != WS_CONNECTED)
return;
if (!_client)
@@ -457,16 +470,26 @@ void AsyncWebSocketClient::_queueMessage(std::shared_ptr> b
{
AsyncWebLockGuard l(_lock);
- if (_messageQueue.size() >= WS_MAX_QUEUED_MESSAGES)
- {
+ if (_messageQueue.size() >= WS_MAX_QUEUED_MESSAGES) {
l.unlock();
- //ets_printf("AsyncWebSocketClient::_queueMessage: Too many messages queued, closing connection\n");
- _status = WS_DISCONNECTED;
- if (_client) _client->close(true);
+ if (closeWhenFull) {
+#ifdef ESP8266
+ ets_printf("AsyncWebSocketClient::_queueMessage: Too many messages queued: closing connection\n");
+#else
+ log_e("Too many messages queued: closing connection");
+#endif
+ _status = WS_DISCONNECTED;
+ if (_client)
+ _client->close(true);
+ } else {
+#ifdef ESP8266
+ ets_printf("AsyncWebSocketClient::_queueMessage: Too many messages queued: discarding new message\n");
+#else
+ log_e("Too many messages queued: discarding new message");
+#endif
+ }
return;
- }
- else
- {
+ } else {
_messageQueue.emplace_back(buffer, opcode, mask);
}
}
@@ -475,29 +498,26 @@ void AsyncWebSocketClient::_queueMessage(std::shared_ptr> b
_runQueue();
}
-void AsyncWebSocketClient::close(uint16_t code, const char * message)
-{
- if(_status != WS_CONNECTED)
+void AsyncWebSocketClient::close(uint16_t code, const char * message) {
+ if (_status != WS_CONNECTED)
return;
- if(code)
- {
+ if (code) {
uint8_t packetLen = 2;
- if (message != NULL)
- {
+ if (message != NULL) {
size_t mlen = strlen(message);
- if(mlen > 123) mlen = 123;
+ if (mlen > 123)
+ mlen = 123;
packetLen += mlen;
}
- char * buf = (char*)malloc(packetLen);
- if (buf != NULL)
- {
+ char * buf = (char *)malloc(packetLen);
+ if (buf != NULL) {
buf[0] = (uint8_t)(code >> 8);
buf[1] = (uint8_t)(code & 0xFF);
- if(message != NULL){
- memcpy(buf+2, message, packetLen -2);
+ if (message != NULL) {
+ memcpy(buf + 2, message, packetLen - 2);
}
- _queueControl(WS_DISCONNECT, (uint8_t*)buf, packetLen);
+ _queueControl(WS_DISCONNECT, (uint8_t *)buf, packetLen);
free(buf);
return;
}
@@ -505,245 +525,233 @@ void AsyncWebSocketClient::close(uint16_t code, const char * message)
_queueControl(WS_DISCONNECT);
}
-void AsyncWebSocketClient::ping(const uint8_t *data, size_t len)
-{
+void AsyncWebSocketClient::ping(const uint8_t * data, size_t len) {
if (_status == WS_CONNECTED)
_queueControl(WS_PING, data, len);
}
-void AsyncWebSocketClient::_onError(int8_t)
-{
+void AsyncWebSocketClient::_onError(int8_t) {
//Serial.println("onErr");
}
-void AsyncWebSocketClient::_onTimeout(uint32_t time)
-{
+void AsyncWebSocketClient::_onTimeout(uint32_t time) {
// Serial.println("onTime");
(void)time;
_client->close(true);
}
-void AsyncWebSocketClient::_onDisconnect()
-{
+void AsyncWebSocketClient::_onDisconnect() {
// Serial.println("onDis");
_client = NULL;
}
-void AsyncWebSocketClient::_onData(void *pbuf, size_t plen)
-{
- // Serial.println("onData");
- _lastMessageTime = millis();
- uint8_t *data = (uint8_t*)pbuf;
- while(plen > 0){
- if(!_pstate){
- const uint8_t *fdata = data;
- _pinfo.index = 0;
- _pinfo.final = (fdata[0] & 0x80) != 0;
- _pinfo.opcode = fdata[0] & 0x0F;
- _pinfo.masked = (fdata[1] & 0x80) != 0;
- _pinfo.len = fdata[1] & 0x7F;
- data += 2;
- plen -= 2;
- if(_pinfo.len == 126){
- _pinfo.len = fdata[3] | (uint16_t)(fdata[2]) << 8;
- data += 2;
- plen -= 2;
- } else if(_pinfo.len == 127){
- _pinfo.len = fdata[9] | (uint16_t)(fdata[8]) << 8 | (uint32_t)(fdata[7]) << 16 | (uint32_t)(fdata[6]) << 24 | (uint64_t)(fdata[5]) << 32 | (uint64_t)(fdata[4]) << 40 | (uint64_t)(fdata[3]) << 48 | (uint64_t)(fdata[2]) << 56;
- data += 8;
- plen -= 8;
- }
+void AsyncWebSocketClient::_onData(void * pbuf, size_t plen) {
+ // Serial.println("onData");
+ _lastMessageTime = millis();
+ uint8_t * data = (uint8_t *)pbuf;
+ while (plen > 0) {
+ if (!_pstate) {
+ const uint8_t * fdata = data;
+ _pinfo.index = 0;
+ _pinfo.final = (fdata[0] & 0x80) != 0;
+ _pinfo.opcode = fdata[0] & 0x0F;
+ _pinfo.masked = (fdata[1] & 0x80) != 0;
+ _pinfo.len = fdata[1] & 0x7F;
+ data += 2;
+ plen -= 2;
+ if (_pinfo.len == 126) {
+ _pinfo.len = fdata[3] | (uint16_t)(fdata[2]) << 8;
+ data += 2;
+ plen -= 2;
+ } else if (_pinfo.len == 127) {
+ _pinfo.len = fdata[9] | (uint16_t)(fdata[8]) << 8 | (uint32_t)(fdata[7]) << 16 | (uint32_t)(fdata[6]) << 24 | (uint64_t)(fdata[5]) << 32
+ | (uint64_t)(fdata[4]) << 40 | (uint64_t)(fdata[3]) << 48 | (uint64_t)(fdata[2]) << 56;
+ data += 8;
+ plen -= 8;
+ }
- if(_pinfo.masked){
- memcpy(_pinfo.mask, data, 4);
- data += 4;
- plen -= 4;
- }
- }
-
- const size_t datalen = std::min((size_t)(_pinfo.len - _pinfo.index), plen);
- const auto datalast = data[datalen];
-
- if(_pinfo.masked){
- for(size_t i=0;i 0) _server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, (uint8_t*)data, datalen);
- _pinfo.index += datalen;
- } else if((datalen + _pinfo.index) == _pinfo.len){
- _pstate = 0;
- if(_pinfo.opcode == WS_DISCONNECT){
- if(datalen){
- uint16_t reasonCode = (uint16_t)(data[0] << 8) + data[1];
- char * reasonString = (char*)(data+2);
- if(reasonCode > 1001){
- _server->_handleEvent(this, WS_EVT_ERROR, (void *)&reasonCode, (uint8_t*)reasonString, strlen(reasonString));
- }
+ const size_t datalen = std::min((size_t)(_pinfo.len - _pinfo.index), plen);
+ const auto datalast = data[datalen];
+
+ if (_pinfo.masked) {
+ for (size_t i = 0; i < datalen; i++)
+ data[i] ^= _pinfo.mask[(_pinfo.index + i) % 4];
}
- if(_status == WS_DISCONNECTING){
- _status = WS_DISCONNECTED;
- _client->close(true);
+
+ if ((datalen + _pinfo.index) < _pinfo.len) {
+ _pstate = 1;
+
+ if (_pinfo.index == 0) {
+ if (_pinfo.opcode) {
+ _pinfo.message_opcode = _pinfo.opcode;
+ _pinfo.num = 0;
+ }
+ }
+ if (datalen > 0)
+ _server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, (uint8_t *)data, datalen);
+
+ _pinfo.index += datalen;
+ } else if ((datalen + _pinfo.index) == _pinfo.len) {
+ _pstate = 0;
+ if (_pinfo.opcode == WS_DISCONNECT) {
+ if (datalen) {
+ uint16_t reasonCode = (uint16_t)(data[0] << 8) + data[1];
+ char * reasonString = (char *)(data + 2);
+ if (reasonCode > 1001) {
+ _server->_handleEvent(this, WS_EVT_ERROR, (void *)&reasonCode, (uint8_t *)reasonString, strlen(reasonString));
+ }
+ }
+ if (_status == WS_DISCONNECTING) {
+ _status = WS_DISCONNECTED;
+ _client->close(true);
+ } else {
+ _status = WS_DISCONNECTING;
+ _client->ackLater();
+ _queueControl(WS_DISCONNECT, data, datalen);
+ }
+ } else if (_pinfo.opcode == WS_PING) {
+ _queueControl(WS_PONG, data, datalen);
+ } else if (_pinfo.opcode == WS_PONG) {
+ if (datalen != AWSC_PING_PAYLOAD_LEN || memcmp(AWSC_PING_PAYLOAD, data, AWSC_PING_PAYLOAD_LEN) != 0)
+ _server->_handleEvent(this, WS_EVT_PONG, NULL, data, datalen);
+ } else if (_pinfo.opcode < 8) { //continuation or text/binary frame
+ _server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, data, datalen);
+ if (_pinfo.final)
+ _pinfo.num = 0;
+ else
+ _pinfo.num += 1;
+ }
} else {
- _status = WS_DISCONNECTING;
- _client->ackLater();
- _queueControl(WS_DISCONNECT, data, datalen);
+ //os_printf("frame error: len: %u, index: %llu, total: %llu\n", datalen, _pinfo.index, _pinfo.len);
+ //what should we do?
+ break;
}
- } else if(_pinfo.opcode == WS_PING){
- _queueControl(WS_PONG, data, datalen);
- } else if(_pinfo.opcode == WS_PONG){
- if(datalen != AWSC_PING_PAYLOAD_LEN || memcmp(AWSC_PING_PAYLOAD, data, AWSC_PING_PAYLOAD_LEN) != 0)
- _server->_handleEvent(this, WS_EVT_PONG, NULL, data, datalen);
- } else if(_pinfo.opcode < 8){//continuation or text/binary frame
- _server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, data, datalen);
- if (_pinfo.final) _pinfo.num = 0;
- else _pinfo.num += 1;
- }
- } else {
- //os_printf("frame error: len: %u, index: %llu, total: %llu\n", datalen, _pinfo.index, _pinfo.len);
- //what should we do?
- break;
+
+ // restore byte as _handleEvent may have added a null terminator i.e., data[len] = 0;
+ if (datalen > 0)
+ data[datalen] = datalast;
+
+ data += datalen;
+ plen -= datalen;
}
-
- // restore byte as _handleEvent may have added a null terminator i.e., data[len] = 0;
- if (datalen > 0)
- data[datalen] = datalast;
-
- data += datalen;
- plen -= datalen;
- }
}
-size_t AsyncWebSocketClient::printf(const char *format, ...)
-{
- va_list arg;
- va_start(arg, format);
- char* temp = new char[MAX_PRINTF_LEN];
- if(!temp){
- va_end(arg);
- return 0;
- }
- char* buffer = temp;
- size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg);
- va_end(arg);
-
- if (len > (MAX_PRINTF_LEN - 1)) {
- buffer = new char[len + 1];
- if (!buffer) {
- delete[] temp;
- return 0;
- }
+size_t AsyncWebSocketClient::printf(const char * format, ...) {
+ va_list arg;
va_start(arg, format);
- vsnprintf(buffer, len + 1, format, arg);
+ char * temp = new char[MAX_PRINTF_LEN];
+ if (!temp) {
+ va_end(arg);
+ return 0;
+ }
+ char * buffer = temp;
+ size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg);
va_end(arg);
- }
- text(buffer, len);
- if (buffer != temp) {
- delete[] buffer;
- }
- delete[] temp;
- return len;
+
+ if (len > (MAX_PRINTF_LEN - 1)) {
+ buffer = new char[len + 1];
+ if (!buffer) {
+ delete[] temp;
+ return 0;
+ }
+ va_start(arg, format);
+ vsnprintf(buffer, len + 1, format, arg);
+ va_end(arg);
+ }
+ text(buffer, len);
+ if (buffer != temp) {
+ delete[] buffer;
+ }
+ delete[] temp;
+ return len;
}
#ifndef ESP32
-size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...)
-{
- va_list arg;
- va_start(arg, formatP);
- char* temp = new char[MAX_PRINTF_LEN];
- if(!temp){
- va_end(arg);
- return 0;
- }
- char* buffer = temp;
- size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg);
- va_end(arg);
-
- if (len > (MAX_PRINTF_LEN - 1)) {
- buffer = new char[len + 1];
- if (!buffer) {
- delete[] temp;
- return 0;
- }
+size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...) {
+ va_list arg;
va_start(arg, formatP);
- vsnprintf_P(buffer, len + 1, formatP, arg);
+ char * temp = new char[MAX_PRINTF_LEN];
+ if (!temp) {
+ va_end(arg);
+ return 0;
+ }
+ char * buffer = temp;
+ size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg);
va_end(arg);
- }
- text(buffer, len);
- if (buffer != temp) {
- delete[] buffer;
- }
- delete[] temp;
- return len;
+
+ if (len > (MAX_PRINTF_LEN - 1)) {
+ buffer = new char[len + 1];
+ if (!buffer) {
+ delete[] temp;
+ return 0;
+ }
+ va_start(arg, formatP);
+ vsnprintf_P(buffer, len + 1, formatP, arg);
+ va_end(arg);
+ }
+ text(buffer, len);
+ if (buffer != temp) {
+ delete[] buffer;
+ }
+ delete[] temp;
+ return len;
}
#endif
namespace {
-std::shared_ptr> makeSharedBuffer(const uint8_t *message, size_t len)
-{
+std::shared_ptr> makeSharedBuffer(const uint8_t * message, size_t len) {
auto buffer = std::make_shared>(len);
std::memcpy(buffer->data(), message, len);
return buffer;
}
-}
+} // namespace
-void AsyncWebSocketClient::text(AsyncWebSocketMessageBuffer * buffer)
-{
+void AsyncWebSocketClient::text(AsyncWebSocketMessageBuffer * buffer) {
if (buffer) {
text(std::move(buffer->_buffer));
delete buffer;
}
}
-void AsyncWebSocketClient::text(std::shared_ptr> buffer)
-{
+void AsyncWebSocketClient::text(std::shared_ptr> buffer) {
_queueMessage(buffer);
}
-void AsyncWebSocketClient::text(const uint8_t *message, size_t len)
-{
+void AsyncWebSocketClient::text(const uint8_t * message, size_t len) {
text(makeSharedBuffer(message, len));
}
-void AsyncWebSocketClient::text(const char *message, size_t len)
-{
+void AsyncWebSocketClient::text(const char * message, size_t len) {
text((const uint8_t *)message, len);
}
-void AsyncWebSocketClient::text(const char *message)
-{
+void AsyncWebSocketClient::text(const char * message) {
text(message, strlen(message));
}
-void AsyncWebSocketClient::text(const String &message)
-{
+void AsyncWebSocketClient::text(const String & message) {
text(message.c_str(), message.length());
}
-void AsyncWebSocketClient::text(const __FlashStringHelper *data)
-{
+void AsyncWebSocketClient::text(const __FlashStringHelper * data) {
PGM_P p = reinterpret_cast(data);
size_t n = 0;
- while (1)
- {
- if (pgm_read_byte(p+n) == 0) break;
- n += 1;
+ while (1) {
+ if (pgm_read_byte(p + n) == 0)
+ break;
+ n += 1;
}
- char * message = (char*) malloc(n+1);
- if(message)
- {
+ char * message = (char *)malloc(n + 1);
+ if (message) {
memcpy_P(message, p, n);
message[n] = 0;
text(message, n);
@@ -751,43 +759,36 @@ void AsyncWebSocketClient::text(const __FlashStringHelper *data)
}
}
-void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer * buffer)
-{
+void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer * buffer) {
if (buffer) {
binary(std::move(buffer->_buffer));
delete buffer;
}
}
-void AsyncWebSocketClient::binary(std::shared_ptr> buffer)
-{
+void AsyncWebSocketClient::binary(std::shared_ptr> buffer) {
_queueMessage(buffer, WS_BINARY);
}
-void AsyncWebSocketClient::binary(const uint8_t *message, size_t len)
-{
+void AsyncWebSocketClient::binary(const uint8_t * message, size_t len) {
binary(makeSharedBuffer(message, len));
}
-void AsyncWebSocketClient::binary(const char *message, size_t len)
-{
+void AsyncWebSocketClient::binary(const char * message, size_t len) {
binary((const uint8_t *)message, len);
}
-void AsyncWebSocketClient::binary(const char *message)
-{
+void AsyncWebSocketClient::binary(const char * message) {
binary(message, strlen(message));
}
-void AsyncWebSocketClient::binary(const String &message)
-{
+void AsyncWebSocketClient::binary(const String & message) {
binary(message.c_str(), message.length());
}
-void AsyncWebSocketClient::binary(const __FlashStringHelper *data, size_t len)
-{
- PGM_P p = reinterpret_cast(data);
- char *message = (char*) malloc(len);
+void AsyncWebSocketClient::binary(const __FlashStringHelper * data, size_t len) {
+ PGM_P p = reinterpret_cast(data);
+ char * message = (char *)malloc(len);
if (message) {
memcpy_P(message, p, len);
binary(message, len);
@@ -795,17 +796,15 @@ void AsyncWebSocketClient::binary(const __FlashStringHelper *data, size_t len)
}
}
-IPAddress AsyncWebSocketClient::remoteIP() const
-{
+IPAddress AsyncWebSocketClient::remoteIP() const {
if (!_client)
return IPAddress((uint32_t)0U);
return _client->remoteIP();
}
-uint16_t AsyncWebSocketClient::remotePort() const
-{
- if(!_client)
+uint16_t AsyncWebSocketClient::remotePort() const {
+ if (!_client)
return 0;
return _client->remotePort();
@@ -817,53 +816,45 @@ uint16_t AsyncWebSocketClient::remotePort() const
* Async Web Socket - Each separate socket location
*/
-AsyncWebSocket::AsyncWebSocket(const String& url)
- :_url(url)
- ,_cNextId(1)
- ,_enabled(true)
-{
- _eventHandler = NULL;
+AsyncWebSocket::AsyncWebSocket(const String & url)
+ : _url(url)
+ , _cNextId(1)
+ , _enabled(true) {
+ _eventHandler = NULL;
}
-AsyncWebSocket::~AsyncWebSocket(){}
-
-void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
- if(_eventHandler != NULL){
- _eventHandler(this, client, type, arg, data, len);
- }
+AsyncWebSocket::~AsyncWebSocket() {
}
-AsyncWebSocketClient *AsyncWebSocket::_newClient(AsyncWebServerRequest *request)
-{
+void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t * data, size_t len) {
+ if (_eventHandler != NULL) {
+ _eventHandler(this, client, type, arg, data, len);
+ }
+}
+
+AsyncWebSocketClient * AsyncWebSocket::_newClient(AsyncWebServerRequest * request) {
_clients.emplace_back(request, this);
return &_clients.back();
}
-bool AsyncWebSocket::availableForWriteAll()
-{
- return std::none_of(std::begin(_clients), std::end(_clients),
- [](const AsyncWebSocketClient &c){ return c.queueIsFull(); });
+bool AsyncWebSocket::availableForWriteAll() {
+ return std::none_of(std::begin(_clients), std::end(_clients), [](const AsyncWebSocketClient & c) { return c.queueIsFull(); });
}
-bool AsyncWebSocket::availableForWrite(uint32_t id)
-{
- const auto iter = std::find_if(std::begin(_clients), std::end(_clients),
- [id](const AsyncWebSocketClient &c){ return c.id() == id; });
+bool AsyncWebSocket::availableForWrite(uint32_t id) {
+ const auto iter = std::find_if(std::begin(_clients), std::end(_clients), [id](const AsyncWebSocketClient & c) { return c.id() == id; });
if (iter == std::end(_clients))
return true;
return !iter->queueIsFull();
}
-size_t AsyncWebSocket::count() const
-{
- return std::count_if(std::begin(_clients), std::end(_clients),
- [](const AsyncWebSocketClient &c){ return c.status() == WS_CONNECTED; });
+size_t AsyncWebSocket::count() const {
+ return std::count_if(std::begin(_clients), std::end(_clients), [](const AsyncWebSocketClient & c) { return c.status() == WS_CONNECTED; });
}
-AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id)
-{
- const auto iter = std::find_if(std::begin(_clients), std::end(_clients),
- [id](const AsyncWebSocketClient &c){ return c.id() == id && c.status() == WS_CONNECTED; });
+AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id) {
+ const auto iter =
+ std::find_if(std::begin(_clients), std::end(_clients), [id](const AsyncWebSocketClient & c) { return c.id() == id && c.status() == WS_CONNECTED; });
if (iter == std::end(_clients))
return nullptr;
@@ -871,26 +862,22 @@ AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id)
}
-void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message)
-{
- if (AsyncWebSocketClient *c = client(id))
+void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message) {
+ if (AsyncWebSocketClient * c = client(id))
c->close(code, message);
}
-void AsyncWebSocket::closeAll(uint16_t code, const char * message)
-{
- for (auto &c : _clients)
+void AsyncWebSocket::closeAll(uint16_t code, const char * message) {
+ for (auto & c : _clients)
if (c.status() == WS_CONNECTED)
c.close(code, message);
}
-void AsyncWebSocket::cleanupClients(uint16_t maxClients)
-{
+void AsyncWebSocket::cleanupClients(uint16_t maxClients) {
if (count() > maxClients)
_clients.front().close();
- for (auto iter = std::begin(_clients); iter != std::end(_clients);)
- {
+ for (auto iter = std::begin(_clients); iter != std::end(_clients);) {
if (iter->shouldBeDeleted())
iter = _clients.erase(iter);
else
@@ -898,186 +885,172 @@ void AsyncWebSocket::cleanupClients(uint16_t maxClients)
}
}
-void AsyncWebSocket::ping(uint32_t id, const uint8_t *data, size_t len)
-{
+void AsyncWebSocket::ping(uint32_t id, const uint8_t * data, size_t len) {
if (AsyncWebSocketClient * c = client(id))
c->ping(data, len);
}
-void AsyncWebSocket::pingAll(const uint8_t *data, size_t len)
-{
- for (auto &c : _clients)
+void AsyncWebSocket::pingAll(const uint8_t * data, size_t len) {
+ for (auto & c : _clients)
if (c.status() == WS_CONNECTED)
c.ping(data, len);
}
-void AsyncWebSocket::text(uint32_t id, const uint8_t *message, size_t len)
-{
+void AsyncWebSocket::text(uint32_t id, const uint8_t * message, size_t len) {
if (AsyncWebSocketClient * c = client(id))
c->text(makeSharedBuffer(message, len));
}
-void AsyncWebSocket::text(uint32_t id, const char *message, size_t len)
-{
+void AsyncWebSocket::text(uint32_t id, const char * message, size_t len) {
text(id, (const uint8_t *)message, len);
}
-void AsyncWebSocket::text(uint32_t id, const char * message)
-{
+void AsyncWebSocket::text(uint32_t id, const char * message) {
text(id, message, strlen(message));
}
-void AsyncWebSocket::text(uint32_t id, const String &message)
-{
+void AsyncWebSocket::text(uint32_t id, const String & message) {
text(id, message.c_str(), message.length());
}
-void AsyncWebSocket::text(uint32_t id, const __FlashStringHelper *data)
-{
+void AsyncWebSocket::text(uint32_t id, const __FlashStringHelper * data) {
PGM_P p = reinterpret_cast(data);
size_t n = 0;
- while (true)
- {
- if (pgm_read_byte(p+n) == 0)
+ while (true) {
+ if (pgm_read_byte(p + n) == 0)
break;
n += 1;
}
- char * message = (char*) malloc(n+1);
- if (message)
- {
+ char * message = (char *)malloc(n + 1);
+ if (message) {
memcpy_P(message, p, n);
message[n] = 0;
text(id, message, n);
free(message);
}
}
-
-void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer)
-{
+void AsyncWebSocket::text(uint32_t id, AsyncWebSocketMessageBuffer * buffer) {
if (buffer) {
- textAll(std::move(buffer->_buffer));
- delete buffer;
+ text(id, std::move(buffer->_buffer));
+ delete buffer;
}
}
-
-void AsyncWebSocket::textAll(std::shared_ptr> buffer)
-{
- for (auto &c : _clients)
- if (c.status() == WS_CONNECTED)
- c.text(buffer);
+void AsyncWebSocket::text(uint32_t id, std::shared_ptr> buffer) {
+ if (AsyncWebSocketClient * c = client(id))
+ c->text(buffer);
}
-void AsyncWebSocket::textAll(const uint8_t *message, size_t len)
-{
+
+void AsyncWebSocket::textAll(const uint8_t * message, size_t len) {
textAll(makeSharedBuffer(message, len));
}
-void AsyncWebSocket::textAll(const char * message, size_t len)
-{
+void AsyncWebSocket::textAll(const char * message, size_t len) {
textAll((const uint8_t *)message, len);
}
-void AsyncWebSocket::textAll(const char *message)
-{
+void AsyncWebSocket::textAll(const char * message) {
textAll(message, strlen(message));
}
-void AsyncWebSocket::textAll(const String &message)
-{
+void AsyncWebSocket::textAll(const String & message) {
textAll(message.c_str(), message.length());
}
-void AsyncWebSocket::textAll(const __FlashStringHelper *data)
-{
+void AsyncWebSocket::textAll(const __FlashStringHelper * data) {
PGM_P p = reinterpret_cast(data);
size_t n = 0;
- while (1)
- {
- if (pgm_read_byte(p+n) == 0) break;
- n += 1;
+ while (1) {
+ if (pgm_read_byte(p + n) == 0)
+ break;
+ n += 1;
}
- char *message = (char*)malloc(n+1);
- if(message)
- {
+ char * message = (char *)malloc(n + 1);
+ if (message) {
memcpy_P(message, p, n);
message[n] = 0;
textAll(message, n);
free(message);
}
}
+void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer) {
+ if (buffer) {
+ textAll(std::move(buffer->_buffer));
+ delete buffer;
+ }
+}
-void AsyncWebSocket::binary(uint32_t id, const uint8_t *message, size_t len)
-{
- if (AsyncWebSocketClient *c = client(id))
+void AsyncWebSocket::textAll(std::shared_ptr> buffer) {
+ for (auto & c : _clients)
+ if (c.status() == WS_CONNECTED)
+ c.text(buffer);
+}
+
+void AsyncWebSocket::binary(uint32_t id, const uint8_t * message, size_t len) {
+ if (AsyncWebSocketClient * c = client(id))
c->binary(makeSharedBuffer(message, len));
}
-void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len)
-{
+void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len) {
binary(id, (const uint8_t *)message, len);
}
-void AsyncWebSocket::binary(uint32_t id, const char * message)
-{
+void AsyncWebSocket::binary(uint32_t id, const char * message) {
binary(id, message, strlen(message));
}
-void AsyncWebSocket::binary(uint32_t id, const String &message)
-{
+void AsyncWebSocket::binary(uint32_t id, const String & message) {
binary(id, message.c_str(), message.length());
}
-void AsyncWebSocket::binary(uint32_t id, const __FlashStringHelper *data, size_t len)
-{
- PGM_P p = reinterpret_cast(data);
- char *message = (char*) malloc(len);
- if (message)
- {
+void AsyncWebSocket::binary(uint32_t id, const __FlashStringHelper * data, size_t len) {
+ PGM_P p = reinterpret_cast(data);
+ char * message = (char *)malloc(len);
+ if (message) {
memcpy_P(message, p, len);
binary(id, message, len);
free(message);
}
}
-
-void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer)
-{
+void AsyncWebSocket::binary(uint32_t id, AsyncWebSocketMessageBuffer * buffer) {
if (buffer) {
- binaryAll(std::move(buffer->_buffer));
+ binary(id, std::move(buffer->_buffer));
delete buffer;
}
}
-
-void AsyncWebSocket::binaryAll(std::shared_ptr> buffer)
-{
- for (auto &c : _clients)
- if (c.status() == WS_CONNECTED)
- c.binary(buffer);
+void AsyncWebSocket::binary(uint32_t id, std::shared_ptr> buffer) {
+ if (AsyncWebSocketClient * c = client(id))
+ c->binary(buffer);
}
-void AsyncWebSocket::binaryAll(const uint8_t *message, size_t len)
-{
+
+void AsyncWebSocket::binaryAll(const uint8_t * message, size_t len) {
binaryAll(makeSharedBuffer(message, len));
}
-
-void AsyncWebSocket::binaryAll(const char *message, size_t len)
-{
+void AsyncWebSocket::binaryAll(const char * message, size_t len) {
binaryAll((const uint8_t *)message, len);
}
-void AsyncWebSocket::binaryAll(const char *message)
-{
+void AsyncWebSocket::binaryAll(const char * message) {
binaryAll(message, strlen(message));
}
-void AsyncWebSocket::binaryAll(const String &message)
-{
+void AsyncWebSocket::binaryAll(const String & message) {
binaryAll(message.c_str(), message.length());
}
-void AsyncWebSocket::binaryAll(const __FlashStringHelper *data, size_t len)
-{
- PGM_P p = reinterpret_cast(data);
- char * message = (char*) malloc(len);
- if(message)
- {
+void AsyncWebSocket::binaryAll(const __FlashStringHelper * data, size_t len) {
+ PGM_P p = reinterpret_cast(data);
+ char * message = (char *)malloc(len);
+ if (message) {
memcpy_P(message, p, len);
binaryAll(message, len);
free(message);
}
}
+void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer) {
+ if (buffer) {
+ binaryAll(std::move(buffer->_buffer));
+ delete buffer;
+ }
+}
+void AsyncWebSocket::binaryAll(std::shared_ptr> buffer) {
+ for (auto & c : _clients)
+ if (c.status() == WS_CONNECTED)
+ c.binary(buffer);
+}
-size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...){
+size_t AsyncWebSocket::printf(uint32_t id, const char * format, ...) {
AsyncWebSocketClient * c = client(id);
- if (c)
- {
+ if (c) {
va_list arg;
va_start(arg, format);
size_t len = c->printf(format, arg);
@@ -1087,10 +1060,9 @@ size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...){
return 0;
}
-size_t AsyncWebSocket::printfAll(const char *format, ...)
-{
+size_t AsyncWebSocket::printfAll(const char * format, ...) {
va_list arg;
- char *temp = new char[MAX_PRINTF_LEN];
+ char * temp = new char[MAX_PRINTF_LEN];
if (!temp)
return 0;
@@ -1102,7 +1074,7 @@ size_t AsyncWebSocket::printfAll(const char *format, ...)
std::shared_ptr> buffer = std::make_shared>(len);
va_start(arg, format);
- vsnprintf( (char *)buffer->data(), len + 1, format, arg);
+ vsnprintf((char *)buffer->data(), len + 1, format, arg);
va_end(arg);
textAll(buffer);
@@ -1110,23 +1082,22 @@ size_t AsyncWebSocket::printfAll(const char *format, ...)
}
#ifndef ESP32
-size_t AsyncWebSocket::printf_P(uint32_t id, PGM_P formatP, ...){
- AsyncWebSocketClient * c = client(id);
- if(c != NULL){
- va_list arg;
- va_start(arg, formatP);
- size_t len = c->printf_P(formatP, arg);
- va_end(arg);
- return len;
- }
- return 0;
+size_t AsyncWebSocket::printf_P(uint32_t id, PGM_P formatP, ...) {
+ AsyncWebSocketClient * c = client(id);
+ if (c != NULL) {
+ va_list arg;
+ va_start(arg, formatP);
+ size_t len = c->printf_P(formatP, arg);
+ va_end(arg);
+ return len;
+ }
+ return 0;
}
#endif
-size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...)
-{
+size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...) {
va_list arg;
- char *temp = new char[MAX_PRINTF_LEN];
+ char * temp = new char[MAX_PRINTF_LEN];
if (!temp)
return 0;
@@ -1145,15 +1116,15 @@ size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...)
return len;
}
-const char __WS_STR_CONNECTION[] PROGMEM = { "Connection" };
-const char __WS_STR_UPGRADE[] PROGMEM = { "Upgrade" };
-const char __WS_STR_ORIGIN[] PROGMEM = { "Origin" };
-const char __WS_STR_COOKIE[] PROGMEM = { "Cookie" };
-const char __WS_STR_VERSION[] PROGMEM = { "Sec-WebSocket-Version" };
-const char __WS_STR_KEY[] PROGMEM = { "Sec-WebSocket-Key" };
-const char __WS_STR_PROTOCOL[] PROGMEM = { "Sec-WebSocket-Protocol" };
-const char __WS_STR_ACCEPT[] PROGMEM = { "Sec-WebSocket-Accept" };
-const char __WS_STR_UUID[] PROGMEM = { "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" };
+const char __WS_STR_CONNECTION[] PROGMEM = {"Connection"};
+const char __WS_STR_UPGRADE[] PROGMEM = {"Upgrade"};
+const char __WS_STR_ORIGIN[] PROGMEM = {"Origin"};
+const char __WS_STR_COOKIE[] PROGMEM = {"Cookie"};
+const char __WS_STR_VERSION[] PROGMEM = {"Sec-WebSocket-Version"};
+const char __WS_STR_KEY[] PROGMEM = {"Sec-WebSocket-Key"};
+const char __WS_STR_PROTOCOL[] PROGMEM = {"Sec-WebSocket-Protocol"};
+const char __WS_STR_ACCEPT[] PROGMEM = {"Sec-WebSocket-Accept"};
+const char __WS_STR_UUID[] PROGMEM = {"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"};
#define WS_STR_CONNECTION FPSTR(__WS_STR_CONNECTION)
#define WS_STR_UPGRADE FPSTR(__WS_STR_UPGRADE)
@@ -1165,11 +1136,11 @@ const char __WS_STR_UUID[] PROGMEM = { "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" };
#define WS_STR_ACCEPT FPSTR(__WS_STR_ACCEPT)
#define WS_STR_UUID FPSTR(__WS_STR_UUID)
-bool AsyncWebSocket::canHandle(AsyncWebServerRequest *request){
- if(!_enabled)
+bool AsyncWebSocket::canHandle(AsyncWebServerRequest * request) {
+ if (!_enabled)
return false;
- if(request->method() != HTTP_GET || !request->url().equals(_url) || !request->isExpectedRequestedConnType(RCT_WS))
+ if (request->method() != HTTP_GET || !request->url().equals(_url) || !request->isExpectedRequestedConnType(RCT_WS))
return false;
request->addInterestingHeader(WS_STR_CONNECTION);
@@ -1182,47 +1153,40 @@ bool AsyncWebSocket::canHandle(AsyncWebServerRequest *request){
return true;
}
-void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request)
-{
- if (!request->hasHeader(WS_STR_VERSION) || !request->hasHeader(WS_STR_KEY))
- {
+void AsyncWebSocket::handleRequest(AsyncWebServerRequest * request) {
+ if (!request->hasHeader(WS_STR_VERSION) || !request->hasHeader(WS_STR_KEY)) {
request->send(400);
return;
}
- if ((_username.length() && _password.length()) && !request->authenticate(_username.c_str(), _password.c_str()))
- {
+ if ((_username.length() && _password.length()) && !request->authenticate(_username.c_str(), _password.c_str())) {
return request->requestAuthentication();
}
- if (_handshakeHandler != nullptr){
- if(!_handshakeHandler(request)){
+ if (_handshakeHandler != nullptr) {
+ if (!_handshakeHandler(request)) {
request->send(401);
return;
}
}
- AsyncWebHeader* version = request->getHeader(WS_STR_VERSION);
- if (version->value().toInt() != 13)
- {
- AsyncWebServerResponse *response = request->beginResponse(400);
+ AsyncWebHeader * version = request->getHeader(WS_STR_VERSION);
+ if (version->value().toInt() != 13) {
+ AsyncWebServerResponse * response = request->beginResponse(400);
response->addHeader(WS_STR_VERSION, F("13"));
request->send(response);
return;
}
- AsyncWebHeader* key = request->getHeader(WS_STR_KEY);
- AsyncWebServerResponse *response = new AsyncWebSocketResponse(key->value(), this);
- if (request->hasHeader(WS_STR_PROTOCOL))
- {
- AsyncWebHeader* protocol = request->getHeader(WS_STR_PROTOCOL);
+ AsyncWebHeader * key = request->getHeader(WS_STR_KEY);
+ AsyncWebServerResponse * response = new AsyncWebSocketResponse(key->value(), this);
+ if (request->hasHeader(WS_STR_PROTOCOL)) {
+ AsyncWebHeader * protocol = request->getHeader(WS_STR_PROTOCOL);
//ToDo: check protocol
response->addHeader(WS_STR_PROTOCOL, protocol->value());
}
request->send(response);
}
-AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size)
-{
+AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size) {
AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(size);
- if (buffer->length() != size)
- {
+ if (buffer->length() != size) {
delete buffer;
return nullptr;
} else {
@@ -1230,11 +1194,9 @@ AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size)
}
}
-AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t size)
-{
+AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t size) {
AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(data, size);
- if (buffer->length() != size)
- {
+ if (buffer->length() != size) {
delete buffer;
return nullptr;
} else {
@@ -1247,21 +1209,18 @@ AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t
* Authentication code from https://github.com/Links2004/arduinoWebSockets/blob/master/src/WebSockets.cpp#L480
*/
-AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket *server)
-{
- _server = server;
- _code = 101;
+AsyncWebSocketResponse::AsyncWebSocketResponse(const String & key, AsyncWebSocket * server) {
+ _server = server;
+ _code = 101;
_sendContentLength = false;
- uint8_t * hash = (uint8_t*)malloc(20);
- if(hash == NULL)
- {
+ uint8_t * hash = (uint8_t *)malloc(20);
+ if (hash == NULL) {
_state = RESPONSE_FAILED;
return;
}
- char * buffer = (char *) malloc(33);
- if(buffer == NULL)
- {
+ char * buffer = (char *)malloc(33);
+ if (buffer == NULL) {
free(hash);
_state = RESPONSE_FAILED;
return;
@@ -1269,29 +1228,26 @@ AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket
#ifdef ESP8266
sha1(key + WS_STR_UUID, hash);
#else
- (String&)key += WS_STR_UUID;
- mbedtls_sha1_context ctx;
- mbedtls_sha1_init(&ctx);
- mbedtls_sha1_starts(&ctx);
- mbedtls_sha1_update(&ctx, (const unsigned char*)key.c_str(), key.length());
- mbedtls_sha1_finish(&ctx, hash);
- mbedtls_sha1_free(&ctx);
+ String k = key + WS_STR_UUID;
+ SHA1Builder sha1;
+ sha1.begin();
+ sha1.add((const uint8_t *)k.c_str(), k.length());
+ sha1.calculate();
+ sha1.getBytes(hash);
#endif
base64_encodestate _state;
base64_init_encodestate(&_state);
- int len = base64_encode_block((const char *) hash, 20, buffer, &_state);
- len = base64_encode_blockend((buffer + len), &_state);
+ int len = base64_encode_block((const char *)hash, 20, buffer, &_state);
+ len = base64_encode_blockend((buffer + len), &_state);
addHeader(WS_STR_CONNECTION, WS_STR_UPGRADE);
addHeader(WS_STR_UPGRADE, F("websocket"));
- addHeader(WS_STR_ACCEPT,buffer);
+ addHeader(WS_STR_ACCEPT, buffer);
free(buffer);
free(hash);
}
-void AsyncWebSocketResponse::_respond(AsyncWebServerRequest *request)
-{
- if(_state == RESPONSE_FAILED)
- {
+void AsyncWebSocketResponse::_respond(AsyncWebServerRequest * request) {
+ if (_state == RESPONSE_FAILED) {
request->client()->close(true);
return;
}
@@ -1300,12 +1256,11 @@ void AsyncWebSocketResponse::_respond(AsyncWebServerRequest *request)
_state = RESPONSE_WAIT_ACK;
}
-size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time)
-{
+size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest * request, size_t len, uint32_t time) {
(void)time;
- if(len)
+ if (len)
_server->_newClient(request);
return 0;
-}
+}
\ No newline at end of file
diff --git a/lib/ESPAsyncWebServer/src/AsyncWebSocket.h b/lib/ESPAsyncWebServer/src/AsyncWebSocket.h
index ac49d2b82..b744a08bd 100644
--- a/lib/ESPAsyncWebServer/src/AsyncWebSocket.h
+++ b/lib/ESPAsyncWebServer/src/AsyncWebSocket.h
@@ -89,8 +89,8 @@ typedef enum { WS_MSG_SENDING, WS_MSG_SENT, WS_MSG_ERROR } AwsMessageStatus;
typedef enum { WS_EVT_CONNECT, WS_EVT_DISCONNECT, WS_EVT_PONG, WS_EVT_ERROR, WS_EVT_DATA } AwsEventType;
class AsyncWebSocketMessageBuffer {
- friend AsyncWebSocket;
- friend AsyncWebSocketClient;
+ friend AsyncWebSocket;
+ friend AsyncWebSocketClient;
private:
std::shared_ptr> _buffer;
@@ -98,114 +98,165 @@ class AsyncWebSocketMessageBuffer {
public:
AsyncWebSocketMessageBuffer();
AsyncWebSocketMessageBuffer(size_t size);
- AsyncWebSocketMessageBuffer(uint8_t* data, size_t size);
+ AsyncWebSocketMessageBuffer(uint8_t * data, size_t size);
~AsyncWebSocketMessageBuffer();
- bool reserve(size_t size);
- uint8_t* get() { return _buffer->data(); }
- size_t length() const { return _buffer->size(); }
+ bool reserve(size_t size);
+ uint8_t * get() {
+ return _buffer->data();
+ }
+ size_t length() const {
+ return _buffer->size();
+ }
};
-class AsyncWebSocketMessage
-{
-private:
+class AsyncWebSocketMessage {
+ private:
std::shared_ptr> _WSbuffer;
- uint8_t _opcode{WS_TEXT};
- bool _mask{false};
- AwsMessageStatus _status{WS_MSG_ERROR};
- size_t _sent{};
- size_t _ack{};
- size_t _acked{};
+ uint8_t _opcode{WS_TEXT};
+ bool _mask{false};
+ AwsMessageStatus _status{WS_MSG_ERROR};
+ size_t _sent{};
+ size_t _ack{};
+ size_t _acked{};
-public:
- AsyncWebSocketMessage(std::shared_ptr> buffer, uint8_t opcode=WS_TEXT, bool mask=false);
+ public:
+ AsyncWebSocketMessage(std::shared_ptr> buffer, uint8_t opcode = WS_TEXT, bool mask = false);
- bool finished() const { return _status != WS_MSG_SENDING; }
- bool betweenFrames() const { return _acked == _ack; }
+ bool finished() const {
+ return _status != WS_MSG_SENDING;
+ }
+ bool betweenFrames() const {
+ return _acked == _ack;
+ }
- void ack(size_t len, uint32_t time);
- size_t send(AsyncClient *client);
+ void ack(size_t len, uint32_t time);
+ size_t send(AsyncClient * client);
};
class AsyncWebSocketClient {
private:
- AsyncClient *_client;
- AsyncWebSocket *_server;
- uint32_t _clientId;
- AwsClientStatus _status;
+ AsyncClient * _client;
+ AsyncWebSocket * _server;
+ uint32_t _clientId;
+ AwsClientStatus _status;
AsyncWebLock _lock;
std::deque _controlQueue;
std::deque _messageQueue;
+ bool closeWhenFull = true;
- uint8_t _pstate;
+ uint8_t _pstate;
AwsFrameInfo _pinfo;
uint32_t _lastMessageTime;
uint32_t _keepAlivePeriod;
- void _queueControl(uint8_t opcode, const uint8_t *data=NULL, size_t len=0, bool mask=false);
- void _queueMessage(std::shared_ptr> buffer, uint8_t opcode=WS_TEXT, bool mask=false);
+ void _queueControl(uint8_t opcode, const uint8_t * data = NULL, size_t len = 0, bool mask = false);
+ void _queueMessage(std::shared_ptr> buffer, uint8_t opcode = WS_TEXT, bool mask = false);
void _runQueue();
void _clearQueue();
public:
- void *_tempObject;
+ void * _tempObject;
- AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server);
+ AsyncWebSocketClient(AsyncWebServerRequest * request, AsyncWebSocket * server);
~AsyncWebSocketClient();
//client id increments for the given server
- uint32_t id() const { return _clientId; }
- AwsClientStatus status() const { return _status; }
- AsyncClient* client() { return _client; }
- const AsyncClient* client() const { return _client; }
- AsyncWebSocket *server(){ return _server; }
- const AsyncWebSocket *server() const { return _server; }
- AwsFrameInfo const &pinfo() const { return _pinfo; }
+ uint32_t id() const {
+ return _clientId;
+ }
+ AwsClientStatus status() const {
+ return _status;
+ }
+ AsyncClient * client() {
+ return _client;
+ }
+ const AsyncClient * client() const {
+ return _client;
+ }
+ AsyncWebSocket * server() {
+ return _server;
+ }
+ const AsyncWebSocket * server() const {
+ return _server;
+ }
+ AwsFrameInfo const & pinfo() const {
+ return _pinfo;
+ }
+
+ // - If "true" (default), the connection will be closed if the message queue is full.
+ // This is the default behavior in yubox-node-org, which is not silently discarding messages but instead closes the connection.
+ // The big issue with this behavior is that is can cause the UI to automatically re-create a new WS connection, which can be filled again,
+ // and so on, causing a resource exhaustion.
+ //
+ // - If "false", the incoming message will be discarded if the queue is full.
+ // This is the default behavior in the original ESPAsyncWebServer library from me-no-dev.
+ // This behavior allows the best performance at the expense of unreliable message delivery in case the queue is full (some messages may be lost).
+ //
+ // - In any case, when the queue is full, a message is logged.
+ // - IT is recommended to use the methods queueIsFull(), availableForWriteAll(), availableForWrite(clientId) to check if the queue is full before sending a message.
+ //
+ // Usage:
+ // - can be set in the onEvent listener when connecting (event type is: WS_EVT_CONNECT)
+ //
+ // Use cases:,
+ // - if using websocket to send logging messages, maybe some loss is acceptable.
+ // - But if using websocket to send UI update messages, maybe the connection should be closed and the UI redrawn.
+ void setCloseClientOnQueueFull(bool close) {
+ closeWhenFull = close;
+ }
+ bool willCloseClientOnQueueFull() const {
+ return closeWhenFull;
+ }
IPAddress remoteIP() const;
uint16_t remotePort() const;
- bool shouldBeDeleted() const { return !_client; }
+ bool shouldBeDeleted() const {
+ return !_client;
+ }
//control frames
- void close(uint16_t code=0, const char * message=NULL);
- void ping(const uint8_t *data=NULL, size_t len=0);
+ void close(uint16_t code = 0, const char * message = NULL);
+ void ping(const uint8_t * data = NULL, size_t len = 0);
//set auto-ping period in seconds. disabled if zero (default)
- void keepAlivePeriod(uint16_t seconds){
- _keepAlivePeriod = seconds * 1000;
+ void keepAlivePeriod(uint16_t seconds) {
+ _keepAlivePeriod = seconds * 1000;
}
- uint16_t keepAlivePeriod(){
- return (uint16_t)(_keepAlivePeriod / 1000);
+ uint16_t keepAlivePeriod() {
+ return (uint16_t)(_keepAlivePeriod / 1000);
}
//data packets
- void message(std::shared_ptr> buffer, uint8_t opcode=WS_TEXT, bool mask=false) { _queueMessage(buffer, opcode, mask); }
- bool queueIsFull() const;
+ void message(std::shared_ptr> buffer, uint8_t opcode = WS_TEXT, bool mask = false) {
+ _queueMessage(buffer, opcode, mask);
+ }
+ bool queueIsFull() const;
size_t queueLen() const;
- size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+ size_t printf(const char * format, ...) __attribute__((format(printf, 2, 3)));
#ifndef ESP32
- size_t printf_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3)));
+ size_t printf_P(PGM_P formatP, ...) __attribute__((format(printf, 2, 3)));
#endif
void text(std::shared_ptr> buffer);
- void text(const uint8_t *message, size_t len);
- void text(const char *message, size_t len);
- void text(const char *message);
- void text(const String &message);
- void text(const __FlashStringHelper *message);
- void text(AsyncWebSocketMessageBuffer *buffer);
+ void text(const uint8_t * message, size_t len);
+ void text(const char * message, size_t len);
+ void text(const char * message);
+ void text(const String & message);
+ void text(const __FlashStringHelper * message);
+ void text(AsyncWebSocketMessageBuffer * buffer);
void binary(std::shared_ptr> buffer);
- void binary(const uint8_t *message, size_t len);
+ void binary(const uint8_t * message, size_t len);
void binary(const char * message, size_t len);
void binary(const char * message);
- void binary(const String &message);
- void binary(const __FlashStringHelper *message, size_t len);
- void binary(AsyncWebSocketMessageBuffer *buffer);
+ void binary(const String & message);
+ void binary(const __FlashStringHelper * message, size_t len);
+ void binary(AsyncWebSocketMessageBuffer * buffer);
bool canSend() const;
@@ -215,114 +266,133 @@ class AsyncWebSocketClient {
void _onPoll();
void _onTimeout(uint32_t time);
void _onDisconnect();
- void _onData(void *pbuf, size_t plen);
+ void _onData(void * pbuf, size_t plen);
};
-typedef std::function AwsHandshakeHandler;
-typedef std::function AwsEventHandler;
+typedef std::function AwsHandshakeHandler;
+typedef std::function AwsEventHandler;
//WebServer Handler implementation that plays the role of a socket server
-class AsyncWebSocket: public AsyncWebHandler {
+class AsyncWebSocket : public AsyncWebHandler {
private:
- String _url;
+ String _url;
std::list _clients;
- uint32_t _cNextId;
- AwsEventHandler _eventHandler;
- AwsHandshakeHandler _handshakeHandler;
- bool _enabled;
- AsyncWebLock _lock;
+ uint32_t _cNextId;
+ AwsEventHandler _eventHandler;
+ AwsHandshakeHandler _handshakeHandler;
+ bool _enabled;
+ AsyncWebLock _lock;
public:
- AsyncWebSocket(const String& url);
+ AsyncWebSocket(const String & url);
~AsyncWebSocket();
- const char * url() const { return _url.c_str(); }
- void enable(bool e){ _enabled = e; }
- bool enabled() const { return _enabled; }
+ const char * url() const {
+ return _url.c_str();
+ }
+ void enable(bool e) {
+ _enabled = e;
+ }
+ bool enabled() const {
+ return _enabled;
+ }
bool availableForWriteAll();
bool availableForWrite(uint32_t id);
- size_t count() const;
+ size_t count() const;
AsyncWebSocketClient * client(uint32_t id);
- bool hasClient(uint32_t id){ return client(id) != NULL; }
+ bool hasClient(uint32_t id) {
+ return client(id) != NULL;
+ }
- void close(uint32_t id, uint16_t code=0, const char * message=NULL);
- void closeAll(uint16_t code=0, const char * message=NULL);
+ void close(uint32_t id, uint16_t code = 0, const char * message = NULL);
+ void closeAll(uint16_t code = 0, const char * message = NULL);
void cleanupClients(uint16_t maxClients = DEFAULT_MAX_WS_CLIENTS);
- void ping(uint32_t id, const uint8_t *data=NULL, size_t len=0);
- void pingAll(const uint8_t *data=NULL, size_t len=0); // done
+ void ping(uint32_t id, const uint8_t * data = NULL, size_t len = 0);
+ void pingAll(const uint8_t * data = NULL, size_t len = 0); // done
void text(uint32_t id, const uint8_t * message, size_t len);
- void text(uint32_t id, const char *message, size_t len);
- void text(uint32_t id, const char *message);
- void text(uint32_t id, const String &message);
- void text(uint32_t id, const __FlashStringHelper *message);
+ void text(uint32_t id, const char * message, size_t len);
+ void text(uint32_t id, const char * message);
+ void text(uint32_t id, const String & message);
+ void text(uint32_t id, const __FlashStringHelper * message);
+ void text(uint32_t id, AsyncWebSocketMessageBuffer * buffer);
+ void text(uint32_t id, std::shared_ptr> buffer);
- void textAll(std::shared_ptr> buffer);
- void textAll(const uint8_t *message, size_t len);
+ void textAll(const uint8_t * message, size_t len);
void textAll(const char * message, size_t len);
void textAll(const char * message);
- void textAll(const String &message);
- void textAll(const __FlashStringHelper *message); // need to convert
- void textAll(AsyncWebSocketMessageBuffer *buffer);
+ void textAll(const String & message);
+ void textAll(const __FlashStringHelper * message);
+ void textAll(AsyncWebSocketMessageBuffer * buffer);
+ void textAll(std::shared_ptr> buffer);
- void binary(uint32_t id, const uint8_t *message, size_t len);
- void binary(uint32_t id, const char *message, size_t len);
- void binary(uint32_t id, const char *message);
- void binary(uint32_t id, const String &message);
- void binary(uint32_t id, const __FlashStringHelper *message, size_t len);
+ void binary(uint32_t id, const uint8_t * message, size_t len);
+ void binary(uint32_t id, const char * message, size_t len);
+ void binary(uint32_t id, const char * message);
+ void binary(uint32_t id, const String & message);
+ void binary(uint32_t id, const __FlashStringHelper * message, size_t len);
+ void binary(uint32_t id, AsyncWebSocketMessageBuffer * buffer);
+ void binary(uint32_t id, std::shared_ptr> buffer);
+ void binaryAll(const uint8_t * message, size_t len);
+ void binaryAll(const char * message, size_t len);
+ void binaryAll(const char * message);
+ void binaryAll(const String & message);
+ void binaryAll(const __FlashStringHelper * message, size_t len);
+ void binaryAll(AsyncWebSocketMessageBuffer * buffer);
void binaryAll(std::shared_ptr> buffer);
- void binaryAll(const uint8_t *message, size_t len);
- void binaryAll(const char *message, size_t len);
- void binaryAll(const char *message);
- void binaryAll(const String &message);
- void binaryAll(const __FlashStringHelper *message, size_t len);
- void binaryAll(AsyncWebSocketMessageBuffer *buffer);
- size_t printf(uint32_t id, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
- size_t printfAll(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+ size_t printf(uint32_t id, const char * format, ...) __attribute__((format(printf, 3, 4)));
+ size_t printfAll(const char * format, ...) __attribute__((format(printf, 2, 3)));
#ifndef ESP32
- size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__ ((format (printf, 3, 4)));
+ size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__((format(printf, 3, 4)));
#endif
- size_t printfAll_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3)));
+ size_t printfAll_P(PGM_P formatP, ...) __attribute__((format(printf, 2, 3)));
//event listener
- void onEvent(AwsEventHandler handler){
- _eventHandler = handler;
+ void onEvent(AwsEventHandler handler) {
+ _eventHandler = handler;
}
// Handshake Handler
- void handleHandshake(AwsHandshakeHandler handler){
- _handshakeHandler = handler;
+ void handleHandshake(AwsHandshakeHandler handler) {
+ _handshakeHandler = handler;
}
-
+
//system callbacks (do not call)
- uint32_t _getNextId(){ return _cNextId++; }
- AsyncWebSocketClient *_newClient(AsyncWebServerRequest *request);
- void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
- virtual bool canHandle(AsyncWebServerRequest *request) override final;
- virtual void handleRequest(AsyncWebServerRequest *request) override final;
+ uint32_t _getNextId() {
+ return _cNextId++;
+ }
+ AsyncWebSocketClient * _newClient(AsyncWebServerRequest * request);
+ void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t * data, size_t len);
+ virtual bool canHandle(AsyncWebServerRequest * request) override final;
+ virtual void handleRequest(AsyncWebServerRequest * request) override final;
- // messagebuffer functions/objects.
- AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0);
- AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size);
+ // messagebuffer functions/objects.
+ AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0);
+ AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size);
- const std::list &getClients() const { return _clients; }
+ const std::list & getClients() const {
+ return _clients;
+ }
};
//WebServer response to authenticate the socket and detach the tcp client from the web server request
-class AsyncWebSocketResponse: public AsyncWebServerResponse {
+class AsyncWebSocketResponse : public AsyncWebServerResponse {
private:
- String _content;
- AsyncWebSocket *_server;
+ String _content;
+ AsyncWebSocket * _server;
+
public:
- AsyncWebSocketResponse(const String& key, AsyncWebSocket *server);
- void _respond(AsyncWebServerRequest *request);
- size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
- bool _sourceValid() const { return true; }
+ AsyncWebSocketResponse(const String & key, AsyncWebSocket * server);
+ void _respond(AsyncWebServerRequest * request);
+ size_t _ack(AsyncWebServerRequest * request, size_t len, uint32_t time);
+ bool _sourceValid() const {
+ return true;
+ }
};
-#endif /* ASYNCWEBSOCKET_H_ */
+#endif /* ASYNCWEBSOCKET_H_ */
\ No newline at end of file
diff --git a/lib/ESPAsyncWebServer/src/WebAuthentication.cpp b/lib/ESPAsyncWebServer/src/WebAuthentication.cpp
index a1e6459e2..656adbc61 100644
--- a/lib/ESPAsyncWebServer/src/WebAuthentication.cpp
+++ b/lib/ESPAsyncWebServer/src/WebAuthentication.cpp
@@ -21,7 +21,7 @@
#include "WebAuthentication.h"
#include
#ifdef ESP32
-#include "mbedtls/md5.h"
+#include
#else
#include "md5.h"
#endif
@@ -29,220 +29,221 @@
// Basic Auth hash = base64("username:password")
-bool checkBasicAuthentication(const char * hash, const char * username, const char * password){
- if(username == NULL || password == NULL || hash == NULL)
- return false;
+bool checkBasicAuthentication(const char * hash, const char * username, const char * password) {
+ if (username == NULL || password == NULL || hash == NULL)
+ return false;
- size_t toencodeLen = strlen(username)+strlen(password)+1;
- size_t encodedLen = base64_encode_expected_len(toencodeLen);
- if(strlen(hash) != encodedLen)
+ size_t toencodeLen = strlen(username) + strlen(password) + 1;
+ size_t encodedLen = base64_encode_expected_len(toencodeLen);
+ if (strlen(hash) != encodedLen)
// Fix from https://github.com/me-no-dev/ESPAsyncWebServer/issues/667
#ifdef ARDUINO_ARCH_ESP32
- if(strlen(hash) != encodedLen)
+ if (strlen(hash) != encodedLen)
#else
- if (strlen(hash) != encodedLen - 1)
+ if (strlen(hash) != encodedLen - 1)
#endif
- return false;
+ return false;
- char *toencode = new char[toencodeLen+1];
- if(toencode == NULL){
- return false;
- }
- char *encoded = new char[base64_encode_expected_len(toencodeLen)+1];
- if(encoded == NULL){
- delete[] toencode;
- return false;
- }
- sprintf_P(toencode, PSTR("%s:%s"), username, password);
- if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && memcmp(hash, encoded, encodedLen) == 0){
+ char * toencode = new char[toencodeLen + 1];
+ if (toencode == NULL) {
+ return false;
+ }
+ char * encoded = new char[base64_encode_expected_len(toencodeLen) + 1];
+ if (encoded == NULL) {
+ delete[] toencode;
+ return false;
+ }
+ sprintf_P(toencode, PSTR("%s:%s"), username, password);
+ if (base64_encode_chars(toencode, toencodeLen, encoded) > 0 && memcmp(hash, encoded, encodedLen) == 0) {
+ delete[] toencode;
+ delete[] encoded;
+ return true;
+ }
delete[] toencode;
delete[] encoded;
- return true;
- }
- delete[] toencode;
- delete[] encoded;
- return false;
+ return false;
}
-static bool getMD5(uint8_t * data, uint16_t len, char * output){//33 bytes or more
+static bool getMD5(uint8_t * data, uint16_t len, char * output) { //33 bytes or more
#ifdef ESP32
- mbedtls_md5_context _ctx;
+ MD5Builder md5;
+ md5.begin();
+ md5.add(data, len);
+ md5.calculate();
+ md5.getChars(output);
#else
md5_context_t _ctx;
-#endif
- uint8_t i;
- uint8_t * _buf = (uint8_t*)malloc(16);
- if(_buf == NULL)
- return false;
- memset(_buf, 0x00, 16);
-#ifdef ESP32
-#if ESP_IDF_VERSION_MAJOR < 5
- mbedtls_md5_init(&_ctx);
- mbedtls_md5_starts_ret(&_ctx);
- mbedtls_md5_update_ret(&_ctx, data, len);
- mbedtls_md5_finish_ret(&_ctx, _buf);
-#else
- mbedtls_md5_init(&_ctx);
- mbedtls_md5_starts(&_ctx);
- mbedtls_md5_update(&_ctx, data, len);
- mbedtls_md5_finish(&_ctx, _buf);
-#endif
-#else
- MD5Init(&_ctx);
- MD5Update(&_ctx, data, len);
- MD5Final(_buf, &_ctx);
-#endif
- for(i = 0; i < 16; i++) {
- sprintf_P(output + (i * 2), PSTR("%02x"), _buf[i]);
- }
- free(_buf);
- return true;
-}
-static String genRandomMD5(){
-#ifdef ESP8266
- uint32_t r = RANDOM_REG32;
-#else
- uint32_t r = rand();
-#endif
- char * out = (char*)malloc(33);
- if(out == NULL || !getMD5((uint8_t*)(&r), 4, out))
- return emptyString;
- String res = String(out);
- free(out);
- return res;
-}
+ uint8_t * _buf = (uint8_t *)malloc(16);
+ if (_buf == NULL)
+ return false;
+ memset(_buf, 0x00, 16);
-static String stringMD5(const String& in){
- char * out = (char*)malloc(33);
- if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out))
- return emptyString;
- String res = String(out);
- free(out);
- return res;
-}
+ MD5Init(&_ctx);
+ MD5Update(&_ctx, data, len);
+ MD5Final(_buf, &_ctx);
-String generateDigestHash(const char * username, const char * password, const char * realm){
- if(username == NULL || password == NULL || realm == NULL){
- return emptyString;
- }
- char * out = (char*)malloc(33);
- String res = String(username);
- res += ':';
- res.concat(realm);
- res += ':';
- String in = res;
- in.concat(password);
- if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out))
- return emptyString;
- res.concat(out);
- free(out);
- return res;
-}
-
-String requestDigestAuthentication(const char * realm){
- String header = F("realm=\"");
- if(realm == NULL)
- header.concat(F("asyncesp"));
- else
- header.concat(realm);
- header.concat(F("\", qop=\"auth\", nonce=\""));
- header.concat(genRandomMD5());
- header.concat(F("\", opaque=\""));
- header.concat(genRandomMD5());
- header += '"';
- return header;
-}
-
-bool checkDigestAuthentication(const char * header, const __FlashStringHelper *method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri){
- if(username == NULL || password == NULL || header == NULL || method == NULL){
- //os_printf("AUTH FAIL: missing requred fields\n");
- return false;
- }
-
- String myHeader = String(header);
- int nextBreak = myHeader.indexOf(',');
- if(nextBreak < 0){
- //os_printf("AUTH FAIL: no variables\n");
- return false;
- }
-
- String myUsername = String();
- String myRealm = String();
- String myNonce = String();
- String myUri = String();
- String myResponse = String();
- String myQop = String();
- String myNc = String();
- String myCnonce = String();
-
- myHeader += F(", ");
- do {
- String avLine = myHeader.substring(0, nextBreak);
- avLine.trim();
- myHeader = myHeader.substring(nextBreak+1);
- nextBreak = myHeader.indexOf(',');
-
- int eqSign = avLine.indexOf('=');
- if(eqSign < 0){
- //os_printf("AUTH FAIL: no = sign\n");
- return false;
- }
- String varName = avLine.substring(0, eqSign);
- avLine = avLine.substring(eqSign + 1);
- if(avLine.startsWith(String('"'))){
- avLine = avLine.substring(1, avLine.length() - 1);
+ for (uint8_t i = 0; i < 16; i++) {
+ sprintf_P(output + (i * 2), PSTR("%02x"), _buf[i]);
}
- if(varName.equals(F("username"))){
- if(!avLine.equals(username)){
- //os_printf("AUTH FAIL: username\n");
- return false;
- }
- myUsername = avLine;
- } else if(varName.equals(F("realm"))){
- if(realm != NULL && !avLine.equals(realm)){
- //os_printf("AUTH FAIL: realm\n");
- return false;
- }
- myRealm = avLine;
- } else if(varName.equals(F("nonce"))){
- if(nonce != NULL && !avLine.equals(nonce)){
- //os_printf("AUTH FAIL: nonce\n");
- return false;
- }
- myNonce = avLine;
- } else if(varName.equals(F("opaque"))){
- if(opaque != NULL && !avLine.equals(opaque)){
- //os_printf("AUTH FAIL: opaque\n");
- return false;
- }
- } else if(varName.equals(F("uri"))){
- if(uri != NULL && !avLine.equals(uri)){
- //os_printf("AUTH FAIL: uri\n");
- return false;
- }
- myUri = avLine;
- } else if(varName.equals(F("response"))){
- myResponse = avLine;
- } else if(varName.equals(F("qop"))){
- myQop = avLine;
- } else if(varName.equals(F("nc"))){
- myNc = avLine;
- } else if(varName.equals(F("cnonce"))){
- myCnonce = avLine;
- }
- } while(nextBreak > 0);
-
- String ha1 = (passwordIsHash) ? String(password) : stringMD5(myUsername + ':' + myRealm + ':' + String(password));
- String ha2 = String(method) + ':' + myUri;
- String response = ha1 + ':' + myNonce + ':' + myNc + ':' + myCnonce + ':' + myQop + ':' + stringMD5(ha2);
-
- if(myResponse.equals(stringMD5(response))){
- //os_printf("AUTH SUCCESS\n");
+ free(_buf);
+#endif
return true;
- }
-
- //os_printf("AUTH FAIL: password\n");
- return false;
}
+
+static String genRandomMD5() {
+#ifdef ESP8266
+ uint32_t r = RANDOM_REG32;
+#else
+ uint32_t r = rand();
+#endif
+ char * out = (char *)malloc(33);
+ if (out == NULL || !getMD5((uint8_t *)(&r), 4, out))
+ return emptyString;
+ String res = String(out);
+ free(out);
+ return res;
+}
+
+static String stringMD5(const String & in) {
+ char * out = (char *)malloc(33);
+ if (out == NULL || !getMD5((uint8_t *)(in.c_str()), in.length(), out))
+ return emptyString;
+ String res = String(out);
+ free(out);
+ return res;
+}
+
+String generateDigestHash(const char * username, const char * password, const char * realm) {
+ if (username == NULL || password == NULL || realm == NULL) {
+ return emptyString;
+ }
+ char * out = (char *)malloc(33);
+ String res = String(username);
+ res += ':';
+ res.concat(realm);
+ res += ':';
+ String in = res;
+ in.concat(password);
+ if (out == NULL || !getMD5((uint8_t *)(in.c_str()), in.length(), out))
+ return emptyString;
+ res.concat(out);
+ free(out);
+ return res;
+}
+
+String requestDigestAuthentication(const char * realm) {
+ String header = F("realm=\"");
+ if (realm == NULL)
+ header.concat(F("asyncesp"));
+ else
+ header.concat(realm);
+ header.concat(F("\", qop=\"auth\", nonce=\""));
+ header.concat(genRandomMD5());
+ header.concat(F("\", opaque=\""));
+ header.concat(genRandomMD5());
+ header += '"';
+ return header;
+}
+
+bool checkDigestAuthentication(const char * header,
+ const __FlashStringHelper * method,
+ const char * username,
+ const char * password,
+ const char * realm,
+ bool passwordIsHash,
+ const char * nonce,
+ const char * opaque,
+ const char * uri) {
+ if (username == NULL || password == NULL || header == NULL || method == NULL) {
+ //os_printf("AUTH FAIL: missing requred fields\n");
+ return false;
+ }
+
+ String myHeader = String(header);
+ int nextBreak = myHeader.indexOf(',');
+ if (nextBreak < 0) {
+ //os_printf("AUTH FAIL: no variables\n");
+ return false;
+ }
+
+ String myUsername = String();
+ String myRealm = String();
+ String myNonce = String();
+ String myUri = String();
+ String myResponse = String();
+ String myQop = String();
+ String myNc = String();
+ String myCnonce = String();
+
+ myHeader += F(", ");
+ do {
+ String avLine = myHeader.substring(0, nextBreak);
+ avLine.trim();
+ myHeader = myHeader.substring(nextBreak + 1);
+ nextBreak = myHeader.indexOf(',');
+
+ int eqSign = avLine.indexOf('=');
+ if (eqSign < 0) {
+ //os_printf("AUTH FAIL: no = sign\n");
+ return false;
+ }
+ String varName = avLine.substring(0, eqSign);
+ avLine = avLine.substring(eqSign + 1);
+ if (avLine.startsWith(String('"'))) {
+ avLine = avLine.substring(1, avLine.length() - 1);
+ }
+
+ if (varName.equals(F("username"))) {
+ if (!avLine.equals(username)) {
+ //os_printf("AUTH FAIL: username\n");
+ return false;
+ }
+ myUsername = avLine;
+ } else if (varName.equals(F("realm"))) {
+ if (realm != NULL && !avLine.equals(realm)) {
+ //os_printf("AUTH FAIL: realm\n");
+ return false;
+ }
+ myRealm = avLine;
+ } else if (varName.equals(F("nonce"))) {
+ if (nonce != NULL && !avLine.equals(nonce)) {
+ //os_printf("AUTH FAIL: nonce\n");
+ return false;
+ }
+ myNonce = avLine;
+ } else if (varName.equals(F("opaque"))) {
+ if (opaque != NULL && !avLine.equals(opaque)) {
+ //os_printf("AUTH FAIL: opaque\n");
+ return false;
+ }
+ } else if (varName.equals(F("uri"))) {
+ if (uri != NULL && !avLine.equals(uri)) {
+ //os_printf("AUTH FAIL: uri\n");
+ return false;
+ }
+ myUri = avLine;
+ } else if (varName.equals(F("response"))) {
+ myResponse = avLine;
+ } else if (varName.equals(F("qop"))) {
+ myQop = avLine;
+ } else if (varName.equals(F("nc"))) {
+ myNc = avLine;
+ } else if (varName.equals(F("cnonce"))) {
+ myCnonce = avLine;
+ }
+ } while (nextBreak > 0);
+
+ String ha1 = (passwordIsHash) ? String(password) : stringMD5(myUsername + ':' + myRealm + ':' + String(password));
+ String ha2 = String(method) + ':' + myUri;
+ String response = ha1 + ':' + myNonce + ':' + myNc + ':' + myCnonce + ':' + myQop + ':' + stringMD5(ha2);
+
+ if (myResponse.equals(stringMD5(response))) {
+ //os_printf("AUTH SUCCESS\n");
+ return true;
+ }
+
+ //os_printf("AUTH FAIL: password\n");
+ return false;
+}
\ No newline at end of file
diff --git a/lib/ESPAsyncWebServer/src/port/SHA1Builder.cpp b/lib/ESPAsyncWebServer/src/port/SHA1Builder.cpp
new file mode 100644
index 000000000..b41754dd0
--- /dev/null
+++ b/lib/ESPAsyncWebServer/src/port/SHA1Builder.cpp
@@ -0,0 +1,284 @@
+/*
+ * FIPS-180-1 compliant SHA-1 implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ * Modified for esp32 by Lucas Saavedra Vaz on 11 Jan 2024
+ */
+
+#include
+#if ESP_IDF_VERSION_MAJOR < 5
+
+#include "SHA1Builder.h"
+
+// 32-bit integer manipulation macros (big endian)
+
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n, b, i) \
+ { (n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | ((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); }
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n, b, i) \
+ { \
+ (b)[(i)] = (uint8_t)((n) >> 24); \
+ (b)[(i) + 1] = (uint8_t)((n) >> 16); \
+ (b)[(i) + 2] = (uint8_t)((n) >> 8); \
+ (b)[(i) + 3] = (uint8_t)((n)); \
+ }
+#endif
+
+// Constants
+
+static const uint8_t sha1_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+// Private methods
+
+void SHA1Builder::process(const uint8_t * data) {
+ uint32_t temp, W[16], A, B, C, D, E;
+
+ GET_UINT32_BE(W[0], data, 0);
+ GET_UINT32_BE(W[1], data, 4);
+ GET_UINT32_BE(W[2], data, 8);
+ GET_UINT32_BE(W[3], data, 12);
+ GET_UINT32_BE(W[4], data, 16);
+ GET_UINT32_BE(W[5], data, 20);
+ GET_UINT32_BE(W[6], data, 24);
+ GET_UINT32_BE(W[7], data, 28);
+ GET_UINT32_BE(W[8], data, 32);
+ GET_UINT32_BE(W[9], data, 36);
+ GET_UINT32_BE(W[10], data, 40);
+ GET_UINT32_BE(W[11], data, 44);
+ GET_UINT32_BE(W[12], data, 48);
+ GET_UINT32_BE(W[13], data, 52);
+ GET_UINT32_BE(W[14], data, 56);
+ GET_UINT32_BE(W[15], data, 60);
+
+#define sha1_S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define sha1_R(t) (temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ W[(t - 14) & 0x0F] ^ W[t & 0x0F], (W[t & 0x0F] = sha1_S(temp, 1)))
+
+#define sha1_P(a, b, c, d, e, x) \
+ { \
+ e += sha1_S(a, 5) + sha1_F(b, c, d) + sha1_K + x; \
+ b = sha1_S(b, 30); \
+ }
+
+ A = state[0];
+ B = state[1];
+ C = state[2];
+ D = state[3];
+ E = state[4];
+
+#define sha1_F(x, y, z) (z ^ (x & (y ^ z)))
+#define sha1_K 0x5A827999
+
+ sha1_P(A, B, C, D, E, W[0]);
+ sha1_P(E, A, B, C, D, W[1]);
+ sha1_P(D, E, A, B, C, W[2]);
+ sha1_P(C, D, E, A, B, W[3]);
+ sha1_P(B, C, D, E, A, W[4]);
+ sha1_P(A, B, C, D, E, W[5]);
+ sha1_P(E, A, B, C, D, W[6]);
+ sha1_P(D, E, A, B, C, W[7]);
+ sha1_P(C, D, E, A, B, W[8]);
+ sha1_P(B, C, D, E, A, W[9]);
+ sha1_P(A, B, C, D, E, W[10]);
+ sha1_P(E, A, B, C, D, W[11]);
+ sha1_P(D, E, A, B, C, W[12]);
+ sha1_P(C, D, E, A, B, W[13]);
+ sha1_P(B, C, D, E, A, W[14]);
+ sha1_P(A, B, C, D, E, W[15]);
+ sha1_P(E, A, B, C, D, sha1_R(16));
+ sha1_P(D, E, A, B, C, sha1_R(17));
+ sha1_P(C, D, E, A, B, sha1_R(18));
+ sha1_P(B, C, D, E, A, sha1_R(19));
+
+#undef sha1_K
+#undef sha1_F
+
+#define sha1_F(x, y, z) (x ^ y ^ z)
+#define sha1_K 0x6ED9EBA1
+
+ sha1_P(A, B, C, D, E, sha1_R(20));
+ sha1_P(E, A, B, C, D, sha1_R(21));
+ sha1_P(D, E, A, B, C, sha1_R(22));
+ sha1_P(C, D, E, A, B, sha1_R(23));
+ sha1_P(B, C, D, E, A, sha1_R(24));
+ sha1_P(A, B, C, D, E, sha1_R(25));
+ sha1_P(E, A, B, C, D, sha1_R(26));
+ sha1_P(D, E, A, B, C, sha1_R(27));
+ sha1_P(C, D, E, A, B, sha1_R(28));
+ sha1_P(B, C, D, E, A, sha1_R(29));
+ sha1_P(A, B, C, D, E, sha1_R(30));
+ sha1_P(E, A, B, C, D, sha1_R(31));
+ sha1_P(D, E, A, B, C, sha1_R(32));
+ sha1_P(C, D, E, A, B, sha1_R(33));
+ sha1_P(B, C, D, E, A, sha1_R(34));
+ sha1_P(A, B, C, D, E, sha1_R(35));
+ sha1_P(E, A, B, C, D, sha1_R(36));
+ sha1_P(D, E, A, B, C, sha1_R(37));
+ sha1_P(C, D, E, A, B, sha1_R(38));
+ sha1_P(B, C, D, E, A, sha1_R(39));
+
+#undef sha1_K
+#undef sha1_F
+
+#define sha1_F(x, y, z) ((x & y) | (z & (x | y)))
+#define sha1_K 0x8F1BBCDC
+
+ sha1_P(A, B, C, D, E, sha1_R(40));
+ sha1_P(E, A, B, C, D, sha1_R(41));
+ sha1_P(D, E, A, B, C, sha1_R(42));
+ sha1_P(C, D, E, A, B, sha1_R(43));
+ sha1_P(B, C, D, E, A, sha1_R(44));
+ sha1_P(A, B, C, D, E, sha1_R(45));
+ sha1_P(E, A, B, C, D, sha1_R(46));
+ sha1_P(D, E, A, B, C, sha1_R(47));
+ sha1_P(C, D, E, A, B, sha1_R(48));
+ sha1_P(B, C, D, E, A, sha1_R(49));
+ sha1_P(A, B, C, D, E, sha1_R(50));
+ sha1_P(E, A, B, C, D, sha1_R(51));
+ sha1_P(D, E, A, B, C, sha1_R(52));
+ sha1_P(C, D, E, A, B, sha1_R(53));
+ sha1_P(B, C, D, E, A, sha1_R(54));
+ sha1_P(A, B, C, D, E, sha1_R(55));
+ sha1_P(E, A, B, C, D, sha1_R(56));
+ sha1_P(D, E, A, B, C, sha1_R(57));
+ sha1_P(C, D, E, A, B, sha1_R(58));
+ sha1_P(B, C, D, E, A, sha1_R(59));
+
+#undef sha1_K
+#undef sha1_F
+
+#define sha1_F(x, y, z) (x ^ y ^ z)
+#define sha1_K 0xCA62C1D6
+
+ sha1_P(A, B, C, D, E, sha1_R(60));
+ sha1_P(E, A, B, C, D, sha1_R(61));
+ sha1_P(D, E, A, B, C, sha1_R(62));
+ sha1_P(C, D, E, A, B, sha1_R(63));
+ sha1_P(B, C, D, E, A, sha1_R(64));
+ sha1_P(A, B, C, D, E, sha1_R(65));
+ sha1_P(E, A, B, C, D, sha1_R(66));
+ sha1_P(D, E, A, B, C, sha1_R(67));
+ sha1_P(C, D, E, A, B, sha1_R(68));
+ sha1_P(B, C, D, E, A, sha1_R(69));
+ sha1_P(A, B, C, D, E, sha1_R(70));
+ sha1_P(E, A, B, C, D, sha1_R(71));
+ sha1_P(D, E, A, B, C, sha1_R(72));
+ sha1_P(C, D, E, A, B, sha1_R(73));
+ sha1_P(B, C, D, E, A, sha1_R(74));
+ sha1_P(A, B, C, D, E, sha1_R(75));
+ sha1_P(E, A, B, C, D, sha1_R(76));
+ sha1_P(D, E, A, B, C, sha1_R(77));
+ sha1_P(C, D, E, A, B, sha1_R(78));
+ sha1_P(B, C, D, E, A, sha1_R(79));
+
+#undef sha1_K
+#undef sha1_F
+
+ state[0] += A;
+ state[1] += B;
+ state[2] += C;
+ state[3] += D;
+ state[4] += E;
+}
+
+// Public methods
+
+void SHA1Builder::begin(void) {
+ total[0] = 0;
+ total[1] = 0;
+
+ state[0] = 0x67452301;
+ state[1] = 0xEFCDAB89;
+ state[2] = 0x98BADCFE;
+ state[3] = 0x10325476;
+ state[4] = 0xC3D2E1F0;
+
+ memset(buffer, 0x00, sizeof(buffer));
+ memset(hash, 0x00, sizeof(hash));
+}
+
+void SHA1Builder::add(const uint8_t * data, size_t len) {
+ size_t fill;
+ uint32_t left;
+
+ if (len == 0) {
+ return;
+ }
+
+ left = total[0] & 0x3F;
+ fill = 64 - left;
+
+ total[0] += (uint32_t)len;
+ total[0] &= 0xFFFFFFFF;
+
+ if (total[0] < (uint32_t)len) {
+ total[1]++;
+ }
+
+ if (left && len >= fill) {
+ memcpy((void *)(buffer + left), data, fill);
+ process(buffer);
+ data += fill;
+ len -= fill;
+ left = 0;
+ }
+
+ while (len >= 64) {
+ process(data);
+ data += 64;
+ len -= 64;
+ }
+
+ if (len > 0) {
+ memcpy((void *)(buffer + left), data, len);
+ }
+}
+
+void SHA1Builder::calculate(void) {
+ uint32_t last, padn;
+ uint32_t high, low;
+ uint8_t msglen[8];
+
+ high = (total[0] >> 29) | (total[1] << 3);
+ low = (total[0] << 3);
+
+ PUT_UINT32_BE(high, msglen, 0);
+ PUT_UINT32_BE(low, msglen, 4);
+
+ last = total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ add((uint8_t *)sha1_padding, padn);
+ add(msglen, 8);
+
+ PUT_UINT32_BE(state[0], hash, 0);
+ PUT_UINT32_BE(state[1], hash, 4);
+ PUT_UINT32_BE(state[2], hash, 8);
+ PUT_UINT32_BE(state[3], hash, 12);
+ PUT_UINT32_BE(state[4], hash, 16);
+}
+
+void SHA1Builder::getBytes(uint8_t * output) {
+ memcpy(output, hash, SHA1_HASH_SIZE);
+}
+
+#endif // ESP_IDF_VERSION_MAJOR < 5
\ No newline at end of file
diff --git a/lib/ESPAsyncWebServer/src/port/SHA1Builder.h b/lib/ESPAsyncWebServer/src/port/SHA1Builder.h
new file mode 100644
index 000000000..5049cde39
--- /dev/null
+++ b/lib/ESPAsyncWebServer/src/port/SHA1Builder.h
@@ -0,0 +1,39 @@
+// Copyright 2024 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SHA1Builder_h
+#define SHA1Builder_h
+
+#include
+#include
+
+#define SHA1_HASH_SIZE 20
+
+class SHA1Builder {
+ private:
+ uint32_t total[2]; /* number of bytes processed */
+ uint32_t state[5]; /* intermediate digest state */
+ unsigned char buffer[64]; /* data block being processed */
+ uint8_t hash[SHA1_HASH_SIZE]; /* SHA-1 result */
+
+ void process(const uint8_t * data);
+
+ public:
+ void begin();
+ void add(const uint8_t * data, size_t len);
+ void calculate();
+ void getBytes(uint8_t * output);
+};
+
+#endif // SHA1Builder_h
\ No newline at end of file
diff --git a/mock-api/rest_server.ts b/mock-api/rest_server.ts
index 8ee5a404a..fbc601214 100644
--- a/mock-api/rest_server.ts
+++ b/mock-api/rest_server.ts
@@ -381,7 +381,11 @@ const system_status = {
free_heap: 143,
ntp_status: 2,
mqtt_status: true,
- ap_status: false
+ ap_status: false,
+ network_status: 3, // wifi connected
+ // network_status: 10, // ethernet connected
+ // network_status: 6, // wifi disconnected
+ wifi_rssi: -41
};
let security_settings = {
@@ -2134,19 +2138,26 @@ let emsesp_modules = {
"modules": [
{
id: 1,
- "name": "ModuleTest1",
+ "key": "ModuleTest1",
+ "name": "Module Test 1",
"author": "proddy",
"version": "1.0.0",
"enabled": true,
- "status": "active"
+ "status": 1,
+ "message": "Ready",
+ "license": "1234567890"
},
{
id: 2,
- "name": "ModuleTest2",
+ "key": "ModuleTest2",
+ "name": "Module Test 2",
"author": "proddy",
"version": "1.0.0",
"enabled": true,
- "status": "active"
+ "status": 2,
+ "message": "Ready",
+ "license": "ABCDEFGHIJKL"
+
}
]
}
@@ -2386,7 +2397,9 @@ router
return status(200);
})
.get(VERIFY_AUTHORIZATION_ENDPOINT, () => verify_authentication)
- .post(RESTART_ENDPOINT, () => status(200))
+ .post(RESTART_ENDPOINT, () => {
+ console.log('restarting...');
+ return status(200);})
.post(FACTORY_RESET_ENDPOINT, () => status(200))
.post(SIGN_IN_ENDPOINT, () => signin)
.get(GENERATE_TOKEN_ENDPOINT, () => generate_token);
@@ -2514,10 +2527,11 @@ router
const content = await request.json();
let modules = content.modules;
for (let i = 0; i < modules.length; i++) {
- const name = modules[i].name;
- const objIndex = emsesp_modules.modules.findIndex((obj: any) => obj.name === name);
+ const key = modules[i].key;
+ const objIndex = emsesp_modules.modules.findIndex((obj: any) => obj.key === key);
if (objIndex !== -1) {
emsesp_modules.modules[objIndex].enabled = modules[i].enabled;
+ emsesp_modules.modules[objIndex].license = modules[i].license;
}
}
console.log('modules updated', emsesp_modules);
diff --git a/src/web/WebModulesService.cpp b/src/web/WebModulesService.cpp
index c9eaa73f1..3f00b6330 100644
--- a/src/web/WebModulesService.cpp
+++ b/src/web/WebModulesService.cpp
@@ -32,55 +32,62 @@ WebModulesService::WebModulesService(AsyncWebServer * server, FS * fs, SecurityM
// load the settings when the service starts
void WebModulesService::begin() {
EMSESP::logger().info("Starting Modules service");
- moduleLibrary.start(emsesp_);
- _fsPersistence.readFromFS(); // read the file from FS
+#ifdef EMSESP_TEST
+ moduleLibrary.start(emsesp_, true); // hot load the test modules as well
+#else
+ moduleLibrary.start(emsesp_);
+#endif
+
+ _fsPersistence.readFromFS(); // read the file from FS - this will call the update function WebModules::update()
}
void WebModulesService::loop() {
moduleLibrary.loop(); // loop the external library modules
}
-// this creates the modules file, saving it to the FS
-// and also calls when the Modules web page is refreshed
+// this creates the modules settings file, saving it to the file system
+// it adds data to an empty 'root' json object
+// and also calls when the Modules web page is refreshed/loaded
void WebModules::read(WebModules & webModules, JsonObject root) {
-#ifdef EMSESP_DEBUG
- EMSESP::logger().debug("module read called");
-#endif
-
+ emsesp_->logger().err("debug: in WebModules::read()"); // TODO remove
JsonDocument doc_modules;
JsonObject root_modules = doc_modules.to();
- moduleLibrary.list(root_modules); // get list the external library modules, put in root json object
+ moduleLibrary.list(root_modules); // get list the external library modules, put in a json object
JsonArray modules = root["modules"].to();
uint8_t counter = 0;
for (const JsonObject module : root_modules["modules"].as()) {
JsonObject mi = modules.add();
mi["id"] = counter++; // id is only used to render the table and must be unique
+ mi["key"] = module["key"].as();
mi["name"] = module["name"].as();
mi["author"] = module["author"].as();
mi["version"] = module["version"].as();
- mi["status"] = module["status"].as();
+ mi["status"] = module["status"].as();
mi["enabled"] = module["enabled"].as();
+ mi["message"] = module["message"].as();
+ mi["license"] = module["license"].as();
}
}
-// read any Module settings from the FS settings
-// and then apply the enable/disable
-// it's also called on a save
+// read any Module settings from the settings file
+// and then apply the enable/disable that is set by the user
+// This function is called when ems-esp boots and also on a save from the Modules web page
StateUpdateResult WebModules::update(JsonObject root, WebModules & webModules) {
-#ifdef EMSESP_DEBUG
- EMSESP::logger().debug("module update called");
-#endif
-
if (root["modules"].is()) {
for (const JsonObject module : root["modules"].as()) {
- // set enabled/disabled
- moduleLibrary.enable(module["name"], module["enabled"].as());
+ auto key = module["key"].as();
+ auto license = module["license"].as();
+ auto enable = module["enabled"].as();
+
+ if (!moduleLibrary.enable(key, license, enable)) {
+ return StateUpdateResult::ERROR;
+ }
}
}
- return StateUpdateResult::CHANGED_RESTART;
+ return StateUpdateResult::CHANGED;
}
} // namespace emsesp
diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp
index 68be0b171..e3805d037 100644
--- a/src/web/WebSettingsService.cpp
+++ b/src/web/WebSettingsService.cpp
@@ -251,7 +251,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
settings.analog_enabled = root["analog_enabled"] | EMSESP_DEFAULT_ANALOG_ENABLED;
check_flag(prev, settings.analog_enabled, ChangeFlags::ADC);
-
//
// these need system restarts first before settings are activated...
//
@@ -294,7 +293,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
//
// without checks or necessary restarts...
//
-
settings.trace_raw = root["trace_raw"] | EMSESP_DEFAULT_TRACELOG_RAW;
EMSESP::trace_raw(settings.trace_raw);
diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp
index 3d988176a..105931f5e 100644
--- a/src/web/WebStatusService.cpp
+++ b/src/web/WebStatusService.cpp
@@ -70,6 +70,14 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
root["ap_status"] = EMSESP::esp8266React.apStatus();
+ if (emsesp::EMSESP::system_.ethernet_connected()) {
+ root["network_status"] = 10; // custom code #10 - ETHERNET_STATUS_CONNECTED
+ root["wifi_rssi"] = 0;
+ } else {
+ root["network_status"] = static_cast(WiFi.status());
+ root["wifi_rssi"] = WiFi.RSSI();
+ }
+
response->setLength();
request->send(response);
}