NetBurner 3.5.6
PDF Version
TCP Notification System

Advanced callback mechanism for asynchronous TCP socket event notification. More...

Typedefs

typedef void tcp_notify_handler(int tcpFd)
 TCP notification callback function type.
 

Functions

void RegisterTCPReadNotify (int tcpFd, tcp_notify_handler *notifyHandler)
 Register a callback for read event notifications.
 
void RegisterTCPWriteNotify (int tcpFd, tcp_notify_handler *notifyHandler)
 Register a callback for write event notifications.
 

Detailed Description

Advanced callback mechanism for asynchronous TCP socket event notification.

#include< tcp.h>


The TCP notification system provides an event-driven approach to handling TCP socket activity. Instead of polling sockets for read/write availability, applications can register callback functions that are automatically invoked when:

Callback functions have full access to normal TCP socket operations and can perform any standard read/write operations during notification handling.

Typedef Documentation

◆ tcp_notify_handler

typedef void tcp_notify_handler(int tcpFd)

#include <tcp.h>

TCP notification callback function type.

Applications implement callback functions of this type to handle TCP socket notifications. The callback is invoked from the TCP stack when the registered event occurs (data available for reading or buffer space available for writing).

Parameters
tcpFdFile descriptor of the socket that triggered the notification
See also
RegisterTCPReadNotify(), RegisterTCPWriteNotify()

Expand for Example Usage

Examples

Basic Read Callback Implementation
void MyReadHandler(int tcpFd) {
char buffer[256];
int bytesRead = read(tcpFd, buffer, sizeof(buffer));
if (bytesRead > 0) {
printf("Received %d bytes via callback\n", bytesRead);
buffer[bytesRead] = '\0';
printf("Data: %s\n", buffer);
}
}
int read(int fd, char *buf, int nbytes)
Read data from a file descriptor (fd).
Basic Write Callback Implementation
void MyWriteHandler(int tcpFd) {
const char *data = "Response from write callback\n";
int bytesWritten = write(tcpFd, data, strlen(data));
if (bytesWritten > 0) {
printf("Wrote %d bytes via callback\n", bytesWritten);
}
}
int write(int fd, const char *buf, int nbytes)
Write data to the stream associated with a file descriptor (fd). Can be used to write data to stdio,...
State Machine Callback
enum ConnectionState { WAITING_HEADER, WAITING_DATA, PROCESSING };
struct ClientContext {
ConnectionState state;
int expectedBytes;
char buffer[1024];
int bufferPos;
};
ClientContext contexts[10]; // Support up to 10 clients
void StateMachineHandler(int tcpFd) {
ClientContext *ctx = &contexts[tcpFd % 10];
switch (ctx->state) {
case WAITING_HEADER:
if (dataavail(tcpFd) >= 4) {
read(tcpFd, &ctx->expectedBytes, 4);
ctx->state = WAITING_DATA;
ctx->bufferPos = 0;
}
break;
case WAITING_DATA:
int available = dataavail(tcpFd);
int toRead = (ctx->expectedBytes - ctx->bufferPos);
if (toRead > available) toRead = available;
int n = read(tcpFd, ctx->buffer + ctx->bufferPos, toRead);
ctx->bufferPos += n;
if (ctx->bufferPos >= ctx->expectedBytes) {
ctx->state = PROCESSING;
ProcessData(ctx->buffer, ctx->expectedBytes);
ctx->state = WAITING_HEADER;
}
break;
}
}
int dataavail(int fd)
Check the specified file descriptor to detmeine if data is available to be read.
Multiple Socket Handler with Context
struct SocketData {
int fd;
char name[32];
uint32_t bytesReceived;
};
SocketData socketContexts[5];
void UniversalReadHandler(int tcpFd) {
// Find context for this socket
SocketData *ctx = NULL;
for (int i = 0; i < 5; i++) {
if (socketContexts[i].fd == tcpFd) {
ctx = &socketContexts[i];
break;
}
}
if (ctx != NULL) {
char buffer[128];
int n = read(tcpFd, buffer, sizeof(buffer));
ctx->bytesReceived += n;
printf("[%s] Received %d bytes (total: %lu)\n",
ctx->name, n, ctx->bytesReceived);
}
}

Function Documentation

◆ RegisterTCPReadNotify()

void RegisterTCPReadNotify ( int tcpFd,
tcp_notify_handler * notifyHandler )

#include <tcp.h>

Register a callback for read event notifications.

Registers a callback function to be invoked whenever data becomes available for reading on the specified TCP socket. The callback is called automatically by the TCP stack when new data arrives.

Parameters
tcpFdFile descriptor of the socket to monitor
notifyHandlerPointer to the callback function
See also
RegisterTCPWriteNotify(), tcp_notify_handler

Expand for Example Usage

Examples

