Beispiel #1
0
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;
}
Beispiel #2
0
/* 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;
}
Beispiel #3
0
static void
_flush_series (Npcfsys *fs, Npcfid *root)
{
    Npfcall *rc = NULL, *tc = NULL, *ac = NULL;
    u16 tag, flushtag;
    int n, i;
    struct sigaction sa;

    assert (fs->trans != NULL);

    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = _alarm_clock;
    if (sigaction (SIGALRM, &sa, NULL) < 0)
        err_exit ("sigaction");

    /* write 100 tversions */
    for (i = 0; i < 100; i++) {
        if (!(tc = np_create_tversion (fs->msize, "9P2000.L")))
            msg_exit ("out of memory");
        flushtag = tag = npc_get_id(fs->tagpool);
        np_set_tag(tc, tag);
        n = np_trans_write(fs->trans, tc->pkt, tc->size);
        if (n < 0)
            errn_exit (np_rerror (), "np_trans_write");
        if (n != tc->size)
            msg_exit ("np_trans_write came up unexpectedly short");
        //msg ("sent tversion tag %d", tc->tag);
        free(tc);
    }
    msg ("sent 100 tversions");

    /* flush the most recent */
    if (!(ac = np_create_tflush (flushtag)))
        msg_exit ("out of memory");
    tag = npc_get_id(fs->tagpool);
    np_set_tag(ac, tag);
    n = np_trans_write(fs->trans, ac->pkt, ac->size);
    if (n < 0)
        errn_exit (np_rerror (), "np_trans_write");
    if (n != ac->size)
        msg_exit ("np_trans_write came up unexpectedly short");
    //msg ("sent tflush tag %d (flushing tag %d)", ac->tag, flushtag);
    free (ac);
    msg ("sent 1 tflush");
        
    /* receive up to 101 responses with 1s timeout */
    for (i = 0; i < 101; i++) {
        if (!(rc = malloc(sizeof(*rc) + fs->msize)))
            msg_exit ("out of memory");
        rc->pkt = (u8*)rc + sizeof(*rc);
        alarm (1);
        n = np_trans_read(fs->trans, rc->pkt, fs->msize);
        if (n < 0) {
            if (errno == EINTR)
                break;
            errn_exit (np_rerror (), "np_trans_read");
        }
        alarm (0);
        if (n == 0)
            msg_exit ("np_trans_read: unexpected EOF");
        if (!np_deserialize (rc, rc->pkt))
            msg_exit ("failed to deserialize response in one go");
        //msg ("received tag %d", rc->tag);
        free(rc);
        //npc_put_id(fs->tagpool, rc->tag);
    }
    if (i == 100 || i == 101)
        msg ("received 100/101 respones");
    else 
        msg ("received %d responses", i);
}