Skip to content

Commit

Permalink
Added example for XAPI async server
Browse files Browse the repository at this point in the history
  • Loading branch information
kala13x committed Nov 26, 2024
1 parent f1dc96c commit 0ea4135
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 3 deletions.
3 changes: 2 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ endif()
# replace with your actual source files
set(SOURCE_FILES
array.c
async-server.c
basic-server.c
http-server.c
tcp-server.c
ws-server.c
ws-client.c
statcov.c
Expand Down
3 changes: 2 additions & 1 deletion examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ CFLAGS += -I../src \
-I../src/sys

EXECS = array \
async-server \
basic-server \
http-server \
tcp-server \
ws-server \
ws-client \
statcov \
Expand Down
246 changes: 246 additions & 0 deletions examples/async-server.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
/*!
* @file libxutils/examples/async-server.c
*
* This source is part of "libxutils" project
* 2015-2020 Sun Dro ([email protected])
*
* @brief Implementation of high performance event based non-blocking async server.
* The library will use poll(), epoll() or WSAPoll() depending on the operating system.
*/

#include "xstd.h"
#include "xver.h"
#include "xlog.h"
#include "xsig.h"
#include "xfs.h"
#include "api.h"

static int g_nInterrupted = 0;
extern char *optarg;

typedef struct {
char sCaPath[XPATH_MAX];
char sCertPath[XPATH_MAX];
char sKeyPath[XPATH_MAX];
char sAddr[XSOCK_ADDR_MAX];
uint16_t nPort;
xbool_t bForce;
xbool_t bUnix;
xbool_t bSSL;
} xunix_srv_args_t;

void signal_callback(int sig)
{
if (sig == SIGINT) printf("\n");
g_nInterrupted = 1;
}

int handle_status(xapi_ctx_t *pCtx, xapi_data_t *pData)
{
const char *pStr = XAPI_GetStatus(pCtx);
int nFD = pData ? (int)pData->sock.nFD : XSTDERR;

if (pCtx->eCbType == XAPI_CB_STATUS)
xlogn("%s: fd(%d)", pStr, nFD);
else if (pCtx->eCbType == XAPI_CB_ERROR)
xloge("%s: fd(%d), errno(%d)", pStr, nFD, errno);

if (pCtx->nStatus == XAPI_DESTROY)
{
xapi_t *pApi = pCtx->pApi;
xunix_srv_args_t *pArgs = (xunix_srv_args_t*)pApi->pUserCtx;
if (pArgs->bUnix) XPath_Remove(pArgs->sAddr);
}

return XAPI_CONTINUE;
}

int handle_request(xapi_ctx_t *pCtx, xapi_data_t *pData)
{
xbyte_buffer_t *pBuffer = &pData->rxBuffer;

xlogn("Received data: fd(%d), buff(%zu)",
(int)pData->sock.nFD, pBuffer->nUsed);

// Echo response
XByteBuffer_AddBuff(&pData->txBuffer, &pData->rxBuffer);

return XAPI_EnableEvent(pData, XPOLLOUT);
}

int init_data(xapi_ctx_t *pCtx, xapi_data_t *pData)
{
xlogn("Accepted connection: fd(%d)", (int)pData->sock.nFD);
return XAPI_SetEvents(pData, XPOLLIN);
}

int service_callback(xapi_ctx_t *pCtx, xapi_data_t *pData)
{
switch (pCtx->eCbType)
{
case XAPI_CB_ERROR:
case XAPI_CB_STATUS:
return handle_status(pCtx, pData);
case XAPI_CB_READ:
return handle_request(pCtx, pData);
case XAPI_CB_ACCEPTED:
return init_data(pCtx, pData);
case XAPI_CB_LISTENING:
xlogn("Server started listening: fd(%d)", (int)pData->sock.nFD);
break;
case XAPI_CB_CLOSED:
xlogn("Connection closed: fd(%d)", (int)pData->sock.nFD);
break;
case XAPI_CB_COMPLETE:
xlogn("Response sent: fd(%d)", (int)pData->sock.nFD);
return XAPI_DISCONNECT;
case XAPI_CB_INTERRUPT:
if (g_nInterrupted) return XAPI_DISCONNECT;
break;
default:
break;
}

return XAPI_CONTINUE;
}

void display_usage(const char *pName)
{
printf("============================================================\n");
printf(" XAPI server example - xutils: %s\n", XUtils_Version());
printf("============================================================\n");
printf("Usage: %s [options]\n\n", pName);
printf("Options are:\n");
printf(" -a <addr> # Listener address (%s*%s)\n", XSTR_CLR_RED, XSTR_FMT_RESET);
printf(" -p <port> # Listener port\n");
printf(" -c <path> # SSL Cert file path\n");
printf(" -k <path> # SSL Key file path\n");
printf(" -r <path> # SSL CA file path\n");
printf(" -s # SSL mode\n");
printf(" -f # Force bind socket\n");
printf(" -u # Use unix socket\n");
printf(" -h # Version and usage\n\n");
}

xbool_t parse_args(xunix_srv_args_t *pArgs, int argc, char *argv[])
{
pArgs->sCertPath[0] = XSTR_NUL;
pArgs->sKeyPath[0] = XSTR_NUL;
pArgs->sCaPath[0] = XSTR_NUL;
pArgs->sAddr[0] = XSTR_NUL;
pArgs->nPort = XSTDNON;
pArgs->bForce = XFALSE;
pArgs->bUnix = XFALSE;
pArgs->bSSL = XFALSE;
int nChar = XSTDNON;

while ((nChar = getopt(argc, argv, "a:p:c:k:r:f1:u1:s1:h1")) != -1)
{
switch (nChar)
{
case 'a':
xstrncpy(pArgs->sAddr, sizeof(pArgs->sAddr), optarg);
break;
case 'c':
xstrncpy(pArgs->sCertPath, sizeof(pArgs->sCertPath), optarg);
break;
case 'k':
xstrncpy(pArgs->sKeyPath, sizeof(pArgs->sKeyPath), optarg);
break;
case 'r':
xstrncpy(pArgs->sCaPath, sizeof(pArgs->sCaPath), optarg);
break;
case 'p':
pArgs->nPort = atoi(optarg);
break;
case 'f':
pArgs->bForce = XTRUE;
break;
case 'u':
pArgs->bUnix = XTRUE;
break;
case 's':
pArgs->bSSL = XTRUE;
break;
case 'h':
default:
return XFALSE;
}
}

if (!xstrused(pArgs->sAddr))
{
xloge("Missing listener addr");
return XFALSE;
}

if (!pArgs->nPort && !pArgs->bUnix)
{
xloge("Missing listener port");
return XFALSE;
}

if (pArgs->bSSL &&
(!xstrused(pArgs->sCertPath) ||
!xstrused(pArgs->sKeyPath)))
{
xloge("Missing SSL cert or key path");
return XFALSE;
}

return XTRUE;
}

int main(int argc, char* argv[])
{
xlog_defaults();
xlog_timing(XLOG_TIME);
xlog_setfl(XLOG_ALL);
xlog_indent(XTRUE);

int nSignals[2] = { SIGTERM, SIGINT };
XSig_Register(nSignals, 2, signal_callback);

xunix_srv_args_t args;
if (!parse_args(&args, argc, argv))
{
display_usage(argv[0]);
return XSTDERR;
}

xapi_t api;
XAPI_Init(&api, service_callback, &args, XSTDNON);

xapi_endpoint_t endpt;
XAPI_InitEndpoint(&endpt);

endpt.eType = XAPI_SOCK;
endpt.pAddr = args.sAddr;
endpt.nPort = args.nPort;
endpt.bUnix = args.bUnix;
endpt.bTLS = args.bSSL;
endpt.bForce = args.bForce;

if (endpt.bTLS)
{
endpt.certs.pCaPath = args.sCaPath;
endpt.certs.pKeyPath = args.sKeyPath;
endpt.certs.pCertPath = args.sCertPath;
#ifdef SSL_VERIFY_PEER
endpt.certs.nVerifyFlags = SSL_VERIFY_PEER;
#endif
}

if (XAPI_Listen(&api, &endpt) < 0)
{
XAPI_Destroy(&api);
return XSTDERR;
}

xevent_status_t status;
do status = XAPI_Service(&api, 100);
while (status == XEVENT_STATUS_SUCCESS);

XAPI_Destroy(&api);
return 0;
}
2 changes: 1 addition & 1 deletion examples/tcp-server.c → examples/basic-server.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* examples/tcp-server.c
* examples/basic-server.c
*
* Copyleft (C) 2015 Sun Dro (a.k.a. kala13x)
*
Expand Down

0 comments on commit 0ea4135

Please sign in to comment.