static tb_bool_t tb_demo_sock_conn_func(tb_aice_t const* aice) { // check tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_CONN, tb_false); // the context tb_demo_context_t* context = (tb_demo_context_t*)aice->priv; tb_assert_and_check_return_val(context, tb_false); // connection ok? if (aice->state == TB_STATE_OK) { // trace tb_trace_i("conn[%p]: ok", aice->aico); // post recv from server if (!tb_aico_recv(aice->aico, context->data, TB_DEMO_SOCK_RECV_MAXN, tb_demo_sock_recv_func, context)) return tb_false; } // timeout or failed? else { // exit loop tb_trace_i("conn[%p]: state: %s", aice->aico, tb_state_cstr(aice->state)); // exit context tb_demo_context_exit(context); } // ok return tb_true; }
static tb_bool_t tb_demo_file_read_func(tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_READ, tb_false); // the context tb_demo_context_t* context = (tb_demo_context_t*)aice->priv; tb_assert_and_check_return_val(context, tb_false); // ok? if (aice->state == TB_STATE_OK) { // trace tb_trace_d("read[%p]: real: %lu, size: %lu, seek: %llu", aice->aico, aice->u.read.real, aice->u.read.size, aice->u.read.seek); // post send to client if (!tb_aico_send(context->aico[0], aice->u.read.data, aice->u.read.real, tb_demo_sock_send_func, context)) return tb_false; } // closed or failed? else { tb_trace_i("read[%p]: state: %s", aice->aico, tb_state_cstr(aice->state)); tb_demo_context_exit(context); } // ok return tb_true; }
static tb_bool_t tb_demo_sock_sendf_func(tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_SENDF, tb_false); // the context tb_demo_context_t* context = (tb_demo_context_t*)aice->priv; tb_assert_and_check_return_val(context, tb_false); // ok? if (aice->state == TB_STATE_OK) { // trace tb_trace_d("sendf[%p]: real: %lu, size: %llu", aice->aico, aice->u.sendf.real, aice->u.sendf.size); // save size context->size += aice->u.sendf.real; // continue to send it? if (aice->u.sendf.real < aice->u.sendf.size) { // post sendf from file if (!tb_aico_sendf(aice->aico, context->file, context->size, aice->u.sendf.size - aice->u.sendf.real, tb_demo_sock_sendf_func, context)) return tb_false; } else { tb_trace_i("sendf[%p]: finished", aice->aico); tb_demo_context_exit(context); } } // closed or failed? else { tb_trace_i("sendf[%p]: state: %s", aice->aico, tb_state_cstr(aice->state)); tb_demo_context_exit(context); } // ok return tb_true; }
static tb_bool_t tb_demo_sock_recv_func(tb_aice_t const* aice) { // check tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_RECV, tb_false); // the context tb_demo_context_t* context = (tb_demo_context_t*)aice->priv; tb_assert_and_check_return_val(context, tb_false); // ok? if (aice->state == TB_STATE_OK) { // trace tb_trace_d("recv[%p]: real: %lu, size: %lu", aice->aico, aice->u.recv.real, aice->u.recv.size); // post writ to file if (!tb_aico_writ(context->file, context->size, aice->u.recv.data, aice->u.recv.real, tb_demo_file_writ_func, context)) return tb_false; // save size context->size += aice->u.recv.real; // compute speed context->peak += aice->u.recv.real; if (!context->time) { context->time = tb_mclock(); context->base = tb_mclock(); context->sped = context->peak; } else if (tb_mclock() > context->time + 1000) { context->sped = context->peak; context->peak = 0; context->time = tb_mclock(); // trace tb_trace_i("recv[%p]: size: %llu, sped: %lu KB/s", aice->aico, context->size, context->sped / 1000); } } // closed or failed? else { // trace tb_trace_i("recv[%p]: state: %s", aice->aico, tb_state_cstr(aice->state)); // exit context tb_demo_context_exit(context); } // ok return tb_true; }
static tb_bool_t tb_demo_sock_send_func(tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_SEND, tb_false); // the context tb_demo_context_t* context = (tb_demo_context_t*)aice->priv; tb_assert_and_check_return_val(context, tb_false); // ok? if (aice->state == TB_STATE_OK) { // trace tb_trace_d("send[%p]: real: %lu, size: %lu", aice->aico, aice->u.send.real, aice->u.send.size); // save size context->size += aice->u.send.real; // continue? if (aice->u.send.real < aice->u.send.size) { // post send to client if (!tb_aico_send(aice->aico, aice->u.send.data + aice->u.send.real, aice->u.send.size - aice->u.send.real, tb_demo_sock_send_func, context)) return tb_false; } // ok? else { // post read from file if (!tb_aico_read(context->aico[1], context->size, context->data, TB_DEMO_FILE_READ_MAXN, tb_demo_file_read_func, context)) return tb_false; } } // closed or failed? else { tb_trace_i("send[%p]: state: %s", aice->aico, tb_state_cstr(aice->state)); tb_demo_context_exit(context); } // ok return tb_true; }
static tb_bool_t tb_demo_file_writ_func(tb_aice_t const* aice) { // check tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_WRIT, tb_false); // the context tb_demo_context_t* context = (tb_demo_context_t*)aice->priv; tb_assert_and_check_return_val(context, tb_false); // ok? if (aice->state == TB_STATE_OK) { // trace tb_trace_d("writ[%p]: real: %lu, size: %lu", aice->aico, aice->u.writ.real, aice->u.writ.size); // continue? if (aice->u.writ.real < aice->u.writ.size) { // post writ to file if (!tb_aico_writ(aice->aico, aice->u.writ.seek + aice->u.writ.real, aice->u.writ.data + aice->u.writ.real, aice->u.writ.size - aice->u.writ.real, tb_demo_file_writ_func, context)) return tb_false; } // ok? else { // post recv from server if (!tb_aico_recv(context->sock, context->data, TB_DEMO_SOCK_RECV_MAXN, tb_demo_sock_recv_func, context)) return tb_false; } } // closed or failed? else { // trace tb_trace_i("writ[%p]: %s", aice->aico, tb_state_cstr(aice->state)); // exit context tb_demo_context_exit(context); } // ok return tb_true; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_asio_aiopd_main(tb_int_t argc, tb_char_t** argv) { // check tb_assert_and_check_return_val(argv[1], 0); // done tb_socket_ref_t sock = tb_null; tb_aiop_ref_t aiop = tb_null; do { // init sock sock = tb_socket_init(TB_SOCKET_TYPE_TCP); tb_assert_and_check_break(sock); // init aiop aiop = tb_aiop_init(16); tb_assert_and_check_break(aiop); // bind if (!tb_socket_bind(sock, tb_null, 9090)) break; // listen sock if (!tb_socket_listen(sock, 20)) break; // addo sock if (!tb_aiop_addo(aiop, sock, TB_AIOE_CODE_ACPT, tb_null)) break; // accept tb_aioe_t list[16]; while (1) { // wait tb_long_t objn = tb_aiop_wait(aiop, list, 16, -1); tb_assert_and_check_break(objn >= 0); // walk list tb_size_t i = 0; for (i = 0; i < objn; i++) { // the aioo tb_aioo_ref_t aioo = list[i].aioo; // check tb_assert_and_check_break(aioo && tb_aioo_sock(aioo)); // acpt? if (list[i].code & TB_AIOE_CODE_ACPT) { // done acpt tb_bool_t ok = tb_false; tb_demo_context_t* context = tb_null; do { // make context context = tb_malloc0_type(tb_demo_context_t); tb_assert_and_check_break(context); // init sock context->sock = tb_socket_accept(tb_aioo_sock(aioo), tb_null, tb_null); tb_assert_and_check_break(context->sock); // init file context->file = tb_file_init(argv[1], TB_FILE_MODE_RO); tb_assert_and_check_break(context->file); // init data context->data = tb_malloc_bytes(TB_DEMO_FILE_READ_MAXN); tb_assert_and_check_break(context->data); // addo sock context->aioo = tb_aiop_addo(aiop, context->sock, TB_AIOE_CODE_SEND, context); tb_assert_and_check_break(context->aioo); // trace tb_trace_i("acpt[%p]: ok", context->sock); // init left context->left = tb_file_size(context->file); // done read tb_long_t real = tb_file_read(context->file, context->data, tb_min((tb_size_t)context->left, TB_DEMO_FILE_READ_MAXN)); tb_assert_and_check_break(real > 0); // save size context->left -= real; // trace // tb_trace_i("read[%p]: real: %ld", context->file, real); // done send context->send = real; real = tb_socket_send(context->sock, context->data + context->real, context->send - context->real); if (real >= 0) { // save real context->real += real; // trace // tb_trace_i("send[%p]: real: %ld", context->sock, real); } else { // trace tb_trace_i("send[%p]: closed", context->sock); break; } // ok ok = tb_true; } while (0); // failed or closed? if (!ok) { // exit context tb_demo_context_exit(aiop, context); break; } } // writ? else if (list[i].code & TB_AIOE_CODE_SEND) { // the context tb_demo_context_t* context = (tb_demo_context_t*)list[i].priv; tb_assert_and_check_break(context); // continue to send it if not finished if (context->real < context->send) { // done send tb_long_t real = tb_socket_send(tb_aioo_sock(aioo), context->data + context->real, context->send - context->real); if (real > 0) { // save real context->real += real; // trace // tb_trace_i("send[%p]: real: %ld", tb_aioo_sock(aioo), real); } else { // trace tb_trace_i("send[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } // finished? read file else if (context->left) { // init context->real = 0; context->send = 0; // done read tb_size_t tryn = 1; tb_long_t real = 0; while (!(real = tb_file_read(context->file, context->data, tb_min((tb_size_t)context->left, TB_DEMO_FILE_READ_MAXN))) && tryn--); if (real > 0) { // save left context->left -= real; // trace // tb_trace_i("read[%p]: real: %ld", context->file, real); // done send context->send = real; real = tb_socket_send(tb_aioo_sock(aioo), context->data, context->send); if (real >= 0) { // save real context->real += real; // trace // tb_trace_i("send[%p]: real: %ld", tb_aioo_sock(aioo), real); } else { // trace tb_trace_i("send[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } else { // trace tb_trace_i("read[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } else { // trace tb_trace_i("read[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } // error? else { tb_trace_i("aioe[%p]: unknown code: %lu", tb_aioo_sock(aioo), list[i].code); break; } } } } while (0); // trace tb_trace_i("end"); // exit socket if (sock) tb_socket_exit(sock); // exit aiop if (aiop) tb_aiop_exit(aiop); // end return 0; }
static tb_bool_t tb_demo_sock_acpt_func(tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_ACPT, tb_false); // the file path tb_char_t const* path = (tb_char_t const*)aice->priv; tb_assert_and_check_return_val(path, tb_false); // the aicp tb_aicp_ref_t aicp = tb_aico_aicp(aice->aico); tb_assert_and_check_return_val(aicp, tb_false); // acpt ok? if (aice->state == TB_STATE_OK) { // trace tb_trace_i("acpt[%p]: %p", aice->aico, aice->u.acpt.aico); // done tb_bool_t ok = tb_false; tb_demo_context_t* context = tb_null; do { // make context context = tb_malloc0_type(tb_demo_context_t); tb_assert_and_check_break(context); #ifdef TB_DEMO_MODE_SENDF // init file context->file = tb_file_init(path, TB_FILE_MODE_RO | TB_FILE_MODE_ASIO); tb_assert_and_check_break(context->file); // init sock aico context->aico[0] = aice->u.acpt.aico; tb_assert_and_check_break(context->aico[0]); // post sendf from file if (!tb_aico_sendf(context->aico[0], context->file, 0ULL, tb_file_size(context->file), tb_demo_sock_sendf_func, context)) break; #else // init data context->data = tb_malloc_bytes(TB_DEMO_FILE_READ_MAXN); tb_assert_and_check_break(context->file && context->data); // init sock aico context->aico[0] = aice->u.acpt.aico; tb_assert_and_check_break(context->aico[0]); // init file aico context->aico[1] = tb_aico_init(aicp); tb_assert_and_check_break(context->aico[1]); // open file aico if (!tb_aico_open_file_from_path(context->aico[1], path, TB_FILE_MODE_RO)) break; // post read from file if (!tb_aico_read(context->aico[1], context->size, context->data, TB_DEMO_FILE_READ_MAXN, tb_demo_file_read_func, context)) break; #endif // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit context if (context) tb_demo_context_exit(context); } } // failed? else { // exit loop tb_trace_i("acpt[%p]: state: %s", aice->aico, tb_state_cstr(aice->state)); // clos aico if (aice->aico) tb_aico_clos(aice->aico, tb_demo_aico_clos, tb_null); } // ok return tb_true; }