static void _excute_read_cmd(SocketCmd * cmd, ddcl_Service source, ddcl_Session session){ ddcl_Socket h = cmd->h; Socket * s = _find_socket(h); if(!s || s->fd != cmd->fd){ const char * err = "socket fd error"; ddcl_send_b(source, 0, DDCL_PTYPE_RESP, DDCL_CMD_ERROR, session, err, strlen(err) + 1); return; } if(s->forward){ const char * err = "socket fd is forward mode"; ddcl_send_b(source, 0, DDCL_PTYPE_RESP, DDCL_CMD_ERROR, session, err, strlen(err) + 1); return; } size_t sz = cmd->sz; if(!_read_buff_is_empty(s)){ _push_read_buff(s, cmd->sz, source, session); _add_evt_2_poll(s->st->poll, s, DDSOCKETPOLL_READ); return; } size_t rlen = 0; char * rbuf; for(;;){ if(s->cbuf_sz > 0 && s->cbuf_sz >= sz){ if(sz == 0) sz = s->cbuf_sz; _rsp_read(s->st->svr, s->h, source, session, DDCL_SOCKET_READ, _read_cache_buff(s, sz), sz); return; } if (sz == 0) rlen = DEFAULT_RECV_SIZE; else rlen = sz - s->cbuf_sz; if(rlen <= DEFAULT_RECV_SIZE) rbuf = s->crbuf; else rbuf = ddcl_malloc(rlen); int rsz = recv(s->fd, rbuf, (int)rlen, 0); if(rsz > 0){ _push_cache_buff(s, rbuf, rsz, rlen <= DEFAULT_RECV_SIZE); if(rlen > DEFAULT_RECV_SIZE) ddcl_free(rbuf); }else{ if(rlen > DEFAULT_RECV_SIZE) ddcl_free(rbuf); break; } } _push_read_buff(s, sz, source, session); if(!(s->poll_evt & DDSOCKETPOLL_READ)) _add_evt_2_poll(s->st->poll, s, DDSOCKETPOLL_READ); }
static void _execute_event(SocketThread * st, ddcl_Socket h, int evt){ Socket * s = _find_socket(h); if(!s) return; switch(s->status){ case _SS_CONNECTING: _execute_event_in_fd_connecting(st, s, evt); break; case _SS_CONNECTED: _execute_event_on_fd_connected(st, s, evt); break; case _SS_LISTENING: _execute_event_on_fd_listening(st, s, evt); break; /* case _SS_CLOSE: _execute_event_in_fd_close(st, s, evt); break; */ default: assert(0); break; } }
static void _excute_send_cmd(SocketCmd * cmd, ddcl_Service source, ddcl_Session session){ ddcl_Socket h = cmd->h; Socket * s = _find_socket(h); if(!s || s->fd != cmd->fd){ return; } char * buf = cmd->data; size_t sz = cmd->sz; size_t slen = 0; if(_send_buff_is_empty(s)){ int n; for(;;){ n = send(s->fd, buf + slen, (int)(sz - slen), 0); if(n <= 0) break; slen += n; if (slen >= sz) { ddcl_free(cmd->data); return; } } } _push_send_buff(s, buf + slen, sz - slen); _add_evt_2_poll(s->st->poll, s, DDSOCKETPOLL_WRITE); ddcl_free(cmd->data); }
static void _excute_close_cmd(SocketCmd * cmd, ddcl_Service source, ddcl_Session session){ Socket * s = _find_socket(cmd->h); if(s && s->fd == cmd->fd){ _del_fd(s); } }
int recv(VSOCKET socket, char *data, size_t size) { LOCK(mu,0); shared_ptr<Node> con = _find_socket(socket); if(con) { return con->recv(data, size); } return -1; }
bool getsockopt(VSOCKET sock, const string &option, string &dst) { LOCK(mu,0); shared_ptr<Node> n = _find_socket(sock); if(n) { return n->get_option(option, dst); } return false; }
int connect(VSL::VSOCKET socket, const list<URL> &peers) { LOCK(mu,0); shared_ptr<Node> tun = _find_socket(socket); if(tun) tun.reset(); tun = net->createTunnel(peers); sockets[socket] = tun; return 0; }
static void _excute_forward_cmd (SocketCmd * cmd, ddcl_Service source, ddcl_Session session){ ddcl_Socket h = cmd->h; Socket * s = _find_socket(cmd->h); if(!s || s->fd != cmd->fd){ return; } s->forward = 1; _add_evt_2_poll(s->st->poll, s, DDSOCKETPOLL_READ | DDSOCKETPOLL_ERROR); }
int connect(VSOCKET socket, const URL &url) { LOCK(mu,0); shared_ptr<Node> con = _find_socket(socket); if(con) { con->close(); con.reset(); } con = net->connect(url); sockets[socket] = con; return 0; }
int bind(VSOCKET socket, const URL &url) { LOCK(mu,0); shared_ptr<Node> con = _find_socket(socket); if(!con) con = net->createNode(url.protocol()); if(con) { sockets[socket] = con; return con->bind(url); } return -1; }
VSL::VSOCKET accept(VSL::VSOCKET socket) { LOCK(mu,0); shared_ptr<Node> con = _find_socket(socket); if(con) { unique_ptr<Node> client = con->accept(); if(client) { VSOCKET s = _create_socket(); sockets[s] = move(client); return s; } return 0; // listening but no connection } return -1; // invalid descriptor }
DDCLAPI int ddcl_forward_socket (ddcl_Socket fd, ddcl_Service from){ Socket * s = _find_socket(fd); if (!s) return DDCLSOCKET_INVALID_HANDLE; SocketCmd cmd; cmd.cmd = _SCMD_FORWARD; cmd.h = fd; cmd.fd = s->fd; SocketThread * st = _st_find(fd); ddcl_send_b(st->svr, from, DDCL_PTYPE_SEND, DDCL_CMD_SOCKET, 0, (char *)&cmd, sizeof(SocketCmd)); return DDCL_OK; }
DDCLAPI int ddcl_read_socket(ddcl_Socket fd, ddcl_Service from, size_t sz, ddcl_Session * session){ Socket * s = _find_socket(fd); if (!s) return DDCLSOCKET_INVALID_HANDLE; SocketCmd cmd; cmd.cmd = _SCMD_READ; cmd.h = fd; cmd.fd = s->fd; cmd.sz = sz; SocketThread * st = _st_find(fd); ddcl_call_b(st->svr, from, DDCL_PTYPE_SEND, DDCL_CMD_SOCKET, session, (char *)&cmd, sizeof(cmd)); return DDCL_OK; }
int getsockinfo(VSOCKET sock, SOCKINFO *info) { LOCK(mu,0); shared_ptr<Node> n = _find_socket(sock); if(!n) return -1; if(n->state & CON_STATE_CONNECTING) info->state = VSOCKET_CONNECTING; else if(n->state & CON_STATE_CONNECTED) info->state = VSOCKET_CONNECTED; else if(n->state & CON_STATE_DISCONNECTED) info->state = VSOCKET_DISCONNECTED; else if(n->state & CON_STATE_IDLE) info->state = VSOCKET_IDLE; else if(n->state & CON_STATE_LISTENING) info->state = VSOCKET_LISTENING; info->is_connected = (n->state & CON_STATE_CONNECTED) != 0; return 0; }
static void _excute_accept_cmd(SocketCmd * cmd, ddcl_Service source, ddcl_Session session){ ddcl_Socket h = cmd->h; Socket * s = _find_socket(cmd->h); if(!s || s->fd != cmd->fd){ const char * err = "unknow listen fd for accepting"; ddcl_send_b(source, 0, DDCL_PTYPE_RESP, DDCL_CMD_ERROR, session, err, strlen(err) + 1); return; } if(s->forward){ const char * err = "socket fd is forward mode"; ddcl_send_b(source, 0, DDCL_PTYPE_RESP, DDCL_CMD_ERROR, session, err, strlen(err) + 1); return; } if(!_read_buff_is_empty(s)){ _push_read_buff(s, cmd->sz, source, session); _add_evt_2_poll(s->st->poll, s, DDSOCKETPOLL_READ | DDSOCKETPOLL_ERROR); return; } SockAddrAll saa; socklen_t len = sizeof(SockAddrAll); DDSOCK_FD fd = accept(s->fd, &(saa.s), &len); if(fd != -1){ _set_keepalive(fd); _set_non_blocking(fd); Socket *ns = _register_fd(fd, _SS_CONNECTED); ns->source = s->source; ns->session = s->session; _add_in_poll(ns->h, ns, DDSOCKETPOLL_ERROR); ns->poll_evt = DDSOCKETPOLL_ERROR; _rsp_socket(ns->st, ns, source, session, DDCL_SOCKET_ACCEPT); }else{ _push_read_buff(s, 0, source, session); if(!(s->poll_evt & DDSOCKETPOLL_READ)) _add_evt_2_poll(s->st->poll, s, DDSOCKETPOLL_READ); } }
DDCLAPI int ddcl_send_socket(ddcl_Socket fd, ddcl_Service from, const void * buf, size_t sz){ Socket * s = _find_socket(fd); if(!s) return DDCLSOCKET_INVALID_HANDLE; SocketCmd cmd; cmd.cmd = _SCMD_SEND; cmd.h = fd; cmd.fd = s->fd; cmd.sz = sz; cmd.data = ddcl_malloc(sz); memcpy(cmd.data, buf, sz); SocketThread * st = _st_find(fd); ddcl_send_b(st->svr, from, DDCL_PTYPE_SEND, DDCL_CMD_SOCKET, 0, (char *)&cmd, sizeof(SocketCmd)); return DDCL_OK; }
int listen(VSOCKET socket, const list<URL> &url) { LOCK(mu,0); shared_ptr<Node> tun = _find_socket(socket); if(tun) tun.reset(); if(url.size() > 1) { tun = net->createTunnel(list<URL>(url.begin(), std::prev(url.end()))); URL u = *(std::prev(url.end())); LOG(3, "VSL: attempting to listen remotely on "<<u.url()); tun->listen(u); } else { URL u = (*url.begin()); tun = net->createNode(u.protocol()); if(tun) { LOG(3, "VSL: attempting to listen on "<<u.url()); tun->listen(u); } } sockets[socket] = tun; return -1; }