Пример #1
0
int cpeer_kill(struct cpeer *p)
{
        if(!p)
	    return 0;
	if(__sync_bool_compare_and_swap(&p->status,CPEER_CONNECTED,CPEER_DISCONNECTED))
	{
		printf("ref:%d,close peer id:%lu,peer:%p,nc:%p\n",p->refcount,p->id,p,p->nc);
		close(p->sd);
		fdev_del(&p->ioev);

		//push one msg to notify disconnect
		struct msg_t *msg = (struct msg_t *)mmalloc(p->nc->allocator,
			sizeof(struct msg_t));
		msg->buf = NULL;
		msg->len = 0;
		msg->peer_id = p->id;
		msg->type = MSG_DISCONNECT;

		queue_push(p->nc->recv_queue,msg);
	}

	if(__sync_bool_compare_and_swap(&p->refcount,0,1))
	{
		printf("free peer id:%lu\n",p->id);
		iobuf_free(p->allocator,&p->recvbuf);
		iobuf_free(p->allocator,&p->sendbuf);
		//free send queue
		struct msg_t *msg = NULL,*next = NULL;
		thread_mutex_lock(p->sq_mutex);
		msg = BTPDQ_FIRST(&p->send_queue);
		while(msg){
			next = BTPDQ_NEXT(msg,msg_entry);
			BTPDQ_REMOVE(&p->send_queue,msg,msg_entry);

			mfree(p->allocator,msg->buf);
			mfree(p->allocator,msg);
			msg = next;
		}
		thread_mutex_unlock(p->sq_mutex);

		thread_mutex_destroy(p->mpool_mutex);
		thread_mutex_destroy(p->sq_mutex);

		allocator_destroy(p->allocator);

		thread_mutex_lock(p->nc->peer_mutex);
		mfree(p->nc->allocator,p);
		p->nc->peer = NULL;
		thread_mutex_unlock(p->nc->peer_mutex);
	}
	return 0;
}
Пример #2
0
static void ns_destroy_conn(struct ns_connection *conn) {
  closesocket(conn->sock);
  iobuf_free(&conn->recv_iobuf);
  iobuf_free(&conn->send_iobuf);
#ifdef NS_ENABLE_SSL
  if (conn->ssl != NULL) {
    SSL_free(conn->ssl);
  }
  if (conn->ssl_ctx != NULL) {
    SSL_CTX_free(conn->ssl_ctx);
  }
#endif
  NS_FREE(conn);
}
Пример #3
0
static const char *test_iobuf(void) {
  struct iobuf io;

  iobuf_init(&io, 0);
  ASSERT(io.buf == NULL && io.len == 0 && io.size == 0);
  iobuf_free(&io);
  ASSERT(io.buf == NULL && io.len == 0 && io.size == 0);

  iobuf_init(&io, 10);
  ASSERT(io.buf != NULL && io.len == 0 && io.size == 10);
  iobuf_free(&io);
  ASSERT(io.buf == NULL && io.len == 0 && io.size == 0);

  return NULL;
}
Пример #4
0
static void test_empty()
{
	struct iobuf *buf = iobuf_new();
	TEST_ASSERT(iobuf_rstart(buf) == NULL);
	TEST_ASSERT(iobuf_rsize(buf) == 0);
	TEST_ASSERT(iobuf_wstart(buf) == NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 0);

	iobuf_drain(buf, 0);
	TEST_ASSERT(iobuf_rstart(buf) == NULL);
	TEST_ASSERT(iobuf_rsize(buf) == 0);
	TEST_ASSERT(iobuf_wstart(buf) == NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 0);

	iobuf_reserve(buf, 0);
	TEST_ASSERT(iobuf_rstart(buf) == NULL);
	TEST_ASSERT(iobuf_rsize(buf) == 0);
	TEST_ASSERT(iobuf_wstart(buf) == NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 0);

	iobuf_fill(buf, 0);
	TEST_ASSERT(iobuf_rstart(buf) == NULL);
	TEST_ASSERT(iobuf_rsize(buf) == 0);
	TEST_ASSERT(iobuf_wstart(buf) == NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 0);

	iobuf_free(buf);
}
Пример #5
0
static void test_preallocated()
{
	struct iobuf *buf = iobuf_new1(4096);
	TEST_ASSERT(iobuf_rstart(buf) != NULL);
	TEST_ASSERT(iobuf_rsize(buf) == 0);
	TEST_ASSERT(iobuf_wstart(buf) != NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 4096);

	size_t size = iobuf_wsize(buf);
	memset(iobuf_wstart(buf), 42, size);
	iobuf_fill(buf, size);

	TEST_ASSERT(iobuf_rstart(buf) != NULL);
	TEST_ASSERT(iobuf_rsize(buf) == 4096);
	TEST_ASSERT(iobuf_wstart(buf) != NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 0);

	char *rbuf = ((char *)iobuf_rstart(buf));
	for (size_t i = 0; i < 4096; ++i) {
		TEST_ASSERT(rbuf[i] == 42);
		TEST_ASSERT(iobuf_rsize(buf) >= 1);
		iobuf_drain(buf, 1);
	}

	TEST_ASSERT(iobuf_rsize(buf) == 0);
	TEST_ASSERT(iobuf_wsize(buf) == 4096);

	iobuf_free(buf);
}
Пример #6
0
static void test_one_byte()
{
	struct iobuf *buf = iobuf_new();

	iobuf_reserve(buf, 1);
	TEST_ASSERT(iobuf_rstart(buf) != NULL);
	TEST_ASSERT(iobuf_rsize(buf) == 0);
	TEST_ASSERT(iobuf_wstart(buf) != NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 1);

	*((char *)iobuf_wstart(buf)) = 42;
	iobuf_fill(buf, 1);
	TEST_ASSERT(iobuf_rstart(buf) != NULL);
	TEST_ASSERT(iobuf_rsize(buf) == 1);
	TEST_ASSERT(iobuf_wstart(buf) != NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 0);

	TEST_ASSERT(*((char *)iobuf_rstart(buf)) == 42);
	iobuf_drain(buf, 1);

	TEST_ASSERT(iobuf_rstart(buf) != NULL);
	TEST_ASSERT(iobuf_rsize(buf) == 0);
	TEST_ASSERT(iobuf_wstart(buf) != NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 1);

	iobuf_free(buf);
}
Пример #7
0
void uv_custom_poll_free(struct uv_custom_poll_t *data) {
	if(data->is_ssl == 1) {
		mbedtls_ssl_free(&data->ssl.ctx);
	}
	if(data->host != NULL) {
		FREE(data->host);
	}
	if(data->send_iobuf.size > 0) {
		iobuf_free(&data->send_iobuf);
	}
	if(data->recv_iobuf.size > 0) {
		iobuf_free(&data->recv_iobuf);
	}

	FREE(data);
}
Пример #8
0
static void test_random_access()
{
	struct fake_fd fd;
	fake_fd_init(&fd);
	char out[sizeof(fd.in)];
	memset(out, 0, sizeof(out));

	size_t read = 0;
	struct iobuf *buf = iobuf_new();
	for (;;) {
		iobuf_reserve(buf, 1024);
		TEST_ASSERT(iobuf_wsize(buf) >= 1024);
		ssize_t ret = fake_read(&fd, iobuf_wstart(buf), 1024);
		if (ret == 0) {
			break;
		}

		TEST_ASSERT(ret);
		read += ret;
	}

	TEST_ASSERT_EQUAL(sizeof(fd.in), read);

	iobuf_free(buf);
}
Пример #9
0
static void test_reserved()
{
	struct iobuf *buf = iobuf_new();
	iobuf_reserve(buf, 4096);
	TEST_ASSERT(iobuf_wstart(buf) != NULL);
	TEST_ASSERT(iobuf_wsize(buf) == 4096);
	iobuf_free(buf);
}
Пример #10
0
static void
httptr_free(struct httptr_req *treq)
{
    if (treq->sd != -1) {
        btpd_ev_del(&treq->ioev);
        close(treq->sd);
    }
    btpd_timer_del(&treq->timer);
    iobuf_free(&treq->buf);
    free(treq);
}
Пример #11
0
static int
write_buffer(struct cli *cli, struct iobuf *iob)
{
    int err = 0;
    if (!iob->error) {
        uint32_t len = iob->off;
        write_fully(cli->sd, &len, sizeof(len));
        err = write_fully(cli->sd, iob->buf, iob->off);
    } else
        btpd_err("Out of memory.\n");
    iobuf_free(iob);
    return err;
}
Пример #12
0
static const char *test_hexdump_file(void) {
  const char *path = "test_hexdump";
  const char *want =  "0xbeef :0 -> :0 3\n"
                      "0000  66 6f 6f   "
                      "                                      foo\n\n";
  char *data, *got;
  size_t size;
  struct ns_connection *nc = (struct ns_connection *) calloc(1, sizeof(*nc));

  /* "In the GNU system, non-null pointers are printed as unsigned integers,
   * as if a `%#x' conversion were used. Null pointers print as `(nil)'.
   * (Pointers might print differently in other systems.)"
   * indeed it prints 0x0 on apple.
   */
  nc->user_data = (void *)0xbeef;
  truncate(path, 0);

  iobuf_append(&nc->send_iobuf, "foo", 3);
  iobuf_append(&nc->recv_iobuf, "bar", 3);
  ns_hexdump_connection(nc, path, 3, NS_SEND);

  iobuf_free(&nc->send_iobuf);
  iobuf_free(&nc->recv_iobuf);
  free(nc);

  ASSERT((data = read_file(path, &size)) != NULL);
  unlink(path);

  got = data;
  while(got-data < (int)size && *got++ != ' ');
  size -= got-data;
  ASSERT(strncmp(got, want, size) == 0);

  free(data);
  return NULL;
}
Пример #13
0
int write_status(enum cntr_status cntr_status,
	const char *path, struct cntr *cntr)
{
	time_t now=0;
	time_t diff=0;
	static time_t lasttime=0;
	static size_t l=0;
	static struct iobuf *wbuf=NULL;

	if(!wasfd) return 0;
	if(!cntr || !cntr->bno)
		return 0;

	// Only update every 2 seconds.
	now=time(NULL);
	diff=now-lasttime;
	if(diff<2)
	{
		// Might as well do this in case they fiddled their
		// clock back in time.
		if(diff<0) lasttime=now;
		return 0;
	}
	lasttime=now;

	// Only get a new string if we did not manage to write the previous
	// one.
	if(!l)
	{
		cntr->cntr_status=cntr_status;
		if(!(l=cntr_to_str(cntr, path))) goto error;
		if(!wbuf && !(wbuf=iobuf_alloc())) goto error;
		iobuf_set(wbuf, CMD_APPEND, cntr->str, l);
	}

	switch(wasfd->append_all_to_write_buffer(wasfd, wbuf))
	{
		case APPEND_OK:
			l=0; // Fall through.
		case APPEND_BLOCKED:
			return 0;
		default:
			break;
	}
error:
	iobuf_free(&wbuf);
	return -1;
}
Пример #14
0
static void test_grow()
{
	struct iobuf *buf = iobuf_new();

	for (size_t i = 0; i < 4096; ++i) {
		iobuf_reserve(buf, i);
		TEST_ASSERT(iobuf_wsize(buf) == i);
	}

	for (size_t i = 4096; i != 0; --i) {
		iobuf_reserve(buf, i);
		TEST_ASSERT(iobuf_wsize(buf) == 4096);
	}

	iobuf_free(buf);
}
Пример #15
0
static void test_reclaim_full()
{
	struct iobuf *buf = iobuf_new();
	iobuf_reserve(buf, 4096);
	TEST_ASSERT(iobuf_wsize(buf) == 4096);
	memset(iobuf_wstart(buf), 1, 4096);
	iobuf_fill(buf, 4096);
	TEST_ASSERT(iobuf_wsize(buf) == 0);
	TEST_ASSERT(iobuf_rsize(buf) == 4096);
	TEST_ASSERT(memneq(iobuf_rstart(buf), 1, iobuf_rsize(buf)));
	iobuf_drain(buf, 2048);
	TEST_ASSERT(iobuf_wsize(buf) == 0);
	TEST_ASSERT(iobuf_rsize(buf) == 2048);
	iobuf_reserve(buf, 2048);
	TEST_ASSERT(iobuf_wsize(buf) == 2048);
	TEST_ASSERT(iobuf_rsize(buf) == 2048);
	TEST_ASSERT(memneq(iobuf_rstart(buf), 1, iobuf_rsize(buf)));
	iobuf_free(buf);
}
Пример #16
0
static void test_reclaim()
{
	struct iobuf *buf = iobuf_new();

	iobuf_reserve(buf, 4096);
	TEST_ASSERT(iobuf_wsize(buf) == 4096);
	memset(iobuf_wstart(buf), 1, 2048);
	iobuf_fill(buf, 2048);
	TEST_ASSERT(iobuf_wsize(buf) == 2048);
	TEST_ASSERT(iobuf_rsize(buf) == 2048);
	TEST_ASSERT(memneq(iobuf_rstart(buf), 1, iobuf_rsize(buf)));
	iobuf_drain(buf, 1024);
	TEST_ASSERT_EQUAL(2048, iobuf_wsize(buf));
	TEST_ASSERT_EQUAL(1024, iobuf_rsize(buf));
	iobuf_reserve(buf, 4096);
	TEST_ASSERT_EQUAL(4096, iobuf_wsize(buf));
	TEST_ASSERT_EQUAL(1024, iobuf_rsize(buf));
	TEST_ASSERT(memneq(iobuf_rstart(buf), 1, iobuf_rsize(buf)));

	iobuf_free(buf);
}
Пример #17
0
static void test_fill_drain()
{
	struct iobuf *buf = iobuf_new();

	iobuf_reserve(buf, 4096);
	TEST_ASSERT(iobuf_wsize(buf) == 4096);

	iobuf_fill(buf, 2048);
	TEST_ASSERT(iobuf_wsize(buf) == 2048);
	TEST_ASSERT(iobuf_rsize(buf) == 2048);
	iobuf_reserve(buf, 4096);
	TEST_ASSERT(iobuf_wsize(buf) == 4096);
	TEST_ASSERT(iobuf_rsize(buf) == 2048);
	iobuf_fill(buf, 2048);
	TEST_ASSERT(iobuf_wsize(buf) == 2048);
	TEST_ASSERT(iobuf_rsize(buf) == 4096);
	iobuf_drain(buf, 2048);
	TEST_ASSERT_EQUAL(2048, iobuf_wsize(buf));
	TEST_ASSERT(iobuf_rsize(buf) == 2048);
	iobuf_drain(buf, 2048);
	TEST_ASSERT_EQUAL(4096 + 2048, iobuf_wsize(buf));

	iobuf_free(buf);
}
Пример #18
0
int peer_kill(struct peer *p)
{
    if(!p)
        return 0;
    if(__sync_bool_compare_and_swap(&p->status,PEER_CONNECTED,PEER_DISCONNECTED))
    {
		close(p->sd);
		fdev_del(&p->ioev);
        log_error(p->ns->log,"ns peer socket closed,peer ip:%s.", inet_ntoa(p->addr.sin_addr));
		//push one msg to notify disconnect
        if(!p->ns->close_func)
        {
            struct msg_t *msg = (struct msg_t *)mmalloc(p->ns->allocator,
                    sizeof(struct msg_t));
            msg->buf = NULL;
            msg->len = 0;
            msg->peer_id = p->id;
            msg->type = MSG_DISCONNECT;

            queue_push(p->ns->recv_queue,msg);
            log_error(p->ns->log,"ns push notify msg for client:%s disconneced.", inet_ntoa(p->addr.sin_addr));
        }
        else
        {
            log_error(p->ns->log,"ns call close_func for client:%s disconneced.", inet_ntoa(p->addr.sin_addr));
            p->ns->close_func(p->ns,p->id);
        }
	}

	if(__sync_bool_compare_and_swap(&p->refcount,0,1))
	{
        log_error(p->ns->log,"ns peer freed,peer ip:%s.", inet_ntoa(p->addr.sin_addr));
		iobuf_free(p->allocator,&p->recvbuf);
		iobuf_free(p->allocator,&p->sendbuf);
		//free send queue
		struct msg_t *msg = NULL,*next = NULL;
		thread_mutex_lock(p->sq_mutex);
		msg = BTPDQ_FIRST(&p->send_queue);
		while(msg){
			next = BTPDQ_NEXT(msg,msg_entry);
			BTPDQ_REMOVE(&p->send_queue,msg,msg_entry);

			mfree(p->allocator,msg->buf);
			mfree(p->allocator,msg);
			msg = next;
		}
		thread_mutex_unlock(p->sq_mutex);

		thread_mutex_destroy(p->mpool_mutex);
		thread_mutex_destroy(p->sq_mutex);

		allocator_destroy(p->allocator);

		mfree(p->ns->allocator,p);

		thread_mutex_lock(p->ns->ptbl_mutex);
		ptbl_remove(p->ns->ptbl,&p->id);
		p->ns->npeers--;
		thread_mutex_unlock(p->ns->ptbl_mutex);
	}
	return 0;
}
Пример #19
0
static int
cmd_tget(struct cli *cli, int argc, const char *args)
{
    if (argc != 1 || !benc_isdct(args))
        return IPC_COMMERR;

    size_t nkeys;
    const char *keys, *p;
    enum ipc_tval *opts;
    struct iobuf iob;

    if ((keys = benc_dget_lst(args, "keys")) == NULL)
        return IPC_COMMERR;

    nkeys = benc_nelems(keys);
    opts = btpd_calloc(nkeys, sizeof(*opts));

    p = benc_first(keys);
    for (int i = 0; i < nkeys; i++)
        opts[i] = benc_int(p, &p);

    iob = iobuf_init(1 << 15);
    iobuf_swrite(&iob, "d4:codei0e6:resultl");
    p = benc_dget_any(args, "from");
    if (benc_isint(p)) {
        enum ipc_twc from = benc_int(p, NULL);
        struct htbl_iter it;
        struct tlib *tl;
        for (tl = tlib_iter_first(&it); tl != NULL; tl = tlib_iter_next(&it)) {
            if (!torrent_haunting(tl) && (
                    from == IPC_TWC_ALL ||
                    (!torrent_active(tl) && from == IPC_TWC_INACTIVE) ||
                    (torrent_active(tl) && from == IPC_TWC_ACTIVE))) {
                iobuf_swrite(&iob, "l");
                for (int k = 0; k < nkeys; k++)
                    write_ans(&iob, tl, opts[k]);
                iobuf_swrite(&iob, "e");
            }
        }
    } else if (benc_islst(p)) {
        for (p = benc_first(p); p != NULL; p = benc_next(p)) {
            struct tlib *tl = NULL;
            if (benc_isint(p))
                tl = tlib_by_num(benc_int(p, NULL));
            else if (benc_isstr(p) && benc_strlen(p) == 20)
                tl = tlib_by_hash(benc_mem(p, NULL, NULL));
            else {
                iobuf_free(&iob);
                free(opts);
                return IPC_COMMERR;
            }
            if (tl != NULL && !torrent_haunting(tl)) {
                iobuf_swrite(&iob, "l");
                for (int i = 0; i < nkeys; i++)
                    write_ans(&iob, tl, opts[i]);
                iobuf_swrite(&iob, "e");
            } else
                iobuf_print(&iob, "i%de", IPC_ENOTENT);
        }
    }
    iobuf_swrite(&iob, "ee");
    free(opts);
    return write_buffer(cli, &iob);
}
Пример #20
0
int backup_phase2_client_burp2(struct asfd *asfd, struct conf *conf, int resume)
{
	int ret=-1;
	int sigs_end=0;
	int backup_end=0;
	int requests_end=0;
	int blk_requests_end=0;
	struct win *win=NULL; // Rabin sliding window.
	struct slist *slist=NULL;
	struct blist *blist=NULL;
	struct iobuf *rbuf=NULL;
	struct iobuf *wbuf=NULL;

	logp("Phase 2 begin (send backup data)\n");

	if(!(slist=slist_alloc())
	  || !(blist=blist_alloc())
	  || !(wbuf=iobuf_alloc())
	  || blks_generate_init(conf)
	  || !(win=win_alloc(&conf->rconf)))
		goto end;
	rbuf=asfd->rbuf;

	if(!resume)
	{
		// Only do this bit if the server did not tell us to resume.
		if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
		  || asfd->read_expect(asfd, CMD_GEN, "ok"))
			goto end;
	}
	else if(conf->send_client_cntr)
	{
		// On resume, the server might update the client with the
		// counters.
		if(cntr_recv(asfd, conf))
			goto end;
        }

	while(!backup_end)
	{
		if(!wbuf->len)
		{
			get_wbuf_from_data(conf, wbuf, slist, blist,
				blk_requests_end);
			if(!wbuf->len)
			{
				get_wbuf_from_blks(wbuf, slist,
					requests_end, &sigs_end);
			}
		}

		if(wbuf->len)
			asfd->append_all_to_write_buffer(asfd, wbuf);
		if(asfd->as->read_write(asfd->as))
		{
			logp("error in %s\n", __func__);
			goto end;
		}

		if(rbuf->buf && deal_with_read(rbuf, slist, blist,
			conf, &backup_end, &requests_end, &blk_requests_end))
				goto end;

		if(slist->head
		// Need to limit how many blocks are allocated at once.
		  && (!blist->head
		   || blist->tail->index - blist->head->index<BLKS_MAX_IN_MEM)
		)
		{
			if(add_to_blks_list(asfd, conf, slist, blist, win))
				goto end;
		}

		if(blk_requests_end)
		{
			// If got to the end of the file request list
			// and the last block of the last file, and
			// the write buffer is empty, we got to the end.
			if(slist->head==slist->tail)
			{
				if(!slist->tail
				  || blist->last_sent==slist->tail->burp2->bend)
				{
					if(!wbuf->len)
						break;
				}
			}

		}
	}

	if(asfd->write_str(asfd, CMD_GEN, "backup_end"))
		goto end;

	ret=0;