Basic Registration - Echo Server
void EchoHandler(int tcpFd) {
char buffer[256];
int n = read(tcpFd, buffer, sizeof(buffer));
if (n > 0) {
write(tcpFd, buffer, n); // Echo back
}
}
void UserMain(void *pd) {
init();
int listenFd = socket(AF_INET, SOCK_STREAM, 0);
// ... bind and listen ...
int clientFd = accept(listenFd, NULL, NULL);
// Register read notification
RegisterTCPReadNotify(clientFd, EchoHandler);
while (1) {
OSTimeDly(TICKS_PER_SECOND);
}
}
#define TICKS_PER_SECOND
System clock ticks per second.
Definition constants.h:49
int accept(int listening_socket, IPADDR *address, uint16_t *port, uint16_t timeout)
Accept an incoming connection on a listening socket.
void RegisterTCPReadNotify(int tcpFd, tcp_notify_handler *notifyHandler)
Register a callback for read event notifications.
void init()
System initialization. Ideally called at the beginning of all applications, since the easiest Recover...
Multiple Client Handler
void ClientReadHandler(int tcpFd) {
char buffer[512];
int n = read(tcpFd, buffer, sizeof(buffer));
if (n > 0) {
buffer[n] = '\0';
printf("Client FD %d: %s\n", tcpFd, buffer);
ProcessCommand(tcpFd, buffer);
} else if (n < 0) {
printf("Client FD %d disconnected\n", tcpFd);
close(tcpFd);
}
}
void ServerTask(void *pd) {
int listenFd = socket(AF_INET, SOCK_STREAM, 0);
// ... bind and listen ...
while (1) {
int clientFd = accept(listenFd, NULL, NULL);
if (clientFd > 0) {
printf("New client connected, FD: %d\n", clientFd);
RegisterTCPReadNotify(clientFd, ClientReadHandler);
}
OSTimeDly(TICKS_PER_SECOND / 10);
}
}
int close(int fd)
Close the specified file descriptor and free the associated resources.
Event-Driven HTTP Server
void HttpReadHandler(int tcpFd) {
static char requestBuffer[2048];
static int bufferPos = 0;
int n = read(tcpFd, requestBuffer + bufferPos,
sizeof(requestBuffer) - bufferPos - 1);
if (n > 0) {
bufferPos += n;
requestBuffer[bufferPos] = '\0';
// Check for end of HTTP headers
if (strstr(requestBuffer, "\r\n\r\n") != NULL) {
ProcessHttpRequest(tcpFd, requestBuffer);
bufferPos = 0; // Reset for next request
}
}
}
void StartEventDrivenHttpServer() {
int listenFd = socket(AF_INET, SOCK_STREAM, 0);
// ... bind to port 80 and listen ...
while (1) {
int clientFd = accept(listenFd, NULL, NULL);
if (clientFd > 0) {
RegisterTCPReadNotify(clientFd, HttpReadHandler);
}
}
}
Removing Notification (Unregister)
void TemporaryReadHandler(int tcpFd) {
char buffer[128];
int n = read(tcpFd, buffer, sizeof(buffer));
if (n > 0) {
printf("Received: %.*s\n", n, buffer);
// Unregister after first read
RegisterTCPReadNotify(tcpFd, NULL);
printf("Read notification removed\n");
}
}
void UserMain(void *pd) {
init();
int fd = socket(AF_INET, SOCK_STREAM, 0);
connect(fd, ...);
RegisterTCPReadNotify(fd, TemporaryReadHandler);
while (1) {
OSTimeDly(TICKS_PER_SECOND);
}
}
int connect(const IPADDR &ipAddress, uint16_t remotePort, uint32_t timeout)
Establish a TCP connection to a remote host.
Definition tcp.h:1547
Protocol Parser with Notification
#define PROTO_START_BYTE 0xAA
#define PROTO_END_BYTE 0x55
void ProtocolReadHandler(int tcpFd) {
static char msgBuffer[256];
static int msgPos = 0;
static bool inMessage = false;
while (dataavail(tcpFd) > 0) {
char byte;
read(tcpFd, &byte, 1);
if (byte == PROTO_START_BYTE) {
inMessage = true;
msgPos = 0;
} else if (byte == PROTO_END_BYTE && inMessage) {
ProcessProtocolMessage(msgBuffer, msgPos);
inMessage = false;
msgPos = 0;
} else if (inMessage) {
if (msgPos < sizeof(msgBuffer)) {
msgBuffer[msgPos++] = byte;
}
}
}
}

◆ RegisterTCPWriteNotify()

void RegisterTCPWriteNotify ( int tcpFd,
tcp_notify_handler * notifyHandler )

#include <tcp.h>

Register a callback for write event notifications.

Registers a callback function to be invoked whenever buffer space becomes available for writing on the specified TCP socket. The callback is called automatically by the TCP stack when the transmit buffer has space available.

Parameters
tcpFdFile descriptor of the socket to monitor
notifyHandlerPointer to the callback function
See also
RegisterTCPReadNotify(), tcp_notify_handler

Expand for Example Usage

Examples

