static void done_recv_request(void * args) { AsyncReqInfo * req = (AsyncReqInfo *) args; PortConnection * conn = (PortConnection *) (req)->client_data; port_unlock(conn); if (conn->connected == 0) { port_connection_close(conn); return; } if (req->u.sio.rval == 0 || (req->u.sio.rval == -1 && req->error != EINTR)) { /* Check if we are in auto connect mode and server has not been * shut down */ if (conn->server->auto_connect && conn->server->sock != -1) { /* Client has disconnected; don't close the connection if we * are in auto connect mode but simply unbind the client from * the port. */ port_connection_unbind(conn); } else port_connection_close(conn); return; } port_lock(conn); conn->server->client_addr_len = req->u.sio.addrlen; send_packet(conn, req->u.sio.bufp, req->u.sio.rval); }
static void done_send_request(void * args) { AsyncReqInfo * req = (AsyncReqInfo *) args; PortConnection * conn = (PortConnection *) (req)->client_data; int idx = conn->send_in_progress; port_unlock(conn); conn->send_in_progress = -1; if (conn->connected == 0) { port_connection_close(conn); return; } if (req->u.sio.rval == 0 || (req->u.sio.rval == -1 && req->error != EINTR)) { /* Check if we are in auto connect mode and server has not been * shutdown */ if (conn->server->auto_connect && conn->server->sock != -1) { /* Client has disconnected; don't close the connection if we * are in auto connect mode but simply unbind the client from * the port. */ port_connection_unbind(conn); /* Still read packets from the target even if no client is * connected. This may have to be revisited. */ read_packet(conn, idx); } else port_connection_close(conn); return; } if (conn->pending_send_req != 0) { int next_idx; int loop; /* Get the next packet to send. In general, it is the next buffer * but there are some error cases (connection lost, empty packet * received from TCF agent) which may break this rule. */ for (loop = 0; loop < MAX_STREAM_READ; loop++) { next_idx = (idx + loop) % MAX_STREAM_READ; if (conn->pending_send_req & (1 << next_idx)) break; } assert (loop != MAX_STREAM_READ && (conn->pending_send_req & (1 << next_idx))); conn->send_in_progress = next_idx; conn->pending_send_req &= ~(1 << next_idx); conn->send_req.u.sio.bufp = conn->read_buffer[next_idx]; conn->send_req.u.sio.bufsz = conn->read_buffer_size[next_idx]; port_lock(conn); conn->send_req.u.sio.sock = conn->fd; conn->send_req.u.sio.addr = &conn->server->client_addr; conn->send_req.u.sio.addrlen = conn->server->client_addr_len; async_req_post(&conn->send_req); } read_packet(conn, idx); }
static void port_connection_close(PortConnection * conn) { PortServer * server = conn->server; PortConnection * prev; port_connection_unbind(conn); if (conn->connected) { if (server->disconnect_callback) server->disconnect_callback(server, server->callback_data); disconnect_port(conn); conn->connected = 0; return; } if (conn->lock_cnt > 0) return; if (server->list == conn) server->list = conn->next; else { prev = server->list; while (prev->next != conn) prev = prev->next; assert (prev->next == conn); prev->next = conn->next; } loc_free(conn); /* If the last port connection has been closed and server shutdown is * in progress, complete it. */ if (server->list == NULL) { if (server->sock == -1) { port_server_shutdown(server); } else if (server->auto_connect) { /* Retry target connection */ post_event_with_delay(port_connection_open_event, server, server->auto_connect_period * 1000000); } } }