#include "StdAfx.h" #include "lib_acl.h" #include #include #include #include #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; } }