void ipc_init(void) { int sd; struct sockaddr_un addr; size_t psiz = sizeof(addr.sun_path); addr.sun_family = PF_UNIX; if (snprintf(addr.sun_path, psiz, "%s/sock", btpd_dir) >= psiz) btpd_err("'%s/sock' is too long.\n", btpd_dir); if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) btpd_err("sock: %s\n", strerror(errno)); if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { if (errno == EADDRINUSE) { unlink(addr.sun_path); if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) btpd_err("bind: %s\n", strerror(errno)); } else btpd_err("bind: %s\n", strerror(errno)); } if (chmod(addr.sun_path, ipcprot) == -1) btpd_err("chmod: %s (%s).\n", addr.sun_path, strerror(errno)); listen(sd, 4); set_nonblocking(sd); btpd_ev_new(&m_cli_incoming, sd, EV_READ, client_connection_cb, NULL); m_listen_sd = sd; }
static void nc_connect(struct nameconn *nc) { struct addrinfo *ai; int err; again: if ((ai = nc->ai_cur) == NULL) { nc_done(nc, -1); return; } if ((nc->sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) btpd_err("Failed to create socket (%s).\r\n", strerror(errno)); set_nonblocking(nc->sd); err = connect(nc->sd, ai->ai_addr, ai->ai_addrlen); if (err == 0) nc_done(nc, 0); else if (err == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) btpd_ev_new(&nc->write_ev, nc->sd, EV_WRITE, nc_write_cb, nc); else { closesocket(nc->sd); nc->ai_cur = ai->ai_next; goto again; } }
static void http_cb(struct http_req *req, struct http_response *res, void *arg) { struct httptr_req *treq = arg; struct tr_response tres = {0, NULL, -1 }; switch (res->type) { case HTTP_T_ERR: tres.type = TR_RES_BAD; tr_result(treq->tr, &tres); httptr_free(treq); break; case HTTP_T_DATA: if (treq->buf.off + res->v.data.l > MAX_DOWNLOAD) { tres.type = TR_RES_BAD; tr_result(treq->tr, &tres); httptr_cancel(treq); break; } if (!iobuf_write(&treq->buf, res->v.data.p, res->v.data.l)) btpd_err("Out of memory.\n"); break; case HTTP_T_DONE: if (treq->event == TR_EV_STOPPED) { tres.type = TR_RES_OK; tr_result(treq->tr, &tres); } else { parse_reply(treq->tp, &tres, treq->buf.buf, treq->buf.off); tr_result(treq->tr, &tres); } httptr_free(treq); break; default: break; } }
void client_connection_cb(int sd, short type, void *arg) { int nsd; if ((nsd = accept(sd, NULL, NULL)) < 0) { if (errno == EWOULDBLOCK || errno == ECONNABORTED) return; else btpd_err("client accept: %s\n", strerror(errno)); } if ((errno = set_blocking(nsd)) != 0) btpd_err("set_blocking: %s.\n", strerror(errno)); struct cli *cli = btpd_calloc(1, sizeof(*cli)); cli->sd = nsd; btpd_ev_new(&cli->read, cli->sd, EV_READ, cli_read_cb, cli); }
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; }
static void nc_write_cb(int sd, short type, void *arg) { struct nameconn *nc = arg; int error; socklen_t errsiz = sizeof(int); if (getsockopt(nc->sd, SOL_SOCKET, SO_ERROR, &error, &errsiz) < 0) btpd_err("getsockopt error (%s).\r\n", strerror(errno)); if (error == 0) { btpd_ev_del(&nc->write_ev); nc_done(nc, 0); } else { btpd_ev_del(&nc->write_ev); closesocket(nc->sd); nc->ai_cur = nc->ai_cur->ai_next; nc_connect(nc); } }
static int cmd_start_all(struct cli *cli, int argc, const char *args) { struct htbl_iter it; struct tlib *tl; enum ipc_err last_code, ret_code= IPC_OK; if (btpd_is_stopping()) return write_code_buffer(cli, IPC_ESHUTDOWN); for (tl = tlib_iter_first(&it); tl != NULL; tl = tlib_iter_next(&it)) { if (torrent_startable(tl)) { if ((last_code = torrent_start(tl)) == IPC_OK) { active_add(tl->hash); } else { btpd_err("torrent_start(%d) failed.\n", tl->num); ret_code = last_code; } } } return write_code_buffer(cli, ret_code); }