static void recv_data_check(sg_etp_session_t * session) { int len = 0; recv_req_t * req = NULL; while ((len = ikcp_peeksize(session->kcp)) > 0) /*if (len > 0)*/ { req = malloc(sizeof(recv_req_t) + len); if (NULL != req) { len = ikcp_recv(session->kcp, req->data, len); if (len >= 0) { req->data_len = len; req->session = session; uv_queue_work(session->loop, &req->req, recv_data_proc, recv_data_proc_cleanup); } else { free(req); } } else { LOG_E("recv_data malloc failed"); break; } } }
ssize_t UDPSession::Read(char *buf, size_t sz) noexcept { if (m_streambufsiz > 0) { size_t n = m_streambufsiz; if (n > sz) { n = sz; } memcpy(buf, m_streambuf, n); m_streambufsiz -= n; if (m_streambufsiz != 0) { memmove(m_streambuf, m_streambuf + n, m_streambufsiz); } return n; } int psz = ikcp_peeksize(m_kcp); if (psz <= 0) { return 0; } if (psz <= sz) { return (ssize_t) ikcp_recv(m_kcp, buf, int(sz)); } else { ikcp_recv(m_kcp, m_streambuf, UDPSession::streamBufferLimit); memcpy(buf, m_streambuf, sz); m_streambufsiz = psz - sz; memmove(m_streambuf, m_streambuf + sz, psz - sz); return sz; } }
int sg_etp_session_close(sg_etp_session_t * session) { LOG_D("ikcp_peeksize: %d, ikcp_waitsnd: %d", ikcp_peeksize(session->kcp), ikcp_waitsnd(session->kcp)); if (ikcp_waitsnd(session->kcp) > 0 || ikcp_peeksize(session->kcp) > 0) { session->to_close = true; /* mark for close later */ return OK; } LOG_D("close session"); ikcp_release(session->kcp); uv_timer_stop(&(session->timer)); if (session->udp == &(session->udp_hdl)) /* self-contained udp, should close here */ { uv_close((uv_handle_t*)session->udp, on_uv_close_done); } if (session->loop == &(session->loop_hdl)) /* self-contained loop, should close here */ { uv_loop_close(session->loop); } SG_CALLBACK(session->on_close, session, OK, "ok"); if (NULL != session->recv_buf) { free(session->recv_buf); } free(session); return OK; }
int Conn::recv_kcp(char*& buf, uint32_t& size) { int len = ikcp_peeksize(_kcp); if (len < 0) { return -1; } char* data = new char[len]; int r = ikcp_recv(_kcp, data, len); if (r < 0) { delete[]data; return r; } buf = data; size = (uint32_t)len; return 0; }
/** TODO: check buf and size */ int conn_recv_kcp(conn_t * thiz, char** buf, uint32_t * size) { int len = ikcp_peeksize(thiz->_kcp); if (len < 0) { return -1; } char * data = malloc(sizeof(char) * len); int r = ikcp_recv(thiz->_kcp, data, len); if (r < 0) { free(data); return r; } *buf = data; *size = (uint32_t)len; return 0; }
/* for libuv */ static void on_uv_timer_cb(uv_timer_t * handle) { sg_etp_session_t * session = handle->data; IUINT32 now = 0; /*LOG_D("update %d", client->conv);*/ /* update ikcp */ now = (IUINT32)uv_now(session->loop); sg_etp_update_speed((sg_etp_t *)session, now); if (now >= session->kcp_update_time) { ikcp_update(session->kcp, now); session->kcp_update_time = ikcp_check(session->kcp, now); LOG_D("update %lu @ %lu, timeout: %lu", session->conv, session->kcp_update_time, session->recv_data_time); /* check received data and add to work queue */ //recv_data_check(session); if (ikcp_peeksize(session->kcp) > 0) { uv_idle_start(&(session->idle), on_uv_idle_cb); } } /* check if session is timeout */ if (session->recv_data_time < now) { session->to_close = true; /* mark to close this session. */ ikcp_flush(session->kcp); LOG_I("session %lu timeout, will be closed", session->conv); } /* check if should close this session */ if (session->to_close) { sg_etp_session_close(session); } }
static void on_uv_idle_cb(uv_idle_t * handle) { sg_etp_session_t * session = (sg_etp_session_t *)handle->data; int len = 0; len = ikcp_peeksize(session->kcp); if (len > 0) { if (len > session->recv_buf_len) { session->recv_buf = realloc(session->recv_buf, len); session->recv_buf_len = len; } SG_ASSERT(NULL != session->recv_buf, "alloc recv buf failed"); len = ikcp_recv(session->kcp, session->recv_buf, len); SG_CALLBACK(session->on_data, session, session->recv_buf, len); } else { uv_idle_stop(&(session->idle)); } }