end:
blk_print_alloc_stats();
//sbuf_print_alloc_stats();
	win_free(win);
	slist_free(&slist);
	blist_free(&blist);
	// Write buffer did not allocate 'buf'.
	wbuf->buf=NULL;
	iobuf_free(&wbuf);

	cntr_print_end(conf->cntr);
	cntr_print(conf->cntr, ACTION_BACKUP);
	if(ret) logp("Error in backup\n");
	logp("End backup\n");

	return ret;
}
Пример #21
0
int backup_phase2_server(struct async *as, struct sdirs *sdirs,
	const char *manifest_dir, int resume, struct conf *conf)
{
	int ret=-1;
	int sigs_end=0;
	int backup_end=0;
	int requests_end=0;
	int blk_requests_end=0;
	struct slist *slist=NULL;
	struct blist *blist=NULL;
	struct iobuf *wbuf=NULL;
	struct dpth *dpth=NULL;
	struct manio *cmanio=NULL;	// current manifest
	struct manio *p1manio=NULL;	// phase1 scan manifest
	struct manio *chmanio=NULL;	// changed manifest
	struct manio *unmanio=NULL;	// unchanged manifest
	// This is used to tell the client that a number of consecutive blocks
	// have been found and can be freed.
	uint64_t wrap_up=0;
	// Main fd is first in the list.
	struct asfd *asfd=as->asfd;
	// Champ chooser fd is second in the list.
	struct asfd *chfd=asfd->next;

	logp("Phase 2 begin (recv backup data)\n");

	//if(champ_chooser_init(sdirs->data, conf)
	if(!(cmanio=manio_alloc())
	  || !(p1manio=manio_alloc())
	  || !(chmanio=manio_alloc())
	  || !(unmanio=manio_alloc())
	  || manio_init_read(cmanio, sdirs->cmanifest)
	  || manio_init_read(p1manio, sdirs->phase1data)
	  || manio_init_write(chmanio, sdirs->changed)
	  || manio_init_write(unmanio, sdirs->unchanged)
	  || !(slist=slist_alloc())
	  || !(blist=blist_alloc())
	  || !(wbuf=iobuf_alloc())
	  || !(dpth=dpth_alloc(sdirs->data))
	  || dpth_init(dpth))
		goto end;

	// The phase1 manifest looks the same as a burp1 one.
	manio_set_protocol(p1manio, PROTO_BURP1);

	while(!backup_end)
	{
		if(maybe_add_from_scan(asfd,
			p1manio, cmanio, unmanio, slist, conf))
				goto end;

		if(!wbuf->len)
		{
			if(get_wbuf_from_sigs(wbuf, slist, blist,
			  sigs_end, &blk_requests_end, dpth, conf))
				goto end;
			if(!wbuf->len)
			{
				get_wbuf_from_files(wbuf, slist,
					p1manio, &requests_end);
			}
		}

		if(wbuf->len)
			asfd->append_all_to_write_buffer(asfd, wbuf);

		append_for_champ_chooser(chfd, blist, sigs_end);

		if(as->read_write(as))
		{
			logp("error in %s\n", __func__);
			goto end;
		}

		while(asfd->rbuf->buf)
		{
			if(deal_with_read(asfd->rbuf, slist, blist,
				conf, &sigs_end, &backup_end, dpth))
					goto end;
			// Get as much out of the
			// readbuf as possible.
			if(asfd->parse_readbuf(asfd)) goto end;
		}
		while(chfd->rbuf->buf)
		{
			if(deal_with_read_from_chfd(asfd, chfd,
				blist, &wrap_up, dpth)) goto end;
			// Get as much out of the
			// readbuf as possible.
			if(chfd->parse_readbuf(chfd)) goto end;
		}

		if(write_to_changed_file(asfd, chfd, chmanio,
			slist, blist, dpth, backup_end, conf))
				goto end;
	}

	// Hack: If there are some entries left after the last entry that
	// contains block data, it will not be written to the changed file
	// yet because the last entry of block data has not had
	// sb->burp2->bend set.
	if(slist->head && slist->head->next)
	{
		slist->head=slist->head->next;
		if(write_to_changed_file(asfd, chfd, chmanio,
			slist, blist, dpth, backup_end, conf))
				goto end;
	}

	if(manio_close(unmanio)
	  || manio_close(chmanio))
		goto end;

	if(blist->head)
	{
		logp("ERROR: finishing but still want block: %lu\n",
			blist->head->index);
		goto end;
	}

	// Need to release the last left. There should be one at most.
	if(dpth->head && dpth->head->next)
	{
		logp("ERROR: More data locks remaining after: %s\n",
			dpth->head->save_path);
		goto end;
	}
	if(dpth_release_all(dpth)) goto end;

	ret=0;
end:
	logp("End backup\n");
	slist_free(slist);
	blist_free(blist);
	iobuf_free_content(asfd->rbuf);
	iobuf_free_content(chfd->rbuf);
	// Write buffer did not allocate 'buf'. 
	if(wbuf) wbuf->buf=NULL;
	iobuf_free(wbuf);
	dpth_release_all(dpth);
	dpth_free(&dpth);
	manio_free(&cmanio);
	manio_free(&p1manio);
	manio_free(&chmanio);
	manio_free(&unmanio);
	return ret;
}
Пример #22
0
// Return p1manio position.
static man_off_t *do_resume_work(struct sdirs *sdirs,
                                 struct dpth *dpth, struct conf **cconfs)
{
    man_off_t *pos=NULL;
    man_off_t *p1pos=NULL;
    struct iobuf *chb=NULL;
    struct manio *cmanio=NULL;
    struct manio *umanio=NULL;
    struct manio *p1manio=NULL;
    enum protocol protocol=get_protocol(cconfs);
    struct cntr *cntr=get_cntr(cconfs);
    int compression=get_int(cconfs[OPT_COMPRESSION]);

