acl/lib_acl/samples/winaio/aio_server.cpp

188 lines
4.5 KiB
C++

#include "StdAfx.h"
#include "lib_acl.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "aio_server.h"
#define USE_GETS
/* forward functions */
static char __data[1024];
static int __dlen;
static int __echo_src;
static int __gets_callback(ACL_ASTREAM *stream, void *context,
const char *data, int dlen);
static void default_write_fn(void *arg acl_unused, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
acl_msg_info2(fmt, ap);
va_end(ap);
}
static void default_fflush_fn(void *arg)
{
arg = arg;
}
static void (*__write_fn)(void *arg, const char *fmt, ...) = default_write_fn;
static void *__write_arg = NULL;
static void (*__fflush_fn)(void *arg) = default_fflush_fn;
static void *__fflush_arg = NULL;
void aio_server_log_fn(void (*write_fn)(void *, const char *fmt, ...),
void *write_arg,
void (*fflush_fn)(void *),
void *fflush_arg)
{
if (write_fn) {
__write_fn = write_fn;
__write_arg = write_arg;
}
if (fflush_fn) {
__fflush_fn = fflush_fn;
__fflush_arg = fflush_arg;
}
}
/*---------------------------------------------------------------------------*/
static int __io_close(ACL_ASTREAM *astream, void *context acl_unused)
{
const char *myname = "__io_close";
ACL_VSTREAM *stream = acl_aio_vstream(astream);
__write_fn(__write_arg, "%s, %s(%d): client(%d) exception!",
__FILE__, myname, __LINE__, ACL_VSTREAM_SOCK(stream));
return (-1);
}
static int __io_timeout(ACL_ASTREAM *astream, void *context acl_unused)
{
const char *myname = "__io_timeout";
ACL_VSTREAM *stream = acl_aio_vstream(astream);
__write_fn(__write_arg, "%s, %s(%d): client(%d) timeout!",
__FILE__, myname, __LINE__, ACL_VSTREAM_SOCK(stream));
return (-1);
}
static int __write_callback(ACL_ASTREAM *client, void *context acl_unused,
const char *data acl_unused, int dlen acl_unused)
{
#ifdef USE_GETS
acl_aio_gets(client);
#else
acl_aio_read(client);
#endif
return (0);
}
static int __gets_callback(ACL_ASTREAM *stream, void *context acl_unused,
const char *data, int dlen)
{
if (__echo_src)
(void) acl_aio_writen(stream, data, dlen);
else
acl_aio_writen(stream, __data, __dlen);
return (0);
}
static int __accept_callback(ACL_ASTREAM *client, void *context acl_unused)
{
acl_aio_ctl(client, ACL_AIO_CTL_READ_HOOK_ADD, __gets_callback, NULL,
ACL_AIO_CTL_WRITE_HOOK_ADD, __write_callback, NULL,
ACL_AIO_CTL_CLOSE_HOOK_ADD, __io_close, NULL,
ACL_AIO_CTL_TIMEO_HOOK_ADD, __io_timeout, NULL,
ACL_AIO_CTL_END);
#ifdef USE_GETS
acl_aio_gets(client);
#else
acl_aio_read(client);
#endif
return (0);
}
static void __listen_callback(ACL_ASTREAM *sstream, void *context)
{
ACL_VSTREAM *cstream;
ACL_ASTREAM *client;
ACL_AIO *aio = (ACL_AIO *) context;
int i;
for (i = 0; i < 10; i++) {
cstream = acl_vstream_accept(acl_aio_vstream(sstream), NULL, 0);
if (cstream == NULL)
break;
cstream->rw_timeout = 0;
acl_non_blocking(ACL_VSTREAM_SOCK(cstream), ACL_NON_BLOCKING);
client = acl_aio_open(aio, cstream);
acl_aio_ctl(client,
ACL_AIO_CTL_READ_HOOK_ADD, __gets_callback, NULL,
ACL_AIO_CTL_WRITE_HOOK_ADD, __write_callback, NULL,
ACL_AIO_CTL_CLOSE_HOOK_ADD, __io_close, NULL,
ACL_AIO_CTL_TIMEO_HOOK_ADD, __io_timeout, NULL,
ACL_AIO_CTL_END);
#ifdef USE_GETS
acl_aio_gets(client);
#else
acl_aio_read(client);
#endif
}
}
static ACL_ASTREAM *__listener = NULL;
void aiho_server_start(ACL_AIO *aio, const char *addr, int accept_auto, int echo_src)
{
const char *myname = "echo_start";
ACL_VSTREAM *sstream;
ACL_ASTREAM *astream;
memset(__data, 'X', sizeof(__data));
__data[sizeof(__data) - 1] = 0;
__data[sizeof(__data) - 2] = '\n';
__data[sizeof(__data) - 3] = '\r';
__dlen = (int) strlen(__data);
__echo_src = echo_src;
sstream = acl_vstream_listen(addr, 128);
assert(sstream);
acl_aio_set_keep_read(aio, 1);
astream = acl_aio_open(aio, sstream);
__listener = astream;
printf(">>>listen: %s ...\r\n", addr);
if (!accept_auto) {
acl_aio_ctl(astream, ACL_AIO_CTL_LISTEN_FN, __listen_callback,
ACL_AIO_CTL_CTX, aio,
ACL_AIO_CTL_END);
acl_aio_listen(astream);
} else {
acl_aio_ctl(astream, ACL_AIO_CTL_ACCEPT_FN, __accept_callback,
ACL_AIO_CTL_CTX, aio,
ACL_AIO_CTL_END);
acl_aio_accept(astream);
}
}
void aio_server_end(void)
{
if (__listener) {
acl_aio_iocp_close(__listener);
acl_aio_loop(__listener->aio);
__listener = NULL;
}
}