static void np_conn_destroy(Npconn *conn) { int n; NP_ASSERT(conn != NULL); NP_ASSERT(conn->refcount == 0); /* issue 83: remove from srv->conns before destroying fidpool */ np_srv_remove_conn (conn->srv, conn); if (conn->fidpool) { if ((n = np_fidpool_destroy(conn->fidpool)) > 0) { np_logmsg (conn->srv, "%s: connection closed with " "%d unclunked fids", np_conn_get_client_id (conn), n); } conn->fidpool = NULL; } if (conn->trans) { np_trans_destroy (conn->trans); conn->trans = NULL; } pthread_mutex_destroy(&conn->lock); pthread_mutex_destroy(&conn->wlock); pthread_cond_destroy(&conn->refcond); free(conn); }
static void npc_decref_fsys(Npcfsys *fs) { xpthread_mutex_lock(&fs->lock); fs->refcount--; if (fs->refcount) { xpthread_mutex_unlock(&fs->lock); return; } if (fs->trans) { np_trans_destroy(fs->trans); /* closes fds */ fs->trans = NULL; } if (fs->tagpool) { npc_destroy_pool(fs->tagpool); fs->tagpool = NULL; } if (fs->fidpool) { npc_destroy_pool(fs->fidpool); fs->fidpool = NULL; } xpthread_mutex_unlock(&fs->lock); pthread_mutex_destroy(&fs->lock); free(fs); }
void np_conn_shutdown(Npconn *conn) { Nptrans *trans; pthread_mutex_lock(&conn->lock); trans = conn->trans; conn->trans = NULL; pthread_mutex_unlock(&conn->lock); np_trans_destroy(trans); }
void np_conn_respond(Npreq *req) { int n; Npconn *conn; Nptrans *trans; Npfcall *rc; trans = NULL; conn = req->conn; rc = req->rcall; pthread_mutex_lock(&conn->lock); if (conn->trans && !conn->resetting && rc) { if (conn->srv->debuglevel) { print_timestamp(stderr); fprintf(stderr, " >>> (%p) ", conn); np_printfcall(stderr, rc, conn->dotu); if ( req->tcall->encryptor ) fprintf(stderr, " (encrypted)"); fprintf(stderr, "\n"); } if ( req->tcall->encryptor ) { /* Request was encrypted => encrypt also the response */ rc->encryptor = req->tcall->encryptor; rc = np_encrypt_fcall(rc); req->rcall = rc; } n = np_trans_write(conn->trans, rc->pkt, rc->size); if (n <= 0) { trans = conn->trans; conn->trans = NULL; } } np_conn_free_incall(req->conn, req->tcall); free(req->rcall); req->tcall = NULL; req->rcall = NULL; pthread_mutex_unlock(&conn->lock); if (conn->resetting) { pthread_mutex_lock(&conn->srv->lock); pthread_cond_broadcast(&conn->resetcond); pthread_mutex_unlock(&conn->srv->lock); } if (trans) np_trans_destroy(trans); /* np_conn_read_proc will take care of resetting */ }
void np_conn_respond(Npreq *req) { int n, send; Npconn *conn; Nptrans *trans; Npfcall *rc; trans = NULL; conn = req->conn; rc = req->rcall; if (!rc) goto done; pthread_mutex_lock(&conn->lock); send = conn->trans && !conn->resetting; pthread_mutex_unlock(&conn->lock); if (send) { pthread_mutex_lock(&conn->wlock); if (conn->srv->debuglevel) { fprintf(stderr, ">>> (%p) ", conn); np_printfcall(stderr, rc, conn->dotu); fprintf(stderr, "\n"); } n = np_trans_write(conn->trans, rc->pkt, rc->size); pthread_mutex_unlock(&conn->wlock); if (n <= 0) { pthread_mutex_lock(&conn->lock); trans = conn->trans; conn->trans = NULL; pthread_mutex_unlock(&conn->lock); } } done: np_conn_free_incall(req->conn, req->tcall, 1); free(req->rcall); req->tcall = NULL; req->rcall = NULL; if (conn->resetting) { pthread_mutex_lock(&conn->srv->lock); pthread_cond_broadcast(&conn->resetcond); pthread_mutex_unlock(&conn->srv->lock); } if (trans) np_trans_destroy(trans); /* np_conn_read_proc will take care of resetting */ }
/* Called by srv workers to transmit req->rcall->pkt. */ void np_conn_respond(Npreq *req) { int n, send; Npconn *conn = req->conn; Npsrv *srv = conn->srv; Npfcall *rc = req->rcall; Nptrans *trans = NULL; if (!rc) goto done; xpthread_mutex_lock(&conn->lock); send = conn->trans && !conn->resetting; xpthread_mutex_unlock(&conn->lock); if (send) { if ((srv->flags & SRV_FLAGS_DEBUG_9PTRACE)) _debug_trace (srv, rc); xpthread_mutex_lock(&conn->wlock); n = np_trans_write(conn->trans, rc->pkt, rc->size); conn->reqs_out++; xpthread_mutex_unlock(&conn->wlock); if (n <= 0) { /* write error */ xpthread_mutex_lock(&conn->lock); trans = conn->trans; conn->trans = NULL; xpthread_mutex_unlock(&conn->lock); } } done: _free_npfcall(req->tcall); free(req->rcall); req->tcall = NULL; req->rcall = NULL; if (conn->resetting) { xpthread_mutex_lock(&conn->srv->lock); xpthread_cond_broadcast(&conn->resetcond); xpthread_mutex_unlock(&conn->srv->lock); } if (trans) /* np_conn_read_proc will take care of resetting */ np_trans_destroy(trans); }
/* Per-connection read thread. */ static void * np_conn_read_proc(void *a) { int i, n, size; Npsrv *srv; Npconn *conn = (Npconn *)a; Nptrans *trans; Npreq *req; Npfcall *fc, *fc1; pthread_detach(pthread_self()); np_conn_incref(conn); srv = conn->srv; fc = _alloc_npfcall(conn->msize); n = 0; while (fc && conn->trans && (i = np_trans_read(conn->trans, fc->pkt + n, conn->msize - n)) > 0) { n += i; again: size = np_peek_size (fc->pkt, n); if (size == 0 || n < size) continue; /* Corruption on the transport, unhandled op, etc. * is fatal to the connection. We could consider returning * an error to the client here. However, various kernels * may not handle that well, depending on where it happens. */ if (!np_deserialize(fc, fc->pkt)) { _debug_trace (srv, fc); np_logerr (srv, "protocol error - " "dropping connection to '%s'", conn->client_id); break; } if ((srv->flags & SRV_FLAGS_DEBUG_9PTRACE)) _debug_trace (srv, fc); /* Replace fc, and copy any data past the current packet * to the replacement. */ fc1 = _alloc_npfcall(conn->msize); if (!fc1) { np_logerr (srv, "out of memory in receive path - " "dropping connection to '%s'", conn->client_id); break; } if (n > size) memmove(fc1->pkt, fc->pkt + size, n - size); n -= size; /* Encapsulate fc in a request and hand to srv worker threads. * In np_req_alloc, req->fid is looked up/initialized. */ req = np_req_alloc(conn, fc); if (!req) { np_logerr (srv, "out of memory in receive path - " "dropping connection to '%s'", conn->client_id); break; } np_srv_add_req(srv, req); xpthread_mutex_lock(&conn->lock); conn->reqs_in++; xpthread_mutex_unlock(&conn->lock); fc = fc1; if (n > 0) goto again; } /* Just got EOF on read, or some other fatal error for the * connection like out of memory. */ xpthread_mutex_lock(&conn->lock); trans = conn->trans; conn->trans = NULL; if (fc) _free_npfcall(fc); xpthread_mutex_unlock(&conn->lock); np_srv_remove_conn(conn->srv, conn); np_conn_reset(conn); if (trans) np_trans_destroy(trans); np_conn_decref(conn); return NULL; }
static void * np_conn_read_proc(void *a) { int i, n, size, msize; Npsrv *srv; Npconn *conn; Nptrans *trans; Npreq *req; Npfcall *fc, *fc1; pthread_detach(pthread_self()); conn = a; np_conn_incref(conn); srv = conn->srv; msize = conn->msize; fc = np_conn_new_incall(conn); n = 0; while (conn->trans && (i = np_trans_read(conn->trans, fc->pkt + n, msize - n)) > 0) { pthread_mutex_lock(&conn->lock); if (conn->resetting) { while(conn->resetting) pthread_cond_wait(&conn->resetdonecond, &conn->lock); n = 0; /* discard all input */ i = 0; } pthread_mutex_unlock(&conn->lock); n += i; again: if (n < 4) continue; size = fc->pkt[0] | (fc->pkt[1]<<8) | (fc->pkt[2]<<16) | (fc->pkt[3]<<24); if (n < size) continue; if (!np_deserialize(fc, fc->pkt, conn->dotu)) break; if (conn->srv->debuglevel) { fprintf(stderr, "<<< (%p) ", conn); np_printfcall(stderr, fc, conn->dotu); fprintf(stderr, "\n"); } fc1 = np_conn_new_incall(conn); if (n > size) memmove(fc1->pkt, fc->pkt + size, n - size); n -= size; req = np_req_alloc(conn, fc); pthread_mutex_lock(&srv->lock); if (!conn->resetting) np_srv_add_req(srv, req); else np_req_unref(req); pthread_mutex_unlock(&srv->lock); fc = fc1; if (n > 0) goto again; } pthread_mutex_lock(&conn->lock); trans = conn->trans; conn->trans = NULL; np_conn_free_incall(conn, fc); pthread_mutex_unlock(&conn->lock); np_srv_remove_conn(conn->srv, conn); np_conn_reset(conn, 0, 0); if (trans) np_trans_destroy(trans); np_conn_decref(conn); return NULL; }