    if(!(p1manio=manio_open_phase1(sdirs->phase1data, "rb", protocol))
            || !(cmanio=manio_open_phase2(sdirs->changed, "rb", protocol))
            || !(umanio=manio_open_phase2(sdirs->unchanged, "rb", protocol)))
        goto end;

    if(!(chb=iobuf_alloc()))
        return NULL;

    logp("Setting up resume positions...\n");

    if(get_last_good_entry(cmanio, chb, cntr, dpth, protocol, &pos))
        goto error;
    if(manio_close_and_truncate(&cmanio, pos, compression)) goto error;
    man_off_t_free(&pos);
    if(chb->buf)
    {
        logp("  last good entry:    %s\n", chb->buf);
        // Now need to go to the appropriate places in p1manio and
        // unchanged.
        if(forward_past_entry(p1manio, chb, protocol, &p1pos))
            goto error;

        // The unchanged file needs to be positioned just before the
        // found entry, otherwise it ends up having a duplicated entry.
        if(forward_before_entry(umanio,
                                chb, cntr, dpth, protocol, &pos))
            goto error;
        if(manio_close_and_truncate(&umanio, pos, compression))
            goto error;
        man_off_t_free(&pos);
    }
    else
    {
        logp("  nothing previously transferred\n");
        if(!(p1pos=manio_tell(p1manio)))
            goto error;
        if(!(pos=manio_tell(umanio)))
            goto error;
        if(manio_close_and_truncate(&umanio, pos, compression))
            goto error;
    }

