📄 event.c
字号:
list_find(task, down, !strcasecmp(task->nick, nm) && !strcasecmp(task->rfn, rfn) && task->state==WAITING); fn = ud_basename(rfn); /* note: fn is a pointer into rfn! Do not free rfn while fn is still needed. */ if (!size) { rsock(m->fd, &buf); wp(win, "* Error downloading \"%s\" from %s (returned a size of 0) " \ "[%s]\n", fn, nm, buf?quote(buf):""); drw(win); if (task) { free(task->check); task->state = FAILED; task->d_time = time(0); } free(rfn); free(nm); delsock(m->fd); return(1); } if (!task) { /* this error is frequently the result of a download request which timed out before the remote client got in touch with us. We omit the error message, since it is confusing and not useful */ /* wp(win, "%s* Error: %s tried to send (push) \"%s\", but we did not request it!%s\n", RED, nm, fn, WHITE); drw(win); */ free(nm); free(rfn); delsock(m->fd); return(1); } /* try to open local file for this download */ r = opendownloadfile(fn, &f, &lfn); if (r==-1) { wp(win, ""RED"* Error: could not open local file \"%s\": %s"WHITE"\n", lfn, strerror(errno)); drw(win); free(lfn); } if (r==-1 || r==-2) { free(nm); free(rfn); free(task->check); task->state = FAILED; task->d_time = time(0); delsock(m->fd); return(1); } free(nm); free(rfn); task->sk = m; task->lfn = lfn; task->f = f; task->size = size; task->bsz = 0; task->pos = 0; task->p_time = time(0); task->state = IN_PROGRESS; /* rename connection from "conn" to "d #", and connect it to this task */ free(m->socknm); m->socknm = strdup(gnum(0)); m->dtask = task; m->bwlimit = 1; bandwidth_init(&m->bw); m->func = gfile; sv = findsock("server"); if (sv) sendpack(sv->fd, NAP_DOWN, NULL); /* send offset */ ssock(m->fd, "%lu", (long)0); return(1);}/* try to open a port that is specified by the string dataport. Dataport must either be a port number such as "6699" or a range such as "6699-6799". Return port number used if successful, or -1 if failure (with errno set). If port 0 is requested, return 0 without opening anything - this probably was configured by the user if we're behind a firewall. */int initfserv(char *dataport){ struct sockaddr_in me; int s, on = 1; int port, first, last; char *p; if (!dataport) return(0); /* parse dataport */ first = last = strtol(dataport, &p, 10); while (p && isspace(*p)) { p++; } if (p && *p=='-') { /* range given? parse second part */ last = strtol(p+1, &p, 10); } if (!p || *p!='\0') { /* parse error */ errno = EINVAL; return -1; } s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) return(-1); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); setkeepalive(s); for (port = first; port <= last; port++) { me.sin_addr.s_addr = INADDR_ANY; me.sin_port = htons(port); me.sin_family = AF_INET; if (bind(s, (struct sockaddr *)&me, sizeof(me)) != -1) { /* success */ listen(s, 5); addsock(s, "fserv", S_R, gconn); return(port); } } return(-1); /* overall failure */}void closefserv(){ sock_t *sk; sk = findsock("fserv"); if (!sk) return; delsock(sk->fd);}/* We are about to upload a file to a remote client. We had to initiate * the connection because we are firewalled and cannot accept incoming * connections. The upload is in state CONNECTING. */int initsend(WINDOW *win, sock_t *m){ int s = m->fd, r; upload_t *task = m->utask; sock_t *sk; struct stat st; char c; FILE *f; /* read the initial "1" from remote client */ if (recv(s, &c, 1, 0) <= 0) { wp(win, "%s* Error sending file \"%s\" to %s: connection refused by remote client%s\n", RED, task->fn, task->nick, WHITE); drw(win); task->state=FAILED; task->d_time = time(0); delsock(m->fd); return(1); } /* Open the local file for reading. Note: we already checked that this file was in the shared library before we created this task. Thus, the local file *should* exist. However, it might be unreadable, or the library might be out of date. */ f = fopen(task->lfn, "rb"); if (!f) { wp(win, ""RED"* \"%s\" not found (requested by %s)"WHITE"\n", task->lfn, task->nick); drw(win); task->state=FAILED; task->d_time = time(0); delsock(m->fd); return(1); } /* determine file size */ fstat(fileno(f), &st); r = ssock(s, "SEND"); /* send "mynick filename filesize" */ r = ssock(s, "%s \"%s\" %lu", info.user, task->rfn, st.st_size); if (r <= 0) { wp(win, ""RED"* Error sending file (%s) to %s: %s%s"WHITE"", RED, task->rfn, task->nick, r ? strerror(errno) : "remote client is misconfigured"); drw(win); sk = findsock("server"); if (sk) sendpack(sk->fd, NAP_MISCONFIGURE, "%s", task->nick); fclose(f); task->state=FAILED; task->d_time = time(0); delsock(m->fd); return(1); } /* go to state CONNECTING1, continue with ssize() */ task->state = CONNECTING1; task->f = f; task->size = st.st_size; m->func = ssize; m->t = S_R; return(1);}/* continue what was started by initsend. Next the remote (firewalled) client will send the byte offset. Upload's state is CONNECTING1. */int ssize(WINDOW *win, sock_t *m){ char buf[32]; int r; upload_t *task = m->utask; size_t bsz; memset(buf, 0, 32); r = recv(m->fd, buf, sizeof(buf), 0); if (r<=0) { wp(win, ""RED"* Error sending file \"%s\" to %s: %s"WHITE"\n", task->fn, task->nick, r ? strerror(errno) : "did not receive a proper offset"); drw(win); fclose(task->f); task->state = FAILED; task->d_time = time(0); delsock(m->fd); return(1); } bsz = strtoul(buf, 0, 10); if (bsz > task->size) { wp(win, ""RED"* Error sending file \"%s\" to %s: illegal offset requested (%lu/%lu)"WHITE"\n", task->fn, task->nick, (long)bsz, (long)task->size); drw(win); fclose(task->f); task->state = FAILED; task->d_time = time(0); delsock(m->fd); return(1); } fseek(task->f, bsz, SEEK_SET); /* go to state IN_PROGRESS */ task->bsz = bsz; task->pos = bsz; task->p_time = time(0); task->state = IN_PROGRESS; m->bwlimit = 1; bandwidth_init(&m->bw); m->func = sfile; m->t = S_W; wp(win, "* Sending file \"%s\" to %s (%lu bytes)\n", task->fn, task->nick, (long)(task->size - bsz)); drw(win); return(1);}/* we have connected to a remote client and we are about to issue a request * for a file */int initget(WINDOW *win, sock_t *m){ int s = m->fd, r; download_t *task = m->dtask; /* state of task is CONNECTING */ download_t *elt; sock_t *sk; char ch; /* remote client should send a '1' (ASCII character 49) */ r = recv(s, &ch, 1, 0); if (r <= 0) { wp(win, "%s* Error getting file (%s) from %s: %s%s\n", RED, task->fn, task->nick, r ? strerror(errno) : "connection refused", WHITE); drw(win); free(task->check); task->state = FAILED; task->d_time = time(0); delsock(m->fd); return(1); } /* make sure the task is not stale */ list_find(elt, down, elt==task); if (!elt) { delsock(m->fd); return(1); } r = ssock(s, "GET"); r = ssock(s, "%s \"%s\" %lu", info.user, task->rfn, (long)0); if (r <= 0) { wp(win, "%s* Error getting file (%s) from %s: %s%s\n", RED, task->fn, task->nick, r ? strerror(errno) : "remote client misconfigured", WHITE); drw(win); sk = findsock("server"); if (sk) sendpack(sk->fd, NAP_MISCONFIGURE, "%s", task->nick); free(task->check); task->state = FAILED; task->d_time = time(0); delsock(m->fd); return(1); } m->func = gsize; /* m->t = S_R; */ return(1);}/* continue the GET started by initget, now receive remote host's answer */int gsize(WINDOW *win, sock_t *m){ char buf[32]; int i, s = m->fd; download_t *task = m->dtask; /* state is still CONNECTING */ sock_t *sk; int r; FILE *f; char *lfn; /* read file size. drscholl's napster spec says: * "keep reading until you hit a character that is not a digit" */ for (i=0; i<31; i++) /* but don't overflow buf[] ! */ { r = recv(s, &buf[i], 1, MSG_PEEK); if (r <= 0 && !i) { wp(win, "%s* Error getting file (%s) from %s: %s%s\n", RED, task->fn, task->nick, r ? strerror(errno) : "remote client misconfigured", WHITE); drw(win); sk = findsock("server"); if (sk) sendpack(sk->fd, NAP_MISCONFIGURE, "%s", task->nick); free(task->check); task->state = FAILED; task->d_time = time(0); delsock(m->fd); return(1); } /* abort only if first character is not a digit. * this catches messages such as "INVALID REQUEST" or "FILE NOT SHARED" * but does not barf on ID3 tags that follow the file size. * (Before, an error was signaled if an alphabetic character * followed 0 or more numeric characters. This caused a problem with * mp3 files that start with ID3 tags.) -NBL */ if (!isdigit(buf[i]) && (i == 0)) { recv(s, buf, 32, 0); buf[31]=0; /* make sure it's 0 terminated */ wp(win, ""RED"* Error getting \"%s\" from %s [%s]"WHITE"\n", task->fn, task->nick, quote(buf)); drw(win); free(task->check); task->state = FAILED; task->d_time = time(0); delsock(m->fd); return(1); } if (!isdigit(buf[i])) break; recv(s, &buf[i], 1, 0); } /* get rid of the non-digit that was just read * (or if i reached 31, make sure that buf[] is '\0'-terminated) */ buf[i] = '\0'; /* we need the debugging code here, since we didn't call rsock for this */ if (nvar("debug") == 2) { wp(win, ""DARK GREEN"<-- [from %d=%s] <%s>"WHITE"\n", s, m->socknm, quote(buf)); drw(win); } /* try to open local file for this download */ r = opendownloadfile(task->fn, &f, &lfn); if (r==-1) { wp(win, ""RED"* Error: could not open local file \"%s\": %s"WHITE"\n", lfn, strerror(errno)); drw(win); free(lfn); } if (r==-1 || r==-2) { free(task->check); task->state = FAILED; task->d_time = time(0); delsock(m->fd); return(1); } task->lfn = lfn; task->f = f; task->size = strtoul(buf, 0, 10); task->bsz = 0; task->pos = 0; task->p_time = time(0); task->state = IN_PROGRESS; m->bwlimit = 1; bandwidth_init(&m->bw); m->func = gfile; return(1);}/* Sending data to a remote client. State is IN_PROGRESS */int sfile(WINDOW *win, sock_t *m){ char buf[2048], *start, *end; upload_t *task = m->utask; FILE *f; int n, r; time_t t; /* is this mix of low-level and high-level i/o safe? Why use FILE* object if using low-level i/o? -PS */ n = read(fileno(task->f), buf, sizeof(buf)); if (n <= 0) { t = time(0); wp(win, "* Finished sending \"%s\" to %s (%lu of %lu bytes in %lu seconds)\n", task->fn, task->nick, (long)(task->pos-task->bsz), (long)(task->size-task->bsz), (long)(t-task->p_time)); drw(win); if (info.logfile) { f = fopen(info.logfile, "a"); if (f) { start = strdup(ctime(&task->p_time)); start[strlen(start)-1] = 0; end = strdup(ctime(&t)); end[strlen(end)-1] = 0; fprintf(f, "S %s %s \"%s\" %s\n", start, task->nick, task->lfn, end); fclose(f); free(start); free(end); } } fclose(task->f); task->d_time = t; task->state = COMPLETE; delsock(m->fd); return(1); } r = send(m->fd, buf, n, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -