mirror of
https://github.com/Links2004/arduinoWebSockets.git
synced 2025-06-29 17:01:00 +02:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
dc6fd04a98 | |||
7da1dc5c6e | |||
d6d4c516b3 | |||
e364e66884 | |||
d5f0d3c4b5 | |||
0e127c9a76 | |||
11cf06897c | |||
af1b0256b9 |
24
.github/workflows/main.yml
vendored
24
.github/workflows/main.yml
vendored
@ -37,13 +37,13 @@ jobs:
|
||||
echo -en "matrix=" >> $GITHUB_OUTPUT
|
||||
echo -en "[" >> $GITHUB_OUTPUT
|
||||
|
||||
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.0 esp8266:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Serial1,lvl=SSL,wipe=none,baud=115200 >> $GITHUB_OUTPUT
|
||||
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.3 esp8266:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Serial1,lvl=SSL,wipe=none,baud=115200 >> $GITHUB_OUTPUT
|
||||
echo -en "," >> $GITHUB_OUTPUT
|
||||
|
||||
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.0 esp8266:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=115200 >> $GITHUB_OUTPUT
|
||||
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp8266_pico esp8266 0.35.3 esp8266:esp8266:generic:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,ResetMethod=nodemcu,CrystalFreq=26,FlashFreq=80,FlashMode=qio,eesz=4M2M,led=2,sdk=nonosdk_190703,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=115200 >> $GITHUB_OUTPUT
|
||||
echo -en "," >> $GITHUB_OUTPUT
|
||||
|
||||
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp32 esp32 0.35.0 esp32:esp32:esp32:FlashFreq=80 >> $GITHUB_OUTPUT
|
||||
get_sketches_json_matrix arduino $GITHUB_WORKSPACE/examples/esp32 esp32 0.35.3 esp32:esp32:esp32:FlashFreq=80 >> $GITHUB_OUTPUT
|
||||
|
||||
echo -en "]" >> $GITHUB_OUTPUT
|
||||
echo >> $GITHUB_OUTPUT
|
||||
@ -55,7 +55,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
CLI_VERSION: [0.35.0]
|
||||
CLI_VERSION: [0.35.3]
|
||||
env:
|
||||
CLI_VERSION: ${{ matrix.CLI_VERSION }}
|
||||
ARDUINO_DIRECTORIES_DATA: /home/runner/arduino_ide
|
||||
@ -63,10 +63,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Get Date
|
||||
id: get-date
|
||||
- name: Get hash
|
||||
id: get-hash
|
||||
run: |
|
||||
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
|
||||
echo "hash=$(/bin/date -u "+%Y%m%d")-$(md5sum ".github/workflows/main.yml" | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- uses: actions/cache@v3
|
||||
@ -75,7 +75,7 @@ jobs:
|
||||
path: |
|
||||
/home/runner/arduino_ide
|
||||
/home/runner/Arduino
|
||||
key: ${{ runner.os }}-${{ steps.get-date.outputs.date }}-${{ matrix.CLI_VERSION }}-cli
|
||||
key: ${{ runner.os }}-${{ steps.get-hash.outputs.hash }}-${{ matrix.CLI_VERSION }}-cli
|
||||
|
||||
- name: download IDE
|
||||
if: steps.cache_all.outputs.cache-hit != 'true'
|
||||
@ -122,10 +122,10 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get install -y libgtk2.0-0
|
||||
|
||||
- name: Get Date
|
||||
id: get-date
|
||||
- name: Get hash
|
||||
id: get-hash
|
||||
run: |
|
||||
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
|
||||
echo "hash=$(/bin/date -u "+%Y%m%d")-$(md5sum ".github/workflows/main.yml" | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- uses: actions/cache@v3
|
||||
@ -134,7 +134,7 @@ jobs:
|
||||
path: |
|
||||
/home/runner/arduino_ide
|
||||
/home/runner/Arduino
|
||||
key: ${{ runner.os }}-${{ steps.get-date.outputs.date }}-${{ matrix.cliversion }}-cli
|
||||
key: ${{ runner.os }}-${{ steps.get-hash.outputs.hash }}-${{ matrix.cliversion }}-cli
|
||||
|
||||
- name: install python serial
|
||||
if: matrix.cpu == 'esp32'
|
||||
|
19
README.md
19
README.md
@ -1,4 +1,4 @@
|
||||
WebSocket Server and Client for Arduino [](https://github.com/Links2004/arduinoWebSockets/actions?query=workflow%3ACI+branch%3Amaster)
|
||||
WebSocket Server and Client for Arduino [](https://github.com/Links2004/arduinoWebSockets/actions?query=branch%3Amaster)
|
||||
===========================================
|
||||
|
||||
a WebSocket Server and Client for Arduino based on RFC6455.
|
||||
@ -32,6 +32,7 @@ a WebSocket Server and Client for Arduino based on RFC6455.
|
||||
- ATmega328 with enc28j60 (ATmega branch)
|
||||
- ATmega2560 with Ethernet Shield (ATmega branch)
|
||||
- ATmega2560 with enc28j60 (ATmega branch)
|
||||
- Arduino UNO [R4 WiFi](https://github.com/arduino/ArduinoCore-renesas)
|
||||
|
||||
###### Note: ######
|
||||
|
||||
@ -73,19 +74,19 @@ The mode can be activated in the ```WebSockets.h``` (see WEBSOCKETS_NETWORK_TYPE
|
||||
```c++
|
||||
void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
|
||||
void begin(String host, uint16_t port, String url = "/", String protocol = "arduino");
|
||||
```
|
||||
```
|
||||
- `onEvent`: Callback to handle for websocket events
|
||||
|
||||
```c++
|
||||
```c++
|
||||
void onEvent(WebSocketClientEvent cbEvent);
|
||||
```
|
||||
```
|
||||
|
||||
- `WebSocketClientEvent`: Handler for websocket events
|
||||
```c++
|
||||
```c++
|
||||
void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length)
|
||||
```
|
||||
```
|
||||
Where `WStype_t type` is defined as:
|
||||
```c++
|
||||
```c++
|
||||
typedef enum {
|
||||
WStype_ERROR,
|
||||
WStype_DISCONNECTED,
|
||||
@ -99,13 +100,11 @@ Where `WStype_t type` is defined as:
|
||||
WStype_PING,
|
||||
WStype_PONG,
|
||||
} WStype_t;
|
||||
```
|
||||
```
|
||||
|
||||
### Issues ###
|
||||
Submit issues to: https://github.com/Links2004/arduinoWebSockets/issues
|
||||
|
||||
[](https://gitter.im/Links2004/arduinoWebSockets?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
### License and credits ###
|
||||
|
||||
The library is licensed under [LGPLv2.1](https://github.com/Links2004/arduinoWebSockets/blob/master/LICENSE)
|
||||
|
@ -0,0 +1,109 @@
|
||||
#include <Arduino.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "WiFiS3.h"
|
||||
#include <WebSocketsClient.h>
|
||||
|
||||
#define WIFI_SSID ""
|
||||
#define WIFI_PASS ""
|
||||
|
||||
WebSocketsClient webSocket;
|
||||
|
||||
void webSocketEvent(WStype_t type, uint8_t *payload, size_t length) {
|
||||
|
||||
switch (type) {
|
||||
case WStype_DISCONNECTED:
|
||||
Serial.println("[WSc] Disconnected!");
|
||||
break;
|
||||
case WStype_CONNECTED:
|
||||
Serial.println("[WSc] Connected!");
|
||||
|
||||
// send message to server when Connected
|
||||
webSocket.sendTXT("Connected");
|
||||
break;
|
||||
case WStype_TEXT:
|
||||
Serial.print("[WSc] get text:");
|
||||
Serial.println((char *)payload);
|
||||
|
||||
// send message to server
|
||||
// webSocket.sendTXT("message here");
|
||||
break;
|
||||
case WStype_BIN:
|
||||
// send data to server
|
||||
// webSocket.sendBIN(payload, length);
|
||||
break;
|
||||
case WStype_ERROR:
|
||||
case WStype_FRAGMENT_TEXT_START:
|
||||
case WStype_FRAGMENT_BIN_START:
|
||||
case WStype_FRAGMENT:
|
||||
case WStype_FRAGMENT_FIN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for native USB port only
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
for (uint8_t t = 4; t > 0; t--) {
|
||||
Serial.println("[SETUP] BOOT WAIT ...");
|
||||
Serial.flush();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// check for the WiFi module:
|
||||
if (WiFi.status() == WL_NO_MODULE) {
|
||||
Serial.println("Communication with WiFi module failed!");
|
||||
// don't continue
|
||||
while (true)
|
||||
;
|
||||
}
|
||||
|
||||
String fv = WiFi.firmwareVersion();
|
||||
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
|
||||
Serial.println("Please upgrade the firmware");
|
||||
}
|
||||
|
||||
Serial.println("[Wifi]: Connecting");
|
||||
|
||||
int status = WL_IDLE_STATUS;
|
||||
|
||||
// attempt to connect to WiFi network:
|
||||
while (status != WL_CONNECTED) {
|
||||
Serial.print("[Wifi]: Attempting to connect to SSID: ");
|
||||
Serial.println(WIFI_SSID);
|
||||
|
||||
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
|
||||
status = WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("Connected!");
|
||||
|
||||
// print your board's IP address:
|
||||
IPAddress ip = WiFi.localIP();
|
||||
Serial.print("IP Address: ");
|
||||
Serial.println(ip);
|
||||
|
||||
// server address, port and URL
|
||||
webSocket.begin("192.168.0.123", 8011);
|
||||
|
||||
// event handler
|
||||
webSocket.onEvent(webSocketEvent);
|
||||
|
||||
// try ever 5000 again if connection has failed
|
||||
webSocket.setReconnectInterval(5000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
webSocket.loop();
|
||||
}
|
@ -112,7 +112,13 @@ void setup() {
|
||||
// server address, port and URL. This server can be flakey.
|
||||
// Expected response: Request served by 0123456789abcdef
|
||||
// webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", rootca_crt_bundle_start, "");
|
||||
// ESP32 3.0.4 or higher needs the size of the bundle
|
||||
// webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", rootca_crt_bundle_start, sizeof(rootca_crt_bundle_start), "");
|
||||
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
|
||||
webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", NULL, 0, "");
|
||||
#else
|
||||
webSocket.beginSslWithBundle("echo.websocket.org", 443, "/", NULL, "");
|
||||
#endif
|
||||
|
||||
// event handler
|
||||
webSocket.onEvent(webSocketEvent);
|
||||
|
@ -16,10 +16,10 @@
|
||||
"keywords": "wifi, http, web, server, client, websocket",
|
||||
"license": "LGPL-2.1",
|
||||
"name": "WebSockets",
|
||||
"platforms": "atmelavr, espressif8266, espressif32, raspberrypi",
|
||||
"platforms": "atmelavr, espressif8266, espressif32, raspberrypi, renesas_uno",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Links2004/arduinoWebSockets.git"
|
||||
},
|
||||
"version": "2.4.1"
|
||||
"version": "2.5.2"
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
name=WebSockets
|
||||
version=2.4.1
|
||||
version=2.5.2
|
||||
author=Markus Sattler
|
||||
maintainer=Markus Sattler
|
||||
sentence=WebSockets for Arduino (Server + Client)
|
||||
|
@ -93,6 +93,12 @@
|
||||
#define WEBSOCKETS_YIELD() yield()
|
||||
#define WEBSOCKETS_YIELD_MORE() delay(1)
|
||||
|
||||
#elif defined(ARDUINO_UNOWIFIR4)
|
||||
|
||||
#define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024)
|
||||
#define WEBSOCKETS_YIELD() yield()
|
||||
#define WEBSOCKETS_YIELD_MORE() delay(1)
|
||||
|
||||
#else
|
||||
|
||||
// atmega328p has only 2KB ram!
|
||||
@ -114,6 +120,7 @@
|
||||
#define NETWORK_ESP32 (4)
|
||||
#define NETWORK_ESP32_ETH (5)
|
||||
#define NETWORK_RP2040 (6)
|
||||
#define NETWORK_UNOWIFIR4 (7)
|
||||
|
||||
// max size of the WS Message Header
|
||||
#define WEBSOCKETS_MAX_HEADER_SIZE (14)
|
||||
@ -132,6 +139,9 @@
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
#define WEBSOCKETS_NETWORK_TYPE NETWORK_RP2040
|
||||
|
||||
#elif defined(ARDUINO_UNOWIFIR4)
|
||||
#define WEBSOCKETS_NETWORK_TYPE NETWORK_UNOWIFIR4
|
||||
|
||||
#else
|
||||
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100
|
||||
|
||||
@ -224,6 +234,13 @@
|
||||
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
|
||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
|
||||
|
||||
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_UNOWIFIR4)
|
||||
|
||||
#include <WiFiS3.h>
|
||||
|
||||
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
|
||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
|
||||
|
||||
#else
|
||||
#error "no network type selected!"
|
||||
#endif
|
||||
|
@ -49,7 +49,10 @@ void WebSocketsClient::begin(const char * host, uint16_t port, const char * url,
|
||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
||||
_CA_cert = NULL;
|
||||
#ifdef ESP32
|
||||
_CA_bundle = NULL;
|
||||
_CA_bundle = NULL;
|
||||
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
|
||||
_CA_bundle_size = 0;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -124,6 +127,17 @@ void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const ch
|
||||
_CA_cert = CA_cert;
|
||||
_CA_bundle = NULL;
|
||||
}
|
||||
|
||||
#if defined(ESP32) && ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
|
||||
void WebSocketsClient::beginSslWithBundle(const char * host, uint16_t port, const char * url, const uint8_t * CA_bundle, size_t CA_bundle_size, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSSL = true;
|
||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
||||
_CA_cert = NULL;
|
||||
_CA_bundle = CA_bundle;
|
||||
_CA_bundle_size = CA_bundle_size;
|
||||
}
|
||||
#else
|
||||
void WebSocketsClient::beginSslWithBundle(const char * host, uint16_t port, const char * url, const uint8_t * CA_bundle, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSSL = true;
|
||||
@ -131,6 +145,7 @@ void WebSocketsClient::beginSslWithBundle(const char * host, uint16_t port, cons
|
||||
_CA_cert = NULL;
|
||||
_CA_bundle = CA_bundle;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * url, const uint8_t * fingerprint, const char * protocol) {
|
||||
@ -247,9 +262,11 @@ void WebSocketsClient::loop(void) {
|
||||
#if defined(ESP32)
|
||||
} else if(_CA_bundle) {
|
||||
DEBUG_WEBSOCKETS("[WS-Client] setting CA bundle");
|
||||
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
|
||||
_client.ssl->setCACertBundle(_CA_bundle, _CA_bundle_size);
|
||||
#else
|
||||
_client.ssl->setCACertBundle(_CA_bundle);
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
} else if(!SSL_FINGERPRINT_IS_SET) {
|
||||
_client.ssl->setInsecure();
|
||||
#elif defined(SSL_BARESSL)
|
||||
|
@ -54,8 +54,12 @@ class WebSocketsClient : protected WebSockets {
|
||||
#endif
|
||||
void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", const char * CA_cert = NULL, const char * protocol = "arduino");
|
||||
#ifdef ESP32
|
||||
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
|
||||
void beginSslWithBundle(const char * host, uint16_t port, const char * url = "/", const uint8_t * CA_bundle = NULL, size_t CA_bundle_size = 0, const char * protocol = "arduino");
|
||||
#else
|
||||
void beginSslWithBundle(const char * host, uint16_t port, const char * url = "/", const uint8_t * CA_bundle = NULL, const char * protocol = "arduino");
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void beginSocketIO(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
||||
@ -116,6 +120,11 @@ class WebSocketsClient : protected WebSockets {
|
||||
String _fingerprint;
|
||||
const char * _CA_cert;
|
||||
const uint8_t * _CA_bundle;
|
||||
#if defined(ESP32)
|
||||
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 4)
|
||||
size_t _CA_bundle_size;
|
||||
#endif
|
||||
#endif
|
||||
#define SSL_FINGERPRINT_IS_SET (_fingerprint.length())
|
||||
#define SSL_FINGERPRINT_NULL ""
|
||||
#else
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file WebSocketsVersion.h
|
||||
* @date 01.05.2023
|
||||
* @date 29.07.2024
|
||||
* @author Markus Sattler
|
||||
*
|
||||
* Copyright (c) 2015 Markus Sattler. All rights reserved.
|
||||
@ -25,12 +25,12 @@
|
||||
#ifndef WEBSOCKETSVERSION_H_
|
||||
#define WEBSOCKETSVERSION_H_
|
||||
|
||||
#define WEBSOCKETS_VERSION "2.4.1"
|
||||
#define WEBSOCKETS_VERSION "2.5.2"
|
||||
|
||||
#define WEBSOCKETS_VERSION_MAJOR 2
|
||||
#define WEBSOCKETS_VERSION_MINOR 4
|
||||
#define WEBSOCKETS_VERSION_PATCH 1
|
||||
#define WEBSOCKETS_VERSION_MINOR 5
|
||||
#define WEBSOCKETS_VERSION_PATCH 2
|
||||
|
||||
#define WEBSOCKETS_VERSION_INT 2004001
|
||||
#define WEBSOCKETS_VERSION_INT 2005002
|
||||
|
||||
#endif /* WEBSOCKETSVERSION_H_ */
|
||||
|
@ -1,6 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
function build_sketches()
|
||||
{
|
||||
@ -106,11 +105,11 @@ function get_sketches_json_matrix()
|
||||
}
|
||||
|
||||
function get_core_cli() {
|
||||
export ARDUINO_BOARD_MANAGER_ADDITIONAL_URLS="https://arduino.esp8266.com/stable/package_esp8266com_index.json https://espressif.github.io/arduino-esp32/package_esp32_index.json https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json"
|
||||
export ARDUINO_BOARD_MANAGER_ADDITIONAL_URLS="https://arduino.esp8266.com/stable/package_esp8266com_index.json https://espressif.github.io/arduino-esp32/package_esp32_index.json https://github.com/earlephilhower/arduino-pico/releases/download/3.9.2/package_rp2040_index.json"
|
||||
arduino-cli core update-index
|
||||
arduino-cli core install esp8266:esp8266
|
||||
arduino-cli core install esp32:esp32
|
||||
arduino-cli core install arduino:mbed_rp2040
|
||||
arduino-cli core install rp2040:rp2040
|
||||
}
|
||||
|
||||
function get_core()
|
||||
|
Reference in New Issue
Block a user