    // Now should have all file pointers in the right places to resume.

    goto end;
error:
    man_off_t_free(&p1pos);
end:
    iobuf_free(&chb);
    man_off_t_free(&pos);
    manio_close(&p1manio);
    manio_close(&cmanio);
    manio_close(&umanio);
    return p1pos;
}
Пример #23
0
int backup_phase2_client_protocol2(struct asfd *asfd,
	struct conf **confs, int resume)
{
	int ret=-1;
	uint8_t end_flags=0;
	struct slist *slist=NULL;
	struct iobuf *rbuf=NULL;
	struct iobuf *wbuf=NULL;
	struct cntr *cntr=NULL;

	if(confs) cntr=get_cntr(confs);

	if(!asfd || !asfd->as)
	{
		logp("%s() called without async structs!\n", __func__);
		goto end;
	}

	logp("Phase 2 begin (send backup data)\n");
	logfmt("\n");

	if(!(slist=slist_alloc())
	  || !(wbuf=iobuf_alloc())
	  || blks_generate_init())
		goto end;
	rbuf=asfd->rbuf;

	if(!resume)
	{
		// Only do this bit if the server did not tell us to resume.
		if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
		  || asfd_read_expect(asfd, CMD_GEN, "ok"))
			goto end;
	}
	else
	{
		// On resume, the server might update the client with cntr.
		if(cntr_recv(asfd, confs))
			goto end;
        }

	while(!(end_flags&END_BACKUP))
	{
		if(!wbuf->len)
		{
			get_wbuf_from_data(confs, wbuf, slist,
				end_flags);
			if(!wbuf->len)
			{
				if(get_wbuf_from_blks(wbuf, slist,
					&end_flags)) goto end;
			}
		}

		if(wbuf->len)
		{
			if(asfd->append_all_to_write_buffer(asfd, wbuf)
				==APPEND_ERROR)
					goto end;
		}
		if(asfd->as->read_write(asfd->as))
		{
			logp("error in %s\n", __func__);
			goto end;
		}

		if(rbuf->buf && deal_with_read(rbuf, slist, cntr, &end_flags))
			goto end;

		if(slist->head
		// Need to limit how many blocks are allocated at once.
		  && (!slist->blist->head
		   || slist->blist->tail->index
			- slist->blist->head->index<BLKS_MAX_IN_MEM)
		)
		{
			if(add_to_blks_list(asfd, confs, slist))
				goto end;
		}

		if(end_flags&END_BLK_REQUESTS)
		{
			// If got to the end of the file request list
			// and the last block of the last file, and
			// the write buffer is empty, we got to the end.
			if(slist->head==slist->tail)
			{
				if(!slist->tail
				  || slist->blist->last_sent==
					slist->tail->protocol2->bend)
				{
					if(!wbuf->len)
						break;
				}
			}

		}
	}

	if(asfd->write_str(asfd, CMD_GEN, "backup_end"))
		goto end;

	ret=0;
