0% found this document useful (0 votes)
3 views8 pages

ESP32 Chat System Source Code

The document contains source code for an ESP32 chat system that utilizes WebSocket for real-time communication. It includes features such as user login, message broadcasting, and rate limiting to prevent abuse by banning IPs that exceed request limits. The HTML structure for the chat interface is also provided, allowing users to connect and send messages through a web browser.

Uploaded by

cparves774
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views8 pages

ESP32 Chat System Source Code

The document contains source code for an ESP32 chat system that utilizes WebSocket for real-time communication. It includes features such as user login, message broadcasting, and rate limiting to prevent abuse by banning IPs that exceed request limits. The HTML structure for the chat interface is also provided, allowing users to connect and send messages through a web browser.

Uploaded by

cparves774
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

1

Appendix A: Source Code for ESP32 Chat System


#include <WiFi.h>

#include <AsyncTCP.h>

#include <ESPAsyncWebServer.h>

#include <map>

#include <deque>

const char* AP_SSID = "ESP32_Chat";

const char* AP_PASS = "12345678";

AsyncWebServer server(80);

AsyncWebSocket ws("/ws");

// map client id -> username

std::map<uint32_t, String> clientNames;

// === NEW === rate limiting structures

struct ClientActivity {

std::deque<unsigned long> timestamps; // last request times (ms)

unsigned long banUntil = 0; // ban expiry

};

std::map<String, ClientActivity> clientActivity; // key = IP as string

const int MAX_REQUESTS = 4; // max allowed per window


2

const int TIME_WINDOW = 10000; // 10 seconds

const int BAN_DURATION = 30000; // 30 sec ban

// helper: check if IP is banned or exceeding limit

bool isAllowed(const String &ip) {

unsigned long now = millis();

ClientActivity &ca = clientActivity[ip];

// still banned?

if ([Link] > now) return false;

// remove old timestamps

while (![Link]() && now - [Link]() > TIME_WINDOW) {

[Link].pop_front();

// check limit

if ((int)[Link]() >= MAX_REQUESTS) {

[Link] = now + BAN_DURATION; // ban

[Link]();

return false;

// record request

[Link].push_back(now);
3

return true;

void notifyAll(const String &msg) {

[Link](msg);

void handleWebSocketEvent(AsyncWebSocket * serverPtr, AsyncWebSocketClient * client,

AwsEventType type, void * arg, uint8_t *data, size_t len) {

String ip = client->remoteIP().toString();

if(type == WS_EVT_CONNECT) {

// === NEW === limit connections

if (!isAllowed(ip)) {

[Link]("BLOCKED WS connect from %s\n", ip.c_str());

client->close(); // immediately disconnect

return;

[Link]("WS: Client #%u connected from %s\n", client->id(), ip.c_str());

client->printf("SERVER: Please login by sending: login:YourName");

else if(type == WS_EVT_DISCONNECT) {

[Link]("WS: Client #%u disconnected\n", client->id());


4

auto it = [Link](client->id());

if(it != [Link]()){

String leftMsg = String("SYSTEM: ") + it->second + " left the chat";

notifyAll(leftMsg);

[Link](it);

else if(type == WS_EVT_DATA) {

// === NEW === limit data/message spam

if (!isAllowed(ip)) {

[Link]("BLOCKED data from %s\n", ip.c_str());

client->close();

return;

String msg = "";

for(size_t i=0;i<len;i++) msg += (char)data[i];

[Link]("WS: Data from #%u: %s\n", client->id(), msg.c_str());

if([Link]("login:")) {

String name = [Link](6);

[Link]();

if([Link]() == 0) {

client->printf("SERVER: invalid name");


5

return;

clientNames[client->id()] = name;

client->printf("SERVER: Welcome %s", name.c_str());

String announce = String("SYSTEM: ") + name + " joined the chat";

notifyAll(announce);

else if([Link]("msg:")) {

String body = [Link](4);

[Link]();

auto it = [Link](client->id());

String from = (it != [Link]()) ? it->second : String("Unknown");

String out = from + ": " + body;

notifyAll(out);

else {

client->printf("SERVER: unknown command");

// ... keep your webpage code unchanged ...

const char index_html[] PROGMEM = R"rawliteral(

<!doctype html>

<html>
6

<head>

<meta charset="utf-8">

<title>ESP32 Chat</title>

<style>

body {

font-family: Arial, sans-serif;

margin: 20px;

background: #f0f2f5;

h3 {

margin-bottom: 10px;

color: #333;

#status {

margin-bottom: 10px;

font-weight: bold;

color: #0066cc;

#log {

width: 100%;

height: 300px;

border: 1px solid #ccc;

overflow-y: auto;

padding: 8px;

background: #fff;
7

box-shadow: inset 0 0 4px rgba(0,0,0,0.1);

border-radius: 6px;

font-size: 14px;

#controls {

margin-top: 12px;

input, button {

padding: 8px;

font-size: 14px;

border-radius: 4px;

border: 1px solid #ccc;

input:focus {

outline: none;

border-color: #0066cc;

button {

background: #0066cc;

color: white;

border: none;

cursor: pointer;

button:hover {

background: #004999;
8

#msg {

width: 70%;

</style>

</head>

<body>

<h3>IOT Chat (PROJECT BY STINKBUG)</h3>

<div id="status">Not connected</div>

<div id="log"></div>

<div id="controls">

<input id="name" placeholder="Your name">

<button id="btnLogin">Login</button><br><br>

<input id="msg" placeholder="Type a message...">

<button id="btnSend">Send</button>

</div>

<script>

let ws;

function log(s) {

let d = [Link]('log');

You might also like