Basic Write Notification - Queued Data Transfer
struct DataQueue {
char buffer[4096];
int size;
int sent;
} dataQueue;
void WriteNotifyHandler(int tcpFd) {
if (dataQueue.sent < dataQueue.size) {
int remaining = dataQueue.size - dataQueue.sent;
int n = write(tcpFd, dataQueue.buffer + dataQueue.sent, remaining);
if (n > 0) {
dataQueue.sent += n;
printf("Sent %d bytes, %d remaining\n", n,
dataQueue.size - dataQueue.sent);
}
if (dataQueue.sent >= dataQueue.size) {
// All data sent, unregister
RegisterTCPWriteNotify(tcpFd, NULL);
printf("Transfer complete\n");
}
}
}
void QueueDataForSend(int fd, const char *data, int len) {
memcpy(dataQueue.buffer, data, len);
dataQueue.size = len;
dataQueue.sent = 0;
RegisterTCPWriteNotify(fd, WriteNotifyHandler);
}
void RegisterTCPWriteNotify(int tcpFd, tcp_notify_handler *notifyHandler)
Register a callback for write event notifications.
Large File Transfer with Write Notifications
struct FileTransfer {
int fd;
FILE *file;
uint32_t totalBytes;
uint32_t sentBytes;
};
FileTransfer transfer;
void FileWriteHandler(int tcpFd) {
char buffer[1024];
size_t bytesRead = fread(buffer, 1, sizeof(buffer), transfer.file);
if (bytesRead > 0) {
int n = write(tcpFd, buffer, bytesRead);
if (n > 0) {
transfer.sentBytes += n;
printf("Progress: %lu / %lu bytes (%.1f%%)\n",
transfer.sentBytes, transfer.totalBytes,
(float)transfer.sentBytes / transfer.totalBytes * 100);
}
}
if (feof(transfer.file)) {
fclose(transfer.file);
RegisterTCPWriteNotify(tcpFd, NULL);
printf("File transfer complete\n");
}
}
void StartFileTransfer(int tcpFd, const char *filename) {
transfer.file = fopen(filename, "rb");
if (transfer.file) {
fseek(transfer.file, 0, SEEK_END);
transfer.totalBytes = ftell(transfer.file);
fseek(transfer.file, 0, SEEK_SET);
transfer.sentBytes = 0;
transfer.fd = tcpFd;
RegisterTCPWriteNotify(tcpFd, FileWriteHandler);
}
}
Periodic Data Streaming
struct StreamContext {
uint32_t sequenceNumber;
bool streaming;
} stream = {0, true};
void StreamWriteHandler(int tcpFd) {
if (stream.streaming) {
char packet[64];
int len = snprintf(packet, sizeof(packet),
"STREAM:%lu:%lu\n",
stream.sequenceNumber++, Secs);
int n = write(tcpFd, packet, len);
if (n > 0) {
printf("Streamed packet #%lu\n", stream.sequenceNumber - 1);
}
// Continue streaming (notification will fire when space available)
} else {
// Stop streaming, unregister
RegisterTCPWriteNotify(tcpFd, NULL);
}
}
void StartStreaming(int fd) {
stream.sequenceNumber = 0;
stream.streaming = true;
RegisterTCPWriteNotify(fd, StreamWriteHandler);
}
void StopStreaming() {
stream.streaming = false;
}
Write Notification for Flow Control
volatile bool canWrite = true;
void FlowControlWriteHandler(int tcpFd) {
// Buffer space available, we can write again
canWrite = true;
// Unregister until we need it again
RegisterTCPWriteNotify(tcpFd, NULL);
printf("Write buffer available\n");
}
void SendDataWithFlowControl(int tcpFd, const char *data, int len) {
int n = write(tcpFd, data, len);
if (n < len) {
// Couldn't send all data, buffer is full
printf("Buffer full, sent only %d of %d bytes\n", n, len);
canWrite = false;
// Register for notification when space becomes available
RegisterTCPWriteNotify(tcpFd, FlowControlWriteHandler);
// Wait for space
while (!canWrite) {
OSTimeDly(TICKS_PER_SECOND / 100);
}
// Retry sending remaining data
SendDataWithFlowControl(tcpFd, data + n, len - n);
}
}
Combined Read and Write Notifications
void CombinedReadHandler(int tcpFd) {
char buffer[256];
int n = read(tcpFd, buffer, sizeof(buffer));
if (n > 0) {
printf("Read %d bytes\n", n);
ProcessAndQueueResponse(tcpFd, buffer, n);
}
}
void CombinedWriteHandler(int tcpFd) {
if (HasQueuedResponse()) {
char *response = GetQueuedResponse();
int len = strlen(response);
int n = write(tcpFd, response, len);
if (n == len) {
// All sent, unregister write notify
RegisterTCPWriteNotify(tcpFd, NULL);
}
}
}
void SetupConnection(int tcpFd) {
RegisterTCPReadNotify(tcpFd, CombinedReadHandler);
RegisterTCPWriteNotify(tcpFd, CombinedWriteHandler);
}