end:
	slist_free(&slist);
	blks_generate_free();
	if(wbuf)
	{
		// Write buffer did not allocate 'buf'.
		wbuf->buf=NULL;
		iobuf_free(&wbuf);
	}
	cntr_print_end(cntr);
	cntr_print(cntr, ACTION_BACKUP, asfd);
	if(ret) logp("Error in backup\n");
	logp("End backup\n");

	return ret;
}
Пример #24
0
void
cmd_add(int argc, char **argv)
{
    int ch, topdir = 0, start = 1, nfile, nloaded = 0;
    size_t dirlen = 0, labellen = 0;
    char *dir = NULL, *name = NULL, *glabel = NULL, *label;

    while ((ch = getopt_long(argc, argv, "NTd:l:n:", add_opts, NULL)) != -1) {
        switch (ch) {
        case 'N':
            start = 0;
            break;
        case 'T':
            topdir = 1;
            break;
        case 'd':
            dir = optarg;
            if ((dirlen = strlen(dir)) == 0)
                diemsg("bad option value for -d.\n");
            break;
        case 'l':
            glabel = optarg;
            if ((labellen = strlen(dir)) == 0)
                diemsg("bad option value for -l.\n");
            break;
        case 'n':
            name = optarg;
            break;
        default:
            usage_add();
        }
    }
    argc -= optind;
    argv += optind;

    if (argc < 1 || dir == NULL)
        usage_add();

    btpd_connect();
    char *mi;
    size_t mi_size;
    enum ipc_err code;
    char dpath[PATH_MAX];
    struct iobuf iob;

    for (nfile = 0; nfile < argc; nfile++) {
       if ((mi = mi_load(argv[nfile], &mi_size)) == NULL) {
           fprintf(stderr, "error loading '%s' (%s).\n", argv[nfile], strerror(errno));
           continue;
       }
       iob = iobuf_init(PATH_MAX);
       iobuf_write(&iob, dir, dirlen);
       if (topdir && !mi_simple(mi)) {
           size_t tdlen;
           const char *td =
               benc_dget_mem(benc_dget_dct(mi, "info"), "name", &tdlen);
           iobuf_swrite(&iob, "/");
           iobuf_write(&iob, td, tdlen);
       }
       iobuf_swrite(&iob, "\0");
       if ((errno = make_abs_path(iob.buf, dpath)) != 0) {
           fprintf(stderr, "make_abs_path '%s' failed (%s).\n", dpath, strerror(errno));
           iobuf_free(&iob);
           continue;
       }
       if(NULL == glabel)
          label = benc_dget_str(mi, "announce", NULL);
       else
          label = glabel;
       code = btpd_add(ipc, mi, mi_size, dpath, name, label);
       if ((code == IPC_OK) && start) {
           struct ipc_torrent tspec;
           tspec.by_hash = 1;
           mi_info_hash(mi, tspec.u.hash);
           code = btpd_start(ipc, &tspec);
       }
       if (code != IPC_OK) {
           fprintf(stderr, "command failed for '%s' (%s).\n", argv[nfile], ipc_strerror(code));
       } else {
           nloaded++;
       }
       iobuf_free(&iob);
    }

    if (nloaded != nfile) {
       diemsg("error loaded %d of %d files.\n", nloaded, nfile);
    }
}
Пример #25
0
int autoupgrade_client(struct async *as, struct conf *conf)
{
	int a=0;
	int ret=-1;
	char *cp=NULL;
	char *copy=NULL;
	char *script_path=NULL;
	char script_name[32]="";
	char package_name[32]="";
	char write_str[256]="";
	const char *args[2];
	struct iobuf *rbuf=NULL;
	struct asfd *asfd;
	asfd=as->asfd;

	if(!conf->autoupgrade_dir)
	{
		logp("autoupgrade_dir not set!\n");
		goto end;
	}
	if(!conf->autoupgrade_os)
	{
		logp("autoupgrade_os not set!\n");
		goto end;
	}
	if(!(copy=strdup(conf->autoupgrade_dir)))
	{
		log_out_of_memory(__func__);
		goto end;
	}

	strip_trailing_slashes(&copy);
	if((cp=strchr(copy, '/'))) *cp='\0';
	if(mkpath(&(conf->autoupgrade_dir), copy))
		goto end;

	// Let the server know we are ready.
	snprintf(write_str, sizeof(write_str),
		"autoupgrade:%s", conf->autoupgrade_os);
	if(asfd->write_str(asfd, CMD_GEN, write_str))
		goto end;

	if(!(a=asfd->simple_loop(asfd,
		conf, NULL, __func__, autoupgrade_func)))
	{
		ret=0; // No autoupgrade.
		goto end;
	}
	else if(a<0) // Error.

#ifdef HAVE_WIN32
	win32_enable_backup_privileges();
	snprintf(script_name, sizeof(script_name), "script.bat");
	snprintf(package_name, sizeof(package_name), "package.exe");
#else
	snprintf(script_name, sizeof(script_name), "script");
	snprintf(package_name, sizeof(package_name), "package");
#endif

	if(receive_file(asfd, conf->autoupgrade_dir, script_name, conf))
	{
		logp("Problem receiving %s/%s\n",
			conf->autoupgrade_dir, script_name);
		goto end;
	}
	if(receive_file(asfd, conf->autoupgrade_dir, package_name, conf))
	{
		logp("Problem receiving %s/%s\n",
			conf->autoupgrade_dir, package_name);
		goto end;
	}

	if(!(script_path=prepend_s(conf->autoupgrade_dir, script_name)))
		goto end;

	chmod(script_path, 0755);

	/* Run the script here. */
	a=0;
	args[a++]=script_path;
	args[a++]=NULL;
	ret=run_script(asfd, args, NULL, conf,
		0 /* do not wait */, 1 /* use logp */, 1 /* use logw */);
	/* To get round Windows problems to do with installing over files
	   that the current process is running from, I am forking the child,
	   then immediately exiting the parent process. */

	printf("\n");
	logp("The server tried to upgrade your client.\n");
	logp("You will need to try your command again.\n");
	asfd_free(&as->asfd);

	exit(0);
end:
	if(copy) free(copy);
	if(script_path) free(script_path);
	iobuf_free(rbuf);
	return ret;
}